about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock91
-rw-r--r--compiler/rustc_ast/src/ast.rs2
-rw-r--r--compiler/rustc_ast/src/lib.rs1
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs37
-rw-r--r--compiler/rustc_ast/src/visit.rs84
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs50
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs14
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/util.rs30
-rw-r--r--compiler/rustc_attr_parsing/src/lib.rs8
-rw-r--r--compiler/rustc_builtin_macros/Cargo.toml1
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs512
-rw-r--r--compiler/rustc_builtin_macros/src/autodiff.rs73
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/attributes.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/callee.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs26
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs44
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs28
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/naked_asm.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs2
-rw-r--r--compiler/rustc_const_eval/Cargo.toml2
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs17
-rw-r--r--compiler/rustc_const_eval/src/check_consts/mod.rs5
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/util.rs19
-rw-r--r--compiler/rustc_data_structures/Cargo.toml2
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml2
-rw-r--r--compiler/rustc_errors/Cargo.toml2
-rw-r--r--compiler/rustc_expand/Cargo.toml1
-rw-r--r--compiler/rustc_expand/src/base.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs2
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs1
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs11
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml1
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs37
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs70
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs8
-rw-r--r--compiler/rustc_interface/src/passes.rs1
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_lint/Cargo.toml1
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs3
-rw-r--r--compiler/rustc_lint/src/types/literal.rs12
-rw-r--r--compiler/rustc_llvm/build.rs1
-rw-r--r--compiler/rustc_metadata/Cargo.toml1
-rw-r--r--compiler/rustc_metadata/messages.ftl4
-rw-r--r--compiler/rustc_metadata/src/creader.rs21
-rw-r--r--compiler/rustc_metadata/src/errors.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs12
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs8
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs31
-rw-r--r--compiler/rustc_mir_transform/Cargo.toml2
-rw-r--r--compiler/rustc_mir_transform/src/check_inline.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs38
-rw-r--r--compiler/rustc_mir_transform/src/cross_crate_inline.rs2
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs19
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs2
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs6
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs7
-rw-r--r--compiler/rustc_passes/Cargo.toml2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs2
-rw-r--r--compiler/rustc_passes/src/lib_features.rs2
-rw-r--r--compiler/rustc_passes/src/stability.rs24
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs40
-rw-r--r--compiler/rustc_privacy/Cargo.toml2
-rw-r--r--compiler/rustc_privacy/src/lib.rs5
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs2
-rw-r--r--compiler/rustc_query_system/src/lib.rs2
-rw-r--r--compiler/rustc_query_system/src/query/job.rs4
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs133
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs75
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_session/Cargo.toml2
-rw-r--r--compiler/rustc_session/src/config.rs5
-rw-r--r--compiler/rustc_session/src/filesearch.rs12
-rw-r--r--compiler/rustc_session/src/options.rs1
-rw-r--r--compiler/rustc_session/src/session.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/target_features.rs44
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs4
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs2
-rw-r--r--library/alloc/src/str.rs4
-rw-r--r--library/core/src/fmt/float.rs36
-rw-r--r--library/core/src/intrinsics/mod.rs317
-rw-r--r--library/core/src/lib.rs4
-rw-r--r--library/core/src/mem/mod.rs2
-rw-r--r--library/core/src/num/dec2flt/float.rs57
-rw-r--r--library/core/src/num/dec2flt/mod.rs16
-rw-r--r--library/core/src/num/f32.rs806
-rw-r--r--library/core/src/num/f64.rs794
-rw-r--r--library/core/src/num/flt2dec/decoder.rs7
-rw-r--r--library/core/src/pin.rs2
-rw-r--r--library/core/src/ptr/mod.rs293
-rw-r--r--library/core/src/ptr/non_null.rs6
-rw-r--r--library/core/src/slice/mod.rs4
-rw-r--r--library/coretests/tests/floats/f32.rs142
-rw-r--r--library/coretests/tests/floats/f64.rs129
-rw-r--r--library/coretests/tests/num/dec2flt/decimal.rs14
-rw-r--r--library/coretests/tests/num/dec2flt/float.rs40
-rw-r--r--library/coretests/tests/num/dec2flt/lemire.rs133
-rw-r--r--library/coretests/tests/num/dec2flt/mod.rs65
-rw-r--r--library/coretests/tests/num/dec2flt/parse.rs23
-rw-r--r--library/coretests/tests/num/flt2dec/mod.rs234
-rw-r--r--library/coretests/tests/num/flt2dec/random.rs60
-rw-r--r--library/coretests/tests/num/flt2dec/strategy/dragon.rs5
-rw-r--r--library/coretests/tests/num/flt2dec/strategy/grisu.rs4
-rw-r--r--library/coretests/tests/num/mod.rs332
-rw-r--r--library/std/src/f32.rs26
-rw-r--r--library/std/src/f64.rs26
-rw-r--r--library/std/src/ffi/os_str.rs2
-rw-r--r--library/std/src/fs.rs3
-rw-r--r--library/std/src/io/mod.rs53
-rw-r--r--library/std/src/io/tests.rs120
-rw-r--r--library/std/src/lib.rs2
-rw-r--r--library/std/src/path.rs2
-rw-r--r--library/std/src/sync/reentrant_lock.rs8
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs144
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow/thread_info.rs129
-rw-r--r--library/std/src/sys/pal/windows/os.rs2
m---------library/stdarch0
-rw-r--r--src/bootstrap/Cargo.lock71
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/src/bin/rustc.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs23
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs10
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs6
-rw-r--r--src/bootstrap/src/core/builder/mod.rs2
-rw-r--r--src/bootstrap/src/core/sanity.rs20
-rw-r--r--src/bootstrap/src/utils/cache.rs30
-rw-r--r--src/bootstrap/src/utils/cache/tests.rs20
-rw-r--r--src/bootstrap/src/utils/helpers.rs2
-rw-r--r--src/bootstrap/src/utils/job.rs1
-rw-r--r--src/bootstrap/src/utils/shared_helpers.rs2
-rwxr-xr-xsrc/ci/scripts/install-clang.sh4
-rwxr-xr-xsrc/ci/scripts/install-mingw.sh2
-rwxr-xr-xsrc/ci/scripts/install-ninja.sh2
-rwxr-xr-xsrc/ci/scripts/install-sccache.sh2
m---------src/doc/book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
-rw-r--r--src/doc/rustc-dev-guide/rust-version2
-rw-r--r--src/doc/rustc-dev-guide/src/SUMMARY.md2
-rw-r--r--src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md27
-rw-r--r--src/doc/rustc-dev-guide/src/cli.md2
-rw-r--r--src/doc/rustc-dev-guide/src/getting-started.md2
-rw-r--r--src/doc/rustc-dev-guide/src/notification-groups/rust-for-linux.md4
-rw-r--r--src/doc/rustc-dev-guide/src/rustc-driver/intro.md12
-rw-r--r--src/doc/rustc/book.toml2
-rw-r--r--src/doc/rustc/theme/pagetoc.css84
-rw-r--r--src/doc/rustc/theme/pagetoc.js104
-rw-r--r--src/doc/unstable-book/src/language-features/explicit-extern-abis.md4
-rw-r--r--src/etc/test-float-parse/Cargo.toml7
-rw-r--r--src/etc/test-float-parse/src/gen_/subnorm.rs9
-rw-r--r--src/etc/test-float-parse/src/lib.rs7
-rw-r--r--src/etc/test-float-parse/src/traits.rs5
-rw-r--r--src/librustdoc/clean/types.rs14
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/librustdoc/html/layout.rs19
-rw-r--r--src/librustdoc/html/render/context.rs7
-rw-r--r--src/librustdoc/html/render/mod.rs39
-rw-r--r--src/librustdoc/html/render/sidebar.rs10
-rw-r--r--src/librustdoc/html/sources.rs21
-rw-r--r--src/librustdoc/json/conversions.rs6
-rw-r--r--src/librustdoc/lib.rs2
-rw-r--r--src/librustdoc/passes/propagate_stability.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_union_representation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/incompatible_msrv.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/std_instead_of_core.rs2
-rw-r--r--src/tools/clippy/clippy_lints_internal/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs4
-rw-r--r--src/tools/compiletest/Cargo.toml2
-rw-r--r--src/tools/miri/README.md1
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs7
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/helpers.rs6
-rw-r--r--src/tools/miri/src/lib.rs2
-rw-r--r--src/tools/miri/src/machine.rs2
-rw-r--r--src/tools/miri/src/shims/native_lib.rs15
-rw-r--r--src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs9
-rw-r--r--src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs9
-rw-r--r--src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr4
-rw-r--r--src/tools/miri/tests/many-seeds/reentrant-lock.rs19
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs2
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs1
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs1
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs1
-rw-r--r--src/tools/opt-dist/src/bolt.rs2
-rw-r--r--src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/config.yml4
-rw-r--r--src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md2
-rw-r--r--src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/question.md8
-rw-r--r--src/tools/rust-analyzer/.github/workflows/metrics.yaml12
-rw-r--r--src/tools/rust-analyzer/Cargo.lock143
-rw-r--r--src/tools/rust-analyzer/Cargo.toml15
-rw-r--r--src/tools/rust-analyzer/crates/base-db/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/signatures.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/find_path.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/import_map.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs44
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres.rs172
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs109
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs101
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs37
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs148
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs152
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/test_db.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/visibility.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs51
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs35
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs80
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs36
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs63
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/variance.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/attrs.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs30
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs48
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs179
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs52
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs190
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_type_to_generic_arg.rs156
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs17
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs31
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs67
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/defs.rs63
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/documentation.rs83
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs332
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/prime_caches/topologic_sort.rs104
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/rename.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/await_outside_of_async.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/bad_rtn.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/expected_function.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_order.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_derive_target.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/malformed_derive.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_lifetime.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/parenthesized_generic_args_without_fn_trait.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_field.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/undeclared_label.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unimplemented_builtin_macro.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unreachable_label.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_extern_crate.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_ident.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_import.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_method.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_module.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs17
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs118
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs109
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs68
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs67
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs46
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs122
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/parent_module.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs17
-rw-r--r--src/tools/rust-analyzer/crates/load-cargo/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/tests.rs117
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs8
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/lexed_str.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_label.rast37
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_label.rs3
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs5
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs3
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs42
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/symbol.rs47
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs42
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs5
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs270
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs43
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/env.rs1
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs7
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt5
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt5
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs18
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/prime_caches.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs205
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs16
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs5
-rw-r--r--src/tools/rust-analyzer/crates/stdx/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs51
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs61
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs3
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs36
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/lib.rs52
-rw-r--r--src/tools/rust-analyzer/editors/code/package-lock.json6
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--src/tools/rust-analyzer/xtask/Cargo.toml2
-rw-r--r--src/tools/rustfmt/src/parse/macros/asm.rs4
-rw-r--r--src/tools/tidy/src/deps.rs3
-rw-r--r--tests/codegen/autodiff/generic.rs42
-rw-r--r--tests/coverage/async_closure.cov-map21
-rw-r--r--tests/coverage/unused-local-file.coverage7
-rw-r--r--tests/coverage/unused-local-file.rs22
-rw-r--r--tests/crashes/139905.rs6
-rw-r--r--tests/crashes/140011.rs11
-rw-r--r--tests/crashes/140099.rs6
-rw-r--r--tests/crashes/140100.rs7
-rw-r--r--tests/crashes/140123-2.rs12
-rw-r--r--tests/crashes/140123-3.rs10
-rw-r--r--tests/crashes/140123-4.rs13
-rw-r--r--tests/crashes/140123.rs10
-rw-r--r--tests/crashes/140255.rs3
-rw-r--r--tests/crashes/140275.rs5
-rw-r--r--tests/crashes/140281.rs18
-rw-r--r--tests/crashes/140303.rs22
-rw-r--r--tests/crashes/140333.rs9
-rw-r--r--tests/crashes/140365.rs8
-rw-r--r--tests/crashes/140381.rs16
-rw-r--r--tests/crashes/140429.rs6
-rw-r--r--tests/crashes/140479.rs5
-rw-r--r--tests/crashes/140484.rs14
-rw-r--r--tests/crashes/140500.rs14
-rw-r--r--tests/crashes/140530.rs8
-rw-r--r--tests/crashes/140531.rs7
-rw-r--r--tests/crashes/140571.rs14
-rw-r--r--tests/crashes/140577.rs32
-rw-r--r--tests/crashes/140609.rs13
-rw-r--r--tests/crashes/140642.rs8
-rw-r--r--tests/crashes/140683.rs5
-rw-r--r--tests/crashes/140729.rs11
-rw-r--r--tests/crashes/140850.rs7
-rw-r--r--tests/crashes/140860.rs10
-rw-r--r--tests/crashes/140884.rs6
-rw-r--r--tests/crashes/140891.rs6
-rw-r--r--tests/crashes/140974.rs14
-rw-r--r--tests/crashes/140975.rs22
-rw-r--r--tests/crashes/141124.rs16
-rw-r--r--tests/crashes/141143.rs13
-rw-r--r--tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff2
-rw-r--r--tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff2
-rw-r--r--tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff4
-rw-r--r--tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff4
-rw-r--r--tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff4
-rw-r--r--tests/mir-opt/gvn_overlapping.overlapping.GVN.diff18
-rw-r--r--tests/mir-opt/gvn_overlapping.rs36
-rw-r--r--tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.rs9
-rw-r--r--tests/pretty/autodiff/autodiff_forward.pp14
-rw-r--r--tests/pretty/autodiff/autodiff_forward.rs6
-rw-r--r--tests/run-make/core-no-oom-handling/rmake.rs2
-rw-r--r--tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs7
-rw-r--r--tests/ui/abi/homogenous-floats-target-feature-mixup.rs2
-rw-r--r--tests/ui/abi/simd-abi-checks-avx.rs1
-rw-r--r--tests/ui/abi/simd-abi-checks-avx.stderr24
-rw-r--r--tests/ui/asm/aarch64/parse-error.rs109
-rw-r--r--tests/ui/asm/aarch64/parse-error.stderr382
-rw-r--r--tests/ui/asm/parse-error.rs6
-rw-r--r--tests/ui/asm/parse-error.stderr54
-rw-r--r--tests/ui/asm/x86_64/evex512-implicit-feature.rs1
-rw-r--r--tests/ui/asm/x86_64/target-feature-attr.rs2
-rw-r--r--tests/ui/asm/x86_64/target-feature-attr.stderr8
-rw-r--r--tests/ui/async-await/async-drop/dependency-dropped.rs5
-rw-r--r--tests/ui/async-await/async-drop/dependency-dropped.with_feature.run.stdout (renamed from tests/ui/async-await/async-drop/dependency-dropped.run.stdout)0
-rw-r--r--tests/ui/async-await/async-drop/dependency-dropped.without_feature.run.stdout1
-rw-r--r--tests/ui/async-await/async-drop/dependency-dropped.without_feature.stderr10
-rw-r--r--tests/ui/async-await/format-await-send.rs24
-rw-r--r--tests/ui/attributes/auxiliary/use-doc-alias-name-extern.rs24
-rw-r--r--tests/ui/attributes/use-doc-alias-name.rs67
-rw-r--r--tests/ui/attributes/use-doc-alias-name.stderr150
-rw-r--r--tests/ui/consts/const-eval/raw-pointer-ub.rs2
-rw-r--r--tests/ui/consts/const-eval/raw-pointer-ub.stderr4
-rw-r--r--tests/ui/consts/copy-intrinsic.rs20
-rw-r--r--tests/ui/consts/copy-intrinsic.stderr8
-rw-r--r--tests/ui/consts/missing_span_in_backtrace.stderr4
-rw-r--r--tests/ui/drop/drop-order-comparisons.e2021.fixed41
-rw-r--r--tests/ui/drop/drop-order-comparisons.e2021.stderr96
-rw-r--r--tests/ui/drop/drop-order-comparisons.rs41
-rw-r--r--tests/ui/feature-gates/feature-gate-guard-patterns.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-guard-patterns.stderr31
-rw-r--r--tests/ui/fn/coerce-suggestion-infer-region.rs26
-rw-r--r--tests/ui/fn/coerce-suggestion-infer-region.stderr12
-rw-r--r--tests/ui/impl-trait/issues/issue-100075-2.stderr15
-rw-r--r--tests/ui/impl-trait/issues/issue-100075.stderr5
-rw-r--r--tests/ui/impl-trait/issues/issue-103599.rs5
-rw-r--r--tests/ui/impl-trait/issues/issue-103599.stderr13
-rw-r--r--tests/ui/impl-trait/issues/issue-87450.rs4
-rw-r--r--tests/ui/impl-trait/issues/issue-87450.stderr18
-rw-r--r--tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr73
-rw-r--r--tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr53
-rw-r--r--tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr18
-rw-r--r--tests/ui/impl-trait/recursive-in-exhaustiveness.rs6
-rw-r--r--tests/ui/imports/issue-99695-b.fixed2
-rw-r--r--tests/ui/imports/issue-99695-b.stderr2
-rw-r--r--tests/ui/imports/issue-99695.edition_2015.fixed (renamed from tests/ui/imports/issue-99695.fixed)6
-rw-r--r--tests/ui/imports/issue-99695.edition_2015.stderr (renamed from tests/ui/imports/issue-99695.stderr)4
-rw-r--r--tests/ui/imports/issue-99695.edition_2018.fixed21
-rw-r--r--tests/ui/imports/issue-99695.edition_2018.stderr16
-rw-r--r--tests/ui/imports/issue-99695.rs4
-rw-r--r--tests/ui/mir/mir_match_guard_let_chains_drop_order.rs110
-rw-r--r--tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.rs81
-rw-r--r--tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.stderr133
-rw-r--r--tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs15
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/temporary-early-drop.rs29
-rw-r--r--tests/ui/simd/target-feature-mixup.rs1
-rw-r--r--tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs4
-rw-r--r--tests/ui/target-feature/gate.rs3
-rw-r--r--tests/ui/target-feature/gate.stderr10
-rw-r--r--tests/ui/target-feature/unstable-feature.rs4
-rw-r--r--tests/ui/target-feature/unstable-feature.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.rs (renamed from tests/crashes/139817.rs)6
-rw-r--r--tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-fn-tait.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr11
-rw-r--r--triagebot.toml9
520 files changed, 9144 insertions, 4746 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f1fddefcb01..99cb71cd0ac 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -738,7 +738,7 @@ dependencies = [
  "tracing-subscriber",
  "unified-diff",
  "walkdir",
- "windows 0.59.0",
+ "windows",
 ]
 
 [[package]]
@@ -1587,7 +1587,7 @@ dependencies = [
  "js-sys",
  "log",
  "wasm-bindgen",
- "windows-core 0.61.0",
+ "windows-core",
 ]
 
 [[package]]
@@ -3390,6 +3390,7 @@ version = "0.0.0"
 dependencies = [
  "rustc_ast",
  "rustc_ast_pretty",
+ "rustc_attr_data_structures",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -3424,7 +3425,7 @@ dependencies = [
  "rustc-demangle",
  "rustc_abi",
  "rustc_ast",
- "rustc_attr_parsing",
+ "rustc_attr_data_structures",
  "rustc_codegen_ssa",
  "rustc_data_structures",
  "rustc_errors",
@@ -3467,6 +3468,7 @@ dependencies = [
  "rustc_abi",
  "rustc_arena",
  "rustc_ast",
+ "rustc_attr_data_structures",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -3493,7 +3495,7 @@ dependencies = [
  "thorin-dwp",
  "tracing",
  "wasm-encoder 0.219.2",
- "windows 0.59.0",
+ "windows",
 ]
 
 [[package]]
@@ -3504,7 +3506,7 @@ dependencies = [
  "rustc_abi",
  "rustc_apfloat",
  "rustc_ast",
- "rustc_attr_parsing",
+ "rustc_attr_data_structures",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
@@ -3552,7 +3554,7 @@ dependencies = [
  "tempfile",
  "thin-vec",
  "tracing",
- "windows 0.59.0",
+ "windows",
 ]
 
 [[package]]
@@ -3615,7 +3617,7 @@ dependencies = [
  "shlex",
  "stable_mir",
  "tracing",
- "windows 0.59.0",
+ "windows",
 ]
 
 [[package]]
@@ -3670,7 +3672,7 @@ dependencies = [
  "termcolor",
  "termize",
  "tracing",
- "windows 0.59.0",
+ "windows",
 ]
 
 [[package]]
@@ -3680,6 +3682,7 @@ dependencies = [
  "rustc_ast",
  "rustc_ast_passes",
  "rustc_ast_pretty",
+ "rustc_attr_data_structures",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -3768,7 +3771,7 @@ dependencies = [
  "rustc_abi",
  "rustc_arena",
  "rustc_ast",
- "rustc_attr_parsing",
+ "rustc_attr_data_structures",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_feature",
@@ -3805,6 +3808,7 @@ dependencies = [
  "itertools",
  "rustc_abi",
  "rustc_ast",
+ "rustc_attr_data_structures",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -3950,6 +3954,7 @@ dependencies = [
  "rustc_abi",
  "rustc_ast",
  "rustc_ast_pretty",
+ "rustc_attr_data_structures",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -4023,6 +4028,7 @@ dependencies = [
  "odht",
  "rustc_abi",
  "rustc_ast",
+ "rustc_attr_data_structures",
  "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
@@ -4136,7 +4142,7 @@ dependencies = [
  "rustc_abi",
  "rustc_arena",
  "rustc_ast",
- "rustc_attr_parsing",
+ "rustc_attr_data_structures",
  "rustc_const_eval",
  "rustc_data_structures",
  "rustc_errors",
@@ -4162,7 +4168,7 @@ version = "0.0.0"
 dependencies = [
  "rustc_abi",
  "rustc_ast",
- "rustc_attr_parsing",
+ "rustc_attr_data_structures",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
@@ -4232,7 +4238,7 @@ dependencies = [
  "rustc_ast",
  "rustc_ast_lowering",
  "rustc_ast_pretty",
- "rustc_attr_parsing",
+ "rustc_attr_data_structures",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_expand",
@@ -4278,7 +4284,7 @@ name = "rustc_privacy"
 version = "0.0.0"
 dependencies = [
  "rustc_ast",
- "rustc_attr_parsing",
+ "rustc_attr_data_structures",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
@@ -4415,7 +4421,7 @@ dependencies = [
  "smallvec",
  "termize",
  "tracing",
- "windows 0.59.0",
+ "windows",
 ]
 
 [[package]]
@@ -5102,7 +5108,7 @@ dependencies = [
  "libc",
  "objc2-core-foundation",
  "objc2-io-kit",
- "windows 0.61.1",
+ "windows",
 ]
 
 [[package]]
@@ -6004,22 +6010,12 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1"
-dependencies = [
- "windows-core 0.59.0",
- "windows-targets 0.53.0",
-]
-
-[[package]]
-name = "windows"
 version = "0.61.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
 dependencies = [
  "windows-collections",
- "windows-core 0.61.0",
+ "windows-core",
  "windows-future",
  "windows-link",
  "windows-numerics",
@@ -6042,20 +6038,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
 dependencies = [
- "windows-core 0.61.0",
-]
-
-[[package]]
-name = "windows-core"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
-dependencies = [
- "windows-implement 0.59.0",
- "windows-interface",
- "windows-result",
- "windows-strings 0.3.1",
- "windows-targets 0.53.0",
+ "windows-core",
 ]
 
 [[package]]
@@ -6064,11 +6047,11 @@ version = "0.61.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
 dependencies = [
- "windows-implement 0.60.0",
+ "windows-implement",
  "windows-interface",
  "windows-link",
  "windows-result",
- "windows-strings 0.4.0",
+ "windows-strings",
 ]
 
 [[package]]
@@ -6077,23 +6060,12 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
 dependencies = [
- "windows-core 0.61.0",
+ "windows-core",
  "windows-link",
 ]
 
 [[package]]
 name = "windows-implement"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.101",
-]
-
-[[package]]
-name = "windows-implement"
 version = "0.60.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
@@ -6126,7 +6098,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
 dependencies = [
- "windows-core 0.61.0",
+ "windows-core",
  "windows-link",
 ]
 
@@ -6141,15 +6113,6 @@ dependencies = [
 
 [[package]]
 name = "windows-strings"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
-dependencies = [
- "windows-link",
-]
-
-[[package]]
-name = "windows-strings"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 4ace80a7344..a16219361c0 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -610,7 +610,7 @@ impl Pat {
     /// Walk top-down and call `it` in each place where a pattern occurs
     /// starting with the root pattern `walk` is called on. If `it` returns
     /// false then we will descend no further but siblings will be processed.
-    pub fn walk(&self, it: &mut impl FnMut(&Pat) -> bool) {
+    pub fn walk<'ast>(&'ast self, it: &mut impl FnMut(&'ast Pat) -> bool) {
         if !it(self) {
             return;
         }
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 89a5a67eb53..4fc7c7475d7 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -15,6 +15,7 @@
 #![feature(associated_type_defaults)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
+#![feature(macro_metavar_expr)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(rustdoc_internals)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index e49886721e3..a90349f318c 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -20,7 +20,7 @@ use thin_vec::ThinVec;
 use crate::ast::*;
 use crate::ptr::P;
 use crate::tokenstream::*;
-use crate::visit::{AssocCtxt, BoundKind, FnCtxt};
+use crate::visit::{AssocCtxt, BoundKind, FnCtxt, try_visit};
 
 pub trait ExpectOne<A: Array> {
     fn expect_one(self, err: &'static str) -> A::Item;
@@ -388,6 +388,8 @@ pub trait MutVisitor: Sized {
     }
 }
 
+super::common_visitor_and_walkers!((mut) MutVisitor);
+
 /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
 /// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
 /// method.
@@ -778,15 +780,6 @@ fn visit_defaultness<T: MutVisitor>(vis: &mut T, defaultness: &mut Defaultness)
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_safety<T: MutVisitor>(vis: &mut T, safety: &mut Safety) {
-    match safety {
-        Safety::Unsafe(span) => vis.visit_span(span),
-        Safety::Safe(span) => vis.visit_span(span),
-        Safety::Default => {}
-    }
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 fn visit_polarity<T: MutVisitor>(vis: &mut T, polarity: &mut ImplPolarity) {
     match polarity {
         ImplPolarity::Positive => {}
@@ -794,14 +787,6 @@ fn visit_polarity<T: MutVisitor>(vis: &mut T, polarity: &mut ImplPolarity) {
     }
 }
 
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-fn visit_constness<T: MutVisitor>(vis: &mut T, constness: &mut Const) {
-    match constness {
-        Const::Yes(span) => vis.visit_span(span),
-        Const::No => {}
-    }
-}
-
 fn walk_closure_binder<T: MutVisitor>(vis: &mut T, binder: &mut ClosureBinder) {
     match binder {
         ClosureBinder::NotPresent => {}
@@ -940,15 +925,6 @@ pub fn walk_flat_map_generic_param<T: MutVisitor>(
     smallvec![param]
 }
 
-fn walk_label<T: MutVisitor>(vis: &mut T, Label { ident }: &mut Label) {
-    vis.visit_ident(ident);
-}
-
-fn walk_lifetime<T: MutVisitor>(vis: &mut T, Lifetime { id, ident }: &mut Lifetime) {
-    vis.visit_id(id);
-    vis.visit_ident(ident);
-}
-
 fn walk_generics<T: MutVisitor>(vis: &mut T, generics: &mut Generics) {
     let Generics { params, where_clause, span } = generics;
     params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
@@ -1340,13 +1316,6 @@ fn walk_const_item<T: MutVisitor>(vis: &mut T, item: &mut ConstItem) {
     walk_define_opaques(vis, define_opaque);
 }
 
-fn walk_fn_header<T: MutVisitor>(vis: &mut T, header: &mut FnHeader) {
-    let FnHeader { safety, coroutine_kind, constness, ext: _ } = header;
-    visit_constness(vis, constness);
-    coroutine_kind.as_mut().map(|coroutine_kind| vis.visit_coroutine_kind(coroutine_kind));
-    visit_safety(vis, safety);
-}
-
 pub fn walk_crate<T: MutVisitor>(vis: &mut T, krate: &mut Crate) {
     let Crate { attrs, items, spans, id, is_placeholder: _ } = krate;
     vis.visit_id(id);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 69a186c8cf1..e43d7ae065d 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -315,6 +315,75 @@ pub trait Visitor<'ast>: Sized {
     }
 }
 
+#[macro_export]
+macro_rules! common_visitor_and_walkers {
+    ($(($mut: ident))? $Visitor:ident$(<$lt:lifetime>)?) => {
+        // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
+        $(${ignore($lt)}
+            #[expect(unused, rustc::pass_by_value)]
+            #[inline]
+        )?
+        fn visit_span<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, span: &$($lt)? $($mut)? Span) $(-> <V as Visitor<$lt>>::Result)? {
+            $(
+                let _ = stringify!($mut);
+                visitor.visit_span(span);
+            )?
+            $(${ignore($lt)}V::Result::output())?
+        }
+
+        // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
+        $(${ignore($lt)}
+            #[expect(unused, rustc::pass_by_value)]
+            #[inline]
+        )?
+        fn visit_id<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, id: &$($lt)? $($mut)? NodeId) $(-> <V as Visitor<$lt>>::Result)? {
+            $(
+                let _ = stringify!($mut);
+                visitor.visit_id(id);
+            )?
+            $(${ignore($lt)}V::Result::output())?
+        }
+
+        // this is only used by the MutVisitor. We include this symmetry here to make writing other functions easier
+        fn visit_safety<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, safety: &$($lt)? $($mut)? Safety) $(-> <V as Visitor<$lt>>::Result)? {
+            match safety {
+                Safety::Unsafe(span) => visit_span(vis, span),
+                Safety::Safe(span) => visit_span(vis, span),
+                Safety::Default => { $(${ignore($lt)}V::Result::output())? }
+            }
+        }
+
+        fn visit_constness<$($lt,)? V: $Visitor$(<$lt>)?>(vis: &mut V, constness: &$($lt)? $($mut)? Const) $(-> <V as Visitor<$lt>>::Result)? {
+            match constness {
+                Const::Yes(span) => visit_span(vis, span),
+                Const::No => {
+                    $(<V as Visitor<$lt>>::Result::output())?
+                }
+            }
+        }
+
+        pub fn walk_label<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Label { ident }: &$($lt)? $($mut)? Label) $(-> <V as Visitor<$lt>>::Result)? {
+            visitor.visit_ident(ident)
+        }
+
+        pub fn walk_fn_header<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, header: &$($lt)? $($mut)? FnHeader) $(-> <V as Visitor<$lt>>::Result)? {
+            let FnHeader { safety, coroutine_kind, constness, ext: _ } = header;
+            try_visit!(visit_constness(visitor, constness));
+            if let Some(coroutine_kind) = coroutine_kind {
+                try_visit!(visitor.visit_coroutine_kind(coroutine_kind));
+            }
+            visit_safety(visitor, safety)
+        }
+
+        pub fn walk_lifetime<$($lt,)? V: $Visitor$(<$lt>)?>(visitor: &mut V, Lifetime { id, ident }: &$($lt)? $($mut)? Lifetime) $(-> <V as Visitor<$lt>>::Result)? {
+            try_visit!(visit_id(visitor, id));
+            visitor.visit_ident(ident)
+        }
+    };
+}
+
+common_visitor_and_walkers!(Visitor<'a>);
+
 pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) -> V::Result {
     let Crate { attrs, items, spans: _, id: _, is_placeholder: _ } = krate;
     walk_list!(visitor, visit_attribute, attrs);
@@ -334,15 +403,6 @@ pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) -> V::R
     V::Result::output()
 }
 
-pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, Label { ident }: &'a Label) -> V::Result {
-    visitor.visit_ident(ident)
-}
-
-pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime) -> V::Result {
-    let Lifetime { id: _, ident } = lifetime;
-    visitor.visit_ident(ident)
-}
-
 pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef) -> V::Result
 where
     V: Visitor<'a>,
@@ -926,12 +986,6 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy)
     V::Result::output()
 }
 
-pub fn walk_fn_header<'a, V: Visitor<'a>>(visitor: &mut V, fn_header: &'a FnHeader) -> V::Result {
-    let FnHeader { safety: _, coroutine_kind, constness: _, ext: _ } = fn_header;
-    visit_opt!(visitor, visit_coroutine_kind, coroutine_kind.as_ref());
-    V::Result::output()
-}
-
 pub fn walk_fn_decl<'a, V: Visitor<'a>>(
     visitor: &mut V,
     FnDecl { inputs, output }: &'a FnDecl,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index f48a571b86a..e98d6c50ee7 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -70,44 +70,32 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
         }
     }
 
-    pub(super) fn lower_node(&mut self, def_id: LocalDefId) -> hir::MaybeOwner<'hir> {
+    pub(super) fn lower_node(&mut self, def_id: LocalDefId) {
         let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
         if let hir::MaybeOwner::Phantom = owner {
             let node = self.ast_index[def_id];
             match node {
                 AstOwner::NonOwner => {}
-                AstOwner::Crate(c) => self.lower_crate(c),
-                AstOwner::Item(item) => self.lower_item(item),
-                AstOwner::AssocItem(item, ctxt) => self.lower_assoc_item(item, ctxt),
-                AstOwner::ForeignItem(item) => self.lower_foreign_item(item),
+                AstOwner::Crate(c) => {
+                    debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
+                    self.with_lctx(CRATE_NODE_ID, |lctx| {
+                        let module = lctx.lower_mod(&c.items, &c.spans);
+                        // FIXME(jdonszelman): is dummy span ever a problem here?
+                        lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP);
+                        hir::OwnerNode::Crate(module)
+                    })
+                }
+                AstOwner::Item(item) => {
+                    self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
+                }
+                AstOwner::AssocItem(item, ctxt) => {
+                    self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt))
+                }
+                AstOwner::ForeignItem(item) => self.with_lctx(item.id, |lctx| {
+                    hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))
+                }),
             }
         }
-
-        self.owners[def_id]
-    }
-
-    #[instrument(level = "debug", skip(self, c))]
-    fn lower_crate(&mut self, c: &Crate) {
-        debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
-        self.with_lctx(CRATE_NODE_ID, |lctx| {
-            let module = lctx.lower_mod(&c.items, &c.spans);
-            // FIXME(jdonszelman): is dummy span ever a problem here?
-            lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP);
-            hir::OwnerNode::Crate(module)
-        })
-    }
-
-    #[instrument(level = "debug", skip(self))]
-    fn lower_item(&mut self, item: &Item) {
-        self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
-    }
-
-    fn lower_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) {
-        self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt))
-    }
-
-    fn lower_foreign_item(&mut self, item: &ForeignItem) {
-        self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)))
     }
 }
 
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 19095f2e01e..422e79ca82f 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -444,14 +444,14 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
         tcx.definitions_untracked().def_index_count(),
     );
 
+    let mut lowerer = item::ItemLowerer {
+        tcx,
+        resolver: &mut resolver,
+        ast_index: &ast_index,
+        owners: &mut owners,
+    };
     for def_id in ast_index.indices() {
-        item::ItemLowerer {
-            tcx,
-            resolver: &mut resolver,
-            ast_index: &ast_index,
-            owners: &mut owners,
-        }
-        .lower_node(def_id);
+        lowerer.lower_node(def_id);
     }
 
     drop(ast_index);
diff --git a/compiler/rustc_attr_parsing/src/attributes/util.rs b/compiler/rustc_attr_parsing/src/attributes/util.rs
index 05a9029c59a..503d2f1fae1 100644
--- a/compiler/rustc_attr_parsing/src/attributes/util.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/util.rs
@@ -26,3 +26,33 @@ pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
 pub fn find_crate_name(attrs: &[impl AttributeExt]) -> Option<Symbol> {
     first_attr_value_str_by_name(attrs, sym::crate_name)
 }
+
+pub fn is_doc_alias_attrs_contain_symbol<'tcx, T: AttributeExt + 'tcx>(
+    attrs: impl Iterator<Item = &'tcx T>,
+    symbol: Symbol,
+) -> bool {
+    let doc_attrs = attrs.filter(|attr| attr.has_name(sym::doc));
+    for attr in doc_attrs {
+        let Some(values) = attr.meta_item_list() else {
+            continue;
+        };
+        let alias_values = values.iter().filter(|v| v.has_name(sym::alias));
+        for v in alias_values {
+            if let Some(nested) = v.meta_item_list() {
+                // #[doc(alias("foo", "bar"))]
+                let mut iter = nested.iter().filter_map(|item| item.lit()).map(|item| item.symbol);
+                if iter.any(|s| s == symbol) {
+                    return true;
+                }
+            } else if let Some(meta) = v.meta_item()
+                && let Some(lit) = meta.name_value_literal()
+            {
+                // #[doc(alias = "foo")]
+                if lit.symbol == symbol {
+                    return true;
+                }
+            }
+        }
+    }
+    false
+}
diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs
index 177df356742..63bccf52018 100644
--- a/compiler/rustc_attr_parsing/src/lib.rs
+++ b/compiler/rustc_attr_parsing/src/lib.rs
@@ -60,7 +60,8 @@
 //! `#[stable(...)]` and `#[unstable()]` cannot occur together, and both semantically define
 //! a "stability" of an item. So, the stability attribute has an
 //! [`AttributeParser`](attributes::AttributeParser) that recognizes both the `#[stable()]`
-//! and `#[unstable()]` syntactic attributes, and at the end produce a single [`AttributeKind::Stability`].
+//! and `#[unstable()]` syntactic attributes, and at the end produce a single
+//! [`AttributeKind::Stability`](rustc_attr_data_structures::AttributeKind::Stability).
 //!
 //! As a rule of thumb, when a syntactical attribute can be applied more than once, they should be
 //! combined into a single semantic attribute. For example:
@@ -89,8 +90,9 @@ pub mod parser;
 mod session_diagnostics;
 
 pub use attributes::cfg::*;
-pub use attributes::util::{find_crate_name, is_builtin_attr, parse_version};
+pub use attributes::util::{
+    find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
+};
 pub use context::{AttributeParser, OmitDoc};
-pub use rustc_attr_data_structures::*;
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index 1289d21308b..5c1ae90f729 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -10,6 +10,7 @@ doctest = false
 # tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 3e8ddb8abd4..62ee71fecc2 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -18,7 +18,31 @@ use {rustc_ast as ast, rustc_parse_format as parse};
 use crate::errors;
 use crate::util::{ExprToSpannedString, expr_to_spanned_string};
 
-pub struct AsmArgs {
+/// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise
+/// not validated at all.
+pub struct AsmArg {
+    pub kind: AsmArgKind,
+    pub span: Span,
+}
+
+pub enum AsmArgKind {
+    Template(P<ast::Expr>),
+    Operand(Option<Symbol>, ast::InlineAsmOperand),
+    Options(Vec<AsmOption>),
+    ClobberAbi(Vec<(Symbol, Span)>),
+}
+
+pub struct AsmOption {
+    pub symbol: Symbol,
+    pub span: Span,
+    // A bitset, with only the bit for this option's symbol set.
+    pub options: ast::InlineAsmOptions,
+    // Used when suggesting to remove an option.
+    pub span_with_comma: Span,
+}
+
+/// Validated assembly arguments, ready for macro expansion.
+struct ValidatedAsmArgs {
     pub templates: Vec<P<ast::Expr>>,
     pub operands: Vec<(ast::InlineAsmOperand, Span)>,
     named_args: FxIndexMap<Symbol, usize>,
@@ -59,41 +83,95 @@ fn eat_operand_keyword<'a>(
     }
 }
 
-fn parse_args<'a>(
-    ecx: &ExtCtxt<'a>,
-    sp: Span,
-    tts: TokenStream,
+fn parse_asm_operand<'a>(
+    p: &mut Parser<'a>,
     asm_macro: AsmMacro,
-) -> PResult<'a, AsmArgs> {
-    let mut p = ecx.new_parser_from_tts(tts);
-    parse_asm_args(&mut p, sp, asm_macro)
+) -> PResult<'a, Option<ast::InlineAsmOperand>> {
+    let dcx = p.dcx();
+
+    Ok(Some(if eat_operand_keyword(p, exp!(In), asm_macro)? {
+        let reg = parse_reg(p)?;
+        if p.eat_keyword(exp!(Underscore)) {
+            let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
+            return Err(err);
+        }
+        let expr = p.parse_expr()?;
+        ast::InlineAsmOperand::In { reg, expr }
+    } else if eat_operand_keyword(p, exp!(Out), asm_macro)? {
+        let reg = parse_reg(p)?;
+        let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
+        ast::InlineAsmOperand::Out { reg, expr, late: false }
+    } else if eat_operand_keyword(p, exp!(Lateout), asm_macro)? {
+        let reg = parse_reg(p)?;
+        let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
+        ast::InlineAsmOperand::Out { reg, expr, late: true }
+    } else if eat_operand_keyword(p, exp!(Inout), asm_macro)? {
+        let reg = parse_reg(p)?;
+        if p.eat_keyword(exp!(Underscore)) {
+            let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
+            return Err(err);
+        }
+        let expr = p.parse_expr()?;
+        if p.eat(exp!(FatArrow)) {
+            let out_expr =
+                if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
+            ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: false }
+        } else {
+            ast::InlineAsmOperand::InOut { reg, expr, late: false }
+        }
+    } else if eat_operand_keyword(p, exp!(Inlateout), asm_macro)? {
+        let reg = parse_reg(p)?;
+        if p.eat_keyword(exp!(Underscore)) {
+            let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
+            return Err(err);
+        }
+        let expr = p.parse_expr()?;
+        if p.eat(exp!(FatArrow)) {
+            let out_expr =
+                if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
+            ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: true }
+        } else {
+            ast::InlineAsmOperand::InOut { reg, expr, late: true }
+        }
+    } else if eat_operand_keyword(p, exp!(Label), asm_macro)? {
+        let block = p.parse_block()?;
+        ast::InlineAsmOperand::Label { block }
+    } else if p.eat_keyword(exp!(Const)) {
+        let anon_const = p.parse_expr_anon_const()?;
+        ast::InlineAsmOperand::Const { anon_const }
+    } else if p.eat_keyword(exp!(Sym)) {
+        let expr = p.parse_expr()?;
+        let ast::ExprKind::Path(qself, path) = &expr.kind else {
+            let err = dcx.create_err(errors::AsmSymNoPath { span: expr.span });
+            return Err(err);
+        };
+        let sym =
+            ast::InlineAsmSym { id: ast::DUMMY_NODE_ID, qself: qself.clone(), path: path.clone() };
+        ast::InlineAsmOperand::Sym { sym }
+    } else {
+        return Ok(None);
+    }))
 }
 
-// Primarily public for rustfmt consumption.
-// Internal consumers should continue to leverage `expand_asm`/`expand__global_asm`
+// Public for rustfmt.
 pub fn parse_asm_args<'a>(
     p: &mut Parser<'a>,
     sp: Span,
     asm_macro: AsmMacro,
-) -> PResult<'a, AsmArgs> {
+) -> PResult<'a, Vec<AsmArg>> {
     let dcx = p.dcx();
 
     if p.token == token::Eof {
         return Err(dcx.create_err(errors::AsmRequiresTemplate { span: sp }));
     }
 
+    let mut args = Vec::new();
+
     let first_template = p.parse_expr()?;
-    let mut args = AsmArgs {
-        templates: vec![first_template],
-        operands: vec![],
-        named_args: Default::default(),
-        reg_args: Default::default(),
-        clobber_abis: Vec::new(),
-        options: ast::InlineAsmOptions::empty(),
-        options_spans: vec![],
-    };
+    args.push(AsmArg { span: first_template.span, kind: AsmArgKind::Template(first_template) });
 
     let mut allow_templates = true;
+
     while p.token != token::Eof {
         if !p.eat(exp!(Comma)) {
             if allow_templates {
@@ -104,27 +182,39 @@ pub fn parse_asm_args<'a>(
                 return Err(p.expect(exp!(Comma)).err().unwrap());
             }
         }
+
+        // Accept trailing commas.
         if p.token == token::Eof {
             break;
-        } // accept trailing commas
+        }
 
-        // Parse clobber_abi
+        let span_start = p.token.span;
+
+        // Parse `clobber_abi`.
         if p.eat_keyword(exp!(ClobberAbi)) {
-            parse_clobber_abi(p, &mut args)?;
             allow_templates = false;
+
+            args.push(AsmArg {
+                kind: AsmArgKind::ClobberAbi(parse_clobber_abi(p)?),
+                span: span_start.to(p.prev_token.span),
+            });
+
             continue;
         }
 
-        // Parse options
+        // Parse `options`.
         if p.eat_keyword(exp!(Options)) {
-            parse_options(p, &mut args, asm_macro)?;
             allow_templates = false;
+
+            args.push(AsmArg {
+                kind: AsmArgKind::Options(parse_options(p, asm_macro)?),
+                span: span_start.to(p.prev_token.span),
+            });
+
             continue;
         }
 
-        let span_start = p.token.span;
-
-        // Parse operand names
+        // Parse operand names.
         let name = if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) {
             let (ident, _) = p.token.ident().unwrap();
             p.bump();
@@ -135,69 +225,13 @@ pub fn parse_asm_args<'a>(
             None
         };
 
-        let mut explicit_reg = false;
-        let op = if eat_operand_keyword(p, exp!(In), asm_macro)? {
-            let reg = parse_reg(p, &mut explicit_reg)?;
-            if p.eat_keyword(exp!(Underscore)) {
-                let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
-                return Err(err);
-            }
-            let expr = p.parse_expr()?;
-            ast::InlineAsmOperand::In { reg, expr }
-        } else if eat_operand_keyword(p, exp!(Out), asm_macro)? {
-            let reg = parse_reg(p, &mut explicit_reg)?;
-            let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
-            ast::InlineAsmOperand::Out { reg, expr, late: false }
-        } else if eat_operand_keyword(p, exp!(Lateout), asm_macro)? {
-            let reg = parse_reg(p, &mut explicit_reg)?;
-            let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
-            ast::InlineAsmOperand::Out { reg, expr, late: true }
-        } else if eat_operand_keyword(p, exp!(Inout), asm_macro)? {
-            let reg = parse_reg(p, &mut explicit_reg)?;
-            if p.eat_keyword(exp!(Underscore)) {
-                let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
-                return Err(err);
-            }
-            let expr = p.parse_expr()?;
-            if p.eat(exp!(FatArrow)) {
-                let out_expr =
-                    if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
-                ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: false }
-            } else {
-                ast::InlineAsmOperand::InOut { reg, expr, late: false }
-            }
-        } else if eat_operand_keyword(p, exp!(Inlateout), asm_macro)? {
-            let reg = parse_reg(p, &mut explicit_reg)?;
-            if p.eat_keyword(exp!(Underscore)) {
-                let err = dcx.create_err(errors::AsmUnderscoreInput { span: p.token.span });
-                return Err(err);
-            }
-            let expr = p.parse_expr()?;
-            if p.eat(exp!(FatArrow)) {
-                let out_expr =
-                    if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
-                ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: true }
-            } else {
-                ast::InlineAsmOperand::InOut { reg, expr, late: true }
-            }
-        } else if eat_operand_keyword(p, exp!(Label), asm_macro)? {
-            let block = p.parse_block()?;
-            ast::InlineAsmOperand::Label { block }
-        } else if p.eat_keyword(exp!(Const)) {
-            let anon_const = p.parse_expr_anon_const()?;
-            ast::InlineAsmOperand::Const { anon_const }
-        } else if p.eat_keyword(exp!(Sym)) {
-            let expr = p.parse_expr()?;
-            let ast::ExprKind::Path(qself, path) = &expr.kind else {
-                let err = dcx.create_err(errors::AsmSymNoPath { span: expr.span });
-                return Err(err);
-            };
-            let sym = ast::InlineAsmSym {
-                id: ast::DUMMY_NODE_ID,
-                qself: qself.clone(),
-                path: path.clone(),
-            };
-            ast::InlineAsmOperand::Sym { sym }
+        if let Some(op) = parse_asm_operand(p, asm_macro)? {
+            allow_templates = false;
+
+            args.push(AsmArg {
+                span: span_start.to(p.prev_token.span),
+                kind: AsmArgKind::Operand(name, op),
+            });
         } else if allow_templates {
             let template = p.parse_expr()?;
             // If it can't possibly expand to a string, provide diagnostics here to include other
@@ -217,55 +251,164 @@ pub fn parse_asm_args<'a>(
                     return Err(err);
                 }
             }
-            args.templates.push(template);
-            continue;
+
+            args.push(AsmArg { span: template.span, kind: AsmArgKind::Template(template) });
         } else {
             p.unexpected_any()?
-        };
+        }
+    }
+
+    Ok(args)
+}
 
-        allow_templates = false;
-        let span = span_start.to(p.prev_token.span);
-        let slot = args.operands.len();
-        args.operands.push((op, span));
-
-        // Validate the order of named, positional & explicit register operands and
-        // clobber_abi/options. We do this at the end once we have the full span
-        // of the argument available.
-        if explicit_reg {
-            if name.is_some() {
-                dcx.emit_err(errors::AsmExplicitRegisterName { span });
+fn parse_args<'a>(
+    ecx: &ExtCtxt<'a>,
+    sp: Span,
+    tts: TokenStream,
+    asm_macro: AsmMacro,
+) -> PResult<'a, ValidatedAsmArgs> {
+    let args = parse_asm_args(&mut ecx.new_parser_from_tts(tts), sp, asm_macro)?;
+    validate_asm_args(ecx, asm_macro, args)
+}
+
+fn validate_asm_args<'a>(
+    ecx: &ExtCtxt<'a>,
+    asm_macro: AsmMacro,
+    args: Vec<AsmArg>,
+) -> PResult<'a, ValidatedAsmArgs> {
+    let dcx = ecx.dcx();
+
+    let mut validated = ValidatedAsmArgs {
+        templates: vec![],
+        operands: vec![],
+        named_args: Default::default(),
+        reg_args: Default::default(),
+        clobber_abis: Vec::new(),
+        options: ast::InlineAsmOptions::empty(),
+        options_spans: vec![],
+    };
+
+    let mut allow_templates = true;
+
+    for arg in args {
+        match arg.kind {
+            AsmArgKind::Template(template) => {
+                // The error for the first template is delayed.
+                if !allow_templates {
+                    match template.kind {
+                        ast::ExprKind::Lit(token_lit)
+                            if matches!(
+                                token_lit.kind,
+                                token::LitKind::Str | token::LitKind::StrRaw(_)
+                            ) => {}
+                        ast::ExprKind::MacCall(..) => {}
+                        _ => {
+                            let err = dcx.create_err(errors::AsmExpectedOther {
+                                span: template.span,
+                                is_inline_asm: matches!(asm_macro, AsmMacro::Asm),
+                            });
+                            return Err(err);
+                        }
+                    }
+                }
+
+                validated.templates.push(template);
             }
-            args.reg_args.insert(slot);
-        } else if let Some(name) = name {
-            if let Some(&prev) = args.named_args.get(&name) {
-                dcx.emit_err(errors::AsmDuplicateArg { span, name, prev: args.operands[prev].1 });
-                continue;
+            AsmArgKind::Operand(name, op) => {
+                allow_templates = false;
+
+                let explicit_reg = matches!(op.reg(), Some(ast::InlineAsmRegOrRegClass::Reg(_)));
+                let span = arg.span;
+                let slot = validated.operands.len();
+                validated.operands.push((op, span));
+
+                // Validate the order of named, positional & explicit register operands and
+                // clobber_abi/options. We do this at the end once we have the full span
+                // of the argument available.
+
+                if explicit_reg {
+                    if name.is_some() {
+                        dcx.emit_err(errors::AsmExplicitRegisterName { span });
+                    }
+                    validated.reg_args.insert(slot);
+                } else if let Some(name) = name {
+                    if let Some(&prev) = validated.named_args.get(&name) {
+                        dcx.emit_err(errors::AsmDuplicateArg {
+                            span,
+                            name,
+                            prev: validated.operands[prev].1,
+                        });
+                        continue;
+                    }
+                    validated.named_args.insert(name, slot);
+                } else if !validated.named_args.is_empty() || !validated.reg_args.is_empty() {
+                    let named =
+                        validated.named_args.values().map(|p| validated.operands[*p].1).collect();
+                    let explicit =
+                        validated.reg_args.iter().map(|p| validated.operands[p].1).collect();
+
+                    dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit });
+                }
             }
-            args.named_args.insert(name, slot);
-        } else if !args.named_args.is_empty() || !args.reg_args.is_empty() {
-            let named = args.named_args.values().map(|p| args.operands[*p].1).collect();
-            let explicit = args.reg_args.iter().map(|p| args.operands[p].1).collect();
+            AsmArgKind::Options(new_options) => {
+                allow_templates = false;
+
+                for asm_option in new_options {
+                    let AsmOption { span, symbol, span_with_comma, options } = asm_option;
 
-            dcx.emit_err(errors::AsmPositionalAfter { span, named, explicit });
+                    if !asm_macro.is_supported_option(options) {
+                        // Tool-only output.
+                        dcx.emit_err(errors::AsmUnsupportedOption {
+                            span,
+                            symbol,
+                            span_with_comma,
+                            macro_name: asm_macro.macro_name(),
+                        });
+                    } else if validated.options.contains(options) {
+                        // Tool-only output.
+                        dcx.emit_err(errors::AsmOptAlreadyprovided {
+                            span,
+                            symbol,
+                            span_with_comma,
+                        });
+                    } else {
+                        validated.options |= asm_option.options;
+                    }
+                }
+
+                validated.options_spans.push(arg.span);
+            }
+            AsmArgKind::ClobberAbi(new_abis) => {
+                allow_templates = false;
+
+                match &new_abis[..] {
+                    // This should have errored above during parsing.
+                    [] => unreachable!(),
+                    [(abi, _span)] => validated.clobber_abis.push((*abi, arg.span)),
+                    _ => validated.clobber_abis.extend(new_abis),
+                }
+            }
         }
     }
 
-    if args.options.contains(ast::InlineAsmOptions::NOMEM)
-        && args.options.contains(ast::InlineAsmOptions::READONLY)
+    if validated.options.contains(ast::InlineAsmOptions::NOMEM)
+        && validated.options.contains(ast::InlineAsmOptions::READONLY)
     {
-        let spans = args.options_spans.clone();
+        let spans = validated.options_spans.clone();
         dcx.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "nomem", opt2: "readonly" });
     }
-    if args.options.contains(ast::InlineAsmOptions::PURE)
-        && args.options.contains(ast::InlineAsmOptions::NORETURN)
+    if validated.options.contains(ast::InlineAsmOptions::PURE)
+        && validated.options.contains(ast::InlineAsmOptions::NORETURN)
     {
-        let spans = args.options_spans.clone();
+        let spans = validated.options_spans.clone();
         dcx.emit_err(errors::AsmMutuallyExclusive { spans, opt1: "pure", opt2: "noreturn" });
     }
-    if args.options.contains(ast::InlineAsmOptions::PURE)
-        && !args.options.intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY)
+    if validated.options.contains(ast::InlineAsmOptions::PURE)
+        && !validated
+            .options
+            .intersects(ast::InlineAsmOptions::NOMEM | ast::InlineAsmOptions::READONLY)
     {
-        let spans = args.options_spans.clone();
+        let spans = validated.options_spans.clone();
         dcx.emit_err(errors::AsmPureCombine { spans });
     }
 
@@ -273,7 +416,7 @@ pub fn parse_asm_args<'a>(
     let mut outputs_sp = vec![];
     let mut regclass_outputs = vec![];
     let mut labels_sp = vec![];
-    for (op, op_sp) in &args.operands {
+    for (op, op_sp) in &validated.operands {
         match op {
             ast::InlineAsmOperand::Out { reg, expr, .. }
             | ast::InlineAsmOperand::SplitInOut { reg, out_expr: expr, .. } => {
@@ -296,10 +439,10 @@ pub fn parse_asm_args<'a>(
             _ => {}
         }
     }
-    if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
-        dcx.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() });
+    if validated.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
+        dcx.emit_err(errors::AsmPureNoOutput { spans: validated.options_spans.clone() });
     }
-    if args.options.contains(ast::InlineAsmOptions::NORETURN)
+    if validated.options.contains(ast::InlineAsmOptions::NORETURN)
         && !outputs_sp.is_empty()
         && labels_sp.is_empty()
     {
@@ -307,15 +450,15 @@ pub fn parse_asm_args<'a>(
         // Bail out now since this is likely to confuse MIR
         return Err(err);
     }
-    if args.options.contains(ast::InlineAsmOptions::MAY_UNWIND) && !labels_sp.is_empty() {
+    if validated.options.contains(ast::InlineAsmOptions::MAY_UNWIND) && !labels_sp.is_empty() {
         dcx.emit_err(errors::AsmMayUnwind { labels_sp });
     }
 
-    if !args.clobber_abis.is_empty() {
+    if !validated.clobber_abis.is_empty() {
         match asm_macro {
             AsmMacro::GlobalAsm | AsmMacro::NakedAsm => {
                 let err = dcx.create_err(errors::AsmUnsupportedClobberAbi {
-                    spans: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
+                    spans: validated.clobber_abis.iter().map(|(_, span)| *span).collect(),
                     macro_name: asm_macro.macro_name(),
                 });
 
@@ -326,71 +469,21 @@ pub fn parse_asm_args<'a>(
                 if !regclass_outputs.is_empty() {
                     dcx.emit_err(errors::AsmClobberNoReg {
                         spans: regclass_outputs,
-                        clobbers: args.clobber_abis.iter().map(|(_, span)| *span).collect(),
+                        clobbers: validated.clobber_abis.iter().map(|(_, span)| *span).collect(),
                     });
                 }
             }
         }
     }
 
-    Ok(args)
+    Ok(validated)
 }
 
-/// Report a duplicate option error.
-///
-/// This function must be called immediately after the option token is parsed.
-/// Otherwise, the suggestion will be incorrect.
-fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
-    // Tool-only output
-    let full_span = if p.token == token::Comma { span.to(p.token.span) } else { span };
-    p.dcx().emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
-}
-
-/// Report an invalid option error.
-///
-/// This function must be called immediately after the option token is parsed.
-/// Otherwise, the suggestion will be incorrect.
-fn err_unsupported_option(p: &Parser<'_>, asm_macro: AsmMacro, symbol: Symbol, span: Span) {
-    // Tool-only output
-    let full_span = if p.token == token::Comma { span.to(p.token.span) } else { span };
-    p.dcx().emit_err(errors::AsmUnsupportedOption {
-        span,
-        symbol,
-        full_span,
-        macro_name: asm_macro.macro_name(),
-    });
-}
-
-/// Try to set the provided option in the provided `AsmArgs`.
-/// If it is already set, report a duplicate option error.
-///
-/// This function must be called immediately after the option token is parsed.
-/// Otherwise, the error will not point to the correct spot.
-fn try_set_option<'a>(
-    p: &Parser<'a>,
-    args: &mut AsmArgs,
-    asm_macro: AsmMacro,
-    symbol: Symbol,
-    option: ast::InlineAsmOptions,
-) {
-    if !asm_macro.is_supported_option(option) {
-        err_unsupported_option(p, asm_macro, symbol, p.prev_token.span);
-    } else if args.options.contains(option) {
-        err_duplicate_option(p, symbol, p.prev_token.span);
-    } else {
-        args.options |= option;
-    }
-}
-
-fn parse_options<'a>(
-    p: &mut Parser<'a>,
-    args: &mut AsmArgs,
-    asm_macro: AsmMacro,
-) -> PResult<'a, ()> {
-    let span_start = p.prev_token.span;
-
+fn parse_options<'a>(p: &mut Parser<'a>, asm_macro: AsmMacro) -> PResult<'a, Vec<AsmOption>> {
     p.expect(exp!(OpenParen))?;
 
+    let mut asm_options = Vec::new();
+
     while !p.eat(exp!(CloseParen)) {
         const OPTIONS: [(ExpKeywordPair, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [
             (exp!(Pure), ast::InlineAsmOptions::PURE),
@@ -405,38 +498,38 @@ fn parse_options<'a>(
         ];
 
         'blk: {
-            for (exp, option) in OPTIONS {
-                let kw_matched = if asm_macro.is_supported_option(option) {
+            for (exp, options) in OPTIONS {
+                // Gives a more accurate list of expected next tokens.
+                let kw_matched = if asm_macro.is_supported_option(options) {
                     p.eat_keyword(exp)
                 } else {
                     p.eat_keyword_noexpect(exp.kw)
                 };
 
                 if kw_matched {
-                    try_set_option(p, args, asm_macro, exp.kw, option);
+                    let span = p.prev_token.span;
+                    let span_with_comma =
+                        if p.token == token::Comma { span.to(p.token.span) } else { span };
+
+                    asm_options.push(AsmOption { symbol: exp.kw, span, options, span_with_comma });
                     break 'blk;
                 }
             }
 
-            return p.unexpected();
+            return p.unexpected_any();
         }
 
-        // Allow trailing commas
+        // Allow trailing commas.
         if p.eat(exp!(CloseParen)) {
             break;
         }
         p.expect(exp!(Comma))?;
     }
 
-    let new_span = span_start.to(p.prev_token.span);
-    args.options_spans.push(new_span);
-
-    Ok(())
+    Ok(asm_options)
 }
 
-fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, ()> {
-    let span_start = p.prev_token.span;
-
+fn parse_clobber_abi<'a>(p: &mut Parser<'a>) -> PResult<'a, Vec<(Symbol, Span)>> {
     p.expect(exp!(OpenParen))?;
 
     if p.eat(exp!(CloseParen)) {
@@ -462,31 +555,14 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
         p.expect(exp!(Comma))?;
     }
 
-    let full_span = span_start.to(p.prev_token.span);
-
-    match &new_abis[..] {
-        // should have errored above during parsing
-        [] => unreachable!(),
-        [(abi, _span)] => args.clobber_abis.push((*abi, full_span)),
-        abis => {
-            for (abi, span) in abis {
-                args.clobber_abis.push((*abi, *span));
-            }
-        }
-    }
-
-    Ok(())
+    Ok(new_abis)
 }
 
-fn parse_reg<'a>(
-    p: &mut Parser<'a>,
-    explicit_reg: &mut bool,
-) -> PResult<'a, ast::InlineAsmRegOrRegClass> {
+fn parse_reg<'a>(p: &mut Parser<'a>) -> PResult<'a, ast::InlineAsmRegOrRegClass> {
     p.expect(exp!(OpenParen))?;
     let result = match p.token.uninterpolate().kind {
         token::Ident(name, IdentIsRaw::No) => ast::InlineAsmRegOrRegClass::RegClass(name),
         token::Literal(token::Lit { kind: token::LitKind::Str, symbol, suffix: _ }) => {
-            *explicit_reg = true;
             ast::InlineAsmRegOrRegClass::Reg(symbol)
         }
         _ => {
@@ -503,7 +579,7 @@ fn parse_reg<'a>(
 fn expand_preparsed_asm(
     ecx: &mut ExtCtxt<'_>,
     asm_macro: AsmMacro,
-    args: AsmArgs,
+    args: ValidatedAsmArgs,
 ) -> ExpandResult<Result<ast::InlineAsm, ErrorGuaranteed>, ()> {
     let mut template = vec![];
     // Register operands are implicitly used since they are not allowed to be
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index 8c5c20c7af4..1ff4fc6aaab 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -73,10 +73,10 @@ mod llvm_enzyme {
     }
 
     // Get information about the function the macro is applied to
-    fn extract_item_info(iitem: &P<ast::Item>) -> Option<(Visibility, FnSig, Ident)> {
+    fn extract_item_info(iitem: &P<ast::Item>) -> Option<(Visibility, FnSig, Ident, Generics)> {
         match &iitem.kind {
-            ItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
-                Some((iitem.vis.clone(), sig.clone(), ident.clone()))
+            ItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => {
+                Some((iitem.vis.clone(), sig.clone(), ident.clone(), generics.clone()))
             }
             _ => None,
         }
@@ -210,16 +210,18 @@ mod llvm_enzyme {
         }
         let dcx = ecx.sess.dcx();
 
-        // first get information about the annotable item:
-        let Some((vis, sig, primal)) = (match &item {
+        // first get information about the annotable item: visibility, signature, name and generic
+        // parameters.
+        // these will be used to generate the differentiated version of the function
+        let Some((vis, sig, primal, generics)) = (match &item {
             Annotatable::Item(iitem) => extract_item_info(iitem),
             Annotatable::Stmt(stmt) => match &stmt.kind {
                 ast::StmtKind::Item(iitem) => extract_item_info(iitem),
                 _ => None,
             },
             Annotatable::AssocItem(assoc_item, Impl { .. }) => match &assoc_item.kind {
-                ast::AssocItemKind::Fn(box ast::Fn { sig, ident, .. }) => {
-                    Some((assoc_item.vis.clone(), sig.clone(), ident.clone()))
+                ast::AssocItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => {
+                    Some((assoc_item.vis.clone(), sig.clone(), ident.clone(), generics.clone()))
                 }
                 _ => None,
             },
@@ -303,6 +305,7 @@ mod llvm_enzyme {
         let (d_sig, new_args, idents, errored) = gen_enzyme_decl(ecx, &sig, &x, span);
         let d_body = gen_enzyme_body(
             ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored,
+            &generics,
         );
 
         // The first element of it is the name of the function to be generated
@@ -310,7 +313,7 @@ mod llvm_enzyme {
             defaultness: ast::Defaultness::Final,
             sig: d_sig,
             ident: first_ident(&meta_item_vec[0]),
-            generics: Generics::default(),
+            generics,
             contract: None,
             body: Some(d_body),
             define_opaque: None,
@@ -475,6 +478,7 @@ mod llvm_enzyme {
         new_decl_span: Span,
         idents: &[Ident],
         errored: bool,
+        generics: &Generics,
     ) -> (P<ast::Block>, P<ast::Expr>, P<ast::Expr>, P<ast::Expr>) {
         let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]);
         let noop = ast::InlineAsm {
@@ -497,7 +501,7 @@ mod llvm_enzyme {
         };
         let unsf_expr = ecx.expr_block(P(unsf_block));
         let blackbox_call_expr = ecx.expr_path(ecx.path(span, blackbox_path));
-        let primal_call = gen_primal_call(ecx, span, primal, idents);
+        let primal_call = gen_primal_call(ecx, span, primal, idents, generics);
         let black_box_primal_call = ecx.expr_call(
             new_decl_span,
             blackbox_call_expr.clone(),
@@ -546,6 +550,7 @@ mod llvm_enzyme {
         sig_span: Span,
         idents: Vec<Ident>,
         errored: bool,
+        generics: &Generics,
     ) -> P<ast::Block> {
         let new_decl_span = d_sig.span;
 
@@ -566,6 +571,7 @@ mod llvm_enzyme {
             new_decl_span,
             &idents,
             errored,
+            generics,
         );
 
         if !has_ret(&d_sig.decl.output) {
@@ -608,7 +614,6 @@ mod llvm_enzyme {
                 panic!("Did not expect Default ret ty: {:?}", span);
             }
         };
-
         if x.mode.is_fwd() {
             // Fwd mode is easy. If the return activity is Const, we support arbitrary types.
             // Otherwise, we only support a scalar, a pair of scalars, or an array of scalars.
@@ -668,8 +673,10 @@ mod llvm_enzyme {
         span: Span,
         primal: Ident,
         idents: &[Ident],
+        generics: &Generics,
     ) -> P<ast::Expr> {
         let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower;
+
         if has_self {
             let args: ThinVec<_> =
                 idents[1..].iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect();
@@ -678,7 +685,51 @@ mod llvm_enzyme {
         } else {
             let args: ThinVec<_> =
                 idents.iter().map(|arg| ecx.expr_path(ecx.path_ident(span, *arg))).collect();
-            let primal_call_expr = ecx.expr_path(ecx.path_ident(span, primal));
+            let mut primal_path = ecx.path_ident(span, primal);
+
+            let is_generic = !generics.params.is_empty();
+
+            match (is_generic, primal_path.segments.last_mut()) {
+                (true, Some(function_path)) => {
+                    let primal_generic_types = generics
+                        .params
+                        .iter()
+                        .filter(|param| matches!(param.kind, ast::GenericParamKind::Type { .. }));
+
+                    let generated_generic_types = primal_generic_types
+                        .map(|type_param| {
+                            let generic_param = TyKind::Path(
+                                None,
+                                ast::Path {
+                                    span,
+                                    segments: thin_vec![ast::PathSegment {
+                                        ident: type_param.ident,
+                                        args: None,
+                                        id: ast::DUMMY_NODE_ID,
+                                    }],
+                                    tokens: None,
+                                },
+                            );
+
+                            ast::AngleBracketedArg::Arg(ast::GenericArg::Type(P(ast::Ty {
+                                id: type_param.id,
+                                span,
+                                kind: generic_param,
+                                tokens: None,
+                            })))
+                        })
+                        .collect();
+
+                    function_path.args =
+                        Some(P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
+                            span,
+                            args: generated_generic_types,
+                        })));
+                }
+                _ => {}
+            }
+
+            let primal_call_expr = ecx.expr_path(primal_path);
             ecx.expr_call(span, primal_call_expr, args)
         }
     }
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index d9aac54ee73..9aa53f9e4f7 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -185,7 +185,8 @@ use rustc_ast::{
     self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
     Generics, Mutability, PatKind, VariantData,
 };
-use rustc_attr_parsing::{AttributeKind, AttributeParser, ReprPacked};
+use rustc_attr_data_structures::{AttributeKind, ReprPacked};
+use rustc_attr_parsing::AttributeParser;
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_hir::Attribute;
 use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index d14ad8f4014..b28f7d312d9 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -910,7 +910,7 @@ pub(crate) struct AsmOptAlreadyprovided {
     pub(crate) span: Span,
     pub(crate) symbol: Symbol,
     #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
-    pub(crate) full_span: Span,
+    pub(crate) span_with_comma: Span,
 }
 
 #[derive(Diagnostic)]
@@ -921,7 +921,7 @@ pub(crate) struct AsmUnsupportedOption {
     pub(crate) span: Span,
     pub(crate) symbol: Symbol,
     #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
-    pub(crate) full_span: Span,
+    pub(crate) span_with_comma: Span,
     pub(crate) macro_name: &'static str,
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs
index e63091c6082..c853c88a6ea 100644
--- a/compiler/rustc_codegen_gcc/src/attributes.rs
+++ b/compiler/rustc_codegen_gcc/src/attributes.rs
@@ -2,8 +2,8 @@
 use gccjit::FnAttribute;
 use gccjit::Function;
 #[cfg(feature = "master")]
-use rustc_attr_parsing::InlineAttr;
-use rustc_attr_parsing::InstructionSetAttr;
+use rustc_attr_data_structures::InlineAttr;
+use rustc_attr_data_structures::InstructionSetAttr;
 #[cfg(feature = "master")]
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 #[cfg(feature = "master")]
diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs
index c133ae4fcdd..c8130b7c010 100644
--- a/compiler/rustc_codegen_gcc/src/callee.rs
+++ b/compiler/rustc_codegen_gcc/src/callee.rs
@@ -106,7 +106,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
                 // This is a monomorphization of a generic function.
                 if !(cx.tcx.sess.opts.share_generics()
                     || tcx.codegen_fn_attrs(instance_def_id).inline
-                        == rustc_attr_parsing::InlineAttr::Never)
+                        == rustc_attr_data_structures::InlineAttr::Never)
                 {
                     // When not sharing generics, all instances are in the same
                     // crate and have hidden visibility.
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 6e2a50d745a..6994c385fc8 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -37,7 +37,7 @@ extern crate tracing;
 extern crate rustc_abi;
 extern crate rustc_apfloat;
 extern crate rustc_ast;
-extern crate rustc_attr_parsing;
+extern crate rustc_attr_data_structures;
 extern crate rustc_codegen_ssa;
 extern crate rustc_data_structures;
 extern crate rustc_errors;
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 3185993c207..bf8ec8c3b91 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -19,7 +19,7 @@ object = { version = "0.36.3", default-features = false, features = ["std", "rea
 rustc-demangle = "0.1.21"
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_attr_parsing = { path = "../rustc_attr_parsing" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 176fb72dfdc..443c2eace55 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -1,5 +1,5 @@
 //! Set and unset common attributes on LLVM values.
-use rustc_attr_parsing::{InlineAttr, InstructionSetAttr, OptimizeAttr};
+use rustc_attr_data_structures::{InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_codegen_ssa::traits::*;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, PatchableFunctionEntry};
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index ea9ab5c02bd..6d68eca60af 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -103,7 +103,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
             // This is a monomorphization of a generic function.
             if !(cx.tcx.sess.opts.share_generics()
                 || tcx.codegen_fn_attrs(instance_def_id).inline
-                    == rustc_attr_parsing::InlineAttr::Never)
+                    == rustc_attr_data_structures::InlineAttr::Never)
             {
                 // When not sharing generics, all instances are in the same
                 // crate and have hidden visibility.
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
index f6000e72840..c207df2fb0b 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
@@ -155,6 +155,20 @@ pub(crate) struct Regions {
 impl Regions {
     /// Returns true if none of this structure's tables contain any regions.
     pub(crate) fn has_no_regions(&self) -> bool {
+        // Every region has a span, so if there are no spans then there are no regions.
+        self.all_cov_spans().next().is_none()
+    }
+
+    pub(crate) fn all_cov_spans(&self) -> impl Iterator<Item = &CoverageSpan> {
+        macro_rules! iter_cov_spans {
+            ( $( $regions:expr ),* $(,)? ) => {
+                std::iter::empty()
+                $(
+                    .chain( $regions.iter().map(|region| &region.cov_span) )
+                )*
+            }
+        }
+
         let Self {
             code_regions,
             expansion_regions,
@@ -163,11 +177,13 @@ impl Regions {
             mcdc_decision_regions,
         } = self;
 
-        code_regions.is_empty()
-            && expansion_regions.is_empty()
-            && branch_regions.is_empty()
-            && mcdc_branch_regions.is_empty()
-            && mcdc_decision_regions.is_empty()
+        iter_cov_spans!(
+            code_regions,
+            expansion_regions,
+            branch_regions,
+            mcdc_branch_regions,
+            mcdc_decision_regions,
+        )
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
index 7bdbc685952..d3a815fabe7 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs
@@ -11,6 +11,7 @@ use rustc_abi::Align;
 use rustc_codegen_ssa::traits::{
     BaseTypeCodegenMethods as _, ConstCodegenMethods, StaticCodegenMethods,
 };
+use rustc_index::IndexVec;
 use rustc_middle::mir::coverage::{
     BasicCoverageBlock, CovTerm, CoverageIdsInfo, Expression, FunctionCoverageInfo, Mapping,
     MappingKind, Op,
@@ -104,6 +105,16 @@ fn fill_region_tables<'tcx>(
     ids_info: &'tcx CoverageIdsInfo,
     covfun: &mut CovfunRecord<'tcx>,
 ) {
+    // If this function is unused, replace all counters with zero.
+    let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter {
+        let term = if covfun.is_used {
+            ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term")
+        } else {
+            CovTerm::Zero
+        };
+        ffi::Counter::from_term(term)
+    };
+
     // Currently a function's mappings must all be in the same file, so use the
     // first mapping's span to determine the file.
     let source_map = tcx.sess.source_map();
@@ -115,6 +126,12 @@ fn fill_region_tables<'tcx>(
 
     let local_file_id = covfun.virtual_file_mapping.push_file(&source_file);
 
+    // If this testing flag is set, add an extra unused entry to the local
+    // file table, to help test the code for detecting unused file IDs.
+    if tcx.sess.coverage_inject_unused_local_file() {
+        covfun.virtual_file_mapping.push_file(&source_file);
+    }
+
     // In rare cases, _all_ of a function's spans are discarded, and coverage
     // codegen needs to handle that gracefully to avoid #133606.
     // It's hard for tests to trigger this organically, so instead we set
@@ -135,16 +152,6 @@ fn fill_region_tables<'tcx>(
     // For each counter/region pair in this function+file, convert it to a
     // form suitable for FFI.
     for &Mapping { ref kind, span } in &fn_cov_info.mappings {
-        // If this function is unused, replace all counters with zero.
-        let counter_for_bcb = |bcb: BasicCoverageBlock| -> ffi::Counter {
-            let term = if covfun.is_used {
-                ids_info.term_for_bcb[bcb].expect("every BCB in a mapping was given a term")
-            } else {
-                CovTerm::Zero
-            };
-            ffi::Counter::from_term(term)
-        };
-
         let Some(coords) = make_coords(span) else { continue };
         let cov_span = coords.make_coverage_span(local_file_id);
 
@@ -177,6 +184,19 @@ fn fill_region_tables<'tcx>(
     }
 }
 
+/// LLVM requires all local file IDs to have at least one mapping region.
+/// If that's not the case, skip this function, to avoid an assertion failure
+/// (or worse) in LLVM.
+fn check_local_file_table(covfun: &CovfunRecord<'_>) -> bool {
+    let mut local_file_id_seen =
+        IndexVec::<u32, _>::from_elem_n(false, covfun.virtual_file_mapping.local_file_table.len());
+    for cov_span in covfun.regions.all_cov_spans() {
+        local_file_id_seen[cov_span.file_id] = true;
+    }
+
+    local_file_id_seen.into_iter().all(|seen| seen)
+}
+
 /// 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.
@@ -185,6 +205,10 @@ pub(crate) fn generate_covfun_record<'tcx>(
     global_file_table: &GlobalFileTable,
     covfun: &CovfunRecord<'tcx>,
 ) {
+    if !check_local_file_table(covfun) {
+        return;
+    }
+
     let &CovfunRecord {
         mangled_function_name,
         source_hash,
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
index 39a59560c9d..574463be7ff 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
@@ -39,7 +39,10 @@ impl Coords {
 /// or other expansions), and if it does happen then skipping a span or function is
 /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid.
 pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) -> Option<Coords> {
-    let span = ensure_non_empty_span(source_map, span)?;
+    if span.is_empty() {
+        debug_assert!(false, "can't make coords from empty span: {span:?}");
+        return None;
+    }
 
     let lo = span.lo();
     let hi = span.hi();
@@ -70,29 +73,6 @@ pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span)
     })
 }
 
-fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
-    if !span.is_empty() {
-        return Some(span);
-    }
-
-    // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
-    source_map
-        .span_to_source(span, |src, start, end| try {
-            // Adjusting span endpoints by `BytePos(1)` is normally a bug,
-            // but in this case we have specifically checked that the character
-            // we're skipping over is one of two specific ASCII characters, so
-            // adjusting by exactly 1 byte is correct.
-            if src.as_bytes().get(end).copied() == Some(b'{') {
-                Some(span.with_hi(span.hi() + BytePos(1)))
-            } else if start > 0 && src.as_bytes()[start - 1] == b'}' {
-                Some(span.with_lo(span.lo() - BytePos(1)))
-            } else {
-                None
-            }
-        })
-        .ok()?
-}
-
 /// If `llvm-cov` sees a source region that is improperly ordered (end < start),
 /// it will immediately exit with a fatal error. To prevent that from happening,
 /// discard regions that are improperly ordered, or might be interpreted in a
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 97eebffd1fe..337c6944177 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -19,6 +19,7 @@ regex = "1.4"
 rustc_abi = { path = "../rustc_abi" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
@@ -58,5 +59,5 @@ default-features = false
 features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write", "wasm"]
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.59.0"
+version = "0.61.0"
 features = ["Win32_Globalization"]
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 5f0a0cf922a..96aec9769d2 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -370,7 +370,7 @@ fn exported_symbols_provider_local<'tcx>(
 
             if !tcx.sess.opts.share_generics() {
                 if tcx.codegen_fn_attrs(mono_item.def_id()).inline
-                    == rustc_attr_parsing::InlineAttr::Never
+                    == rustc_attr_data_structures::InlineAttr::Never
                 {
                     // this is OK, we explicitly allow sharing inline(never) across crates even
                     // without share-generics.
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 775ab9071e7..1890119dca7 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -7,7 +7,7 @@ use itertools::Itertools;
 use rustc_abi::FIRST_VARIANT;
 use rustc_ast as ast;
 use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_name};
-use rustc_attr_parsing::OptimizeAttr;
+use rustc_attr_data_structures::OptimizeAttr;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
 use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 835ffb7d4fc..aa55a0e0f14 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -3,8 +3,8 @@ use std::str::FromStr;
 use rustc_abi::ExternAbi;
 use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
 use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
-use rustc_attr_parsing::ReprAttr::ReprAlign;
-use rustc_attr_parsing::{AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr};
+use rustc_attr_data_structures::ReprAttr::ReprAlign;
+use rustc_attr_data_structures::{AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index d2a687359e0..46fb9a89513 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -1,5 +1,5 @@
 use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
-use rustc_attr_parsing::InstructionSetAttr;
+use rustc_attr_data_structures::InstructionSetAttr;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility};
 use rustc_middle::mir::{InlineAsmOperand, START_BLOCK};
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 8058cd1b178..3ecea522837 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -1,4 +1,4 @@
-use rustc_attr_parsing::InstructionSetAttr;
+use rustc_attr_data_structures::InstructionSetAttr;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_errors::Applicability;
diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml
index 02be8762d6f..93d0d5b9a71 100644
--- a/compiler/rustc_const_eval/Cargo.toml
+++ b/compiler/rustc_const_eval/Cargo.toml
@@ -9,7 +9,7 @@ either = "1"
 rustc_abi = { path = "../rustc_abi" }
 rustc_apfloat = "0.2.0"
 rustc_ast = { path = "../rustc_ast" }
-rustc_attr_parsing = { path = "../rustc_attr_parsing" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index b600b8918dd..b67a3ce03a9 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -6,7 +6,7 @@ use std::mem;
 use std::num::NonZero;
 use std::ops::Deref;
 
-use rustc_attr_parsing::{ConstStability, StabilityLevel};
+use rustc_attr_data_structures as attrs;
 use rustc_errors::{Diag, ErrorGuaranteed};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
@@ -475,7 +475,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
     /// Check the const stability of the given item (fn or trait).
     fn check_callee_stability(&mut self, def_id: DefId) {
         match self.tcx.lookup_const_stability(def_id) {
-            Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
+            Some(attrs::ConstStability { level: attrs::StabilityLevel::Stable { .. }, .. }) => {
                 // All good.
             }
             None => {
@@ -491,8 +491,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
                     });
                 }
             }
-            Some(ConstStability {
-                level: StabilityLevel::Unstable { implied_by: implied_feature, issue, .. },
+            Some(attrs::ConstStability {
+                level: attrs::StabilityLevel::Unstable { implied_by: implied_feature, issue, .. },
                 feature,
                 ..
             }) => {
@@ -918,8 +918,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                 });
                             }
                         }
-                        Some(ConstStability {
-                            level: StabilityLevel::Unstable { .. },
+                        Some(attrs::ConstStability {
+                            level: attrs::StabilityLevel::Unstable { .. },
                             feature,
                             ..
                         }) => {
@@ -930,7 +930,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                                 suggestion: self.crate_inject_span(),
                             });
                         }
-                        Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
+                        Some(attrs::ConstStability {
+                            level: attrs::StabilityLevel::Stable { .. },
+                            ..
+                        }) => {
                             // All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
                             // can be *directly* invoked from stable const code) does not always
                             // have the `#[rustc_intrinsic_const_stable_indirect]` attribute (which controls
diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs
index 06ee7075170..d8421415225 100644
--- a/compiler/rustc_const_eval/src/check_consts/mod.rs
+++ b/compiler/rustc_const_eval/src/check_consts/mod.rs
@@ -4,13 +4,12 @@
 //! has interior mutability or needs to be dropped, as well as the visitor that emits errors when
 //! it finds operations that are invalid in a certain context.
 
-use rustc_attr_parsing::{AttributeKind, find_attr};
 use rustc_errors::DiagCtxtHandle;
-use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::{self, PolyFnSig, TyCtxt};
 use rustc_middle::{bug, mir};
 use rustc_span::Symbol;
+use {rustc_attr_data_structures as attrs, rustc_hir as hir};
 
 pub use self::qualifs::Qualif;
 
@@ -83,7 +82,7 @@ pub fn rustc_allow_const_fn_unstable(
 ) -> bool {
     let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
 
-    find_attr!(attrs, AttributeKind::AllowConstFnUnstable(syms) if syms.contains(&feature_gate))
+    attrs::find_attr!(attrs, attrs::AttributeKind::AllowConstFnUnstable(syms) if syms.contains(&feature_gate))
 }
 
 /// Returns `true` if the given `def_id` (trait or function) is "safe to expose on stable".
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index a1386b4e1be..d13e17a481a 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -147,6 +147,12 @@ pub trait Machine<'tcx>: Sized {
     /// already been checked before.
     const ALL_CONSTS_ARE_PRECHECKED: bool = true;
 
+    /// Determines whether rustc_const_eval functions that make use of the [Machine] should make
+    /// tracing calls (to the `tracing` library). By default this is `false`, meaning the tracing
+    /// calls will supposedly be optimized out. This flag is set to `true` inside Miri, to allow
+    /// tracing the interpretation steps, among other things.
+    const TRACING_ENABLED: bool = false;
+
     /// Whether memory accesses should be alignment-checked.
     fn enforce_alignment(ecx: &InterpCx<'tcx, Self>) -> bool;
 
diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs
index ba579e25f03..847905e8343 100644
--- a/compiler/rustc_const_eval/src/interpret/util.rs
+++ b/compiler/rustc_const_eval/src/interpret/util.rs
@@ -45,3 +45,22 @@ pub(crate) fn create_static_alloc<'tcx>(
     assert!(ecx.memory.alloc_map.insert(alloc_id, (MemoryKind::Stack, alloc)).is_none());
     interp_ok(ecx.ptr_to_mplace(Pointer::from(alloc_id).into(), layout))
 }
+
+/// This struct is needed to enforce `#[must_use]` on [tracing::span::EnteredSpan]
+/// while wrapping them in an `Option`.
+#[must_use]
+pub enum MaybeEnteredSpan {
+    Some(tracing::span::EnteredSpan),
+    None,
+}
+
+#[macro_export]
+macro_rules! enter_trace_span {
+    ($machine:ident, $($tt:tt)*) => {
+        if $machine::TRACING_ENABLED {
+            $crate::interpret::tracing_utils::MaybeEnteredSpan::Some(tracing::info_span!($($tt)*).entered())
+        } else {
+            $crate::interpret::tracing_utils::MaybeEnteredSpan::None
+        }
+    }
+}
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index f48c73b13b9..f6a02011618 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -38,7 +38,7 @@ features = ["nightly"] # for may_dangle
 version = "0.12"
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.59.0"
+version = "0.61.0"
 features = [
     "Win32_Foundation",
     "Win32_Storage_FileSystem",
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 9da4f2dbc27..1971d06aad6 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -60,7 +60,7 @@ libc = "0.2"
 # tidy-alphabetical-end
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.59.0"
+version = "0.61.0"
 features = [
     "Win32_System_Diagnostics_Debug",
 ]
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index b11793c190a..82e7468211d 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -33,7 +33,7 @@ tracing = "0.1"
 # tidy-alphabetical-end
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.59.0"
+version = "0.61.0"
 features = [
     "Win32_Foundation",
     "Win32_Security",
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index 0ba139ea5cc..e8fd2f54d76 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -12,6 +12,7 @@ doctest = false
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_passes = { path = "../rustc_ast_passes" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index f5eaf7d616b..55751aa4908 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -11,7 +11,7 @@ use rustc_ast::token::MetaVarKind;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{AssocCtxt, Visitor};
 use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
-use rustc_attr_parsing::{AttributeKind, Deprecation, Stability, find_attr};
+use rustc_attr_data_structures::{AttributeKind, Deprecation, Stability, find_attr};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync;
 use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, PResult};
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 93604a149f1..783f061ec6c 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -10,7 +10,7 @@ use rustc_ast::token::{self, NonterminalKind, Token, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
 use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
 use rustc_ast_pretty::pprust;
-use rustc_attr_parsing::{AttributeKind, find_attr};
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
 use rustc_feature::Features;
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 809d1630dde..820af9ac84b 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -82,6 +82,8 @@ declare_features! (
     (accepted, attr_literals, "1.30.0", Some(34981)),
     /// Allows overloading augmented assignment operations like `a += b`.
     (accepted, augmented_assignments, "1.8.0", Some(28235)),
+    /// Allows using `avx512*` target features.
+    (accepted, avx512_target_feature, "CURRENT_RUSTC_VERSION", Some(44839)),
     /// Allows mixing bind-by-move in patterns and references to those identifiers in guards.
     (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287)),
     /// Allows bindings in the subpattern of a binding pattern.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 8fb10736539..6cdcf451f37 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -318,7 +318,6 @@ declare_features! (
     (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)),
     (unstable, apx_target_feature, "1.88.0", Some(139284)),
     (unstable, arm_target_feature, "1.27.0", Some(44839)),
-    (unstable, avx512_target_feature, "1.27.0", Some(44839)),
     (unstable, bpf_target_feature, "1.54.0", Some(44839)),
     (unstable, csky_target_feature, "1.73.0", Some(44839)),
     (unstable, ermsb_target_feature, "1.49.0", Some(44839)),
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index 58213c4f4e4..f2b82c679b9 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -13,7 +13,7 @@ itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_attr_parsing = { path = "../rustc_attr_parsing" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index da94331aa26..06814eaefe8 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -2,8 +2,7 @@ use std::cell::LazyCell;
 use std::ops::ControlFlow;
 
 use rustc_abi::FieldIdx;
-use rustc_attr_parsing::AttributeKind;
-use rustc_attr_parsing::ReprAttr::ReprPacked;
+use rustc_attr_data_structures::ReprAttr::ReprPacked;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_errors::MultiSpan;
 use rustc_errors::codes::*;
@@ -31,7 +30,7 @@ use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use tracing::{debug, instrument};
 use ty::TypingMode;
-use {rustc_attr_parsing as attr, rustc_hir as hir};
+use {rustc_attr_data_structures as attrs, rustc_hir as hir};
 
 use super::compare_impl_item::check_type_bounds;
 use super::*;
@@ -1154,7 +1153,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
     let repr = def.repr();
     if repr.packed() {
         if let Some(reprs) =
-            attr::find_attr!(tcx.get_all_attrs(def.did()), AttributeKind::Repr(r) => r)
+            attrs::find_attr!(tcx.get_all_attrs(def.did()), attrs::AttributeKind::Repr(r) => r)
         {
             for (r, _) in reprs {
                 if let ReprPacked(pack) = r
@@ -1371,9 +1370,9 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     def.destructor(tcx); // force the destructor to be evaluated
 
     if def.variants().is_empty() {
-        attr::find_attr!(
+        attrs::find_attr!(
             tcx.get_all_attrs(def_id),
-            AttributeKind::Repr(rs) => {
+            attrs::AttributeKind::Repr(rs) => {
                 struct_span_code_err!(
                     tcx.dcx(),
                     rs.first().unwrap().1,
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index f00125c3e09..c963f0ddefd 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2024"
 itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index fd899425f62..d2fc5ae0543 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -37,7 +37,7 @@
 
 use std::ops::Deref;
 
-use rustc_attr_parsing::InlineAttr;
+use rustc_attr_data_structures::InlineAttr;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, Diag, struct_span_code_err};
 use rustc_hir as hir;
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index d1bc54ed73e..8182851a015 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -84,7 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.annotate_expected_due_to_let_ty(err, expr, error);
         self.annotate_loop_expected_due_to_inference(err, expr, error);
-        if self.annotate_mut_binding_to_immutable_binding(err, expr, error) {
+        if self.annotate_mut_binding_to_immutable_binding(err, expr, expr_ty, expected, error) {
             return;
         }
 
@@ -799,17 +799,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Detect the following case
     ///
     /// ```text
-    /// fn change_object(mut a: &Ty) {
+    /// fn change_object(mut b: &Ty) {
     ///     let a = Ty::new();
     ///     b = a;
     /// }
     /// ```
     ///
-    /// where the user likely meant to modify the value behind there reference, use `a` as an out
+    /// where the user likely meant to modify the value behind there reference, use `b` as an out
     /// parameter, instead of mutating the local binding. When encountering this we suggest:
     ///
     /// ```text
-    /// fn change_object(a: &'_ mut Ty) {
+    /// fn change_object(b: &'_ mut Ty) {
     ///     let a = Ty::new();
     ///     *b = a;
     /// }
@@ -818,13 +818,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         err: &mut Diag<'_>,
         expr: &hir::Expr<'_>,
+        expr_ty: Ty<'tcx>,
+        expected: Ty<'tcx>,
         error: Option<TypeError<'tcx>>,
     ) -> bool {
-        if let Some(TypeError::Sorts(ExpectedFound { expected, found })) = error
+        if let Some(TypeError::Sorts(ExpectedFound { .. })) = error
             && let ty::Ref(_, inner, hir::Mutability::Not) = expected.kind()
 
             // The difference between the expected and found values is one level of borrowing.
-            && self.can_eq(self.param_env, *inner, found)
+            && self.can_eq(self.param_env, *inner, expr_ty)
 
             // We have an `ident = expr;` assignment.
             && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. }) =
diff --git a/compiler/rustc_hir_typeck/src/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 956671fc66e..7d99b0e7869 100644
--- a/compiler/rustc_hir_typeck/src/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -218,7 +218,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
             );
         }
         let old_outermost_fn_param_pat = self.outermost_fn_param_pat.take();
-        intravisit::walk_pat(self, p);
+        if let PatKind::Guard(subpat, _) = p.kind {
+            // We'll visit the guard when checking it. Don't gather its locals twice.
+            self.visit_pat(subpat);
+        } else {
+            intravisit::walk_pat(self, p);
+        }
         self.outermost_fn_param_pat = old_outermost_fn_param_pat;
     }
 
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index bda051f1560..6090c0f9aee 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -2,6 +2,7 @@ use std::cell::{Cell, RefCell};
 use std::cmp::max;
 use std::ops::Deref;
 
+use rustc_attr_parsing::is_doc_alias_attrs_contain_symbol;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sso::SsoHashSet;
 use rustc_errors::Applicability;
@@ -2333,10 +2334,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         };
         let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id);
         let attrs = self.fcx.tcx.hir_attrs(hir_id);
+
+        if is_doc_alias_attrs_contain_symbol(attrs.into_iter(), method.name) {
+            return true;
+        }
+
         for attr in attrs {
-            if attr.has_name(sym::doc) {
-                // do nothing
-            } else if attr.has_name(sym::rustc_confusables) {
+            if attr.has_name(sym::rustc_confusables) {
                 let Some(confusables) = attr.meta_item_list() else {
                     continue;
                 };
@@ -2348,33 +2352,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         return true;
                     }
                 }
-                continue;
-            } else {
-                continue;
-            };
-            let Some(values) = attr.meta_item_list() else {
-                continue;
-            };
-            for v in values {
-                if !v.has_name(sym::alias) {
-                    continue;
-                }
-                if let Some(nested) = v.meta_item_list() {
-                    // #[doc(alias("foo", "bar"))]
-                    for n in nested {
-                        if let Some(lit) = n.lit()
-                            && method.name == lit.symbol
-                        {
-                            return true;
-                        }
-                    }
-                } else if let Some(meta) = v.meta_item()
-                    && let Some(lit) = meta.name_value_literal()
-                    && method.name == lit.symbol
-                {
-                    // #[doc(alias = "foo")]
-                    return true;
-                }
             }
         }
         false
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 6a9fd7cdd48..342eed751a5 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -9,7 +9,7 @@ use std::path::PathBuf;
 
 use hir::Expr;
 use rustc_ast::ast::Mutability;
-use rustc_attr_parsing::{AttributeKind, find_attr};
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::unord::UnordSet;
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 9be041f75d7..b2497cb0de1 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -9,17 +9,21 @@
 //! which creates a new `TypeckResults` which doesn't contain any inference variables.
 
 use std::mem;
+use std::ops::ControlFlow;
 
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::unord::ExtendUnord;
-use rustc_errors::ErrorGuaranteed;
+use rustc_errors::{E0720, ErrorGuaranteed};
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, InferKind, Visitor};
 use rustc_hir::{self as hir, AmbigArg, HirId};
 use rustc_infer::traits::solve::Goal;
 use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion};
 use rustc_middle::ty::{
-    self, DefiningScopeKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
-    TypeVisitableExt, fold_regions,
+    self, DefiningScopeKind, OpaqueHiddenType, Ty, TyCtxt, TypeFoldable, TypeFolder,
+    TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
+    fold_regions,
 };
 use rustc_span::{Span, sym};
 use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
@@ -595,6 +599,35 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 entry.span = prev.span.substitute_dummy(hidden_type.span);
             }
         }
+
+        let recursive_opaques: Vec<_> = self
+            .typeck_results
+            .concrete_opaque_types
+            .iter()
+            .filter(|&(&def_id, hidden_ty)| {
+                hidden_ty
+                    .ty
+                    .visit_with(&mut HasRecursiveOpaque {
+                        def_id,
+                        seen: Default::default(),
+                        opaques: &self.typeck_results.concrete_opaque_types,
+                        tcx,
+                    })
+                    .is_break()
+            })
+            .map(|(def_id, hidden_ty)| (*def_id, hidden_ty.span))
+            .collect();
+        for (def_id, span) in recursive_opaques {
+            let guar = self
+                .fcx
+                .dcx()
+                .struct_span_err(span, "cannot resolve opaque type")
+                .with_code(E0720)
+                .emit();
+            self.typeck_results
+                .concrete_opaque_types
+                .insert(def_id, OpaqueHiddenType { span, ty: Ty::new_error(tcx, guar) });
+        }
     }
 
     fn visit_field_id(&mut self, hir_id: HirId) {
@@ -959,3 +992,34 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
         self.tcx.try_normalize_erasing_regions(self.typing_env, ct).unwrap_or(ct)
     }
 }
+
+struct HasRecursiveOpaque<'a, 'tcx> {
+    def_id: LocalDefId,
+    seen: FxHashSet<LocalDefId>,
+    opaques: &'a FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
+    tcx: TyCtxt<'tcx>,
+}
+
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HasRecursiveOpaque<'_, 'tcx> {
+    type Result = ControlFlow<()>;
+
+    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
+        if let ty::Alias(ty::Opaque, alias_ty) = *t.kind()
+            && let Some(def_id) = alias_ty.def_id.as_local()
+        {
+            if self.def_id == def_id {
+                return ControlFlow::Break(());
+            }
+
+            if self.seen.insert(def_id)
+                && let Some(hidden_ty) = self.opaques.get(&def_id)
+            {
+                ty::EarlyBinder::bind(hidden_ty.ty)
+                    .instantiate(self.tcx, alias_ty.args)
+                    .visit_with(self)?;
+            }
+        }
+
+        t.super_visit_with(self)
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 8dde99c45cf..5fd98e35e5c 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -98,6 +98,14 @@ impl<'tcx> InferCtxt<'tcx> {
         sub_region: Region<'tcx>,
         cause: &ObligationCause<'tcx>,
     ) {
+        // `is_global` means the type has no params, infer, placeholder, or non-`'static`
+        // free regions. If the type has none of these things, then we can skip registering
+        // this outlives obligation since it has no components which affect lifetime
+        // checking in an interesting way.
+        if sup_type.is_global() {
+            return;
+        }
+
         debug!(?sup_type, ?sub_region, ?cause);
         let origin = SubregionOrigin::from_obligation_cause(cause, || {
             infer::RelateParamBound(
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index e28639576f0..8f6c5b47ee2 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -282,6 +282,7 @@ fn configure_and_expand(
     resolver.resolve_crate(&krate);
 
     CStore::from_tcx(tcx).report_incompatible_target_modifiers(tcx, &krate);
+    CStore::from_tcx(tcx).report_incompatible_async_drop_feature(tcx, &krate);
     krate
 }
 
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 068d96c860f..20e081d3360 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -776,7 +776,8 @@ fn test_unstable_options_tracking_hash() {
         CoverageOptions {
             level: CoverageLevel::Mcdc,
             no_mir_spans: true,
-            discard_all_spans_in_codegen: true
+            discard_all_spans_in_codegen: true,
+            inject_unused_local_file: true,
         }
     );
     tracked!(crate_attr, vec!["abc".to_string()]);
diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml
index 7718f16984d..64751eaf1fe 100644
--- a/compiler/rustc_lint/Cargo.toml
+++ b/compiler/rustc_lint/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2024"
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index d1138e8f1fa..048d377b78f 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -1,5 +1,6 @@
 use rustc_abi::ExternAbi;
-use rustc_attr_parsing::{AttributeKind, AttributeParser, ReprAttr};
+use rustc_attr_data_structures::{AttributeKind, ReprAttr};
+use rustc_attr_parsing::AttributeParser;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind};
diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs
index 7cb00262b6f..d44f45177bd 100644
--- a/compiler/rustc_lint/src/types/literal.rs
+++ b/compiler/rustc_lint/src/types/literal.rs
@@ -5,7 +5,7 @@ use rustc_middle::ty::Ty;
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::{bug, ty};
 use rustc_span::Span;
-use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir};
+use {rustc_ast as ast, rustc_attr_data_structures as attrs, rustc_hir as hir};
 
 use crate::LateContext;
 use crate::context::LintContext;
@@ -131,18 +131,18 @@ fn report_bin_hex_error(
     cx: &LateContext<'_>,
     hir_id: HirId,
     span: Span,
-    ty: attr::IntType,
+    ty: attrs::IntType,
     size: Size,
     repr_str: String,
     val: u128,
     negative: bool,
 ) {
     let (t, actually) = match ty {
-        attr::IntType::SignedInt(t) => {
+        attrs::IntType::SignedInt(t) => {
             let actually = if negative { -(size.sign_extend(val)) } else { size.sign_extend(val) };
             (t.name_str(), actually.to_string())
         }
-        attr::IntType::UnsignedInt(t) => {
+        attrs::IntType::UnsignedInt(t) => {
             let actually = size.truncate(val);
             (t.name_str(), actually.to_string())
         }
@@ -264,7 +264,7 @@ fn lint_int_literal<'tcx>(
                 cx,
                 hir_id,
                 span,
-                attr::IntType::SignedInt(ty::ast_int_ty(t)),
+                attrs::IntType::SignedInt(ty::ast_int_ty(t)),
                 Integer::from_int_ty(cx, t).size(),
                 repr_str,
                 v,
@@ -336,7 +336,7 @@ fn lint_uint_literal<'tcx>(
                 cx,
                 hir_id,
                 span,
-                attr::IntType::UnsignedInt(ty::ast_uint_ty(t)),
+                attrs::IntType::UnsignedInt(ty::ast_uint_ty(t)),
                 Integer::from_uint_ty(cx, t).size(),
                 repr_str,
                 lit_val,
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 6692ea73540..a662694ac38 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -255,6 +255,7 @@ fn main() {
     } else if target.contains("haiku")
         || target.contains("darwin")
         || (is_crossed && (target.contains("dragonfly") || target.contains("solaris")))
+        || target.contains("cygwin")
     {
         println!("cargo:rustc-link-lib=z");
     } else if target.contains("netbsd") {
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index 26878c488b7..cfe412e99d8 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -10,6 +10,7 @@ libloading = "0.8.0"
 odht = { version = "0.3.1", features = ["nightly"] }
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index d997ba198ac..bccffe39243 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -1,6 +1,10 @@
 metadata_as_needed_compatibility =
     linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
 
+metadata_async_drop_types_in_dependency =
+    found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}`
+    .help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used
+
 metadata_bad_panic_strategy =
     the linked panic runtime `{$runtime}` is not compiled with this crate's panic strategy `{$strategy}`
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 07fb2de8a3e..c7e9a2936f5 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -473,6 +473,27 @@ impl CStore {
         }
     }
 
+    // Report about async drop types in dependency if async drop feature is disabled
+    pub fn report_incompatible_async_drop_feature(&self, tcx: TyCtxt<'_>, krate: &Crate) {
+        if tcx.features().async_drop() {
+            return;
+        }
+        for (_cnum, data) in self.iter_crate_data() {
+            if data.is_proc_macro_crate() {
+                continue;
+            }
+            if data.has_async_drops() {
+                let extern_crate = data.name();
+                let local_crate = tcx.crate_name(LOCAL_CRATE);
+                tcx.dcx().emit_warn(errors::AsyncDropTypesInDependency {
+                    span: krate.spans.inner_span.shrink_to_lo(),
+                    extern_crate,
+                    local_crate,
+                });
+            }
+        }
+    }
+
     pub fn new(metadata_loader: Box<MetadataLoaderDyn>) -> CStore {
         CStore {
             metadata_loader,
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index c45daeda85d..16f59793e63 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -811,3 +811,13 @@ pub struct UnknownTargetModifierUnsafeAllowed {
     pub span: Span,
     pub flag_name: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(metadata_async_drop_types_in_dependency)]
+#[help]
+pub struct AsyncDropTypesInDependency {
+    #[primary_span]
+    pub span: Span,
+    pub extern_crate: Symbol,
+    pub local_crate: Symbol,
+}
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index bd813cadedc..2e4352ca532 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1984,6 +1984,10 @@ impl CrateMetadata {
         self.root.header.hash
     }
 
+    pub(crate) fn has_async_drops(&self) -> bool {
+        self.root.tables.adt_async_destructor.len > 0
+    }
+
     fn num_def_ids(&self) -> usize {
         self.root.tables.def_keys.size()
     }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 76bae39ef8c..97d31565733 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -2,7 +2,7 @@ use std::any::Any;
 use std::mem;
 use std::sync::Arc;
 
-use rustc_attr_parsing::Deprecation;
+use rustc_attr_data_structures::Deprecation;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index c86cf567283..d3d928aa88e 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -40,7 +40,7 @@ use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextKey};
 use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol};
 use rustc_target::spec::{PanicStrategy, TargetTuple};
 use table::TableBuilder;
-use {rustc_ast as ast, rustc_attr_parsing as attr, rustc_hir as hir};
+use {rustc_ast as ast, rustc_attr_data_structures as attrs, rustc_hir as hir};
 
 use crate::creader::CrateMetadataRef;
 
@@ -200,7 +200,7 @@ type ExpnHashTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnHash>>>;
 #[derive(MetadataEncodable, MetadataDecodable)]
 pub(crate) struct ProcMacroData {
     proc_macro_decls_static: DefIndex,
-    stability: Option<attr::Stability>,
+    stability: Option<attrs::Stability>,
     macros: LazyArray<DefIndex>,
 }
 
@@ -422,10 +422,10 @@ define_tables! {
     safety: Table<DefIndex, hir::Safety>,
     def_span: Table<DefIndex, LazyValue<Span>>,
     def_ident_span: Table<DefIndex, LazyValue<Span>>,
-    lookup_stability: Table<DefIndex, LazyValue<attr::Stability>>,
-    lookup_const_stability: Table<DefIndex, LazyValue<attr::ConstStability>>,
-    lookup_default_body_stability: Table<DefIndex, LazyValue<attr::DefaultBodyStability>>,
-    lookup_deprecation_entry: Table<DefIndex, LazyValue<attr::Deprecation>>,
+    lookup_stability: Table<DefIndex, LazyValue<attrs::Stability>>,
+    lookup_const_stability: Table<DefIndex, LazyValue<attrs::ConstStability>>,
+    lookup_default_body_stability: Table<DefIndex, LazyValue<attrs::DefaultBodyStability>>,
+    lookup_deprecation_entry: Table<DefIndex, LazyValue<attrs::Deprecation>>,
     explicit_predicates_of: Table<DefIndex, LazyValue<ty::GenericPredicates<'static>>>,
     generics_of: Table<DefIndex, LazyValue<ty::Generics>>,
     type_of: Table<DefIndex, LazyValue<ty::EarlyBinder<'static, Ty<'static>>>>,
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 9912e659b05..454ab8c107f 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -5,7 +5,7 @@ use std::num::NonZero;
 
 use rustc_ast::NodeId;
 use rustc_attr_data_structures::{
-    self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
+    self as attrs, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability,
 };
 use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{Applicability, Diag, EmissionGuarantee};
@@ -411,7 +411,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         match stability {
             Some(Stability {
-                level: attr::StabilityLevel::Unstable { reason, issue, is_soft, implied_by },
+                level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, implied_by },
                 feature,
                 ..
             }) => {
@@ -494,7 +494,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         match stability {
             Some(DefaultBodyStability {
-                level: attr::StabilityLevel::Unstable { reason, issue, is_soft, .. },
+                level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, .. },
                 feature,
             }) => {
                 if span.allows_unstable(feature) {
@@ -643,7 +643,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         match stability {
             Some(ConstStability {
-                level: attr::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. },
+                level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. },
                 feature,
                 ..
             }) => {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 657bda23bc4..b2a58897c31 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -121,6 +121,7 @@ use crate::ty;
 use crate::ty::codec::{TyDecoder, TyEncoder};
 pub use crate::ty::diagnostics::*;
 use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::layout::LayoutError;
 use crate::ty::util::Discr;
 use crate::ty::walk::TypeWalker;
 
@@ -1878,6 +1879,11 @@ impl<'tcx> TyCtxt<'tcx> {
         self.def_kind(trait_def_id) == DefKind::TraitAlias
     }
 
+    /// Arena-alloc of LayoutError for coroutine layout
+    fn layout_error(self, err: LayoutError<'tcx>) -> &'tcx LayoutError<'tcx> {
+        self.arena.alloc(err)
+    }
+
     /// Returns layout of a non-async-drop coroutine. Layout might be unavailable if the
     /// coroutine is tainted by errors.
     ///
@@ -1886,12 +1892,14 @@ impl<'tcx> TyCtxt<'tcx> {
     fn ordinary_coroutine_layout(
         self,
         def_id: DefId,
-        coroutine_kind_ty: Ty<'tcx>,
-    ) -> Option<&'tcx CoroutineLayout<'tcx>> {
+        args: GenericArgsRef<'tcx>,
+    ) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> {
+        let coroutine_kind_ty = args.as_coroutine().kind_ty();
         let mir = self.optimized_mir(def_id);
+        let ty = || Ty::new_coroutine(self, def_id, args);
         // Regular coroutine
         if coroutine_kind_ty.is_unit() {
-            mir.coroutine_layout_raw()
+            mir.coroutine_layout_raw().ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
         } else {
             // If we have a `Coroutine` that comes from an coroutine-closure,
             // then it may be a by-move or by-ref body.
@@ -1905,6 +1913,7 @@ impl<'tcx> TyCtxt<'tcx> {
             // a by-ref coroutine.
             if identity_kind_ty == coroutine_kind_ty {
                 mir.coroutine_layout_raw()
+                    .ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
             } else {
                 assert_matches!(coroutine_kind_ty.to_opt_closure_kind(), Some(ClosureKind::FnOnce));
                 assert_matches!(
@@ -1913,6 +1922,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 );
                 self.optimized_mir(self.coroutine_by_move_body_def_id(def_id))
                     .coroutine_layout_raw()
+                    .ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
             }
         }
     }
@@ -1924,12 +1934,15 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
-    ) -> Option<&'tcx CoroutineLayout<'tcx>> {
+    ) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> {
+        let ty = || Ty::new_coroutine(self, def_id, args);
         if args[0].has_placeholders() || args[0].has_non_region_param() {
-            return None;
+            return Err(self.layout_error(LayoutError::TooGeneric(ty())));
         }
         let instance = InstanceKind::AsyncDropGlue(def_id, Ty::new_coroutine(self, def_id, args));
-        self.mir_shims(instance).coroutine_layout_raw()
+        self.mir_shims(instance)
+            .coroutine_layout_raw()
+            .ok_or_else(|| self.layout_error(LayoutError::Unknown(ty())))
     }
 
     /// Returns layout of a coroutine. Layout might be unavailable if the
@@ -1938,7 +1951,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         def_id: DefId,
         args: GenericArgsRef<'tcx>,
-    ) -> Option<&'tcx CoroutineLayout<'tcx>> {
+    ) -> Result<&'tcx CoroutineLayout<'tcx>, &'tcx LayoutError<'tcx>> {
         if self.is_async_drop_in_place_coroutine(def_id) {
             // layout of `async_drop_in_place<T>::{closure}` in case,
             // when T is a coroutine, contains this internal coroutine's ptr in upvars
@@ -1960,12 +1973,12 @@ impl<'tcx> TyCtxt<'tcx> {
                     variant_source_info,
                     storage_conflicts: BitMatrix::new(0, 0),
                 };
-                return Some(self.arena.alloc(proxy_layout));
+                return Ok(self.arena.alloc(proxy_layout));
             } else {
                 self.async_drop_coroutine_layout(def_id, args)
             }
         } else {
-            self.ordinary_coroutine_layout(def_id, args.as_coroutine().kind_ty())
+            self.ordinary_coroutine_layout(def_id, args)
         }
     }
 
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index 9e4b4534dcc..a7d0b3acbe4 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -10,7 +10,7 @@ itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_attr_parsing = { path = "../rustc_attr_parsing" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_const_eval = { path = "../rustc_const_eval" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_mir_transform/src/check_inline.rs b/compiler/rustc_mir_transform/src/check_inline.rs
index 83c3cda5a50..14d9532894f 100644
--- a/compiler/rustc_mir_transform/src/check_inline.rs
+++ b/compiler/rustc_mir_transform/src/check_inline.rs
@@ -1,7 +1,7 @@
 //! Check that a body annotated with `#[rustc_force_inline]` will not fail to inline based on its
 //! definition alone (irrespective of any specific caller).
 
-use rustc_attr_parsing::InlineAttr;
+use rustc_attr_data_structures::InlineAttr;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::{Body, TerminatorKind};
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index ec76076020e..ddeae093df5 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,7 +1,8 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
+use rustc_span::source_map::SourceMap;
+use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span};
 use tracing::instrument;
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
@@ -83,8 +84,18 @@ pub(super) fn extract_refined_covspans<'tcx>(
     // Discard any span that overlaps with a hole.
     discard_spans_overlapping_holes(&mut covspans, &holes);
 
-    // Perform more refinement steps after holes have been dealt with.
+    // Discard spans that overlap in unwanted ways.
     let mut covspans = remove_unwanted_overlapping_spans(covspans);
+
+    // For all empty spans, either enlarge them to be non-empty, or discard them.
+    let source_map = tcx.sess.source_map();
+    covspans.retain_mut(|covspan| {
+        let Some(span) = ensure_non_empty_span(source_map, covspan.span) else { return false };
+        covspan.span = span;
+        true
+    });
+
+    // Merge covspans that can be merged.
     covspans.dedup_by(|b, a| a.merge_if_eligible(b));
 
     code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| {
@@ -230,3 +241,26 @@ fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
         // - Both have the same start and span A extends further right
         .then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
 }
+
+fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
+    if !span.is_empty() {
+        return Some(span);
+    }
+
+    // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
+    source_map
+        .span_to_source(span, |src, start, end| try {
+            // Adjusting span endpoints by `BytePos(1)` is normally a bug,
+            // but in this case we have specifically checked that the character
+            // we're skipping over is one of two specific ASCII characters, so
+            // adjusting by exactly 1 byte is correct.
+            if src.as_bytes().get(end).copied() == Some(b'{') {
+                Some(span.with_hi(span.hi() + BytePos(1)))
+            } else if start > 0 && src.as_bytes()[start - 1] == b'}' {
+                Some(span.with_lo(span.lo() - BytePos(1)))
+            } else {
+                None
+            }
+        })
+        .ok()?
+}
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 4f45d9588a8..727d4a126d2 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -1,4 +1,4 @@
-use rustc_attr_parsing::InlineAttr;
+use rustc_attr_data_structures::InlineAttr;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::mir::visit::Visitor;
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 8b8d1efbbd2..209e818e9e3 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -836,6 +836,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
     #[instrument(level = "trace", skip(self), ret)]
     fn simplify_rvalue(
         &mut self,
+        lhs: &Place<'tcx>,
         rvalue: &mut Rvalue<'tcx>,
         location: Location,
     ) -> Option<VnIndex> {
@@ -855,7 +856,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                 Value::Repeat(op, amount)
             }
             Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
-            Rvalue::Aggregate(..) => return self.simplify_aggregate(rvalue, location),
+            Rvalue::Aggregate(..) => return self.simplify_aggregate(lhs, rvalue, location),
             Rvalue::Ref(_, borrow_kind, ref mut place) => {
                 self.simplify_place_projection(place, location);
                 return Some(self.new_pointer(*place, AddressKind::Ref(borrow_kind)));
@@ -943,6 +944,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
 
     fn simplify_aggregate_to_copy(
         &mut self,
+        lhs: &Place<'tcx>,
         rvalue: &mut Rvalue<'tcx>,
         location: Location,
         fields: &[VnIndex],
@@ -982,12 +984,16 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
 
         // Allow introducing places with non-constant offsets, as those are still better than
         // reconstructing an aggregate.
-        if let Some(place) = self.try_as_place(copy_from_local_value, location, true) {
-            if rvalue.ty(self.local_decls, self.tcx) == place.ty(self.local_decls, self.tcx).ty {
+        if let Some(place) = self.try_as_place(copy_from_local_value, location, true)
+            && rvalue.ty(self.local_decls, self.tcx) == place.ty(self.local_decls, self.tcx).ty
+        {
+            // Avoid creating `*a = copy (*b)`, as they might be aliases resulting in overlapping assignments.
+            // FIXME: This also avoids any kind of projection, not just derefs. We can add allowed projections.
+            if lhs.as_local().is_some() {
                 self.reused_locals.insert(place.local);
                 *rvalue = Rvalue::Use(Operand::Copy(place));
-                return Some(copy_from_local_value);
             }
+            return Some(copy_from_local_value);
         }
 
         None
@@ -995,6 +1001,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
 
     fn simplify_aggregate(
         &mut self,
+        lhs: &Place<'tcx>,
         rvalue: &mut Rvalue<'tcx>,
         location: Location,
     ) -> Option<VnIndex> {
@@ -1090,7 +1097,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
 
         if let AggregateTy::Def(_, _) = ty
             && let Some(value) =
-                self.simplify_aggregate_to_copy(rvalue, location, &fields, variant_index)
+                self.simplify_aggregate_to_copy(lhs, rvalue, location, &fields, variant_index)
         {
             return Some(value);
         }
@@ -1765,7 +1772,7 @@ impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> {
         if let StatementKind::Assign(box (ref mut lhs, ref mut rvalue)) = stmt.kind {
             self.simplify_place_projection(lhs, location);
 
-            let value = self.simplify_rvalue(rvalue, location);
+            let value = self.simplify_rvalue(lhs, rvalue, location);
             let value = if let Some(local) = lhs.as_local()
                 && self.ssa.is_ssa(local)
                 // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 9785c039d53..f48dba9663a 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -5,7 +5,7 @@ use std::iter;
 use std::ops::{Range, RangeFrom};
 
 use rustc_abi::{ExternAbi, FieldIdx};
-use rustc_attr_parsing::{InlineAttr, OptimizeAttr};
+use rustc_attr_data_structures::{InlineAttr, OptimizeAttr};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_index::Idx;
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index f541a32cd26..c8aa7588d03 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -1,7 +1,7 @@
 //! Validates the MIR to ensure that invariants are upheld.
 
 use rustc_abi::{ExternAbi, FIRST_VARIANT, Size};
-use rustc_attr_parsing::InlineAttr;
+use rustc_attr_data_structures::InlineAttr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::LangItem;
 use rustc_index::IndexVec;
@@ -752,7 +752,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                             let layout = if def_id == self.caller_body.source.def_id() {
                                 self.caller_body
                                     .coroutine_layout_raw()
-                                    .or_else(|| self.tcx.coroutine_layout(def_id, args))
+                                    .or_else(|| self.tcx.coroutine_layout(def_id, args).ok())
                             } else if self.tcx.needs_coroutine_by_move_body_def_id(def_id)
                                 && let ty::ClosureKind::FnOnce =
                                     args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap()
@@ -762,7 +762,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                                 // Same if this is the by-move body of a coroutine-closure.
                                 self.caller_body.coroutine_layout_raw()
                             } else {
-                                self.tcx.coroutine_layout(def_id, args)
+                                self.tcx.coroutine_layout(def_id, args).ok()
                             };
 
                             let Some(layout) = layout else {
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index 36b76d261de..063fc8f1c74 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2024"
 # tidy-alphabetical-start
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
-rustc_attr_parsing = { path = "../rustc_attr_parsing" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index c6a81e60b2b..b3d7eaf332b 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -208,7 +208,7 @@
 use std::cell::OnceCell;
 use std::path::PathBuf;
 
-use rustc_attr_parsing::InlineAttr;
+use rustc_attr_data_structures::InlineAttr;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::{MTLock, par_for_each_in};
 use rustc_data_structures::unord::{UnordMap, UnordSet};
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index c3a41529794..b4169a060d4 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -100,6 +100,7 @@ use std::fs::{self, File};
 use std::io::Write;
 use std::path::{Path, PathBuf};
 
+use rustc_attr_data_structures::InlineAttr;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::sync;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
@@ -845,8 +846,7 @@ fn mono_item_visibility<'tcx>(
         return if is_generic
             && (always_export_generics
                 || (can_export_generics
-                    && tcx.codegen_fn_attrs(def_id).inline
-                        == rustc_attr_parsing::InlineAttr::Never))
+                    && tcx.codegen_fn_attrs(def_id).inline == InlineAttr::Never))
         {
             // If it is an upstream monomorphization and we export generics, we must make
             // it available to downstream crates.
@@ -859,8 +859,7 @@ fn mono_item_visibility<'tcx>(
 
     if is_generic {
         if always_export_generics
-            || (can_export_generics
-                && tcx.codegen_fn_attrs(def_id).inline == rustc_attr_parsing::InlineAttr::Never)
+            || (can_export_generics && tcx.codegen_fn_attrs(def_id).inline == InlineAttr::Never)
         {
             if tcx.is_unreachable_local_definition(def_id) {
                 // This instance cannot be used from another crate.
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index ba81ef3103b..b9167489076 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -9,7 +9,7 @@ rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_lowering = { path = "../rustc_ast_lowering" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
-rustc_attr_parsing = { path = "../rustc_attr_parsing" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_expand = { path = "../rustc_expand" }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c68f8df49fc..5c0d0cf4796 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -10,7 +10,7 @@ use std::collections::hash_map::Entry;
 
 use rustc_abi::{Align, ExternAbi, Size};
 use rustc_ast::{AttrStyle, LitKind, MetaItemInner, MetaItemKind, MetaItemLit, ast};
-use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr};
+use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
 use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 7353c1ead5a..b3e6ee9512c 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -4,7 +4,7 @@
 //! but are not declared in one single location (unlike lang features), which means we need to
 //! collect them instead.
 
-use rustc_attr_parsing::{AttributeKind, StabilityLevel, StableSince};
+use rustc_attr_data_structures::{AttributeKind, StabilityLevel, StableSince};
 use rustc_hir::Attribute;
 use rustc_hir::intravisit::Visitor;
 use rustc_middle::hir::nested_filter;
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index d7baad69c78..9884386d68f 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -5,9 +5,9 @@ use std::mem::replace;
 use std::num::NonZero;
 
 use rustc_ast_lowering::stability::extern_abi_stability;
-use rustc_attr_parsing::{
-    self as attr, AttributeKind, ConstStability, DeprecatedSince, PartialConstStability, Stability,
-    StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, find_attr,
+use rustc_attr_data_structures::{
+    self as attrs, AttributeKind, ConstStability, DeprecatedSince, PartialConstStability,
+    Stability, StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, find_attr,
 };
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
@@ -121,7 +121,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
         debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs);
 
-        let depr = attr::find_attr!(attrs, AttributeKind::Deprecation{deprecation, span} => (*deprecation, *span));
+        let depr = attrs::find_attr!(attrs, AttributeKind::Deprecation{deprecation, span} => (*deprecation, *span));
         let const_stability_indirect = find_attr!(attrs, AttributeKind::ConstStabilityIndirect);
 
         let mut is_deprecated = false;
@@ -174,9 +174,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         }
 
         // # Regular and body stability
-        let stab = attr::find_attr!(attrs, AttributeKind::Stability { stability, span } => (*stability, *span));
+        let stab = attrs::find_attr!(attrs, AttributeKind::Stability { stability, span } => (*stability, *span));
         let body_stab =
-            attr::find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability);
+            attrs::find_attr!(attrs, AttributeKind::BodyStability { stability, .. } => *stability);
 
         if let Some((depr, span)) = &depr
             && depr.is_since_rustc_version()
@@ -206,7 +206,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
             // this is *almost surely* an accident.
             if let (
                 &Some(DeprecatedSince::RustcVersion(dep_since)),
-                &attr::StabilityLevel::Stable { since: stab_since, .. },
+                &attrs::StabilityLevel::Stable { since: stab_since, .. },
             ) = (&depr.as_ref().map(|(d, _)| d.since), &stab.level)
             {
                 match stab_since {
@@ -263,7 +263,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
 
         // # Const stability
 
-        let const_stab = attr::find_attr!(attrs, AttributeKind::ConstStability { stability, span } => (*stability, *span));
+        let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability { stability, span } => (*stability, *span));
 
         // If the current node is a function with const stability attributes (directly given or
         // implied), check if the function/method is const or the parent impl block is const.
@@ -713,7 +713,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
         // by default and are unable to be used.
         if tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
             let stability = Stability {
-                level: attr::StabilityLevel::Unstable {
+                level: attrs::StabilityLevel::Unstable {
                     reason: UnstableReason::Default,
                     issue: NonZero::new(27812),
                     is_soft: false,
@@ -796,17 +796,17 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
                 let features = self.tcx.features();
                 if features.staged_api() {
                     let attrs = self.tcx.hir_attrs(item.hir_id());
-                    let stab = attr::find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span));
+                    let stab = attrs::find_attr!(attrs, AttributeKind::Stability{stability, span} => (*stability, *span));
 
                     // FIXME(jdonszelmann): make it impossible to miss the or_else in the typesystem
-                    let const_stab = attr::find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability);
+                    let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability{stability, ..} => *stability);
 
                     // If this impl block has an #[unstable] attribute, give an
                     // error if all involved types and traits are stable, because
                     // it will have no effect.
                     // See: https://github.com/rust-lang/rust/issues/55436
                     if let Some((
-                        Stability { level: attr::StabilityLevel::Unstable { .. }, .. },
+                        Stability { level: attrs::StabilityLevel::Unstable { .. }, .. },
                         span,
                     )) = stab
                     {
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index f63d8b2d79f..2b85d7b26ce 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -6,7 +6,6 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::untranslatable_diagnostic)]
 #![allow(unused_crate_dependencies)]
-#![cfg_attr(all(feature = "rustc", bootstrap), feature(let_chains))]
 // tidy-alphabetical-end
 
 pub mod constructor;
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index a89d01dcbbe..d9f1888bfd9 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -1,6 +1,5 @@
 use std::fmt;
 use std::iter::once;
-use std::ops::ControlFlow;
 
 use rustc_abi::{FIRST_VARIANT, FieldIdx, Integer, VariantIdx};
 use rustc_arena::DroplessArena;
@@ -12,8 +11,7 @@ use rustc_middle::mir::{self, Const};
 use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary};
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{
-    self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
-    TypeVisitableExt, TypeVisitor, VariantDef,
+    self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
@@ -137,22 +135,11 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
     /// Returns the hidden type corresponding to this key if the body under analysis is allowed to
     /// know it.
     fn reveal_opaque_key(&self, key: OpaqueTypeKey<'tcx>) -> Option<Ty<'tcx>> {
-        if let Some(hidden_ty) = self.typeck_results.concrete_opaque_types.get(&key.def_id) {
-            let ty = ty::EarlyBinder::bind(hidden_ty.ty).instantiate(self.tcx, key.args);
-            if ty.visit_with(&mut RecursiveOpaque { def_id: key.def_id.into() }).is_continue() {
-                Some(ty)
-            } else {
-                // HACK: We skip revealing opaque types which recursively expand
-                // to themselves. This is because we may infer hidden types like
-                // `Opaque<T> = Opaque<Opaque<T>>` or `Opaque<T> = Opaque<(T,)>`
-                // in hir typeck.
-                None
-            }
-        } else {
-            None
-        }
+        self.typeck_results
+            .concrete_opaque_types
+            .get(&key.def_id)
+            .map(|x| ty::EarlyBinder::bind(x.ty).instantiate(self.tcx, key.args))
     }
-
     // This can take a non-revealed `Ty` because it reveals opaques itself.
     pub fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
         !ty.inhabited_predicate(self.tcx).apply_revealing_opaque(
@@ -1177,20 +1164,3 @@ fn detect_mixed_deref_pat_ctors<'p, 'tcx>(
     }
     Ok(())
 }
-
-struct RecursiveOpaque {
-    def_id: DefId,
-}
-impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for RecursiveOpaque {
-    type Result = ControlFlow<()>;
-
-    fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
-        if let ty::Alias(ty::Opaque, alias_ty) = t.kind() {
-            if alias_ty.def_id == self.def_id {
-                return ControlFlow::Break(());
-            }
-        }
-
-        if t.has_opaque_types() { t.super_visit_with(self) } else { ControlFlow::Continue(()) }
-    }
-}
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index 242c67d732a..109a7bf49fe 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 rustc_ast = { path = "../rustc_ast" }
-rustc_attr_parsing = { path = "../rustc_attr_parsing" }
+rustc_attr_data_structures = { path = "../rustc_attr_data_structures" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 9c2921cd5b2..e2dfaec61b3 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -20,7 +20,6 @@ use errors::{
 };
 use rustc_ast::MacroDef;
 use rustc_ast::visit::{VisitorResult, try_visit};
-use rustc_attr_parsing::AttributeKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{MultiSpan, listify};
@@ -40,7 +39,7 @@ use rustc_session::lint;
 use rustc_span::hygiene::Transparency;
 use rustc_span::{Ident, Span, Symbol, sym};
 use tracing::debug;
-use {rustc_attr_parsing as attr, rustc_hir as hir};
+use {rustc_attr_data_structures as attrs, rustc_hir as hir};
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
@@ -497,7 +496,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
         let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id);
         let attrs = self.tcx.hir_attrs(hir_id);
 
-        if attr::find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
+        if attrs::find_attr!(attrs, attrs::AttributeKind::MacroTransparency(x) => *x)
             .unwrap_or(Transparency::fallback(md.macro_rules))
             != Transparency::Opaque
         {
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 3ae56cef2c4..d4217e0aa54 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -1433,6 +1433,8 @@ fn panic_on_forbidden_read<D: Deps>(data: &DepGraphData<D>, dep_node_index: DepN
         && let Some(nodes) = &data.current.nodes_in_current_session
     {
         // Try to find it among the nodes allocated so far in this session
+        // This is OK, there's only ever one node result possible so this is deterministic.
+        #[allow(rustc::potential_query_instability)]
         if let Some((node, _)) = nodes.lock().iter().find(|&(_, index)| *index == dep_node_index) {
             dep_node = Some(*node);
         }
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index f1b609a3ca9..79b99c52d0c 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -784,6 +784,8 @@ impl<D: Deps> EncoderState<D> {
     ) {
         if let Some(record_stats) = &self.stats {
             let record_stats = record_stats.lock();
+            // `stats` is sorted below so we can allow this lint here.
+            #[allow(rustc::potential_query_instability)]
             let mut stats: Vec<_> = record_stats.values().collect();
             stats.sort_by_key(|s| -(s.node_counter as i64));
 
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index eba7378b475..d36cb6f0e5b 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -1,5 +1,5 @@
 // tidy-alphabetical-start
-#![allow(rustc::potential_query_instability, internal_features)]
+#![allow(internal_features)]
 #![feature(assert_matches)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 6321abc5087..1e79bd461d2 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -510,6 +510,10 @@ pub fn break_query_cycles<I: Clone + Debug>(
     registry: &rayon_core::Registry,
 ) {
     let mut wakelist = Vec::new();
+    // It is OK per the comments:
+    // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798854932
+    // - https://github.com/rust-lang/rust/pull/131200#issuecomment-2798866392
+    #[allow(rustc::potential_query_instability)]
     let mut jobs: Vec<QueryJobId> = query_map.keys().cloned().collect();
 
     let mut found_cycle = false;
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 0b16983c2c7..d09750fa281 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2493,7 +2493,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else {
             return None;
         };
-        let module_name = crate_module.kind.name().unwrap_or(kw::Empty);
+        let module_name = crate_module.kind.name().unwrap_or(kw::Crate);
         let import_snippet = match import.kind {
             ImportKind::Single { source, target, .. } if source != target => {
                 format!("{source} as {target}")
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index faee0e7dd5f..1b682d0cf8a 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -111,6 +111,19 @@ enum PatBoundCtx {
     Or,
 }
 
+/// Tracks bindings resolved within a pattern. This serves two purposes:
+///
+/// - This tracks when identifiers are bound multiple times within a pattern. In a product context,
+///   this is an error. In an or-pattern, this lets us reuse the same resolution for each instance.
+///   See `fresh_binding` and `resolve_pattern_inner` for more information.
+///
+/// - The guard expression of a guard pattern may use bindings from within the guard pattern, but
+///   not from elsewhere in the pattern containing it. This allows us to isolate the bindings in the
+///   subpattern to construct the scope for the guard.
+///
+/// Each identifier must map to at most one distinct [`Res`].
+type PatternBindings = SmallVec<[(PatBoundCtx, FxIndexMap<Ident, Res>); 1]>;
+
 /// Does this the item (from the item rib scope) allow generic parameters?
 #[derive(Copy, Clone, Debug)]
 pub(crate) enum HasGenericParams {
@@ -786,7 +799,14 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
     fn visit_pat(&mut self, p: &'ast Pat) {
         let prev = self.diag_metadata.current_pat;
         self.diag_metadata.current_pat = Some(p);
-        visit::walk_pat(self, p);
+
+        if let PatKind::Guard(subpat, _) = &p.kind {
+            // We walk the guard expression in `resolve_pattern_inner`. Don't resolve it twice.
+            self.visit_pat(subpat);
+        } else {
+            visit::walk_pat(self, p);
+        }
+
         self.diag_metadata.current_pat = prev;
     }
     fn visit_local(&mut self, local: &'ast Local) {
@@ -2297,7 +2317,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
     fn resolve_fn_params(
         &mut self,
         has_self: bool,
-        inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)>,
+        inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)> + Clone,
     ) -> Result<LifetimeRes, (Vec<MissingLifetime>, Vec<ElisionFnParameter>)> {
         enum Elision {
             /// We have not found any candidate.
@@ -2319,15 +2339,20 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         let mut parameter_info = Vec::new();
         let mut all_candidates = Vec::new();
 
+        // Resolve and apply bindings first so diagnostics can see if they're used in types.
         let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
-        for (index, (pat, ty)) in inputs.enumerate() {
-            debug!(?pat, ?ty);
+        for (pat, _) in inputs.clone() {
+            debug!("resolving bindings in pat = {pat:?}");
             self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
                 if let Some(pat) = pat {
                     this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
                 }
             });
+        }
+        self.apply_pattern_bindings(bindings);
 
+        for (index, (pat, ty)) in inputs.enumerate() {
+            debug!("resolving type for pat = {pat:?}, ty = {ty:?}");
             // Record elision candidates only for this parameter.
             debug_assert_matches!(self.lifetime_elision_candidates, None);
             self.lifetime_elision_candidates = Some(Default::default());
@@ -3615,16 +3640,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         self.visit_path(&delegation.path, delegation.id);
         let Some(body) = &delegation.body else { return };
         self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
-            // `PatBoundCtx` is not necessary in this context
-            let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
-
             let span = delegation.path.segments.last().unwrap().ident.span;
-            this.fresh_binding(
-                Ident::new(kw::SelfLower, span),
-                delegation.id,
-                PatternSource::FnParam,
-                &mut bindings,
-            );
+            let ident = Ident::new(kw::SelfLower, span.normalize_to_macro_rules());
+            let res = Res::Local(delegation.id);
+            this.innermost_rib_bindings(ValueNS).insert(ident, res);
             this.visit_block(body);
         });
     }
@@ -3635,6 +3654,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             for Param { pat, .. } in params {
                 this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
             }
+            this.apply_pattern_bindings(bindings);
         });
         for Param { ty, .. } in params {
             self.visit_ty(ty);
@@ -3851,13 +3871,32 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
     fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
         let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
         self.resolve_pattern(pat, pat_src, &mut bindings);
+        self.apply_pattern_bindings(bindings);
+    }
+
+    /// Apply the bindings from a pattern to the innermost rib of the current scope.
+    fn apply_pattern_bindings(&mut self, mut pat_bindings: PatternBindings) {
+        let rib_bindings = self.innermost_rib_bindings(ValueNS);
+        let Some((_, pat_bindings)) = pat_bindings.pop() else {
+            bug!("tried applying nonexistent bindings from pattern");
+        };
+
+        if rib_bindings.is_empty() {
+            // Often, such as for match arms, the bindings are introduced into a new rib.
+            // In this case, we can move the bindings over directly.
+            *rib_bindings = pat_bindings;
+        } else {
+            rib_bindings.extend(pat_bindings);
+        }
     }
 
+    /// Resolve bindings in a pattern. `apply_pattern_bindings` must be called after to introduce
+    /// the bindings into scope.
     fn resolve_pattern(
         &mut self,
         pat: &'ast Pat,
         pat_src: PatternSource,
-        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
+        bindings: &mut PatternBindings,
     ) {
         // We walk the pattern before declaring the pattern's inner bindings,
         // so that we avoid resolving a literal expression to a binding defined
@@ -3890,9 +3929,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
     #[tracing::instrument(skip(self, bindings), level = "debug")]
     fn resolve_pattern_inner(
         &mut self,
-        pat: &Pat,
+        pat: &'ast Pat,
         pat_src: PatternSource,
-        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
+        bindings: &mut PatternBindings,
     ) {
         // Visit all direct subpatterns of this pattern.
         pat.walk(&mut |pat| {
@@ -3950,6 +3989,31 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     // Prevent visiting `ps` as we've already done so above.
                     return false;
                 }
+                PatKind::Guard(ref subpat, ref guard) => {
+                    // Add a new set of bindings to the stack to collect bindings in `subpat`.
+                    bindings.push((PatBoundCtx::Product, Default::default()));
+                    // Resolving `subpat` adds bindings onto the newly-pushed context. After, the
+                    // total number of contexts on the stack should be the same as before.
+                    let binding_ctx_stack_len = bindings.len();
+                    self.resolve_pattern_inner(subpat, pat_src, bindings);
+                    assert_eq!(bindings.len(), binding_ctx_stack_len);
+                    // These bindings, but none from the surrounding pattern, are visible in the
+                    // guard; put them in scope and resolve `guard`.
+                    let subpat_bindings = bindings.pop().unwrap().1;
+                    self.with_rib(ValueNS, RibKind::Normal, |this| {
+                        *this.innermost_rib_bindings(ValueNS) = subpat_bindings.clone();
+                        this.resolve_expr(guard, None);
+                    });
+                    // Propagate the subpattern's bindings upwards.
+                    // FIXME(guard_patterns): For `if let` guards, we'll also need to get the
+                    // bindings introduced by the guard from its rib and propagate them upwards.
+                    // This will require checking the identifiers for overlaps with `bindings`, like
+                    // what `fresh_binding` does (ideally sharing its logic). To keep them separate
+                    // from `subpat_bindings`, we can introduce a fresh rib for the guard.
+                    bindings.last_mut().unwrap().1.extend(subpat_bindings);
+                    // Prevent visiting `subpat` as we've already done so above.
+                    return false;
+                }
                 _ => {}
             }
             true
@@ -3988,20 +4052,17 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         ident: Ident,
         pat_id: NodeId,
         pat_src: PatternSource,
-        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
+        bindings: &mut PatternBindings,
     ) -> Res {
-        // Add the binding to the local ribs, if it doesn't already exist in the bindings map.
+        // Add the binding to the bindings map, if it doesn't already exist.
         // (We must not add it if it's in the bindings map because that breaks the assumptions
         // later passes make about or-patterns.)
         let ident = ident.normalize_to_macro_rules();
 
-        let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident));
         // Already bound in a product pattern? e.g. `(a, a)` which is not allowed.
-        let already_bound_and = bound_iter.clone().any(|(ctx, _)| *ctx == PatBoundCtx::Product);
-        // Already bound in an or-pattern? e.g. `V1(a) | V2(a)`.
-        // This is *required* for consistency which is checked later.
-        let already_bound_or = bound_iter.any(|(ctx, _)| *ctx == PatBoundCtx::Or);
-
+        let already_bound_and = bindings
+            .iter()
+            .any(|(ctx, map)| *ctx == PatBoundCtx::Product && map.contains_key(&ident));
         if already_bound_and {
             // Overlap in a product pattern somewhere; report an error.
             use ResolutionError::*;
@@ -4014,19 +4075,23 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
             self.report_error(ident.span, error(ident));
         }
 
-        // Record as bound.
-        bindings.last_mut().unwrap().1.insert(ident);
-
-        if already_bound_or {
+        // Already bound in an or-pattern? e.g. `V1(a) | V2(a)`.
+        // This is *required* for consistency which is checked later.
+        let already_bound_or = bindings
+            .iter()
+            .find_map(|(ctx, map)| if *ctx == PatBoundCtx::Or { map.get(&ident) } else { None });
+        let res = if let Some(&res) = already_bound_or {
             // `Variant1(a) | Variant2(a)`, ok
             // Reuse definition from the first `a`.
-            self.innermost_rib_bindings(ValueNS)[&ident]
-        } else {
-            // A completely fresh binding is added to the set.
-            let res = Res::Local(pat_id);
-            self.innermost_rib_bindings(ValueNS).insert(ident, res);
             res
-        }
+        } else {
+            // A completely fresh binding is added to the map.
+            Res::Local(pat_id)
+        };
+
+        // Record as bound.
+        bindings.last_mut().unwrap().1.insert(ident, res);
+        res
     }
 
     fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut FxIndexMap<Ident, Res> {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index b538be34f31..6768907adde 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -11,6 +11,7 @@ use rustc_ast::{
     Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind,
 };
 use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
+use rustc_attr_parsing::is_doc_alias_attrs_contain_symbol;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::codes::*;
 use rustc_errors::{
@@ -39,7 +40,7 @@ use crate::late::{
 };
 use crate::ty::fast_reject::SimplifiedType;
 use crate::{
-    Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Segment, errors,
+    Module, ModuleKind, ModuleOrUniformRoot, PathResult, PathSource, Resolver, Segment, errors,
     path_names_to_string,
 };
 
@@ -477,6 +478,19 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             return (err, Vec::new());
         }
 
+        if let Some((did, item)) = self.lookup_doc_alias_name(path, source.namespace()) {
+            let item_name = item.name;
+            let suggestion_name = self.r.tcx.item_name(did);
+            err.span_suggestion(
+                item.span,
+                format!("`{suggestion_name}` has a name defined in the doc alias attribute as `{item_name}`"),
+                    suggestion_name,
+                    Applicability::MaybeIncorrect
+                );
+
+            return (err, Vec::new());
+        };
+
         let (found, suggested_candidates, mut candidates) = self.try_lookup_name_relaxed(
             &mut err,
             source,
@@ -852,6 +866,65 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         (false, suggested_candidates, candidates)
     }
 
+    fn lookup_doc_alias_name(&mut self, path: &[Segment], ns: Namespace) -> Option<(DefId, Ident)> {
+        let find_doc_alias_name = |r: &mut Resolver<'ra, '_>, m: Module<'ra>, item_name: Symbol| {
+            for resolution in r.resolutions(m).borrow().values() {
+                let Some(did) =
+                    resolution.borrow().binding.and_then(|binding| binding.res().opt_def_id())
+                else {
+                    continue;
+                };
+                if did.is_local() {
+                    // We don't record the doc alias name in the local crate
+                    // because the people who write doc alias are usually not
+                    // confused by them.
+                    continue;
+                }
+                if is_doc_alias_attrs_contain_symbol(r.tcx.get_attrs(did, sym::doc), item_name) {
+                    return Some(did);
+                }
+            }
+            None
+        };
+
+        if path.len() == 1 {
+            for rib in self.ribs[ns].iter().rev() {
+                let item = path[0].ident;
+                if let RibKind::Module(module) = rib.kind
+                    && let Some(did) = find_doc_alias_name(self.r, module, item.name)
+                {
+                    return Some((did, item));
+                }
+            }
+        } else {
+            // Finds to the last resolved module item in the path
+            // and searches doc aliases within that module.
+            //
+            // Example: For the path `a::b::last_resolved::not_exist::c::d`,
+            // we will try to find any item has doc aliases named `not_exist`
+            // in `last_resolved` module.
+            //
+            // - Use `skip(1)` because the final segment must remain unresolved.
+            for (idx, seg) in path.iter().enumerate().rev().skip(1) {
+                let Some(id) = seg.id else {
+                    continue;
+                };
+                let Some(res) = self.r.partial_res_map.get(&id) else {
+                    continue;
+                };
+                if let Res::Def(DefKind::Mod, module) = res.expect_full_res()
+                    && let Some(module) = self.r.get_module(module)
+                    && let item = path[idx + 1].ident
+                    && let Some(did) = find_doc_alias_name(self.r, module, item.name)
+                {
+                    return Some((did, item));
+                }
+                break;
+            }
+        }
+        None
+    }
+
     fn suggest_trait_and_bounds(
         &mut self,
         err: &mut Diag<'_>,
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index c58f8480572..ee905065b96 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -8,7 +8,7 @@ use std::sync::Arc;
 use rustc_ast::expand::StrippedCfgItem;
 use rustc_ast::{self as ast, Crate, NodeId, attr};
 use rustc_ast_pretty::pprust;
-use rustc_attr_parsing::StabilityLevel;
+use rustc_attr_data_structures::StabilityLevel;
 use rustc_data_structures::intern::Interned;
 use rustc_errors::{Applicability, DiagCtxtHandle, StashKey};
 use rustc_expand::base::{
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index 63772a32222..f0ee19e3c67 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -33,7 +33,7 @@ libc = "0.2"
 # tidy-alphabetical-end
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.59.0"
+version = "0.61.0"
 features = [
     "Win32_Foundation",
     "Win32_System_LibraryLoader",
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 60e1b465ba9..144aeb5c369 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -195,6 +195,11 @@ pub struct CoverageOptions {
     /// regression tests for #133606, because we don't have an easy way to
     /// reproduce it from actual source code.
     pub discard_all_spans_in_codegen: bool,
+
+    /// `-Zcoverage-options=inject-unused-local-file`: During codegen, add an
+    /// extra dummy entry to each function's local file table, to exercise the
+    /// code that checks for local file IDs with no mapping regions.
+    pub inject_unused_local_file: bool,
 }
 
 /// Controls whether branch coverage or MC/DC coverage is enabled.
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index bdeca91eb64..92f1bd8ab73 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -78,10 +78,14 @@ fn current_dll_path() -> Result<PathBuf, String> {
                 if libc::dladdr(addr, &mut info) == 0 {
                     return Err("dladdr failed".into());
                 }
-                if info.dli_fname.is_null() {
-                    return Err("dladdr returned null pointer".into());
-                }
-                let bytes = CStr::from_ptr(info.dli_fname).to_bytes();
+                #[cfg(target_os = "cygwin")]
+                let fname_ptr = info.dli_fname.as_ptr();
+                #[cfg(not(target_os = "cygwin"))]
+                let fname_ptr = {
+                    assert!(!info.dli_fname.is_null(), "dli_fname cannot be null");
+                    info.dli_fname
+                };
+                let bytes = CStr::from_ptr(fname_ptr).to_bytes();
                 let os = OsStr::from_bytes(bytes);
                 Ok(PathBuf::from(os))
             }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 5b4068740a1..3d9fdcbc7b1 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1413,6 +1413,7 @@ pub mod parse {
                 "mcdc" => slot.level = CoverageLevel::Mcdc,
                 "no-mir-spans" => slot.no_mir_spans = true,
                 "discard-all-spans-in-codegen" => slot.discard_all_spans_in_codegen = true,
+                "inject-unused-local-file" => slot.inject_unused_local_file = true,
                 _ => return false,
             }
         }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 010ae42c280..34ac37d6378 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -371,6 +371,11 @@ impl Session {
         self.opts.unstable_opts.coverage_options.discard_all_spans_in_codegen
     }
 
+    /// True if testing flag `-Zcoverage-options=inject-unused-local-file` was passed.
+    pub fn coverage_inject_unused_local_file(&self) -> bool {
+        self.opts.unstable_opts.coverage_options.inject_unused_local_file
+    }
+
     pub fn is_sanitizer_cfi_enabled(&self) -> bool {
         self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
     }
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
index c5704c57448..f1b6fa123de 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FramePointer, LinkerFlavor, Lld, Target, TargetMetadata, base};
+use crate::spec::{FramePointer, Target, TargetMetadata, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
@@ -11,11 +11,6 @@ pub(crate) fn target() -> Target {
     // and other services. It must point to the previous {x29, x30} pair on the stack."
     base.frame_pointer = FramePointer::NonLeaf;
 
-    // MSVC emits a warning about code that may trip "Cortex-A53 MPCore processor bug #843419" (see
-    // https://developer.arm.com/documentation/epm048406/latest) which is sometimes emitted by LLVM.
-    // Since Arm64 Windows 10+ isn't supported on that processor, it's safe to disable the warning.
-    base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/arm64hazardfree"]);
-
     Target {
         llvm_target: "aarch64-pc-windows-msvc".into(),
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 5428aa4cf70..99b04ac2720 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -416,25 +416,25 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ),
     ("avx10.2", Unstable(sym::avx10_target_feature), &["avx10.1"]),
     ("avx2", Stable, &["avx"]),
-    ("avx512bf16", Unstable(sym::avx512_target_feature), &["avx512bw"]),
-    ("avx512bitalg", Unstable(sym::avx512_target_feature), &["avx512bw"]),
-    ("avx512bw", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512cd", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512dq", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512f", Unstable(sym::avx512_target_feature), &["avx2", "fma", "f16c"]),
-    ("avx512fp16", Unstable(sym::avx512_target_feature), &["avx512bw"]),
-    ("avx512ifma", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512vbmi", Unstable(sym::avx512_target_feature), &["avx512bw"]),
-    ("avx512vbmi2", Unstable(sym::avx512_target_feature), &["avx512bw"]),
-    ("avx512vl", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512vnni", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512vp2intersect", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avx512vpopcntdq", Unstable(sym::avx512_target_feature), &["avx512f"]),
-    ("avxifma", Unstable(sym::avx512_target_feature), &["avx2"]),
-    ("avxneconvert", Unstable(sym::avx512_target_feature), &["avx2"]),
-    ("avxvnni", Unstable(sym::avx512_target_feature), &["avx2"]),
-    ("avxvnniint16", Unstable(sym::avx512_target_feature), &["avx2"]),
-    ("avxvnniint8", Unstable(sym::avx512_target_feature), &["avx2"]),
+    ("avx512bf16", Stable, &["avx512bw"]),
+    ("avx512bitalg", Stable, &["avx512bw"]),
+    ("avx512bw", Stable, &["avx512f"]),
+    ("avx512cd", Stable, &["avx512f"]),
+    ("avx512dq", Stable, &["avx512f"]),
+    ("avx512f", Stable, &["avx2", "fma", "f16c"]),
+    ("avx512fp16", Stable, &["avx512bw"]),
+    ("avx512ifma", Stable, &["avx512f"]),
+    ("avx512vbmi", Stable, &["avx512bw"]),
+    ("avx512vbmi2", Stable, &["avx512bw"]),
+    ("avx512vl", Stable, &["avx512f"]),
+    ("avx512vnni", Stable, &["avx512f"]),
+    ("avx512vp2intersect", Stable, &["avx512f"]),
+    ("avx512vpopcntdq", Stable, &["avx512f"]),
+    ("avxifma", Stable, &["avx2"]),
+    ("avxneconvert", Stable, &["avx2"]),
+    ("avxvnni", Stable, &["avx2"]),
+    ("avxvnniint16", Stable, &["avx2"]),
+    ("avxvnniint8", Stable, &["avx2"]),
     ("bmi1", Stable, &[]),
     ("bmi2", Stable, &[]),
     ("cmpxchg16b", Stable, &[]),
@@ -442,7 +442,7 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("f16c", Stable, &["avx"]),
     ("fma", Stable, &["avx"]),
     ("fxsr", Stable, &[]),
-    ("gfni", Unstable(sym::avx512_target_feature), &["sse2"]),
+    ("gfni", Stable, &["sse2"]),
     ("kl", Unstable(sym::keylocker_x86), &["sse2"]),
     ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]),
     ("lzcnt", Stable, &[]),
@@ -469,8 +469,8 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("sse4a", Unstable(sym::sse4a_target_feature), &["sse3"]),
     ("ssse3", Stable, &["sse3"]),
     ("tbm", Unstable(sym::tbm_target_feature), &[]),
-    ("vaes", Unstable(sym::avx512_target_feature), &["avx2", "aes"]),
-    ("vpclmulqdq", Unstable(sym::avx512_target_feature), &["avx", "pclmulqdq"]),
+    ("vaes", Stable, &["avx2", "aes"]),
+    ("vpclmulqdq", Stable, &["avx", "pclmulqdq"]),
     ("widekl", Unstable(sym::keylocker_x86), &["kl"]),
     ("x87", Unstable(sym::x87_target_feature), &[]),
     ("xop", Unstable(sym::xop_target_feature), &[/*"fma4", */ "avx", "sse4a"]),
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 908fcb14cb2..ad57555bd24 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -492,9 +492,7 @@ fn layout_of_uncached<'tcx>(
         ty::Coroutine(def_id, args) => {
             use rustc_middle::ty::layout::PrimitiveExt as _;
 
-            let Some(info) = tcx.coroutine_layout(def_id, args) else {
-                return Err(error(cx, LayoutError::Unknown(ty)));
-            };
+            let info = tcx.coroutine_layout(def_id, args)?;
 
             let local_layouts = info
                 .field_tys
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index eae3213ead0..1b5d04e6025 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -193,7 +193,7 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
 
             ReVar(vid) => write!(f, "{vid:?}"),
 
-            RePlaceholder(placeholder) => write!(f, "{placeholder:?}"),
+            RePlaceholder(placeholder) => write!(f, "'{placeholder:?}"),
 
             // Use `'{erased}` as the output instead of `'erased` so that its more obviously distinct from
             // a `ReEarlyParam` named `'erased`. Technically that would print as `'erased/#IDX` so this is
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 24c5d4c92f7..8766fd904b0 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -234,7 +234,7 @@ impl str {
     #[stable(feature = "str_box_extras", since = "1.20.0")]
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
-    pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]> {
+    pub fn into_boxed_bytes(self: Box<Self>) -> Box<[u8]> {
         self.into()
     }
 
@@ -501,7 +501,7 @@ impl str {
     #[rustc_allow_incoherent_impl]
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline]
-    pub fn into_string(self: Box<str>) -> String {
+    pub fn into_string(self: Box<Self>) -> String {
         let slice = Box::<[u8]>::from(self);
         unsafe { String::from_utf8_unchecked(slice.into_vec()) }
     }
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 870ad9df4fd..556db239f24 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -20,6 +20,8 @@ macro_rules! impl_general_format {
     }
 }
 
+#[cfg(target_has_reliable_f16)]
+impl_general_format! { f16 }
 impl_general_format! { f32 f64 }
 
 // Don't inline this so callers don't use the stack space this function
@@ -231,6 +233,13 @@ macro_rules! floating {
 
 floating! { f32 f64 }
 
+#[cfg(target_has_reliable_f16)]
+floating! { f16 }
+
+// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order
+// to avoid ICEs.
+
+#[cfg(not(target_has_reliable_f16))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for f16 {
     #[inline]
@@ -239,6 +248,33 @@ impl Debug for f16 {
     }
 }
 
+#[cfg(not(target_has_reliable_f16))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Display for f16 {
+    #[inline]
+    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
+        Debug::fmt(self, fmt)
+    }
+}
+
+#[cfg(not(target_has_reliable_f16))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl LowerExp for f16 {
+    #[inline]
+    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
+        Debug::fmt(self, fmt)
+    }
+}
+
+#[cfg(not(target_has_reliable_f16))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl UpperExp for f16 {
+    #[inline]
+    fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
+        Debug::fmt(self, fmt)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for f128 {
     #[inline]
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index effdc3c63ee..23bafa778bc 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -62,8 +62,7 @@
 #![allow(missing_docs)]
 
 use crate::marker::{DiscriminantKind, Tuple};
-use crate::mem::SizedTypeProperties;
-use crate::{ptr, ub_checks};
+use crate::ptr;
 
 pub mod fallback;
 pub mod mir;
@@ -3317,7 +3316,7 @@ pub const unsafe fn typed_swap_nonoverlapping<T>(x: *mut T, y: *mut T) {
 /// `#[inline]`), gating assertions on `ub_checks()` rather than `cfg!(ub_checks)` means that
 /// assertions are enabled whenever the *user crate* has UB checks enabled. However, if the
 /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is
-/// primarily used by [`ub_checks::assert_unsafe_precondition`].
+/// primarily used by [`crate::ub_checks::assert_unsafe_precondition`].
 #[rustc_intrinsic_const_stable_indirect] // just for UB checks
 #[inline(always)]
 #[rustc_intrinsic]
@@ -3595,306 +3594,38 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
 #[rustc_intrinsic]
 pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(ptr: *const P) -> M;
 
-// Some functions are defined here because they accidentally got made
-// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
-// (`transmute` also falls into this category, but it cannot be wrapped due to the
-// check that `T` and `U` have the same size.)
-
-/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
-/// and destination must *not* overlap.
-///
-/// For regions of memory which might overlap, use [`copy`] instead.
-///
-/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
-/// with the source and destination arguments swapped,
-/// and `count` counting the number of `T`s instead of bytes.
-///
-/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the
-/// requirements of `T`. The initialization state is preserved exactly.
-///
-/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
-///
-/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
-///
-/// * Both `src` and `dst` must be properly aligned.
-///
-/// * The region of memory beginning at `src` with a size of `count *
-///   size_of::<T>()` bytes must *not* overlap with the region of memory
-///   beginning at `dst` with the same size.
-///
-/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
-/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
-/// in the region beginning at `*src` and the region beginning at `*dst` can
-/// [violate memory safety][read-ownership].
-///
-/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-/// `0`, the pointers must be properly aligned.
-///
-/// [`read`]: crate::ptr::read
-/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
-/// [valid]: crate::ptr#safety
-///
-/// # Examples
-///
-/// Manually implement [`Vec::append`]:
-///
-/// ```
-/// use std::ptr;
-///
-/// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
-/// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
-///     let src_len = src.len();
-///     let dst_len = dst.len();
-///
-///     // Ensure that `dst` has enough capacity to hold all of `src`.
-///     dst.reserve(src_len);
-///
-///     unsafe {
-///         // The call to add is always safe because `Vec` will never
-///         // allocate more than `isize::MAX` bytes.
-///         let dst_ptr = dst.as_mut_ptr().add(dst_len);
-///         let src_ptr = src.as_ptr();
-///
-///         // Truncate `src` without dropping its contents. We do this first,
-///         // to avoid problems in case something further down panics.
-///         src.set_len(0);
-///
-///         // The two regions cannot overlap because mutable references do
-///         // not alias, and two different vectors cannot own the same
-///         // memory.
-///         ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
-///
-///         // Notify `dst` that it now holds the contents of `src`.
-///         dst.set_len(dst_len + src_len);
-///     }
-/// }
-///
-/// let mut a = vec!['r'];
-/// let mut b = vec!['u', 's', 't'];
-///
-/// append(&mut a, &mut b);
-///
-/// assert_eq!(a, &['r', 'u', 's', 't']);
-/// assert!(b.is_empty());
-/// ```
-///
-/// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
-#[doc(alias = "memcpy")]
+/// This is an accidentally-stable alias to [`ptr::copy_nonoverlapping`]; use that instead.
+// Note (intentionally not in the doc comment): `ptr::copy_nonoverlapping` adds some extra
+// debug assertions; if you are writing compiler tests or code inside the standard library
+// that wants to avoid those debug assertions, directly call this intrinsic instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"]
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
-#[inline(always)]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
-pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
-    #[rustc_intrinsic_const_stable_indirect]
-    #[rustc_nounwind]
-    #[rustc_intrinsic]
-    const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
-
-    ub_checks::assert_unsafe_precondition!(
-        check_language_ub,
-        "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
-        and the specified memory ranges do not overlap",
-        (
-            src: *const () = src as *const (),
-            dst: *mut () = dst as *mut (),
-            size: usize = size_of::<T>(),
-            align: usize = align_of::<T>(),
-            count: usize = count,
-        ) => {
-            let zero_size = count == 0 || size == 0;
-            ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size)
-                && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size)
-                && ub_checks::maybe_is_nonoverlapping(src, dst, size, count)
-        }
-    );
-
-    // SAFETY: the safety contract for `copy_nonoverlapping` must be
-    // upheld by the caller.
-    unsafe { copy_nonoverlapping(src, dst, count) }
-}
+#[rustc_nounwind]
+#[rustc_intrinsic]
+pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
 
-/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
-/// and destination may overlap.
-///
-/// If the source and destination will *never* overlap,
-/// [`copy_nonoverlapping`] can be used instead.
-///
-/// `copy` is semantically equivalent to C's [`memmove`], but
-/// with the source and destination arguments swapped,
-/// and `count` counting the number of `T`s instead of bytes.
-/// Copying takes place as if the bytes were copied from `src`
-/// to a temporary array and then copied from the array to `dst`.
-///
-/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the
-/// requirements of `T`. The initialization state is preserved exactly.
-///
-/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
-///
-/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes, and must remain valid even
-///   when `src` is read for `count * size_of::<T>()` bytes. (This means if the memory ranges
-///   overlap, the `dst` pointer must not be invalidated by `src` reads.)
-///
-/// * Both `src` and `dst` must be properly aligned.
-///
-/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
-/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
-/// in the region beginning at `*src` and the region beginning at `*dst` can
-/// [violate memory safety][read-ownership].
-///
-/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-/// `0`, the pointers must be properly aligned.
-///
-/// [`read`]: crate::ptr::read
-/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
-/// [valid]: crate::ptr#safety
-///
-/// # Examples
-///
-/// Efficiently create a Rust vector from an unsafe buffer:
-///
-/// ```
-/// use std::ptr;
-///
-/// /// # Safety
-/// ///
-/// /// * `ptr` must be correctly aligned for its type and non-zero.
-/// /// * `ptr` must be valid for reads of `elts` contiguous elements of type `T`.
-/// /// * Those elements must not be used after calling this function unless `T: Copy`.
-/// # #[allow(dead_code)]
-/// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
-///     let mut dst = Vec::with_capacity(elts);
-///
-///     // SAFETY: Our precondition ensures the source is aligned and valid,
-///     // and `Vec::with_capacity` ensures that we have usable space to write them.
-///     unsafe { ptr::copy(ptr, dst.as_mut_ptr(), elts); }
-///
-///     // SAFETY: We created it with this much capacity earlier,
-///     // and the previous `copy` has initialized these elements.
-///     unsafe { dst.set_len(elts); }
-///     dst
-/// }
-/// ```
-#[doc(alias = "memmove")]
+/// This is an accidentally-stable alias to [`ptr::copy`]; use that instead.
+// Note (intentionally not in the doc comment): `ptr::copy` adds some extra
+// debug assertions; if you are writing compiler tests or code inside the standard library
+// that wants to avoid those debug assertions, directly call this intrinsic instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"]
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
-#[inline(always)]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-#[rustc_diagnostic_item = "ptr_copy"]
-pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
-    #[rustc_intrinsic_const_stable_indirect]
-    #[rustc_nounwind]
-    #[rustc_intrinsic]
-    const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
-
-    // SAFETY: the safety contract for `copy` must be upheld by the caller.
-    unsafe {
-        ub_checks::assert_unsafe_precondition!(
-            check_language_ub,
-            "ptr::copy requires that both pointer arguments are aligned and non-null",
-            (
-                src: *const () = src as *const (),
-                dst: *mut () = dst as *mut (),
-                align: usize = align_of::<T>(),
-                zero_size: bool = T::IS_ZST || count == 0,
-            ) =>
-            ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size)
-                && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size)
-        );
-        copy(src, dst, count)
-    }
-}
+#[rustc_nounwind]
+#[rustc_intrinsic]
+pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize);
 
-/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
-/// `val`.
-///
-/// `write_bytes` is similar to C's [`memset`], but sets `count *
-/// size_of::<T>()` bytes to `val`.
-///
-/// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset
-///
-/// # Safety
-///
-/// Behavior is undefined if any of the following conditions are violated:
-///
-/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
-///
-/// * `dst` must be properly aligned.
-///
-/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
-/// `0`, the pointer must be properly aligned.
-///
-/// Additionally, note that changing `*dst` in this way can easily lead to undefined behavior (UB)
-/// later if the written bytes are not a valid representation of some `T`. For instance, the
-/// following is an **incorrect** use of this function:
-///
-/// ```rust,no_run
-/// unsafe {
-///     let mut value: u8 = 0;
-///     let ptr: *mut bool = &mut value as *mut u8 as *mut bool;
-///     let _bool = ptr.read(); // This is fine, `ptr` points to a valid `bool`.
-///     ptr.write_bytes(42u8, 1); // This function itself does not cause UB...
-///     let _bool = ptr.read(); // ...but it makes this operation UB! ⚠️
-/// }
-/// ```
-///
-/// [valid]: crate::ptr#safety
-///
-/// # Examples
-///
-/// Basic usage:
-///
-/// ```
-/// use std::ptr;
-///
-/// let mut vec = vec![0u32; 4];
-/// unsafe {
-///     let vec_ptr = vec.as_mut_ptr();
-///     ptr::write_bytes(vec_ptr, 0xfe, 2);
-/// }
-/// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]);
-/// ```
-#[doc(alias = "memset")]
+/// This is an accidentally-stable alias to [`ptr::write_bytes`]; use that instead.
+// Note (intentionally not in the doc comment): `ptr::write_bytes` adds some extra
+// debug assertions; if you are writing compiler tests or code inside the standard library
+// that wants to avoid those debug assertions, directly call this intrinsic instead.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_allowed_through_unstable_modules = "import this function via `std::ptr` instead"]
-#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")]
-#[inline(always)]
-#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-#[rustc_diagnostic_item = "ptr_write_bytes"]
-pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
-    #[rustc_intrinsic_const_stable_indirect]
-    #[rustc_nounwind]
-    #[rustc_intrinsic]
-    const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
-
-    // SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
-    unsafe {
-        ub_checks::assert_unsafe_precondition!(
-            check_language_ub,
-            "ptr::write_bytes requires that the destination pointer is aligned and non-null",
-            (
-                addr: *const () = dst as *const (),
-                align: usize = align_of::<T>(),
-                zero_size: bool = T::IS_ZST || count == 0,
-            ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, zero_size)
-        );
-        write_bytes(dst, val, count)
-    }
-}
+#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
 
 /// Returns the minimum (IEEE 754-2008 minNum) of two `f16` values.
 ///
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 64a7ec8906b..e605d7e0d78 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -101,6 +101,7 @@
 #![feature(bstr)]
 #![feature(bstr_internals)]
 #![feature(cfg_match)]
+#![feature(cfg_target_has_reliable_f16_f128)]
 #![feature(const_carrying_mul_add)]
 #![feature(const_eval_select)]
 #![feature(core_intrinsics)]
@@ -111,7 +112,6 @@
 #![feature(is_ascii_octdigit)]
 #![feature(lazy_get)]
 #![feature(link_cfg)]
-#![feature(non_null_from_ref)]
 #![feature(offset_of_enum)]
 #![feature(panic_internals)]
 #![feature(ptr_alignment_type)]
@@ -188,9 +188,9 @@
 //
 // Target features:
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(avx512_target_feature))]
 #![feature(aarch64_unstable_target_feature)]
 #![feature(arm_target_feature)]
-#![feature(avx512_target_feature)]
 #![feature(hexagon_target_feature)]
 #![feature(keylocker_x86)]
 #![feature(loongarch_target_feature)]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 27387754633..0a5f3ee35b1 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -21,6 +21,8 @@ mod transmutability;
 #[unstable(feature = "transmutability", issue = "99571")]
 pub use transmutability::{Assume, TransmuteFrom};
 
+// This one has to be a re-export (rather than wrapping the underlying intrinsic) so that we can do
+// the special magic "types have equal size" check at the call site.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(inline)]
 pub use crate::intrinsics::transmute;
diff --git a/library/core/src/num/dec2flt/float.rs b/library/core/src/num/dec2flt/float.rs
index b8a28a67569..5bf0faf0bc9 100644
--- a/library/core/src/num/dec2flt/float.rs
+++ b/library/core/src/num/dec2flt/float.rs
@@ -45,7 +45,7 @@ macro_rules! int {
     }
 }
 
-int!(u32, u64);
+int!(u16, u32, u64);
 
 /// A helper trait to avoid duplicating basically all the conversion code for IEEE floats.
 ///
@@ -189,9 +189,14 @@ pub trait RawFloat:
 
     /// Returns the mantissa, exponent and sign as integers.
     ///
-    /// That is, this returns `(m, p, s)` such that `s * m * 2^p` represents the original float.
-    /// For 0, the exponent will be `-(EXP_BIAS + SIG_BITS`, which is the
-    /// minimum subnormal power.
+    /// This returns `(m, p, s)` such that `s * m * 2^p` represents the original float. For 0, the
+    /// exponent will be `-(EXP_BIAS + SIG_BITS)`, which is the minimum subnormal power. For
+    /// infinity or NaN, the exponent will be `EXP_SAT - EXP_BIAS - SIG_BITS`.
+    ///
+    /// If subnormal, the mantissa will be shifted one bit to the left. Otherwise, it is returned
+    /// with the explicit bit set but otherwise unshifted
+    ///
+    /// `s` is only ever +/-1.
     fn integer_decode(self) -> (u64, i16, i8) {
         let bits = self.to_bits();
         let sign: i8 = if bits >> (Self::BITS - 1) == Self::Int::ZERO { 1 } else { -1 };
@@ -213,6 +218,50 @@ const fn pow2_to_pow10(a: i64) -> i64 {
     res as i64
 }
 
+#[cfg(target_has_reliable_f16)]
+impl RawFloat for f16 {
+    type Int = u16;
+
+    const INFINITY: Self = Self::INFINITY;
+    const NEG_INFINITY: Self = Self::NEG_INFINITY;
+    const NAN: Self = Self::NAN;
+    const NEG_NAN: Self = -Self::NAN;
+
+    const BITS: u32 = 16;
+    const SIG_TOTAL_BITS: u32 = Self::MANTISSA_DIGITS;
+    const EXP_MASK: Self::Int = Self::EXP_MASK;
+    const SIG_MASK: Self::Int = Self::MAN_MASK;
+
+    const MIN_EXPONENT_ROUND_TO_EVEN: i32 = -22;
+    const MAX_EXPONENT_ROUND_TO_EVEN: i32 = 5;
+    const SMALLEST_POWER_OF_TEN: i32 = -27;
+
+    #[inline]
+    fn from_u64(v: u64) -> Self {
+        debug_assert!(v <= Self::MAX_MANTISSA_FAST_PATH);
+        v as _
+    }
+
+    #[inline]
+    fn from_u64_bits(v: u64) -> Self {
+        Self::from_bits((v & 0xFFFF) as u16)
+    }
+
+    fn pow10_fast_path(exponent: usize) -> Self {
+        #[allow(clippy::use_self)]
+        const TABLE: [f16; 8] = [1e0, 1e1, 1e2, 1e3, 1e4, 0.0, 0.0, 0.];
+        TABLE[exponent & 7]
+    }
+
+    fn to_bits(self) -> Self::Int {
+        self.to_bits()
+    }
+
+    fn classify(self) -> FpCategory {
+        self.classify()
+    }
+}
+
 impl RawFloat for f32 {
     type Int = u32;
 
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index d1a0e1db313..abad7acb104 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -171,9 +171,25 @@ macro_rules! from_str_float_impl {
         }
     };
 }
+
+#[cfg(target_has_reliable_f16)]
+from_str_float_impl!(f16);
 from_str_float_impl!(f32);
 from_str_float_impl!(f64);
 
+// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order
+// to avoid ICEs.
+
+#[cfg(not(target_has_reliable_f16))]
+impl FromStr for f16 {
+    type Err = ParseFloatError;
+
+    #[inline]
+    fn from_str(_src: &str) -> Result<Self, ParseFloatError> {
+        unimplemented!("requires target_has_reliable_f16")
+    }
+}
+
 /// An error which can be returned when parsing a float.
 ///
 /// This error is used as the error type for the [`FromStr`] implementation
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 9525bdb6762..43bf414d6be 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -12,7 +12,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::convert::FloatToInt;
-use crate::num::{FpCategory, libm};
+use crate::num::FpCategory;
 use crate::panic::const_assert;
 use crate::{cfg_match, intrinsics, mem};
 
@@ -1557,413 +1557,441 @@ impl f32 {
     }
 }
 
-/// Experimental version of `floor` in `core`. See [`f32::floor`] for details.
+/// Experimental implementations of floating point functions in `core`.
 ///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let f = 3.7_f32;
-/// let g = 3.0_f32;
-/// let h = -3.7_f32;
-///
-/// assert_eq!(f32::floor(f), 3.0);
-/// assert_eq!(f32::floor(g), 3.0);
-/// assert_eq!(f32::floor(h), -4.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::floor`]: ../../std/primitive.f32.html#method.floor
-#[inline]
+/// _The standalone functions in this module are for testing only.
+/// They will be stabilized as inherent methods._
 #[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn floor(x: f32) -> f32 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::floorf32(x) }
-}
+pub mod math {
+    use crate::intrinsics;
+    use crate::num::libm;
 
-/// Experimental version of `ceil` in `core`. See [`f32::ceil`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let f = 3.01_f32;
-/// let g = 4.0_f32;
-///
-/// assert_eq!(f32::ceil(f), 4.0);
-/// assert_eq!(f32::ceil(g), 4.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::ceil`]: ../../std/primitive.f32.html#method.ceil
-#[inline]
-#[doc(alias = "ceiling")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-#[unstable(feature = "core_float_math", issue = "137578")]
-pub fn ceil(x: f32) -> f32 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::ceilf32(x) }
-}
+    /// Experimental version of `floor` in `core`. See [`f32::floor`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let f = 3.7_f32;
+    /// let g = 3.0_f32;
+    /// let h = -3.7_f32;
+    ///
+    /// assert_eq!(f32::math::floor(f), 3.0);
+    /// assert_eq!(f32::math::floor(g), 3.0);
+    /// assert_eq!(f32::math::floor(h), -4.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::floor`]: ../../../std/primitive.f32.html#method.floor
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn floor(x: f32) -> f32 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::floorf32(x) }
+    }
 
-/// Experimental version of `round` in `core`. See [`f32::round`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let f = 3.3_f32;
-/// let g = -3.3_f32;
-/// let h = -3.7_f32;
-/// let i = 3.5_f32;
-/// let j = 4.5_f32;
-///
-/// assert_eq!(f32::round(f), 3.0);
-/// assert_eq!(f32::round(g), -3.0);
-/// assert_eq!(f32::round(h), -4.0);
-/// assert_eq!(f32::round(i), 4.0);
-/// assert_eq!(f32::round(j), 5.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::round`]: ../../std/primitive.f32.html#method.round
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn round(x: f32) -> f32 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::roundf32(x) }
-}
+    /// Experimental version of `ceil` in `core`. See [`f32::ceil`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let f = 3.01_f32;
+    /// let g = 4.0_f32;
+    ///
+    /// assert_eq!(f32::math::ceil(f), 4.0);
+    /// assert_eq!(f32::math::ceil(g), 4.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::ceil`]: ../../../std/primitive.f32.html#method.ceil
+    #[inline]
+    #[doc(alias = "ceiling")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    pub fn ceil(x: f32) -> f32 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::ceilf32(x) }
+    }
 
-/// Experimental version of `round_ties_even` in `core`. See [`f32::round_ties_even`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let f = 3.3_f32;
-/// let g = -3.3_f32;
-/// let h = 3.5_f32;
-/// let i = 4.5_f32;
-///
-/// assert_eq!(f32::round_ties_even(f), 3.0);
-/// assert_eq!(f32::round_ties_even(g), -3.0);
-/// assert_eq!(f32::round_ties_even(h), 4.0);
-/// assert_eq!(f32::round_ties_even(i), 4.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::round_ties_even`]: ../../std/primitive.f32.html#method.round_ties_even
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn round_ties_even(x: f32) -> f32 {
-    intrinsics::round_ties_even_f32(x)
-}
+    /// Experimental version of `round` in `core`. See [`f32::round`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let f = 3.3_f32;
+    /// let g = -3.3_f32;
+    /// let h = -3.7_f32;
+    /// let i = 3.5_f32;
+    /// let j = 4.5_f32;
+    ///
+    /// assert_eq!(f32::math::round(f), 3.0);
+    /// assert_eq!(f32::math::round(g), -3.0);
+    /// assert_eq!(f32::math::round(h), -4.0);
+    /// assert_eq!(f32::math::round(i), 4.0);
+    /// assert_eq!(f32::math::round(j), 5.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::round`]: ../../../std/primitive.f32.html#method.round
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn round(x: f32) -> f32 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::roundf32(x) }
+    }
 
-/// Experimental version of `trunc` in `core`. See [`f32::trunc`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let f = 3.7_f32;
-/// let g = 3.0_f32;
-/// let h = -3.7_f32;
-///
-/// assert_eq!(f32::trunc(f), 3.0);
-/// assert_eq!(f32::trunc(g), 3.0);
-/// assert_eq!(f32::trunc(h), -3.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::trunc`]: ../../std/primitive.f32.html#method.trunc
-#[inline]
-#[doc(alias = "truncate")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-#[unstable(feature = "core_float_math", issue = "137578")]
-pub fn trunc(x: f32) -> f32 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::truncf32(x) }
-}
+    /// Experimental version of `round_ties_even` in `core`. See [`f32::round_ties_even`] for
+    /// details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let f = 3.3_f32;
+    /// let g = -3.3_f32;
+    /// let h = 3.5_f32;
+    /// let i = 4.5_f32;
+    ///
+    /// assert_eq!(f32::math::round_ties_even(f), 3.0);
+    /// assert_eq!(f32::math::round_ties_even(g), -3.0);
+    /// assert_eq!(f32::math::round_ties_even(h), 4.0);
+    /// assert_eq!(f32::math::round_ties_even(i), 4.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::round_ties_even`]: ../../../std/primitive.f32.html#method.round_ties_even
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn round_ties_even(x: f32) -> f32 {
+        intrinsics::round_ties_even_f32(x)
+    }
 
-/// Experimental version of `fract` in `core`. See [`f32::fract`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let x = 3.6_f32;
-/// let y = -3.6_f32;
-/// let abs_difference_x = (f32::fract(x) - 0.6).abs();
-/// let abs_difference_y = (f32::fract(y) - (-0.6)).abs();
-///
-/// assert!(abs_difference_x <= f32::EPSILON);
-/// assert!(abs_difference_y <= f32::EPSILON);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::fract`]: ../../std/primitive.f32.html#method.fract
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn fract(x: f32) -> f32 {
-    x - trunc(x)
-}
+    /// Experimental version of `trunc` in `core`. See [`f32::trunc`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let f = 3.7_f32;
+    /// let g = 3.0_f32;
+    /// let h = -3.7_f32;
+    ///
+    /// assert_eq!(f32::math::trunc(f), 3.0);
+    /// assert_eq!(f32::math::trunc(g), 3.0);
+    /// assert_eq!(f32::math::trunc(h), -3.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::trunc`]: ../../../std/primitive.f32.html#method.trunc
+    #[inline]
+    #[doc(alias = "truncate")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    pub fn trunc(x: f32) -> f32 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::truncf32(x) }
+    }
 
-/// Experimental version of `mul_add` in `core`. See [`f32::mul_add`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// # // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
-/// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
-/// use core::f32;
-///
-/// let m = 10.0_f32;
-/// let x = 4.0_f32;
-/// let b = 60.0_f32;
-///
-/// assert_eq!(f32::mul_add(m, x, b), 100.0);
-/// assert_eq!(m * x + b, 100.0);
-///
-/// let one_plus_eps = 1.0_f32 + f32::EPSILON;
-/// let one_minus_eps = 1.0_f32 - f32::EPSILON;
-/// let minus_one = -1.0_f32;
-///
-/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
-/// assert_eq!(f32::mul_add(one_plus_eps, one_minus_eps, minus_one), -f32::EPSILON * f32::EPSILON);
-/// // Different rounding with the non-fused multiply and add.
-/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
-/// # }
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::mul_add`]: ../../std/primitive.f32.html#method.mul_add
-#[inline]
-#[doc(alias = "fmaf", alias = "fusedMultiplyAdd")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-#[unstable(feature = "core_float_math", issue = "137578")]
-pub fn mul_add(x: f32, y: f32, z: f32) -> f32 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::fmaf32(x, y, z) }
-}
+    /// Experimental version of `fract` in `core`. See [`f32::fract`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let x = 3.6_f32;
+    /// let y = -3.6_f32;
+    /// let abs_difference_x = (f32::math::fract(x) - 0.6).abs();
+    /// let abs_difference_y = (f32::math::fract(y) - (-0.6)).abs();
+    ///
+    /// assert!(abs_difference_x <= f32::EPSILON);
+    /// assert!(abs_difference_y <= f32::EPSILON);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::fract`]: ../../../std/primitive.f32.html#method.fract
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn fract(x: f32) -> f32 {
+        x - trunc(x)
+    }
 
-/// Experimental version of `div_euclid` in `core`. See [`f32::div_euclid`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let a: f32 = 7.0;
-/// let b = 4.0;
-/// assert_eq!(f32::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
-/// assert_eq!(f32::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
-/// assert_eq!(f32::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
-/// assert_eq!(f32::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::div_euclid`]: ../../std/primitive.f32.html#method.div_euclid
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn div_euclid(x: f32, rhs: f32) -> f32 {
-    let q = trunc(x / rhs);
-    if x % rhs < 0.0 {
-        return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+    /// Experimental version of `mul_add` in `core`. See [`f32::mul_add`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// # // FIXME(#140515): mingw has an incorrect fma
+    /// # // https://sourceforge.net/p/mingw-w64/bugs/848/
+    /// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
+    /// use core::f32;
+    ///
+    /// let m = 10.0_f32;
+    /// let x = 4.0_f32;
+    /// let b = 60.0_f32;
+    ///
+    /// assert_eq!(f32::math::mul_add(m, x, b), 100.0);
+    /// assert_eq!(m * x + b, 100.0);
+    ///
+    /// let one_plus_eps = 1.0_f32 + f32::EPSILON;
+    /// let one_minus_eps = 1.0_f32 - f32::EPSILON;
+    /// let minus_one = -1.0_f32;
+    ///
+    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+    /// assert_eq!(
+    ///     f32::math::mul_add(one_plus_eps, one_minus_eps, minus_one),
+    ///     -f32::EPSILON * f32::EPSILON
+    /// );
+    /// // Different rounding with the non-fused multiply and add.
+    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
+    /// # }
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::mul_add`]: ../../../std/primitive.f32.html#method.mul_add
+    #[inline]
+    #[doc(alias = "fmaf", alias = "fusedMultiplyAdd")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    pub fn mul_add(x: f32, y: f32, z: f32) -> f32 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::fmaf32(x, y, z) }
     }
-    q
-}
 
-/// Experimental version of `rem_euclid` in `core`. See [`f32::rem_euclid`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let a: f32 = 7.0;
-/// let b = 4.0;
-/// assert_eq!(f32::rem_euclid(a, b), 3.0);
-/// assert_eq!(f32::rem_euclid(-a, b), 1.0);
-/// assert_eq!(f32::rem_euclid(a, -b), 3.0);
-/// assert_eq!(f32::rem_euclid(-a, -b), 1.0);
-/// // limitation due to round-off error
-/// assert!(f32::rem_euclid(-f32::EPSILON, 3.0) != 0.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::rem_euclid`]: ../../std/primitive.f32.html#method.rem_euclid
-#[inline]
-#[doc(alias = "modulo", alias = "mod")]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn rem_euclid(x: f32, rhs: f32) -> f32 {
-    let r = x % rhs;
-    if r < 0.0 { r + rhs.abs() } else { r }
-}
+    /// Experimental version of `div_euclid` in `core`. See [`f32::div_euclid`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let a: f32 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(f32::math::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
+    /// assert_eq!(f32::math::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
+    /// assert_eq!(f32::math::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
+    /// assert_eq!(f32::math::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::div_euclid`]: ../../../std/primitive.f32.html#method.div_euclid
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn div_euclid(x: f32, rhs: f32) -> f32 {
+        let q = trunc(x / rhs);
+        if x % rhs < 0.0 {
+            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+        }
+        q
+    }
 
-/// Experimental version of `powi` in `core`. See [`f32::powi`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let x = 2.0_f32;
-/// let abs_difference = (f32::powi(x, 2) - (x * x)).abs();
-/// assert!(abs_difference <= f32::EPSILON);
-///
-/// assert_eq!(f32::powi(f32::NAN, 0), 1.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::powi`]: ../../std/primitive.f32.html#method.powi
-#[inline]
-#[must_use = "method returns a new number and does not mutate the original value"]
-#[unstable(feature = "core_float_math", issue = "137578")]
-pub fn powi(x: f32, n: i32) -> f32 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::powif32(x, n) }
-}
+    /// Experimental version of `rem_euclid` in `core`. See [`f32::rem_euclid`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let a: f32 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(f32::math::rem_euclid(a, b), 3.0);
+    /// assert_eq!(f32::math::rem_euclid(-a, b), 1.0);
+    /// assert_eq!(f32::math::rem_euclid(a, -b), 3.0);
+    /// assert_eq!(f32::math::rem_euclid(-a, -b), 1.0);
+    /// // limitation due to round-off error
+    /// assert!(f32::math::rem_euclid(-f32::EPSILON, 3.0) != 0.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::rem_euclid`]: ../../../std/primitive.f32.html#method.rem_euclid
+    #[inline]
+    #[doc(alias = "modulo", alias = "mod")]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn rem_euclid(x: f32, rhs: f32) -> f32 {
+        let r = x % rhs;
+        if r < 0.0 { r + rhs.abs() } else { r }
+    }
 
-/// Experimental version of `sqrt` in `core`. See [`f32::sqrt`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let positive = 4.0_f32;
-/// let negative = -4.0_f32;
-/// let negative_zero = -0.0_f32;
-///
-/// assert_eq!(f32::sqrt(positive), 2.0);
-/// assert!(f32::sqrt(negative).is_nan());
-/// assert_eq!(f32::sqrt(negative_zero), negative_zero);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::sqrt`]: ../../std/primitive.f32.html#method.sqrt
-#[inline]
-#[doc(alias = "squareRoot")]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn sqrt(x: f32) -> f32 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::sqrtf32(x) }
-}
+    /// Experimental version of `powi` in `core`. See [`f32::powi`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let x = 2.0_f32;
+    /// let abs_difference = (f32::math::powi(x, 2) - (x * x)).abs();
+    /// assert!(abs_difference <= f32::EPSILON);
+    ///
+    /// assert_eq!(f32::math::powi(f32::NAN, 0), 1.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::powi`]: ../../../std/primitive.f32.html#method.powi
+    #[inline]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    pub fn powi(x: f32, n: i32) -> f32 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::powif32(x, n) }
+    }
 
-/// Experimental version of `abs_sub` in `core`. See [`f32::abs_sub`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let x = 3.0f32;
-/// let y = -3.0f32;
-///
-/// let abs_difference_x = (f32::abs_sub(x, 1.0) - 2.0).abs();
-/// let abs_difference_y = (f32::abs_sub(y, 1.0) - 0.0).abs();
-///
-/// assert!(abs_difference_x <= f32::EPSILON);
-/// assert!(abs_difference_y <= f32::EPSILON);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::abs_sub`]: ../../std/primitive.f32.html#method.abs_sub
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(
-    since = "1.10.0",
-    note = "you probably meant `(self - other).abs()`: \
+    /// Experimental version of `sqrt` in `core`. See [`f32::sqrt`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let positive = 4.0_f32;
+    /// let negative = -4.0_f32;
+    /// let negative_zero = -0.0_f32;
+    ///
+    /// assert_eq!(f32::math::sqrt(positive), 2.0);
+    /// assert!(f32::math::sqrt(negative).is_nan());
+    /// assert_eq!(f32::math::sqrt(negative_zero), negative_zero);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::sqrt`]: ../../../std/primitive.f32.html#method.sqrt
+    #[inline]
+    #[doc(alias = "squareRoot")]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn sqrt(x: f32) -> f32 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::sqrtf32(x) }
+    }
+
+    /// Experimental version of `abs_sub` in `core`. See [`f32::abs_sub`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let x = 3.0f32;
+    /// let y = -3.0f32;
+    ///
+    /// let abs_difference_x = (f32::math::abs_sub(x, 1.0) - 2.0).abs();
+    /// let abs_difference_y = (f32::math::abs_sub(y, 1.0) - 0.0).abs();
+    ///
+    /// assert!(abs_difference_x <= f32::EPSILON);
+    /// assert!(abs_difference_y <= f32::EPSILON);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::abs_sub`]: ../../../std/primitive.f32.html#method.abs_sub
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[deprecated(
+        since = "1.10.0",
+        note = "you probably meant `(self - other).abs()`: \
             this operation is `(self - other).max(0.0)` \
             except that `abs_sub` also propagates NaNs (also \
             known as `fdimf` in C). If you truly need the positive \
             difference, consider using that expression or the C function \
             `fdimf`, depending on how you wish to handle NaN (please consider \
             filing an issue describing your use-case too)."
-)]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn abs_sub(x: f32, other: f32) -> f32 {
-    libm::fdimf(x, other)
-}
+    )]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn abs_sub(x: f32, other: f32) -> f32 {
+        libm::fdimf(x, other)
+    }
 
-/// Experimental version of `cbrt` in `core`. See [`f32::cbrt`] for details.
-///
-/// # Unspecified precision
-///
-/// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
-/// can even differ within the same execution from one invocation to the next.
-/// This function currently corresponds to the `cbrtf` from libc on Unix
-/// and Windows. Note that this might change in the future.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f32;
-///
-/// let x = 8.0f32;
-///
-/// // x^(1/3) - 2 == 0
-/// let abs_difference = (f32::cbrt(x) - 2.0).abs();
-///
-/// assert!(abs_difference <= f32::EPSILON);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f32::cbrt`]: ../../std/primitive.f32.html#method.cbrt
-#[inline]
-#[must_use = "method returns a new number and does not mutate the original value"]
-#[unstable(feature = "core_float_math", issue = "137578")]
-pub fn cbrt(x: f32) -> f32 {
-    libm::cbrtf(x)
+    /// Experimental version of `cbrt` in `core`. See [`f32::cbrt`] for details.
+    ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and
+    /// can even differ within the same execution from one invocation to the next.
+    /// This function currently corresponds to the `cbrtf` from libc on Unix
+    /// and Windows. Note that this might change in the future.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f32;
+    ///
+    /// let x = 8.0f32;
+    ///
+    /// // x^(1/3) - 2 == 0
+    /// let abs_difference = (f32::math::cbrt(x) - 2.0).abs();
+    ///
+    /// assert!(abs_difference <= f32::EPSILON);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f32::cbrt`]: ../../../std/primitive.f32.html#method.cbrt
+    #[inline]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    pub fn cbrt(x: f32) -> f32 {
+        libm::cbrtf(x)
+    }
 }
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 76c4e5d1a6f..8fbf2cffbaf 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -12,7 +12,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::convert::FloatToInt;
-use crate::num::{FpCategory, libm};
+use crate::num::FpCategory;
 use crate::panic::const_assert;
 use crate::{intrinsics, mem};
 
@@ -1556,406 +1556,434 @@ impl f64 {
     }
 }
 
-/// Experimental version of `floor` in `core`. See [`f64::floor`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let f = 3.7_f64;
-/// let g = 3.0_f64;
-/// let h = -3.7_f64;
-///
-/// assert_eq!(f64::floor(f), 3.0);
-/// assert_eq!(f64::floor(g), 3.0);
-/// assert_eq!(f64::floor(h), -4.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::floor`]: ../../std/primitive.f64.html#method.floor
-#[inline]
 #[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn floor(x: f64) -> f64 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::floorf64(x) }
-}
-
-/// Experimental version of `ceil` in `core`. See [`f64::ceil`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let f = 3.01_f64;
-/// let g = 4.0_f64;
-///
-/// assert_eq!(f64::ceil(f), 4.0);
-/// assert_eq!(f64::ceil(g), 4.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
+/// Experimental implementations of floating point functions in `core`.
 ///
-/// [`f64::ceil`]: ../../std/primitive.f64.html#method.ceil
-#[inline]
-#[doc(alias = "ceiling")]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn ceil(x: f64) -> f64 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::ceilf64(x) }
-}
+/// _The standalone functions in this module are for testing only.
+/// They will be stabilized as inherent methods._
+pub mod math {
+    use crate::intrinsics;
+    use crate::num::libm;
 
-/// Experimental version of `round` in `core`. See [`f64::round`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let f = 3.3_f64;
-/// let g = -3.3_f64;
-/// let h = -3.7_f64;
-/// let i = 3.5_f64;
-/// let j = 4.5_f64;
-///
-/// assert_eq!(f64::round(f), 3.0);
-/// assert_eq!(f64::round(g), -3.0);
-/// assert_eq!(f64::round(h), -4.0);
-/// assert_eq!(f64::round(i), 4.0);
-/// assert_eq!(f64::round(j), 5.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::round`]: ../../std/primitive.f64.html#method.round
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn round(x: f64) -> f64 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::roundf64(x) }
-}
+    /// Experimental version of `floor` in `core`. See [`f64::floor`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let f = 3.7_f64;
+    /// let g = 3.0_f64;
+    /// let h = -3.7_f64;
+    ///
+    /// assert_eq!(f64::math::floor(f), 3.0);
+    /// assert_eq!(f64::math::floor(g), 3.0);
+    /// assert_eq!(f64::math::floor(h), -4.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::floor`]: ../../../std/primitive.f64.html#method.floor
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn floor(x: f64) -> f64 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::floorf64(x) }
+    }
 
-/// Experimental version of `round_ties_even` in `core`. See [`f64::round_ties_even`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let f = 3.3_f64;
-/// let g = -3.3_f64;
-/// let h = 3.5_f64;
-/// let i = 4.5_f64;
-///
-/// assert_eq!(f64::round_ties_even(f), 3.0);
-/// assert_eq!(f64::round_ties_even(g), -3.0);
-/// assert_eq!(f64::round_ties_even(h), 4.0);
-/// assert_eq!(f64::round_ties_even(i), 4.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::round_ties_even`]: ../../std/primitive.f64.html#method.round_ties_even
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn round_ties_even(x: f64) -> f64 {
-    intrinsics::round_ties_even_f64(x)
-}
+    /// Experimental version of `ceil` in `core`. See [`f64::ceil`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let f = 3.01_f64;
+    /// let g = 4.0_f64;
+    ///
+    /// assert_eq!(f64::math::ceil(f), 4.0);
+    /// assert_eq!(f64::math::ceil(g), 4.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::ceil`]: ../../../std/primitive.f64.html#method.ceil
+    #[inline]
+    #[doc(alias = "ceiling")]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn ceil(x: f64) -> f64 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::ceilf64(x) }
+    }
 
-/// Experimental version of `trunc` in `core`. See [`f64::trunc`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let f = 3.7_f64;
-/// let g = 3.0_f64;
-/// let h = -3.7_f64;
-///
-/// assert_eq!(f64::trunc(f), 3.0);
-/// assert_eq!(f64::trunc(g), 3.0);
-/// assert_eq!(f64::trunc(h), -3.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::trunc`]: ../../std/primitive.f64.html#method.trunc
-#[inline]
-#[doc(alias = "truncate")]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn trunc(x: f64) -> f64 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::truncf64(x) }
-}
+    /// Experimental version of `round` in `core`. See [`f64::round`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let f = 3.3_f64;
+    /// let g = -3.3_f64;
+    /// let h = -3.7_f64;
+    /// let i = 3.5_f64;
+    /// let j = 4.5_f64;
+    ///
+    /// assert_eq!(f64::math::round(f), 3.0);
+    /// assert_eq!(f64::math::round(g), -3.0);
+    /// assert_eq!(f64::math::round(h), -4.0);
+    /// assert_eq!(f64::math::round(i), 4.0);
+    /// assert_eq!(f64::math::round(j), 5.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::round`]: ../../../std/primitive.f64.html#method.round
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn round(x: f64) -> f64 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::roundf64(x) }
+    }
 
-/// Experimental version of `fract` in `core`. See [`f64::fract`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let x = 3.6_f64;
-/// let y = -3.6_f64;
-/// let abs_difference_x = (f64::fract(x) - 0.6).abs();
-/// let abs_difference_y = (f64::fract(y) - (-0.6)).abs();
-///
-/// assert!(abs_difference_x < 1e-10);
-/// assert!(abs_difference_y < 1e-10);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::fract`]: ../../std/primitive.f64.html#method.fract
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn fract(x: f64) -> f64 {
-    x - trunc(x)
-}
+    /// Experimental version of `round_ties_even` in `core`. See [`f64::round_ties_even`] for
+    /// details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let f = 3.3_f64;
+    /// let g = -3.3_f64;
+    /// let h = 3.5_f64;
+    /// let i = 4.5_f64;
+    ///
+    /// assert_eq!(f64::math::round_ties_even(f), 3.0);
+    /// assert_eq!(f64::math::round_ties_even(g), -3.0);
+    /// assert_eq!(f64::math::round_ties_even(h), 4.0);
+    /// assert_eq!(f64::math::round_ties_even(i), 4.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::round_ties_even`]: ../../../std/primitive.f64.html#method.round_ties_even
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn round_ties_even(x: f64) -> f64 {
+        intrinsics::round_ties_even_f64(x)
+    }
 
-/// Experimental version of `mul_add` in `core`. See [`f64::mul_add`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// # // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
-/// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
-/// use core::f64;
-///
-/// let m = 10.0_f64;
-/// let x = 4.0_f64;
-/// let b = 60.0_f64;
-///
-/// assert_eq!(f64::mul_add(m, x, b), 100.0);
-/// assert_eq!(m * x + b, 100.0);
-///
-/// let one_plus_eps = 1.0_f64 + f64::EPSILON;
-/// let one_minus_eps = 1.0_f64 - f64::EPSILON;
-/// let minus_one = -1.0_f64;
-///
-/// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
-/// assert_eq!(f64::mul_add(one_plus_eps, one_minus_eps, minus_one), -f64::EPSILON * f64::EPSILON);
-/// // Different rounding with the non-fused multiply and add.
-/// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
-/// # }
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::mul_add`]: ../../std/primitive.f64.html#method.mul_add
-#[inline]
-#[doc(alias = "fma", alias = "fusedMultiplyAdd")]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn mul_add(x: f64, a: f64, b: f64) -> f64 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::fmaf64(x, a, b) }
-}
+    /// Experimental version of `trunc` in `core`. See [`f64::trunc`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let f = 3.7_f64;
+    /// let g = 3.0_f64;
+    /// let h = -3.7_f64;
+    ///
+    /// assert_eq!(f64::math::trunc(f), 3.0);
+    /// assert_eq!(f64::math::trunc(g), 3.0);
+    /// assert_eq!(f64::math::trunc(h), -3.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::trunc`]: ../../../std/primitive.f64.html#method.trunc
+    #[inline]
+    #[doc(alias = "truncate")]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn trunc(x: f64) -> f64 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::truncf64(x) }
+    }
 
-/// Experimental version of `div_euclid` in `core`. See [`f64::div_euclid`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let a: f64 = 7.0;
-/// let b = 4.0;
-/// assert_eq!(f64::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
-/// assert_eq!(f64::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
-/// assert_eq!(f64::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
-/// assert_eq!(f64::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::div_euclid`]: ../../std/primitive.f64.html#method.div_euclid
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn div_euclid(x: f64, rhs: f64) -> f64 {
-    let q = trunc(x / rhs);
-    if x % rhs < 0.0 {
-        return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+    /// Experimental version of `fract` in `core`. See [`f64::fract`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let x = 3.6_f64;
+    /// let y = -3.6_f64;
+    /// let abs_difference_x = (f64::math::fract(x) - 0.6).abs();
+    /// let abs_difference_y = (f64::math::fract(y) - (-0.6)).abs();
+    ///
+    /// assert!(abs_difference_x < 1e-10);
+    /// assert!(abs_difference_y < 1e-10);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::fract`]: ../../../std/primitive.f64.html#method.fract
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn fract(x: f64) -> f64 {
+        x - trunc(x)
     }
-    q
-}
 
-/// Experimental version of `rem_euclid` in `core`. See [`f64::rem_euclid`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let a: f64 = 7.0;
-/// let b = 4.0;
-/// assert_eq!(f64::rem_euclid(a, b), 3.0);
-/// assert_eq!(f64::rem_euclid(-a, b), 1.0);
-/// assert_eq!(f64::rem_euclid(a, -b), 3.0);
-/// assert_eq!(f64::rem_euclid(-a, -b), 1.0);
-/// // limitation due to round-off error
-/// assert!(f64::rem_euclid(-f64::EPSILON, 3.0) != 0.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::rem_euclid`]: ../../std/primitive.f64.html#method.rem_euclid
-#[inline]
-#[doc(alias = "modulo", alias = "mod")]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn rem_euclid(x: f64, rhs: f64) -> f64 {
-    let r = x % rhs;
-    if r < 0.0 { r + rhs.abs() } else { r }
-}
+    /// Experimental version of `mul_add` in `core`. See [`f64::mul_add`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// # // FIXME(#140515): mingw has an incorrect fma
+    /// # // https://sourceforge.net/p/mingw-w64/bugs/848/
+    /// # #[cfg(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")))] {
+    /// use core::f64;
+    ///
+    /// let m = 10.0_f64;
+    /// let x = 4.0_f64;
+    /// let b = 60.0_f64;
+    ///
+    /// assert_eq!(f64::math::mul_add(m, x, b), 100.0);
+    /// assert_eq!(m * x + b, 100.0);
+    ///
+    /// let one_plus_eps = 1.0_f64 + f64::EPSILON;
+    /// let one_minus_eps = 1.0_f64 - f64::EPSILON;
+    /// let minus_one = -1.0_f64;
+    ///
+    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+    /// assert_eq!(
+    ///     f64::math::mul_add(one_plus_eps, one_minus_eps, minus_one),
+    ///     -f64::EPSILON * f64::EPSILON
+    /// );
+    /// // Different rounding with the non-fused multiply and add.
+    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
+    /// # }
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::mul_add`]: ../../../std/primitive.f64.html#method.mul_add
+    #[inline]
+    #[doc(alias = "fma", alias = "fusedMultiplyAdd")]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn mul_add(x: f64, a: f64, b: f64) -> f64 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::fmaf64(x, a, b) }
+    }
 
-/// Experimental version of `powi` in `core`. See [`f64::powi`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let x = 2.0_f64;
-/// let abs_difference = (f64::powi(x, 2) - (x * x)).abs();
-/// assert!(abs_difference <= f64::EPSILON);
-///
-/// assert_eq!(f64::powi(f64::NAN, 0), 1.0);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::powi`]: ../../std/primitive.f64.html#method.powi
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn powi(x: f64, n: i32) -> f64 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::powif64(x, n) }
-}
+    /// Experimental version of `div_euclid` in `core`. See [`f64::div_euclid`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let a: f64 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(f64::math::div_euclid(a, b), 1.0); // 7.0 > 4.0 * 1.0
+    /// assert_eq!(f64::math::div_euclid(-a, b), -2.0); // -7.0 >= 4.0 * -2.0
+    /// assert_eq!(f64::math::div_euclid(a, -b), -1.0); // 7.0 >= -4.0 * -1.0
+    /// assert_eq!(f64::math::div_euclid(-a, -b), 2.0); // -7.0 >= -4.0 * 2.0
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::div_euclid`]: ../../../std/primitive.f64.html#method.div_euclid
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn div_euclid(x: f64, rhs: f64) -> f64 {
+        let q = trunc(x / rhs);
+        if x % rhs < 0.0 {
+            return if rhs > 0.0 { q - 1.0 } else { q + 1.0 };
+        }
+        q
+    }
 
-/// Experimental version of `sqrt` in `core`. See [`f64::sqrt`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let positive = 4.0_f64;
-/// let negative = -4.0_f64;
-/// let negative_zero = -0.0_f64;
-///
-/// assert_eq!(f64::sqrt(positive), 2.0);
-/// assert!(f64::sqrt(negative).is_nan());
-/// assert_eq!(f64::sqrt(negative_zero), negative_zero);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::sqrt`]: ../../std/primitive.f64.html#method.sqrt
-#[inline]
-#[doc(alias = "squareRoot")]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn sqrt(x: f64) -> f64 {
-    // SAFETY: intrinsic with no preconditions
-    unsafe { intrinsics::sqrtf64(x) }
-}
+    /// Experimental version of `rem_euclid` in `core`. See [`f64::rem_euclid`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let a: f64 = 7.0;
+    /// let b = 4.0;
+    /// assert_eq!(f64::math::rem_euclid(a, b), 3.0);
+    /// assert_eq!(f64::math::rem_euclid(-a, b), 1.0);
+    /// assert_eq!(f64::math::rem_euclid(a, -b), 3.0);
+    /// assert_eq!(f64::math::rem_euclid(-a, -b), 1.0);
+    /// // limitation due to round-off error
+    /// assert!(f64::math::rem_euclid(-f64::EPSILON, 3.0) != 0.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::rem_euclid`]: ../../../std/primitive.f64.html#method.rem_euclid
+    #[inline]
+    #[doc(alias = "modulo", alias = "mod")]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn rem_euclid(x: f64, rhs: f64) -> f64 {
+        let r = x % rhs;
+        if r < 0.0 { r + rhs.abs() } else { r }
+    }
 
-/// Experimental version of `abs_sub` in `core`. See [`f64::abs_sub`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let x = 3.0_f64;
-/// let y = -3.0_f64;
-///
-/// let abs_difference_x = (f64::abs_sub(x, 1.0) - 2.0).abs();
-/// let abs_difference_y = (f64::abs_sub(y, 1.0) - 0.0).abs();
-///
-/// assert!(abs_difference_x < 1e-10);
-/// assert!(abs_difference_y < 1e-10);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::abs_sub`]: ../../std/primitive.f64.html#method.abs_sub
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[deprecated(
-    since = "1.10.0",
-    note = "you probably meant `(self - other).abs()`: \
+    /// Experimental version of `powi` in `core`. See [`f64::powi`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let x = 2.0_f64;
+    /// let abs_difference = (f64::math::powi(x, 2) - (x * x)).abs();
+    /// assert!(abs_difference <= f64::EPSILON);
+    ///
+    /// assert_eq!(f64::math::powi(f64::NAN, 0), 1.0);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::powi`]: ../../../std/primitive.f64.html#method.powi
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn powi(x: f64, n: i32) -> f64 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::powif64(x, n) }
+    }
+
+    /// Experimental version of `sqrt` in `core`. See [`f64::sqrt`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let positive = 4.0_f64;
+    /// let negative = -4.0_f64;
+    /// let negative_zero = -0.0_f64;
+    ///
+    /// assert_eq!(f64::math::sqrt(positive), 2.0);
+    /// assert!(f64::math::sqrt(negative).is_nan());
+    /// assert_eq!(f64::math::sqrt(negative_zero), negative_zero);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::sqrt`]: ../../../std/primitive.f64.html#method.sqrt
+    #[inline]
+    #[doc(alias = "squareRoot")]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn sqrt(x: f64) -> f64 {
+        // SAFETY: intrinsic with no preconditions
+        unsafe { intrinsics::sqrtf64(x) }
+    }
+
+    /// Experimental version of `abs_sub` in `core`. See [`f64::abs_sub`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let x = 3.0_f64;
+    /// let y = -3.0_f64;
+    ///
+    /// let abs_difference_x = (f64::math::abs_sub(x, 1.0) - 2.0).abs();
+    /// let abs_difference_y = (f64::math::abs_sub(y, 1.0) - 0.0).abs();
+    ///
+    /// assert!(abs_difference_x < 1e-10);
+    /// assert!(abs_difference_y < 1e-10);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::abs_sub`]: ../../../std/primitive.f64.html#method.abs_sub
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[deprecated(
+        since = "1.10.0",
+        note = "you probably meant `(self - other).abs()`: \
                 this operation is `(self - other).max(0.0)` \
                 except that `abs_sub` also propagates NaNs (also \
                 known as `fdim` in C). If you truly need the positive \
                 difference, consider using that expression or the C function \
                 `fdim`, depending on how you wish to handle NaN (please consider \
                 filing an issue describing your use-case too)."
-)]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn abs_sub(x: f64, other: f64) -> f64 {
-    libm::fdim(x, other)
-}
+    )]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn abs_sub(x: f64, other: f64) -> f64 {
+        libm::fdim(x, other)
+    }
 
-/// Experimental version of `cbrt` in `core`. See [`f64::cbrt`] for details.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core_float_math)]
-///
-/// use core::f64;
-///
-/// let x = 8.0_f64;
-///
-/// // x^(1/3) - 2 == 0
-/// let abs_difference = (f64::cbrt(x) - 2.0).abs();
-///
-/// assert!(abs_difference < 1e-10);
-/// ```
-///
-/// _This standalone function is for testing only. It will be stabilized as an inherent method._
-///
-/// [`f64::cbrt`]: ../../std/primitive.f64.html#method.cbrt
-#[inline]
-#[unstable(feature = "core_float_math", issue = "137578")]
-#[must_use = "method returns a new number and does not mutate the original value"]
-pub fn cbrt(x: f64) -> f64 {
-    libm::cbrt(x)
+    /// Experimental version of `cbrt` in `core`. See [`f64::cbrt`] for details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(core_float_math)]
+    ///
+    /// use core::f64;
+    ///
+    /// let x = 8.0_f64;
+    ///
+    /// // x^(1/3) - 2 == 0
+    /// let abs_difference = (f64::math::cbrt(x) - 2.0).abs();
+    ///
+    /// assert!(abs_difference < 1e-10);
+    /// ```
+    ///
+    /// _This standalone function is for testing only.
+    /// It will be stabilized as an inherent method._
+    ///
+    /// [`f64::cbrt`]: ../../../std/primitive.f64.html#method.cbrt
+    #[inline]
+    #[unstable(feature = "core_float_math", issue = "137578")]
+    #[must_use = "method returns a new number and does not mutate the original value"]
+    pub fn cbrt(x: f64) -> f64 {
+        libm::cbrt(x)
+    }
 }
diff --git a/library/core/src/num/flt2dec/decoder.rs b/library/core/src/num/flt2dec/decoder.rs
index 40b3aae24a5..bd6e2cdbafe 100644
--- a/library/core/src/num/flt2dec/decoder.rs
+++ b/library/core/src/num/flt2dec/decoder.rs
@@ -45,6 +45,13 @@ pub trait DecodableFloat: RawFloat + Copy {
     fn min_pos_norm_value() -> Self;
 }
 
+#[cfg(target_has_reliable_f16)]
+impl DecodableFloat for f16 {
+    fn min_pos_norm_value() -> Self {
+        f16::MIN_POSITIVE
+    }
+}
+
 impl DecodableFloat for f32 {
     fn min_pos_norm_value() -> Self {
         f32::MIN_POSITIVE
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 257424b355f..aad073cc8cd 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1419,7 +1419,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
     #[stable(feature = "pin_deref_mut", since = "1.84.0")]
     #[must_use = "`self` will be dropped if the result is not used"]
     #[inline(always)]
-    pub fn as_deref_mut(self: Pin<&mut Pin<Ptr>>) -> Pin<&mut Ptr::Target> {
+    pub fn as_deref_mut(self: Pin<&mut Self>) -> Pin<&mut Ptr::Target> {
         // SAFETY: What we're asserting here is that going from
         //
         //     Pin<&mut Pin<Ptr>>
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index bd6c4daa509..35a909f6904 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -405,16 +405,6 @@ mod alignment;
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
 pub use alignment::Alignment;
 
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(inline)]
-pub use crate::intrinsics::copy;
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(inline)]
-pub use crate::intrinsics::copy_nonoverlapping;
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(inline)]
-pub use crate::intrinsics::write_bytes;
-
 mod metadata;
 #[unstable(feature = "ptr_metadata", issue = "81513")]
 pub use metadata::{DynMetadata, Pointee, Thin, from_raw_parts, from_raw_parts_mut, metadata};
@@ -430,6 +420,289 @@ pub use unique::Unique;
 mod const_ptr;
 mod mut_ptr;
 
+// Some functions are defined here because they accidentally got made
+// available in this module on stable. See <https://github.com/rust-lang/rust/issues/15702>.
+// (`transmute` also falls into this category, but it cannot be wrapped due to the
+// check that `T` and `U` have the same size.)
+
+/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
+/// and destination must *not* overlap.
+///
+/// For regions of memory which might overlap, use [`copy`] instead.
+///
+/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but
+/// with the source and destination arguments swapped,
+/// and `count` counting the number of `T`s instead of bytes.
+///
+/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the
+/// requirements of `T`. The initialization state is preserved exactly.
+///
+/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
+///
+/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+///
+/// * Both `src` and `dst` must be properly aligned.
+///
+/// * The region of memory beginning at `src` with a size of `count *
+///   size_of::<T>()` bytes must *not* overlap with the region of memory
+///   beginning at `dst` with the same size.
+///
+/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values
+/// in the region beginning at `*src` and the region beginning at `*dst` can
+/// [violate memory safety][read-ownership].
+///
+/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+/// `0`, the pointers must be properly aligned.
+///
+/// [`read`]: crate::ptr::read
+/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
+/// [valid]: crate::ptr#safety
+///
+/// # Examples
+///
+/// Manually implement [`Vec::append`]:
+///
+/// ```
+/// use std::ptr;
+///
+/// /// Moves all the elements of `src` into `dst`, leaving `src` empty.
+/// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) {
+///     let src_len = src.len();
+///     let dst_len = dst.len();
+///
+///     // Ensure that `dst` has enough capacity to hold all of `src`.
+///     dst.reserve(src_len);
+///
+///     unsafe {
+///         // The call to add is always safe because `Vec` will never
+///         // allocate more than `isize::MAX` bytes.
+///         let dst_ptr = dst.as_mut_ptr().add(dst_len);
+///         let src_ptr = src.as_ptr();
+///
+///         // Truncate `src` without dropping its contents. We do this first,
+///         // to avoid problems in case something further down panics.
+///         src.set_len(0);
+///
+///         // The two regions cannot overlap because mutable references do
+///         // not alias, and two different vectors cannot own the same
+///         // memory.
+///         ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len);
+///
+///         // Notify `dst` that it now holds the contents of `src`.
+///         dst.set_len(dst_len + src_len);
+///     }
+/// }
+///
+/// let mut a = vec!['r'];
+/// let mut b = vec!['u', 's', 't'];
+///
+/// append(&mut a, &mut b);
+///
+/// assert_eq!(a, &['r', 'u', 's', 't']);
+/// assert!(b.is_empty());
+/// ```
+///
+/// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append
+#[doc(alias = "memcpy")]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
+#[inline(always)]
+#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
+pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
+    ub_checks::assert_unsafe_precondition!(
+        check_language_ub,
+        "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
+        and the specified memory ranges do not overlap",
+        (
+            src: *const () = src as *const (),
+            dst: *mut () = dst as *mut (),
+            size: usize = size_of::<T>(),
+            align: usize = align_of::<T>(),
+            count: usize = count,
+        ) => {
+            let zero_size = count == 0 || size == 0;
+            ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size)
+                && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size)
+                && ub_checks::maybe_is_nonoverlapping(src, dst, size, count)
+        }
+    );
+
+    // SAFETY: the safety contract for `copy_nonoverlapping` must be
+    // upheld by the caller.
+    unsafe { crate::intrinsics::copy_nonoverlapping(src, dst, count) }
+}
+
+/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
+/// and destination may overlap.
+///
+/// If the source and destination will *never* overlap,
+/// [`copy_nonoverlapping`] can be used instead.
+///
+/// `copy` is semantically equivalent to C's [`memmove`], but
+/// with the source and destination arguments swapped,
+/// and `count` counting the number of `T`s instead of bytes.
+/// Copying takes place as if the bytes were copied from `src`
+/// to a temporary array and then copied from the array to `dst`.
+///
+/// The copy is "untyped" in the sense that data may be uninitialized or otherwise violate the
+/// requirements of `T`. The initialization state is preserved exactly.
+///
+/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes.
+///
+/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes, and must remain valid even
+///   when `src` is read for `count * size_of::<T>()` bytes. (This means if the memory ranges
+///   overlap, the `dst` pointer must not be invalidated by `src` reads.)
+///
+/// * Both `src` and `dst` must be properly aligned.
+///
+/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of
+/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values
+/// in the region beginning at `*src` and the region beginning at `*dst` can
+/// [violate memory safety][read-ownership].
+///
+/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+/// `0`, the pointers must be properly aligned.
+///
+/// [`read`]: crate::ptr::read
+/// [read-ownership]: crate::ptr::read#ownership-of-the-returned-value
+/// [valid]: crate::ptr#safety
+///
+/// # Examples
+///
+/// Efficiently create a Rust vector from an unsafe buffer:
+///
+/// ```
+/// use std::ptr;
+///
+/// /// # Safety
+/// ///
+/// /// * `ptr` must be correctly aligned for its type and non-zero.
+/// /// * `ptr` must be valid for reads of `elts` contiguous elements of type `T`.
+/// /// * Those elements must not be used after calling this function unless `T: Copy`.
+/// # #[allow(dead_code)]
+/// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
+///     let mut dst = Vec::with_capacity(elts);
+///
+///     // SAFETY: Our precondition ensures the source is aligned and valid,
+///     // and `Vec::with_capacity` ensures that we have usable space to write them.
+///     unsafe { ptr::copy(ptr, dst.as_mut_ptr(), elts); }
+///
+///     // SAFETY: We created it with this much capacity earlier,
+///     // and the previous `copy` has initialized these elements.
+///     unsafe { dst.set_len(elts); }
+///     dst
+/// }
+/// ```
+#[doc(alias = "memmove")]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")]
+#[inline(always)]
+#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_copy"]
+pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
+    // SAFETY: the safety contract for `copy` must be upheld by the caller.
+    unsafe {
+        ub_checks::assert_unsafe_precondition!(
+            check_language_ub,
+            "ptr::copy requires that both pointer arguments are aligned and non-null",
+            (
+                src: *const () = src as *const (),
+                dst: *mut () = dst as *mut (),
+                align: usize = align_of::<T>(),
+                zero_size: bool = T::IS_ZST || count == 0,
+            ) =>
+            ub_checks::maybe_is_aligned_and_not_null(src, align, zero_size)
+                && ub_checks::maybe_is_aligned_and_not_null(dst, align, zero_size)
+        );
+        crate::intrinsics::copy(src, dst, count)
+    }
+}
+
+/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to
+/// `val`.
+///
+/// `write_bytes` is similar to C's [`memset`], but sets `count *
+/// size_of::<T>()` bytes to `val`.
+///
+/// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset
+///
+/// # Safety
+///
+/// Behavior is undefined if any of the following conditions are violated:
+///
+/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes.
+///
+/// * `dst` must be properly aligned.
+///
+/// Note that even if the effectively copied size (`count * size_of::<T>()`) is
+/// `0`, the pointer must be properly aligned.
+///
+/// Additionally, note that changing `*dst` in this way can easily lead to undefined behavior (UB)
+/// later if the written bytes are not a valid representation of some `T`. For instance, the
+/// following is an **incorrect** use of this function:
+///
+/// ```rust,no_run
+/// unsafe {
+///     let mut value: u8 = 0;
+///     let ptr: *mut bool = &mut value as *mut u8 as *mut bool;
+///     let _bool = ptr.read(); // This is fine, `ptr` points to a valid `bool`.
+///     ptr.write_bytes(42u8, 1); // This function itself does not cause UB...
+///     let _bool = ptr.read(); // ...but it makes this operation UB! ⚠️
+/// }
+/// ```
+///
+/// [valid]: crate::ptr#safety
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::ptr;
+///
+/// let mut vec = vec![0u32; 4];
+/// unsafe {
+///     let vec_ptr = vec.as_mut_ptr();
+///     ptr::write_bytes(vec_ptr, 0xfe, 2);
+/// }
+/// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]);
+/// ```
+#[doc(alias = "memset")]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_ptr_write", since = "1.83.0")]
+#[inline(always)]
+#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
+#[rustc_diagnostic_item = "ptr_write_bytes"]
+pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
+    // SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
+    unsafe {
+        ub_checks::assert_unsafe_precondition!(
+            check_language_ub,
+            "ptr::write_bytes requires that the destination pointer is aligned and non-null",
+            (
+                addr: *const () = dst as *const (),
+                align: usize = align_of::<T>(),
+                zero_size: bool = T::IS_ZST || count == 0,
+            ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, zero_size)
+        );
+        crate::intrinsics::write_bytes(dst, val, count)
+    }
+}
+
 /// Executes the destructor (if any) of the pointed-to value.
 ///
 /// This is almost the same as calling [`ptr::read`] and discarding
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index d05fb6a6d31..8b31328de04 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -262,7 +262,8 @@ impl<T: ?Sized> NonNull<T> {
     }
 
     /// Converts a reference to a `NonNull` pointer.
-    #[unstable(feature = "non_null_from_ref", issue = "130823")]
+    #[stable(feature = "non_null_from_ref", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "non_null_from_ref", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn from_ref(r: &T) -> Self {
         // SAFETY: A reference cannot be null.
@@ -270,7 +271,8 @@ impl<T: ?Sized> NonNull<T> {
     }
 
     /// Converts a mutable reference to a `NonNull` pointer.
-    #[unstable(feature = "non_null_from_ref", issue = "130823")]
+    #[stable(feature = "non_null_from_ref", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "non_null_from_ref", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn from_mut(r: &mut T) -> Self {
         // SAFETY: A mutable reference cannot be null.
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 058491b53a1..c9b8231e856 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -4383,7 +4383,7 @@ impl<T> [T] {
     /// assert_eq!(first_three, &['a', 'b', 'c']);
     /// ```
     ///
-    /// Splitting off the last two elements of a slice:
+    /// Splitting off a slice starting with the third element:
     ///
     /// ```
     /// let mut slice: &[_] = &['a', 'b', 'c', 'd'];
@@ -4449,7 +4449,7 @@ impl<T> [T] {
     /// assert_eq!(first_three, &mut ['a', 'b', 'c']);
     /// ```
     ///
-    /// Taking the last two elements of a slice:
+    /// Splitting off a slice starting with the third element:
     ///
     /// ```
     /// let mut slice: &mut [_] = &mut ['a', 'b', 'c', 'd'];
diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs
index 9b551643bae..36f1937bedf 100644
--- a/library/coretests/tests/floats/f32.rs
+++ b/library/coretests/tests/floats/f32.rs
@@ -215,88 +215,88 @@ fn test_classify() {
 
 #[test]
 fn test_floor() {
-    assert_approx_eq!(f32::floor(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::floor(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::floor(1.5f32), 1.0f32);
-    assert_approx_eq!(f32::floor(1.7f32), 1.0f32);
-    assert_approx_eq!(f32::floor(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::floor(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::floor(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::floor(-1.3f32), -2.0f32);
-    assert_approx_eq!(f32::floor(-1.5f32), -2.0f32);
-    assert_approx_eq!(f32::floor(-1.7f32), -2.0f32);
+    assert_approx_eq!(f32::math::floor(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::math::floor(1.3f32), 1.0f32);
+    assert_approx_eq!(f32::math::floor(1.5f32), 1.0f32);
+    assert_approx_eq!(f32::math::floor(1.7f32), 1.0f32);
+    assert_approx_eq!(f32::math::floor(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::math::floor(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::math::floor(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::math::floor(-1.3f32), -2.0f32);
+    assert_approx_eq!(f32::math::floor(-1.5f32), -2.0f32);
+    assert_approx_eq!(f32::math::floor(-1.7f32), -2.0f32);
 }
 
 #[test]
 fn test_ceil() {
-    assert_approx_eq!(f32::ceil(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::ceil(1.3f32), 2.0f32);
-    assert_approx_eq!(f32::ceil(1.5f32), 2.0f32);
-    assert_approx_eq!(f32::ceil(1.7f32), 2.0f32);
-    assert_approx_eq!(f32::ceil(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::ceil(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::ceil(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::ceil(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::ceil(-1.5f32), -1.0f32);
-    assert_approx_eq!(f32::ceil(-1.7f32), -1.0f32);
+    assert_approx_eq!(f32::math::ceil(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::math::ceil(1.3f32), 2.0f32);
+    assert_approx_eq!(f32::math::ceil(1.5f32), 2.0f32);
+    assert_approx_eq!(f32::math::ceil(1.7f32), 2.0f32);
+    assert_approx_eq!(f32::math::ceil(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::math::ceil(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::math::ceil(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::math::ceil(-1.3f32), -1.0f32);
+    assert_approx_eq!(f32::math::ceil(-1.5f32), -1.0f32);
+    assert_approx_eq!(f32::math::ceil(-1.7f32), -1.0f32);
 }
 
 #[test]
 fn test_round() {
-    assert_approx_eq!(f32::round(2.5f32), 3.0f32);
-    assert_approx_eq!(f32::round(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::round(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::round(1.5f32), 2.0f32);
-    assert_approx_eq!(f32::round(1.7f32), 2.0f32);
-    assert_approx_eq!(f32::round(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::round(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::round(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::round(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::round(-1.5f32), -2.0f32);
-    assert_approx_eq!(f32::round(-1.7f32), -2.0f32);
+    assert_approx_eq!(f32::math::round(2.5f32), 3.0f32);
+    assert_approx_eq!(f32::math::round(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::math::round(1.3f32), 1.0f32);
+    assert_approx_eq!(f32::math::round(1.5f32), 2.0f32);
+    assert_approx_eq!(f32::math::round(1.7f32), 2.0f32);
+    assert_approx_eq!(f32::math::round(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::math::round(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::math::round(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::math::round(-1.3f32), -1.0f32);
+    assert_approx_eq!(f32::math::round(-1.5f32), -2.0f32);
+    assert_approx_eq!(f32::math::round(-1.7f32), -2.0f32);
 }
 
 #[test]
 fn test_round_ties_even() {
-    assert_approx_eq!(f32::round_ties_even(2.5f32), 2.0f32);
-    assert_approx_eq!(f32::round_ties_even(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::round_ties_even(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::round_ties_even(1.5f32), 2.0f32);
-    assert_approx_eq!(f32::round_ties_even(1.7f32), 2.0f32);
-    assert_approx_eq!(f32::round_ties_even(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::round_ties_even(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::round_ties_even(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::round_ties_even(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::round_ties_even(-1.5f32), -2.0f32);
-    assert_approx_eq!(f32::round_ties_even(-1.7f32), -2.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(2.5f32), 2.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(1.3f32), 1.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(1.5f32), 2.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(1.7f32), 2.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(-1.3f32), -1.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(-1.5f32), -2.0f32);
+    assert_approx_eq!(f32::math::round_ties_even(-1.7f32), -2.0f32);
 }
 
 #[test]
 fn test_trunc() {
-    assert_approx_eq!(f32::trunc(1.0f32), 1.0f32);
-    assert_approx_eq!(f32::trunc(1.3f32), 1.0f32);
-    assert_approx_eq!(f32::trunc(1.5f32), 1.0f32);
-    assert_approx_eq!(f32::trunc(1.7f32), 1.0f32);
-    assert_approx_eq!(f32::trunc(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::trunc(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::trunc(-1.0f32), -1.0f32);
-    assert_approx_eq!(f32::trunc(-1.3f32), -1.0f32);
-    assert_approx_eq!(f32::trunc(-1.5f32), -1.0f32);
-    assert_approx_eq!(f32::trunc(-1.7f32), -1.0f32);
+    assert_approx_eq!(f32::math::trunc(1.0f32), 1.0f32);
+    assert_approx_eq!(f32::math::trunc(1.3f32), 1.0f32);
+    assert_approx_eq!(f32::math::trunc(1.5f32), 1.0f32);
+    assert_approx_eq!(f32::math::trunc(1.7f32), 1.0f32);
+    assert_approx_eq!(f32::math::trunc(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::math::trunc(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::math::trunc(-1.0f32), -1.0f32);
+    assert_approx_eq!(f32::math::trunc(-1.3f32), -1.0f32);
+    assert_approx_eq!(f32::math::trunc(-1.5f32), -1.0f32);
+    assert_approx_eq!(f32::math::trunc(-1.7f32), -1.0f32);
 }
 
 #[test]
 fn test_fract() {
-    assert_approx_eq!(f32::fract(1.0f32), 0.0f32);
-    assert_approx_eq!(f32::fract(1.3f32), 0.3f32);
-    assert_approx_eq!(f32::fract(1.5f32), 0.5f32);
-    assert_approx_eq!(f32::fract(1.7f32), 0.7f32);
-    assert_approx_eq!(f32::fract(0.0f32), 0.0f32);
-    assert_approx_eq!(f32::fract(-0.0f32), -0.0f32);
-    assert_approx_eq!(f32::fract(-1.0f32), -0.0f32);
-    assert_approx_eq!(f32::fract(-1.3f32), -0.3f32);
-    assert_approx_eq!(f32::fract(-1.5f32), -0.5f32);
-    assert_approx_eq!(f32::fract(-1.7f32), -0.7f32);
+    assert_approx_eq!(f32::math::fract(1.0f32), 0.0f32);
+    assert_approx_eq!(f32::math::fract(1.3f32), 0.3f32);
+    assert_approx_eq!(f32::math::fract(1.5f32), 0.5f32);
+    assert_approx_eq!(f32::math::fract(1.7f32), 0.7f32);
+    assert_approx_eq!(f32::math::fract(0.0f32), 0.0f32);
+    assert_approx_eq!(f32::math::fract(-0.0f32), -0.0f32);
+    assert_approx_eq!(f32::math::fract(-1.0f32), -0.0f32);
+    assert_approx_eq!(f32::math::fract(-1.3f32), -0.3f32);
+    assert_approx_eq!(f32::math::fract(-1.5f32), -0.5f32);
+    assert_approx_eq!(f32::math::fract(-1.7f32), -0.7f32);
 }
 
 #[test]
@@ -417,15 +417,15 @@ fn test_mul_add() {
     let nan: f32 = f32::NAN;
     let inf: f32 = f32::INFINITY;
     let neg_inf: f32 = f32::NEG_INFINITY;
-    assert_approx_eq!(f32::mul_add(12.3f32, 4.5, 6.7), 62.05);
-    assert_approx_eq!(f32::mul_add(-12.3f32, -4.5, -6.7), 48.65);
-    assert_approx_eq!(f32::mul_add(0.0f32, 8.9, 1.2), 1.2);
-    assert_approx_eq!(f32::mul_add(3.4f32, -0.0, 5.6), 5.6);
-    assert!(f32::mul_add(nan, 7.8, 9.0).is_nan());
-    assert_eq!(f32::mul_add(inf, 7.8, 9.0), inf);
-    assert_eq!(f32::mul_add(neg_inf, 7.8, 9.0), neg_inf);
-    assert_eq!(f32::mul_add(8.9f32, inf, 3.2), inf);
-    assert_eq!(f32::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
+    assert_approx_eq!(f32::math::mul_add(12.3f32, 4.5, 6.7), 62.05);
+    assert_approx_eq!(f32::math::mul_add(-12.3f32, -4.5, -6.7), 48.65);
+    assert_approx_eq!(f32::math::mul_add(0.0f32, 8.9, 1.2), 1.2);
+    assert_approx_eq!(f32::math::mul_add(3.4f32, -0.0, 5.6), 5.6);
+    assert!(f32::math::mul_add(nan, 7.8, 9.0).is_nan());
+    assert_eq!(f32::math::mul_add(inf, 7.8, 9.0), inf);
+    assert_eq!(f32::math::mul_add(neg_inf, 7.8, 9.0), neg_inf);
+    assert_eq!(f32::math::mul_add(8.9f32, inf, 3.2), inf);
+    assert_eq!(f32::math::mul_add(-3.2f32, 2.4, neg_inf), neg_inf);
 }
 
 #[test]
diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs
index 988108371d7..97051998353 100644
--- a/library/coretests/tests/floats/f64.rs
+++ b/library/coretests/tests/floats/f64.rs
@@ -1,5 +1,6 @@
-use std::f64::consts;
-use std::num::FpCategory as Fp;
+use core::f64;
+use core::f64::consts;
+use core::num::FpCategory as Fp;
 
 /// Smallest number
 const TINY_BITS: u64 = 0x1;
@@ -201,88 +202,88 @@ fn test_classify() {
 
 #[test]
 fn test_floor() {
-    assert_approx_eq!(f64::floor(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::floor(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::floor(1.5f64), 1.0f64);
-    assert_approx_eq!(f64::floor(1.7f64), 1.0f64);
-    assert_approx_eq!(f64::floor(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::floor(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::floor(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::floor(-1.3f64), -2.0f64);
-    assert_approx_eq!(f64::floor(-1.5f64), -2.0f64);
-    assert_approx_eq!(f64::floor(-1.7f64), -2.0f64);
+    assert_approx_eq!(f64::math::floor(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::math::floor(1.3f64), 1.0f64);
+    assert_approx_eq!(f64::math::floor(1.5f64), 1.0f64);
+    assert_approx_eq!(f64::math::floor(1.7f64), 1.0f64);
+    assert_approx_eq!(f64::math::floor(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::math::floor(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::math::floor(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::math::floor(-1.3f64), -2.0f64);
+    assert_approx_eq!(f64::math::floor(-1.5f64), -2.0f64);
+    assert_approx_eq!(f64::math::floor(-1.7f64), -2.0f64);
 }
 
 #[test]
 fn test_ceil() {
-    assert_approx_eq!(f64::ceil(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::ceil(1.3f64), 2.0f64);
-    assert_approx_eq!(f64::ceil(1.5f64), 2.0f64);
-    assert_approx_eq!(f64::ceil(1.7f64), 2.0f64);
-    assert_approx_eq!(f64::ceil(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::ceil(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::ceil(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::ceil(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::ceil(-1.5f64), -1.0f64);
-    assert_approx_eq!(f64::ceil(-1.7f64), -1.0f64);
+    assert_approx_eq!(f64::math::ceil(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::math::ceil(1.3f64), 2.0f64);
+    assert_approx_eq!(f64::math::ceil(1.5f64), 2.0f64);
+    assert_approx_eq!(f64::math::ceil(1.7f64), 2.0f64);
+    assert_approx_eq!(f64::math::ceil(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::math::ceil(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::math::ceil(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::math::ceil(-1.3f64), -1.0f64);
+    assert_approx_eq!(f64::math::ceil(-1.5f64), -1.0f64);
+    assert_approx_eq!(f64::math::ceil(-1.7f64), -1.0f64);
 }
 
 #[test]
 fn test_round() {
-    assert_approx_eq!(f64::round(2.5f64), 3.0f64);
-    assert_approx_eq!(f64::round(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::round(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::round(1.5f64), 2.0f64);
-    assert_approx_eq!(f64::round(1.7f64), 2.0f64);
-    assert_approx_eq!(f64::round(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::round(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::round(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::round(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::round(-1.5f64), -2.0f64);
-    assert_approx_eq!(f64::round(-1.7f64), -2.0f64);
+    assert_approx_eq!(f64::math::round(2.5f64), 3.0f64);
+    assert_approx_eq!(f64::math::round(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::math::round(1.3f64), 1.0f64);
+    assert_approx_eq!(f64::math::round(1.5f64), 2.0f64);
+    assert_approx_eq!(f64::math::round(1.7f64), 2.0f64);
+    assert_approx_eq!(f64::math::round(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::math::round(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::math::round(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::math::round(-1.3f64), -1.0f64);
+    assert_approx_eq!(f64::math::round(-1.5f64), -2.0f64);
+    assert_approx_eq!(f64::math::round(-1.7f64), -2.0f64);
 }
 
 #[test]
 fn test_round_ties_even() {
-    assert_approx_eq!(f64::round_ties_even(2.5f64), 2.0f64);
-    assert_approx_eq!(f64::round_ties_even(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::round_ties_even(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::round_ties_even(1.5f64), 2.0f64);
-    assert_approx_eq!(f64::round_ties_even(1.7f64), 2.0f64);
-    assert_approx_eq!(f64::round_ties_even(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::round_ties_even(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::round_ties_even(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::round_ties_even(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::round_ties_even(-1.5f64), -2.0f64);
-    assert_approx_eq!(f64::round_ties_even(-1.7f64), -2.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(2.5f64), 2.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(1.3f64), 1.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(1.5f64), 2.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(1.7f64), 2.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(-1.3f64), -1.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(-1.5f64), -2.0f64);
+    assert_approx_eq!(f64::math::round_ties_even(-1.7f64), -2.0f64);
 }
 
 #[test]
 fn test_trunc() {
-    assert_approx_eq!(f64::trunc(1.0f64), 1.0f64);
-    assert_approx_eq!(f64::trunc(1.3f64), 1.0f64);
-    assert_approx_eq!(f64::trunc(1.5f64), 1.0f64);
-    assert_approx_eq!(f64::trunc(1.7f64), 1.0f64);
-    assert_approx_eq!(f64::trunc(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::trunc(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::trunc(-1.0f64), -1.0f64);
-    assert_approx_eq!(f64::trunc(-1.3f64), -1.0f64);
-    assert_approx_eq!(f64::trunc(-1.5f64), -1.0f64);
-    assert_approx_eq!(f64::trunc(-1.7f64), -1.0f64);
+    assert_approx_eq!(f64::math::trunc(1.0f64), 1.0f64);
+    assert_approx_eq!(f64::math::trunc(1.3f64), 1.0f64);
+    assert_approx_eq!(f64::math::trunc(1.5f64), 1.0f64);
+    assert_approx_eq!(f64::math::trunc(1.7f64), 1.0f64);
+    assert_approx_eq!(f64::math::trunc(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::math::trunc(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::math::trunc(-1.0f64), -1.0f64);
+    assert_approx_eq!(f64::math::trunc(-1.3f64), -1.0f64);
+    assert_approx_eq!(f64::math::trunc(-1.5f64), -1.0f64);
+    assert_approx_eq!(f64::math::trunc(-1.7f64), -1.0f64);
 }
 
 #[test]
 fn test_fract() {
-    assert_approx_eq!(f64::fract(1.0f64), 0.0f64);
-    assert_approx_eq!(f64::fract(1.3f64), 0.3f64);
-    assert_approx_eq!(f64::fract(1.5f64), 0.5f64);
-    assert_approx_eq!(f64::fract(1.7f64), 0.7f64);
-    assert_approx_eq!(f64::fract(0.0f64), 0.0f64);
-    assert_approx_eq!(f64::fract(-0.0f64), -0.0f64);
-    assert_approx_eq!(f64::fract(-1.0f64), -0.0f64);
-    assert_approx_eq!(f64::fract(-1.3f64), -0.3f64);
-    assert_approx_eq!(f64::fract(-1.5f64), -0.5f64);
-    assert_approx_eq!(f64::fract(-1.7f64), -0.7f64);
+    assert_approx_eq!(f64::math::fract(1.0f64), 0.0f64);
+    assert_approx_eq!(f64::math::fract(1.3f64), 0.3f64);
+    assert_approx_eq!(f64::math::fract(1.5f64), 0.5f64);
+    assert_approx_eq!(f64::math::fract(1.7f64), 0.7f64);
+    assert_approx_eq!(f64::math::fract(0.0f64), 0.0f64);
+    assert_approx_eq!(f64::math::fract(-0.0f64), -0.0f64);
+    assert_approx_eq!(f64::math::fract(-1.0f64), -0.0f64);
+    assert_approx_eq!(f64::math::fract(-1.3f64), -0.3f64);
+    assert_approx_eq!(f64::math::fract(-1.5f64), -0.5f64);
+    assert_approx_eq!(f64::math::fract(-1.7f64), -0.7f64);
 }
 
 #[test]
diff --git a/library/coretests/tests/num/dec2flt/decimal.rs b/library/coretests/tests/num/dec2flt/decimal.rs
index 1fa06de692e..f759e1dbde6 100644
--- a/library/coretests/tests/num/dec2flt/decimal.rs
+++ b/library/coretests/tests/num/dec2flt/decimal.rs
@@ -7,6 +7,20 @@ const FPATHS_F32: &[FPath<f32>] =
 const FPATHS_F64: &[FPath<f64>] =
     &[((0, 0, false, false), Some(0.0)), ((0, 0, false, false), Some(0.0))];
 
+// FIXME(f16_f128): enable on all targets once possible.
+#[test]
+#[cfg(target_has_reliable_f16)]
+fn check_fast_path_f16() {
+    const FPATHS_F16: &[FPath<f16>] =
+        &[((0, 0, false, false), Some(0.0)), ((0, 0, false, false), Some(0.0))];
+    for ((exponent, mantissa, negative, many_digits), expected) in FPATHS_F16.iter().copied() {
+        let dec = Decimal { exponent, mantissa, negative, many_digits };
+        let actual = dec.try_fast_path::<f16>();
+
+        assert_eq!(actual, expected);
+    }
+}
+
 #[test]
 fn check_fast_path_f32() {
     for ((exponent, mantissa, negative, many_digits), expected) in FPATHS_F32.iter().copied() {
diff --git a/library/coretests/tests/num/dec2flt/float.rs b/library/coretests/tests/num/dec2flt/float.rs
index b5afd3e3b24..264de061be9 100644
--- a/library/coretests/tests/num/dec2flt/float.rs
+++ b/library/coretests/tests/num/dec2flt/float.rs
@@ -1,5 +1,24 @@
 use core::num::dec2flt::float::RawFloat;
 
+// FIXME(f16_f128): enable on all targets once possible.
+#[test]
+#[cfg(target_has_reliable_f16)]
+fn test_f16_integer_decode() {
+    assert_eq!(3.14159265359f16.integer_decode(), (1608, -9, 1));
+    assert_eq!((-8573.5918555f16).integer_decode(), (1072, 3, -1));
+    #[cfg(not(miri))] // miri doesn't have powf16
+    assert_eq!(2f16.powf(14.0).integer_decode(), (1 << 10, 4, 1));
+    assert_eq!(0f16.integer_decode(), (0, -25, 1));
+    assert_eq!((-0f16).integer_decode(), (0, -25, -1));
+    assert_eq!(f16::INFINITY.integer_decode(), (1 << 10, 6, 1));
+    assert_eq!(f16::NEG_INFINITY.integer_decode(), (1 << 10, 6, -1));
+
+    // Ignore the "sign" (quiet / signalling flag) of NAN.
+    // It can vary between runtime operations and LLVM folding.
+    let (nan_m, nan_p, _nan_s) = f16::NAN.integer_decode();
+    assert_eq!((nan_m, nan_p), (1536, 6));
+}
+
 #[test]
 fn test_f32_integer_decode() {
     assert_eq!(3.14159265359f32.integer_decode(), (13176795, -22, 1));
@@ -34,6 +53,27 @@ fn test_f64_integer_decode() {
 
 /* Sanity checks of computed magic numbers */
 
+// FIXME(f16_f128): enable on all targets once possible.
+#[test]
+#[cfg(target_has_reliable_f16)]
+fn test_f16_consts() {
+    assert_eq!(<f16 as RawFloat>::INFINITY, f16::INFINITY);
+    assert_eq!(<f16 as RawFloat>::NEG_INFINITY, -f16::INFINITY);
+    assert_eq!(<f16 as RawFloat>::NAN.to_bits(), f16::NAN.to_bits());
+    assert_eq!(<f16 as RawFloat>::NEG_NAN.to_bits(), (-f16::NAN).to_bits());
+    assert_eq!(<f16 as RawFloat>::SIG_BITS, 10);
+    assert_eq!(<f16 as RawFloat>::MIN_EXPONENT_ROUND_TO_EVEN, -22);
+    assert_eq!(<f16 as RawFloat>::MAX_EXPONENT_ROUND_TO_EVEN, 5);
+    assert_eq!(<f16 as RawFloat>::MIN_EXPONENT_FAST_PATH, -4);
+    assert_eq!(<f16 as RawFloat>::MAX_EXPONENT_FAST_PATH, 4);
+    assert_eq!(<f16 as RawFloat>::MAX_EXPONENT_DISGUISED_FAST_PATH, 7);
+    assert_eq!(<f16 as RawFloat>::EXP_MIN, -14);
+    assert_eq!(<f16 as RawFloat>::EXP_SAT, 0x1f);
+    assert_eq!(<f16 as RawFloat>::SMALLEST_POWER_OF_TEN, -27);
+    assert_eq!(<f16 as RawFloat>::LARGEST_POWER_OF_TEN, 4);
+    assert_eq!(<f16 as RawFloat>::MAX_MANTISSA_FAST_PATH, 2048);
+}
+
 #[test]
 fn test_f32_consts() {
     assert_eq!(<f32 as RawFloat>::INFINITY, f32::INFINITY);
diff --git a/library/coretests/tests/num/dec2flt/lemire.rs b/library/coretests/tests/num/dec2flt/lemire.rs
index 0db80fbd525..6d49d85170e 100644
--- a/library/coretests/tests/num/dec2flt/lemire.rs
+++ b/library/coretests/tests/num/dec2flt/lemire.rs
@@ -1,6 +1,12 @@
 use core::num::dec2flt::float::RawFloat;
 use core::num::dec2flt::lemire::compute_float;
 
+#[cfg(target_has_reliable_f16)]
+fn compute_float16(q: i64, w: u64) -> (i32, u64) {
+    let fp = compute_float::<f16>(q, w);
+    (fp.p_biased, fp.m)
+}
+
 fn compute_float32(q: i64, w: u64) -> (i32, u64) {
     let fp = compute_float::<f32>(q, w);
     (fp.p_biased, fp.m)
@@ -11,23 +17,73 @@ fn compute_float64(q: i64, w: u64) -> (i32, u64) {
     (fp.p_biased, fp.m)
 }
 
+// FIXME(f16_f128): enable on all targets once possible.
+#[test]
+#[cfg(target_has_reliable_f16)]
+fn compute_float_f16_rounding() {
+    // The maximum integer that cna be converted to a `f16` without lost precision.
+    let val = 1 << 11;
+    let scale = 10_u64.pow(10);
+
+    // These test near-halfway cases for half-precision floats.
+    assert_eq!(compute_float16(0, val), (26, 0));
+    assert_eq!(compute_float16(0, val + 1), (26, 0));
+    assert_eq!(compute_float16(0, val + 2), (26, 1));
+    assert_eq!(compute_float16(0, val + 3), (26, 2));
+    assert_eq!(compute_float16(0, val + 4), (26, 2));
+
+    // For the next power up, the two nearest representable numbers are twice as far apart.
+    let val2 = 1 << 12;
+    assert_eq!(compute_float16(0, val2), (27, 0));
+    assert_eq!(compute_float16(0, val2 + 2), (27, 0));
+    assert_eq!(compute_float16(0, val2 + 4), (27, 1));
+    assert_eq!(compute_float16(0, val2 + 6), (27, 2));
+    assert_eq!(compute_float16(0, val2 + 8), (27, 2));
+
+    // These are examples of the above tests, with digits from the exponent shifted
+    // to the mantissa.
+    assert_eq!(compute_float16(-10, val * scale), (26, 0));
+    assert_eq!(compute_float16(-10, (val + 1) * scale), (26, 0));
+    assert_eq!(compute_float16(-10, (val + 2) * scale), (26, 1));
+    // Let's check the lines to see if anything is different in table...
+    assert_eq!(compute_float16(-10, (val + 3) * scale), (26, 2));
+    assert_eq!(compute_float16(-10, (val + 4) * scale), (26, 2));
+
+    // Check the rounding point between infinity and the next representable number down
+    assert_eq!(compute_float16(4, 6), (f16::INFINITE_POWER - 1, 851));
+    assert_eq!(compute_float16(4, 7), (f16::INFINITE_POWER, 0)); // infinity
+    assert_eq!(compute_float16(2, 655), (f16::INFINITE_POWER - 1, 1023));
+}
+
 #[test]
 fn compute_float_f32_rounding() {
+    // the maximum integer that cna be converted to a `f32` without lost precision.
+    let val = 1 << 24;
+    let scale = 10_u64.pow(10);
+
     // These test near-halfway cases for single-precision floats.
-    assert_eq!(compute_float32(0, 16777216), (151, 0));
-    assert_eq!(compute_float32(0, 16777217), (151, 0));
-    assert_eq!(compute_float32(0, 16777218), (151, 1));
-    assert_eq!(compute_float32(0, 16777219), (151, 2));
-    assert_eq!(compute_float32(0, 16777220), (151, 2));
-
-    // These are examples of the above tests, with
-    // digits from the exponent shifted to the mantissa.
-    assert_eq!(compute_float32(-10, 167772160000000000), (151, 0));
-    assert_eq!(compute_float32(-10, 167772170000000000), (151, 0));
-    assert_eq!(compute_float32(-10, 167772180000000000), (151, 1));
+    assert_eq!(compute_float32(0, val), (151, 0));
+    assert_eq!(compute_float32(0, val + 1), (151, 0));
+    assert_eq!(compute_float32(0, val + 2), (151, 1));
+    assert_eq!(compute_float32(0, val + 3), (151, 2));
+    assert_eq!(compute_float32(0, val + 4), (151, 2));
+
+    // For the next power up, the two nearest representable numbers are twice as far apart.
+    let val2 = 1 << 25;
+    assert_eq!(compute_float32(0, val2), (152, 0));
+    assert_eq!(compute_float32(0, val2 + 2), (152, 0));
+    assert_eq!(compute_float32(0, val2 + 4), (152, 1));
+    assert_eq!(compute_float32(0, val2 + 6), (152, 2));
+    assert_eq!(compute_float32(0, val2 + 8), (152, 2));
+
+    // These are examples of the above tests, with digits from the exponent shifted
+    // to the mantissa.
+    assert_eq!(compute_float32(-10, val * scale), (151, 0));
+    assert_eq!(compute_float32(-10, (val + 1) * scale), (151, 0));
+    assert_eq!(compute_float32(-10, (val + 2) * scale), (151, 1));
     // Let's check the lines to see if anything is different in table...
-    assert_eq!(compute_float32(-10, 167772190000000000), (151, 2));
-    assert_eq!(compute_float32(-10, 167772200000000000), (151, 2));
+    assert_eq!(compute_float32(-10, (val + 3) * scale), (151, 2));
+    assert_eq!(compute_float32(-10, (val + 4) * scale), (151, 2));
 
     // Check the rounding point between infinity and the next representable number down
     assert_eq!(compute_float32(38, 3), (f32::INFINITE_POWER - 1, 6402534));
@@ -37,23 +93,38 @@ fn compute_float_f32_rounding() {
 
 #[test]
 fn compute_float_f64_rounding() {
+    // The maximum integer that cna be converted to a `f64` without lost precision.
+    let val = 1 << 53;
+    let scale = 1000;
+
     // These test near-halfway cases for double-precision floats.
-    assert_eq!(compute_float64(0, 9007199254740992), (1076, 0));
-    assert_eq!(compute_float64(0, 9007199254740993), (1076, 0));
-    assert_eq!(compute_float64(0, 9007199254740994), (1076, 1));
-    assert_eq!(compute_float64(0, 9007199254740995), (1076, 2));
-    assert_eq!(compute_float64(0, 9007199254740996), (1076, 2));
-    assert_eq!(compute_float64(0, 18014398509481984), (1077, 0));
-    assert_eq!(compute_float64(0, 18014398509481986), (1077, 0));
-    assert_eq!(compute_float64(0, 18014398509481988), (1077, 1));
-    assert_eq!(compute_float64(0, 18014398509481990), (1077, 2));
-    assert_eq!(compute_float64(0, 18014398509481992), (1077, 2));
-
-    // These are examples of the above tests, with
-    // digits from the exponent shifted to the mantissa.
-    assert_eq!(compute_float64(-3, 9007199254740992000), (1076, 0));
-    assert_eq!(compute_float64(-3, 9007199254740993000), (1076, 0));
-    assert_eq!(compute_float64(-3, 9007199254740994000), (1076, 1));
-    assert_eq!(compute_float64(-3, 9007199254740995000), (1076, 2));
-    assert_eq!(compute_float64(-3, 9007199254740996000), (1076, 2));
+    assert_eq!(compute_float64(0, val), (1076, 0));
+    assert_eq!(compute_float64(0, val + 1), (1076, 0));
+    assert_eq!(compute_float64(0, val + 2), (1076, 1));
+    assert_eq!(compute_float64(0, val + 3), (1076, 2));
+    assert_eq!(compute_float64(0, val + 4), (1076, 2));
+
+    // For the next power up, the two nearest representable numbers are twice as far apart.
+    let val2 = 1 << 54;
+    assert_eq!(compute_float64(0, val2), (1077, 0));
+    assert_eq!(compute_float64(0, val2 + 2), (1077, 0));
+    assert_eq!(compute_float64(0, val2 + 4), (1077, 1));
+    assert_eq!(compute_float64(0, val2 + 6), (1077, 2));
+    assert_eq!(compute_float64(0, val2 + 8), (1077, 2));
+
+    // These are examples of the above tests, with digits from the exponent shifted
+    // to the mantissa.
+    assert_eq!(compute_float64(-3, val * scale), (1076, 0));
+    assert_eq!(compute_float64(-3, (val + 1) * scale), (1076, 0));
+    assert_eq!(compute_float64(-3, (val + 2) * scale), (1076, 1));
+    assert_eq!(compute_float64(-3, (val + 3) * scale), (1076, 2));
+    assert_eq!(compute_float64(-3, (val + 4) * scale), (1076, 2));
+
+    // Check the rounding point between infinity and the next representable number down
+    assert_eq!(compute_float64(308, 1), (f64::INFINITE_POWER - 1, 506821272651936));
+    assert_eq!(compute_float64(308, 2), (f64::INFINITE_POWER, 0)); // infinity
+    assert_eq!(
+        compute_float64(292, 17976931348623157),
+        (f64::INFINITE_POWER - 1, 4503599627370495)
+    );
 }
diff --git a/library/coretests/tests/num/dec2flt/mod.rs b/library/coretests/tests/num/dec2flt/mod.rs
index a9025be5ca7..b8ca220847c 100644
--- a/library/coretests/tests/num/dec2flt/mod.rs
+++ b/library/coretests/tests/num/dec2flt/mod.rs
@@ -11,15 +11,23 @@ mod parse;
 // Requires a *polymorphic literal*, i.e., one that can serve as f64 as well as f32.
 macro_rules! test_literal {
     ($x: expr) => {{
+        #[cfg(target_has_reliable_f16)]
+        let x16: f16 = $x;
         let x32: f32 = $x;
         let x64: f64 = $x;
         let inputs = &[stringify!($x).into(), format!("{:?}", x64), format!("{:e}", x64)];
+
         for input in inputs {
-            assert_eq!(input.parse(), Ok(x64));
-            assert_eq!(input.parse(), Ok(x32));
+            assert_eq!(input.parse(), Ok(x64), "failed f64 {input}");
+            assert_eq!(input.parse(), Ok(x32), "failed f32 {input}");
+            #[cfg(target_has_reliable_f16)]
+            assert_eq!(input.parse(), Ok(x16), "failed f16 {input}");
+
             let neg_input = format!("-{input}");
-            assert_eq!(neg_input.parse(), Ok(-x64));
-            assert_eq!(neg_input.parse(), Ok(-x32));
+            assert_eq!(neg_input.parse(), Ok(-x64), "failed f64 {neg_input}");
+            assert_eq!(neg_input.parse(), Ok(-x32), "failed f32 {neg_input}");
+            #[cfg(target_has_reliable_f16)]
+            assert_eq!(neg_input.parse(), Ok(-x16), "failed f16 {neg_input}");
         }
     }};
 }
@@ -84,48 +92,87 @@ fn fast_path_correct() {
     test_literal!(1.448997445238699);
 }
 
+// FIXME(f16_f128): remove gates once tests work on all targets
+
 #[test]
 fn lonely_dot() {
+    #[cfg(target_has_reliable_f16)]
+    assert!(".".parse::<f16>().is_err());
     assert!(".".parse::<f32>().is_err());
     assert!(".".parse::<f64>().is_err());
 }
 
 #[test]
 fn exponentiated_dot() {
+    #[cfg(target_has_reliable_f16)]
+    assert!(".e0".parse::<f16>().is_err());
     assert!(".e0".parse::<f32>().is_err());
     assert!(".e0".parse::<f64>().is_err());
 }
 
 #[test]
 fn lonely_sign() {
-    assert!("+".parse::<f32>().is_err());
-    assert!("-".parse::<f64>().is_err());
+    #[cfg(target_has_reliable_f16)]
+    assert!("+".parse::<f16>().is_err());
+    assert!("-".parse::<f32>().is_err());
+    assert!("+".parse::<f64>().is_err());
 }
 
 #[test]
 fn whitespace() {
+    #[cfg(target_has_reliable_f16)]
+    assert!("1.0 ".parse::<f16>().is_err());
     assert!(" 1.0".parse::<f32>().is_err());
     assert!("1.0 ".parse::<f64>().is_err());
 }
 
 #[test]
 fn nan() {
+    #[cfg(target_has_reliable_f16)]
+    {
+        assert!("NaN".parse::<f16>().unwrap().is_nan());
+        assert!("-NaN".parse::<f16>().unwrap().is_nan());
+    }
+
     assert!("NaN".parse::<f32>().unwrap().is_nan());
+    assert!("-NaN".parse::<f32>().unwrap().is_nan());
+
     assert!("NaN".parse::<f64>().unwrap().is_nan());
+    assert!("-NaN".parse::<f64>().unwrap().is_nan());
 }
 
 #[test]
 fn inf() {
-    assert_eq!("inf".parse(), Ok(f64::INFINITY));
-    assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
+    #[cfg(target_has_reliable_f16)]
+    {
+        assert_eq!("inf".parse(), Ok(f16::INFINITY));
+        assert_eq!("-inf".parse(), Ok(f16::NEG_INFINITY));
+    }
+
     assert_eq!("inf".parse(), Ok(f32::INFINITY));
     assert_eq!("-inf".parse(), Ok(f32::NEG_INFINITY));
+
+    assert_eq!("inf".parse(), Ok(f64::INFINITY));
+    assert_eq!("-inf".parse(), Ok(f64::NEG_INFINITY));
 }
 
 #[test]
 fn massive_exponent() {
+    #[cfg(target_has_reliable_f16)]
+    {
+        let max = i16::MAX;
+        assert_eq!(format!("1e{max}000").parse(), Ok(f16::INFINITY));
+        assert_eq!(format!("1e-{max}000").parse(), Ok(0.0f16));
+        assert_eq!(format!("1e{max}000").parse(), Ok(f16::INFINITY));
+    }
+
+    let max = i32::MAX;
+    assert_eq!(format!("1e{max}000").parse(), Ok(f32::INFINITY));
+    assert_eq!(format!("1e-{max}000").parse(), Ok(0.0f32));
+    assert_eq!(format!("1e{max}000").parse(), Ok(f32::INFINITY));
+
     let max = i64::MAX;
     assert_eq!(format!("1e{max}000").parse(), Ok(f64::INFINITY));
-    assert_eq!(format!("1e-{max}000").parse(), Ok(0.0));
+    assert_eq!(format!("1e-{max}000").parse(), Ok(0.0f64));
     assert_eq!(format!("1e{max}000").parse(), Ok(f64::INFINITY));
 }
diff --git a/library/coretests/tests/num/dec2flt/parse.rs b/library/coretests/tests/num/dec2flt/parse.rs
index 59be3915052..dccb6b5528d 100644
--- a/library/coretests/tests/num/dec2flt/parse.rs
+++ b/library/coretests/tests/num/dec2flt/parse.rs
@@ -10,6 +10,9 @@ fn new_dec(e: i64, m: u64) -> Decimal {
 fn missing_pieces() {
     let permutations = &[".e", "1e", "e4", "e", ".12e", "321.e", "32.12e+", "12.32e-"];
     for &s in permutations {
+        #[cfg(target_has_reliable_f16)]
+        assert_eq!(dec2flt::<f16>(s), Err(pfe_invalid()));
+        assert_eq!(dec2flt::<f32>(s), Err(pfe_invalid()));
         assert_eq!(dec2flt::<f64>(s), Err(pfe_invalid()));
     }
 }
@@ -17,15 +20,31 @@ fn missing_pieces() {
 #[test]
 fn invalid_chars() {
     let invalid = "r,?<j";
-    let error = Err(pfe_invalid());
     let valid_strings = &["123", "666.", ".1", "5e1", "7e-3", "0.0e+1"];
+
     for c in invalid.chars() {
         for s in valid_strings {
             for i in 0..s.len() {
                 let mut input = String::new();
                 input.push_str(s);
                 input.insert(i, c);
-                assert!(dec2flt::<f64>(&input) == error, "did not reject invalid {:?}", input);
+
+                #[cfg(target_has_reliable_f16)]
+                assert_eq!(
+                    dec2flt::<f16>(&input),
+                    Err(pfe_invalid()),
+                    "f16 did not reject invalid {input:?}",
+                );
+                assert_eq!(
+                    dec2flt::<f32>(&input),
+                    Err(pfe_invalid()),
+                    "f32 did not reject invalid {input:?}",
+                );
+                assert_eq!(
+                    dec2flt::<f64>(&input),
+                    Err(pfe_invalid()),
+                    "f64 did not reject invalid {input:?}",
+                );
             }
         }
     }
diff --git a/library/coretests/tests/num/flt2dec/mod.rs b/library/coretests/tests/num/flt2dec/mod.rs
index c64bb0a3072..ce36db33d05 100644
--- a/library/coretests/tests/num/flt2dec/mod.rs
+++ b/library/coretests/tests/num/flt2dec/mod.rs
@@ -16,7 +16,7 @@ mod random;
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
         FullDecoded::Finite(decoded) => decoded,
-        full_decoded => panic!("expected finite, got {full_decoded:?} instead"),
+        full_decoded => panic!("expected finite, got {full_decoded:?} instead for {v:?}"),
     }
 }
 
@@ -75,6 +75,11 @@ macro_rules! try_fixed {
     })
 }
 
+#[cfg(target_has_reliable_f16)]
+fn ldexp_f16(a: f16, b: i32) -> f16 {
+    ldexp_f64(a as f64, b) as f16
+}
+
 fn ldexp_f32(a: f32, b: i32) -> f32 {
     ldexp_f64(a as f64, b) as f32
 }
@@ -176,6 +181,13 @@ trait TestableFloat: DecodableFloat + fmt::Display {
     fn ldexpi(f: i64, exp: isize) -> Self;
 }
 
+#[cfg(target_has_reliable_f16)]
+impl TestableFloat for f16 {
+    fn ldexpi(f: i64, exp: isize) -> Self {
+        f as Self * (exp as Self).exp2()
+    }
+}
+
 impl TestableFloat for f32 {
     fn ldexpi(f: i64, exp: isize) -> Self {
         f as Self * (exp as Self).exp2()
@@ -225,6 +237,76 @@ macro_rules! check_exact_one {
 //
 // [1] Vern Paxson, A Program for Testing IEEE Decimal-Binary Conversion
 //     ftp://ftp.ee.lbl.gov/testbase-report.ps.Z
+//  or https://www.icir.org/vern/papers/testbase-report.pdf
+
+#[cfg(target_has_reliable_f16)]
+pub fn f16_shortest_sanity_test<F>(mut f: F)
+where
+    F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
+{
+    // 0.0999145507813
+    // 0.0999755859375
+    // 0.100036621094
+    check_shortest!(f(0.1f16) => b"1", 0);
+
+    // 0.3330078125
+    // 0.333251953125 (1/3 in the default rounding)
+    // 0.33349609375
+    check_shortest!(f(1.0f16/3.0) => b"3333", 0);
+
+    // 10^1 * 0.3138671875
+    // 10^1 * 0.3140625
+    // 10^1 * 0.3142578125
+    check_shortest!(f(3.14f16) => b"314", 1);
+
+    // 10^18 * 0.31415916243714048
+    // 10^18 * 0.314159196796878848
+    // 10^18 * 0.314159231156617216
+    check_shortest!(f(3.1415e4f16) => b"3141", 5);
+
+    // regression test for decoders
+    // 10^2 * 0.31984375
+    // 10^2 * 0.32
+    // 10^2 * 0.3203125
+    check_shortest!(f(ldexp_f16(1.0, 5)) => b"32", 2);
+
+    // 10^5 * 0.65472
+    // 10^5 * 0.65504
+    // 10^5 * 0.65536
+    check_shortest!(f(f16::MAX) => b"655", 5);
+
+    // 10^-4 * 0.60975551605224609375
+    // 10^-4 * 0.6103515625
+    // 10^-4 * 0.61094760894775390625
+    check_shortest!(f(f16::MIN_POSITIVE) => b"6104", -4);
+
+    // 10^-9 * 0
+    // 10^-9 * 0.59604644775390625
+    // 10^-8 * 0.11920928955078125
+    let minf16 = ldexp_f16(1.0, -24);
+    check_shortest!(f(minf16) => b"6", -7);
+}
+
+#[cfg(target_has_reliable_f16)]
+pub fn f16_exact_sanity_test<F>(mut f: F)
+where
+    F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
+{
+    let minf16 = ldexp_f16(1.0, -24);
+
+    check_exact!(f(0.1f16)            => b"999755859375     ", -1);
+    check_exact!(f(0.5f16)            => b"5                ", 0);
+    check_exact!(f(1.0f16/3.0)        => b"333251953125     ", 0);
+    check_exact!(f(3.141f16)          => b"3140625          ", 1);
+    check_exact!(f(3.141e4f16)        => b"31408            ", 5);
+    check_exact!(f(f16::MAX)          => b"65504            ", 5);
+    check_exact!(f(f16::MIN_POSITIVE) => b"6103515625       ", -4);
+    check_exact!(f(minf16)            => b"59604644775390625", -7);
+
+    // FIXME(f16_f128): these should gain the check_exact_one tests like `f32` and `f64` have,
+    // but these values are not easy to generate. The algorithm from the Paxon paper [1] needs
+    // to be adapted to binary16.
+}
 
 pub fn f32_shortest_sanity_test<F>(mut f: F)
 where
@@ -553,23 +635,45 @@ where
     assert_eq!(to_string(f, 1.9971e20, Minus, 1), "199710000000000000000.0");
     assert_eq!(to_string(f, 1.9971e20, Minus, 8), "199710000000000000000.00000000");
 
-    assert_eq!(to_string(f, f32::MAX, Minus, 0), format!("34028235{:0>31}", ""));
-    assert_eq!(to_string(f, f32::MAX, Minus, 1), format!("34028235{:0>31}.0", ""));
-    assert_eq!(to_string(f, f32::MAX, Minus, 8), format!("34028235{:0>31}.00000000", ""));
-
-    let minf32 = ldexp_f32(1.0, -149);
-    assert_eq!(to_string(f, minf32, Minus, 0), format!("0.{:0>44}1", ""));
-    assert_eq!(to_string(f, minf32, Minus, 45), format!("0.{:0>44}1", ""));
-    assert_eq!(to_string(f, minf32, Minus, 46), format!("0.{:0>44}10", ""));
+    #[cfg(target_has_reliable_f16)]
+    {
+        // f16
+        assert_eq!(to_string(f, f16::MAX, Minus, 0), "65500");
+        assert_eq!(to_string(f, f16::MAX, Minus, 1), "65500.0");
+        assert_eq!(to_string(f, f16::MAX, Minus, 8), "65500.00000000");
+
+        let minf16 = ldexp_f16(1.0, -24);
+        assert_eq!(to_string(f, minf16, Minus, 0), "0.00000006");
+        assert_eq!(to_string(f, minf16, Minus, 8), "0.00000006");
+        assert_eq!(to_string(f, minf16, Minus, 9), "0.000000060");
+    }
 
-    assert_eq!(to_string(f, f64::MAX, Minus, 0), format!("17976931348623157{:0>292}", ""));
-    assert_eq!(to_string(f, f64::MAX, Minus, 1), format!("17976931348623157{:0>292}.0", ""));
-    assert_eq!(to_string(f, f64::MAX, Minus, 8), format!("17976931348623157{:0>292}.00000000", ""));
+    {
+        // f32
+        assert_eq!(to_string(f, f32::MAX, Minus, 0), format!("34028235{:0>31}", ""));
+        assert_eq!(to_string(f, f32::MAX, Minus, 1), format!("34028235{:0>31}.0", ""));
+        assert_eq!(to_string(f, f32::MAX, Minus, 8), format!("34028235{:0>31}.00000000", ""));
+
+        let minf32 = ldexp_f32(1.0, -149);
+        assert_eq!(to_string(f, minf32, Minus, 0), format!("0.{:0>44}1", ""));
+        assert_eq!(to_string(f, minf32, Minus, 45), format!("0.{:0>44}1", ""));
+        assert_eq!(to_string(f, minf32, Minus, 46), format!("0.{:0>44}10", ""));
+    }
 
-    let minf64 = ldexp_f64(1.0, -1074);
-    assert_eq!(to_string(f, minf64, Minus, 0), format!("0.{:0>323}5", ""));
-    assert_eq!(to_string(f, minf64, Minus, 324), format!("0.{:0>323}5", ""));
-    assert_eq!(to_string(f, minf64, Minus, 325), format!("0.{:0>323}50", ""));
+    {
+        // f64
+        assert_eq!(to_string(f, f64::MAX, Minus, 0), format!("17976931348623157{:0>292}", ""));
+        assert_eq!(to_string(f, f64::MAX, Minus, 1), format!("17976931348623157{:0>292}.0", ""));
+        assert_eq!(
+            to_string(f, f64::MAX, Minus, 8),
+            format!("17976931348623157{:0>292}.00000000", "")
+        );
+
+        let minf64 = ldexp_f64(1.0, -1074);
+        assert_eq!(to_string(f, minf64, Minus, 0), format!("0.{:0>323}5", ""));
+        assert_eq!(to_string(f, minf64, Minus, 324), format!("0.{:0>323}5", ""));
+        assert_eq!(to_string(f, minf64, Minus, 325), format!("0.{:0>323}50", ""));
+    }
 
     if cfg!(miri) {
         // Miri is too slow
@@ -655,27 +759,45 @@ where
     assert_eq!(to_string(f, 1.0e23, Minus, (23, 24), false), "100000000000000000000000");
     assert_eq!(to_string(f, 1.0e23, Minus, (24, 25), false), "1e23");
 
-    assert_eq!(to_string(f, f32::MAX, Minus, (-4, 16), false), "3.4028235e38");
-    assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38");
-    assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", ""));
-
-    let minf32 = ldexp_f32(1.0, -149);
-    assert_eq!(to_string(f, minf32, Minus, (-4, 16), false), "1e-45");
-    assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45");
-    assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", ""));
-
-    assert_eq!(to_string(f, f64::MAX, Minus, (-4, 16), false), "1.7976931348623157e308");
-    assert_eq!(
-        to_string(f, f64::MAX, Minus, (-308, 309), false),
-        format!("17976931348623157{:0>292}", "")
-    );
-    assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false), "1.7976931348623157e308");
+    #[cfg(target_has_reliable_f16)]
+    {
+        // f16
+        assert_eq!(to_string(f, f16::MAX, Minus, (-2, 2), false), "6.55e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, (-4, 4), false), "6.55e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, (-5, 5), false), "65500");
+
+        let minf16 = ldexp_f16(1.0, -24);
+        assert_eq!(to_string(f, minf16, Minus, (-2, 2), false), "6e-8");
+        assert_eq!(to_string(f, minf16, Minus, (-7, 7), false), "6e-8");
+        assert_eq!(to_string(f, minf16, Minus, (-8, 8), false), "0.00000006");
+    }
 
-    let minf64 = ldexp_f64(1.0, -1074);
-    assert_eq!(to_string(f, minf64, Minus, (-4, 16), false), "5e-324");
-    assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", ""));
-    assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324");
+    {
+        // f32
+        assert_eq!(to_string(f, f32::MAX, Minus, (-4, 16), false), "3.4028235e38");
+        assert_eq!(to_string(f, f32::MAX, Minus, (-39, 38), false), "3.4028235e38");
+        assert_eq!(to_string(f, f32::MAX, Minus, (-38, 39), false), format!("34028235{:0>31}", ""));
+
+        let minf32 = ldexp_f32(1.0, -149);
+        assert_eq!(to_string(f, minf32, Minus, (-4, 16), false), "1e-45");
+        assert_eq!(to_string(f, minf32, Minus, (-44, 45), false), "1e-45");
+        assert_eq!(to_string(f, minf32, Minus, (-45, 44), false), format!("0.{:0>44}1", ""));
+    }
 
+    {
+        // f64
+        assert_eq!(to_string(f, f64::MAX, Minus, (-4, 16), false), "1.7976931348623157e308");
+        assert_eq!(
+            to_string(f, f64::MAX, Minus, (-308, 309), false),
+            format!("17976931348623157{:0>292}", "")
+        );
+        assert_eq!(to_string(f, f64::MAX, Minus, (-309, 308), false), "1.7976931348623157e308");
+
+        let minf64 = ldexp_f64(1.0, -1074);
+        assert_eq!(to_string(f, minf64, Minus, (-4, 16), false), "5e-324");
+        assert_eq!(to_string(f, minf64, Minus, (-324, 323), false), format!("0.{:0>323}5", ""));
+        assert_eq!(to_string(f, minf64, Minus, (-323, 324), false), "5e-324");
+    }
     assert_eq!(to_string(f, 1.1, Minus, (i16::MIN, i16::MAX), false), "1.1");
 }
 
@@ -791,6 +913,26 @@ where
         "9.999999999999999547481118258862586856139387236908078193664550781250000e-7"
     );
 
+    #[cfg(target_has_reliable_f16)]
+    {
+        assert_eq!(to_string(f, f16::MAX, Minus, 1, false), "7e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 2, false), "6.6e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 4, false), "6.550e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 5, false), "6.5504e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 6, false), "6.55040e4");
+        assert_eq!(to_string(f, f16::MAX, Minus, 16, false), "6.550400000000000e4");
+
+        let minf16 = ldexp_f16(1.0, -24);
+        assert_eq!(to_string(f, minf16, Minus, 1, false), "6e-8");
+        assert_eq!(to_string(f, minf16, Minus, 2, false), "6.0e-8");
+        assert_eq!(to_string(f, minf16, Minus, 4, false), "5.960e-8");
+        assert_eq!(to_string(f, minf16, Minus, 8, false), "5.9604645e-8");
+        assert_eq!(to_string(f, minf16, Minus, 16, false), "5.960464477539062e-8");
+        assert_eq!(to_string(f, minf16, Minus, 17, false), "5.9604644775390625e-8");
+        assert_eq!(to_string(f, minf16, Minus, 18, false), "5.96046447753906250e-8");
+        assert_eq!(to_string(f, minf16, Minus, 24, false), "5.96046447753906250000000e-8");
+    }
+
     assert_eq!(to_string(f, f32::MAX, Minus, 1, false), "3e38");
     assert_eq!(to_string(f, f32::MAX, Minus, 2, false), "3.4e38");
     assert_eq!(to_string(f, f32::MAX, Minus, 4, false), "3.403e38");
@@ -1069,6 +1211,13 @@ where
         "0.000000999999999999999954748111825886258685613938723690807819366455078125000"
     );
 
+    #[cfg(target_has_reliable_f16)]
+    {
+        assert_eq!(to_string(f, f16::MAX, Minus, 0), "65504");
+        assert_eq!(to_string(f, f16::MAX, Minus, 1), "65504.0");
+        assert_eq!(to_string(f, f16::MAX, Minus, 2), "65504.00");
+    }
+
     assert_eq!(to_string(f, f32::MAX, Minus, 0), "340282346638528859811704183484516925440");
     assert_eq!(to_string(f, f32::MAX, Minus, 1), "340282346638528859811704183484516925440.0");
     assert_eq!(to_string(f, f32::MAX, Minus, 2), "340282346638528859811704183484516925440.00");
@@ -1078,6 +1227,21 @@ where
         return;
     }
 
+    #[cfg(target_has_reliable_f16)]
+    {
+        let minf16 = ldexp_f16(1.0, -24);
+        assert_eq!(to_string(f, minf16, Minus, 0), "0");
+        assert_eq!(to_string(f, minf16, Minus, 1), "0.0");
+        assert_eq!(to_string(f, minf16, Minus, 2), "0.00");
+        assert_eq!(to_string(f, minf16, Minus, 4), "0.0000");
+        assert_eq!(to_string(f, minf16, Minus, 8), "0.00000006");
+        assert_eq!(to_string(f, minf16, Minus, 10), "0.0000000596");
+        assert_eq!(to_string(f, minf16, Minus, 15), "0.000000059604645");
+        assert_eq!(to_string(f, minf16, Minus, 20), "0.00000005960464477539");
+        assert_eq!(to_string(f, minf16, Minus, 24), "0.000000059604644775390625");
+        assert_eq!(to_string(f, minf16, Minus, 32), "0.00000005960464477539062500000000");
+    }
+
     let minf32 = ldexp_f32(1.0, -149);
     assert_eq!(to_string(f, minf32, Minus, 0), "0");
     assert_eq!(to_string(f, minf32, Minus, 1), "0.0");
diff --git a/library/coretests/tests/num/flt2dec/random.rs b/library/coretests/tests/num/flt2dec/random.rs
index 586b49df7d9..7386139aace 100644
--- a/library/coretests/tests/num/flt2dec/random.rs
+++ b/library/coretests/tests/num/flt2dec/random.rs
@@ -79,6 +79,20 @@ where
     (npassed, nignored)
 }
 
+#[cfg(target_has_reliable_f16)]
+pub fn f16_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
+where
+    F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>,
+    G: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
+{
+    let mut rng = crate::test_rng();
+    let f16_range = Uniform::new(0x0001u16, 0x7c00).unwrap();
+    iterate("f16_random_equivalence_test", k, n, f, g, |_| {
+        let x = f16::from_bits(f16_range.sample(&mut rng));
+        decode_finite(x)
+    });
+}
+
 pub fn f32_random_equivalence_test<F, G>(f: F, g: G, k: usize, n: usize)
 where
     F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>,
@@ -105,6 +119,24 @@ where
     });
 }
 
+#[cfg(target_has_reliable_f16)]
+pub fn f16_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
+where
+    F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>,
+    G: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
+{
+    // Unlike the other float types, `f16` is small enough that these exhaustive tests
+    // can run in less than a second so we don't need to ignore it.
+
+    // iterate from 0x0001 to 0x7bff, i.e., all finite ranges
+    let (npassed, nignored) =
+        iterate("f16_exhaustive_equivalence_test", k, 0x7bff, f, g, |i: usize| {
+            let x = f16::from_bits(i as u16 + 1);
+            decode_finite(x)
+        });
+    assert_eq!((npassed, nignored), (29735, 2008));
+}
+
 pub fn f32_exhaustive_equivalence_test<F, G>(f: F, g: G, k: usize)
 where
     F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>,
@@ -133,6 +165,17 @@ fn shortest_random_equivalence_test() {
 
     f64_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, n);
     f32_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, n);
+    #[cfg(target_has_reliable_f16)]
+    f16_random_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS, n);
+}
+
+#[test]
+#[cfg_attr(miri, ignore)] // Miri is to slow
+#[cfg(target_has_reliable_f16)]
+fn shortest_f16_exhaustive_equivalence_test() {
+    // see the f32 version
+    use core::num::flt2dec::strategy::dragon::format_shortest as fallback;
+    f16_exhaustive_equivalence_test(format_shortest_opt, fallback, MAX_SIG_DIGITS);
 }
 
 #[test]
@@ -159,6 +202,23 @@ fn shortest_f64_hard_random_equivalence_test() {
 }
 
 #[test]
+#[cfg(target_has_reliable_f16)]
+fn exact_f16_random_equivalence_test() {
+    use core::num::flt2dec::strategy::dragon::format_exact as fallback;
+    // Miri is too slow
+    let n = if cfg!(miri) { 3 } else { 1_000 };
+
+    for k in 1..21 {
+        f16_random_equivalence_test(
+            |d, buf| format_exact_opt(d, buf, i16::MIN),
+            |d, buf| fallback(d, buf, i16::MIN),
+            k,
+            n,
+        );
+    }
+}
+
+#[test]
 fn exact_f32_random_equivalence_test() {
     use core::num::flt2dec::strategy::dragon::format_exact as fallback;
     // Miri is too slow
diff --git a/library/coretests/tests/num/flt2dec/strategy/dragon.rs b/library/coretests/tests/num/flt2dec/strategy/dragon.rs
index be25fee3f6c..43bb6024f9c 100644
--- a/library/coretests/tests/num/flt2dec/strategy/dragon.rs
+++ b/library/coretests/tests/num/flt2dec/strategy/dragon.rs
@@ -18,6 +18,8 @@ fn test_mul_pow10() {
 fn shortest_sanity_test() {
     f64_shortest_sanity_test(format_shortest);
     f32_shortest_sanity_test(format_shortest);
+    #[cfg(target_has_reliable_f16)]
+    f16_shortest_sanity_test(format_shortest);
     more_shortest_sanity_test(format_shortest);
 }
 
@@ -41,6 +43,9 @@ fn exact_sanity_test() {
         f64_exact_sanity_test(format_exact);
     }
     f32_exact_sanity_test(format_exact);
+
+    #[cfg(target_has_reliable_f16)]
+    f16_exact_sanity_test(format_exact);
 }
 
 #[test]
diff --git a/library/coretests/tests/num/flt2dec/strategy/grisu.rs b/library/coretests/tests/num/flt2dec/strategy/grisu.rs
index 9b2f0453de7..117191e0c8f 100644
--- a/library/coretests/tests/num/flt2dec/strategy/grisu.rs
+++ b/library/coretests/tests/num/flt2dec/strategy/grisu.rs
@@ -38,6 +38,8 @@ fn test_max_pow10_no_more_than() {
 fn shortest_sanity_test() {
     f64_shortest_sanity_test(format_shortest);
     f32_shortest_sanity_test(format_shortest);
+    #[cfg(target_has_reliable_f16)]
+    f16_shortest_sanity_test(format_shortest);
     more_shortest_sanity_test(format_shortest);
 }
 
@@ -50,6 +52,8 @@ fn exact_sanity_test() {
         f64_exact_sanity_test(format_exact);
     }
     f32_exact_sanity_test(format_exact);
+    #[cfg(target_has_reliable_f16)]
+    f16_exact_sanity_test(format_exact);
 }
 
 #[test]
diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs
index 0add9a01e68..a6b75f70266 100644
--- a/library/coretests/tests/num/mod.rs
+++ b/library/coretests/tests/num/mod.rs
@@ -732,157 +732,157 @@ assume_usize_width! {
 }
 
 macro_rules! test_float {
-    ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => {
+    ($modname: ident, $fassert: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr, $min: expr, $max: expr, $min_pos: expr, $max_exp:expr) => {
         mod $modname {
             #[test]
             fn min() {
-                assert_eq!((0.0 as $fty).min(0.0), 0.0);
-                assert!((0.0 as $fty).min(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).min(-0.0), -0.0);
-                assert!((-0.0 as $fty).min(-0.0).is_sign_negative());
-                assert_eq!((9.0 as $fty).min(9.0), 9.0);
-                assert_eq!((-9.0 as $fty).min(0.0), -9.0);
-                assert_eq!((0.0 as $fty).min(9.0), 0.0);
-                assert!((0.0 as $fty).min(9.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).min(9.0), -0.0);
-                assert!((-0.0 as $fty).min(9.0).is_sign_negative());
-                assert_eq!((-0.0 as $fty).min(-9.0), -9.0);
-                assert_eq!(($inf as $fty).min(9.0), 9.0);
-                assert_eq!((9.0 as $fty).min($inf), 9.0);
-                assert_eq!(($inf as $fty).min(-9.0), -9.0);
-                assert_eq!((-9.0 as $fty).min($inf), -9.0);
-                assert_eq!(($neginf as $fty).min(9.0), $neginf);
-                assert_eq!((9.0 as $fty).min($neginf), $neginf);
-                assert_eq!(($neginf as $fty).min(-9.0), $neginf);
-                assert_eq!((-9.0 as $fty).min($neginf), $neginf);
-                assert_eq!(($nan as $fty).min(9.0), 9.0);
-                assert_eq!(($nan as $fty).min(-9.0), -9.0);
-                assert_eq!((9.0 as $fty).min($nan), 9.0);
-                assert_eq!((-9.0 as $fty).min($nan), -9.0);
-                assert!(($nan as $fty).min($nan).is_nan());
+                $fassert!((0.0 as $fty).min(0.0), 0.0);
+                $fassert!((0.0 as $fty).min(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).min(-0.0), -0.0);
+                $fassert!((-0.0 as $fty).min(-0.0).is_sign_negative());
+                $fassert!((9.0 as $fty).min(9.0), 9.0);
+                $fassert!((-9.0 as $fty).min(0.0), -9.0);
+                $fassert!((0.0 as $fty).min(9.0), 0.0);
+                $fassert!((0.0 as $fty).min(9.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).min(9.0), -0.0);
+                $fassert!((-0.0 as $fty).min(9.0).is_sign_negative());
+                $fassert!((-0.0 as $fty).min(-9.0), -9.0);
+                $fassert!(($inf as $fty).min(9.0), 9.0);
+                $fassert!((9.0 as $fty).min($inf), 9.0);
+                $fassert!(($inf as $fty).min(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).min($inf), -9.0);
+                $fassert!(($neginf as $fty).min(9.0), $neginf);
+                $fassert!((9.0 as $fty).min($neginf), $neginf);
+                $fassert!(($neginf as $fty).min(-9.0), $neginf);
+                $fassert!((-9.0 as $fty).min($neginf), $neginf);
+                $fassert!(($nan as $fty).min(9.0), 9.0);
+                $fassert!(($nan as $fty).min(-9.0), -9.0);
+                $fassert!((9.0 as $fty).min($nan), 9.0);
+                $fassert!((-9.0 as $fty).min($nan), -9.0);
+                $fassert!(($nan as $fty).min($nan).is_nan());
             }
             #[test]
             fn max() {
-                assert_eq!((0.0 as $fty).max(0.0), 0.0);
-                assert!((0.0 as $fty).max(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).max(-0.0), -0.0);
-                assert!((-0.0 as $fty).max(-0.0).is_sign_negative());
-                assert_eq!((9.0 as $fty).max(9.0), 9.0);
-                assert_eq!((-9.0 as $fty).max(0.0), 0.0);
-                assert!((-9.0 as $fty).max(0.0).is_sign_positive());
-                assert_eq!((-9.0 as $fty).max(-0.0), -0.0);
-                assert!((-9.0 as $fty).max(-0.0).is_sign_negative());
-                assert_eq!((0.0 as $fty).max(9.0), 9.0);
-                assert_eq!((0.0 as $fty).max(-9.0), 0.0);
-                assert!((0.0 as $fty).max(-9.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).max(-9.0), -0.0);
-                assert!((-0.0 as $fty).max(-9.0).is_sign_negative());
-                assert_eq!(($inf as $fty).max(9.0), $inf);
-                assert_eq!((9.0 as $fty).max($inf), $inf);
-                assert_eq!(($inf as $fty).max(-9.0), $inf);
-                assert_eq!((-9.0 as $fty).max($inf), $inf);
-                assert_eq!(($neginf as $fty).max(9.0), 9.0);
-                assert_eq!((9.0 as $fty).max($neginf), 9.0);
-                assert_eq!(($neginf as $fty).max(-9.0), -9.0);
-                assert_eq!((-9.0 as $fty).max($neginf), -9.0);
-                assert_eq!(($nan as $fty).max(9.0), 9.0);
-                assert_eq!(($nan as $fty).max(-9.0), -9.0);
-                assert_eq!((9.0 as $fty).max($nan), 9.0);
-                assert_eq!((-9.0 as $fty).max($nan), -9.0);
-                assert!(($nan as $fty).max($nan).is_nan());
+                $fassert!((0.0 as $fty).max(0.0), 0.0);
+                $fassert!((0.0 as $fty).max(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).max(-0.0), -0.0);
+                $fassert!((-0.0 as $fty).max(-0.0).is_sign_negative());
+                $fassert!((9.0 as $fty).max(9.0), 9.0);
+                $fassert!((-9.0 as $fty).max(0.0), 0.0);
+                $fassert!((-9.0 as $fty).max(0.0).is_sign_positive());
+                $fassert!((-9.0 as $fty).max(-0.0), -0.0);
+                $fassert!((-9.0 as $fty).max(-0.0).is_sign_negative());
+                $fassert!((0.0 as $fty).max(9.0), 9.0);
+                $fassert!((0.0 as $fty).max(-9.0), 0.0);
+                $fassert!((0.0 as $fty).max(-9.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).max(-9.0), -0.0);
+                $fassert!((-0.0 as $fty).max(-9.0).is_sign_negative());
+                $fassert!(($inf as $fty).max(9.0), $inf);
+                $fassert!((9.0 as $fty).max($inf), $inf);
+                $fassert!(($inf as $fty).max(-9.0), $inf);
+                $fassert!((-9.0 as $fty).max($inf), $inf);
+                $fassert!(($neginf as $fty).max(9.0), 9.0);
+                $fassert!((9.0 as $fty).max($neginf), 9.0);
+                $fassert!(($neginf as $fty).max(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).max($neginf), -9.0);
+                $fassert!(($nan as $fty).max(9.0), 9.0);
+                $fassert!(($nan as $fty).max(-9.0), -9.0);
+                $fassert!((9.0 as $fty).max($nan), 9.0);
+                $fassert!((-9.0 as $fty).max($nan), -9.0);
+                $fassert!(($nan as $fty).max($nan).is_nan());
             }
             #[test]
             fn minimum() {
-                assert_eq!((0.0 as $fty).minimum(0.0), 0.0);
-                assert!((0.0 as $fty).minimum(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).minimum(0.0), -0.0);
-                assert!((-0.0 as $fty).minimum(0.0).is_sign_negative());
-                assert_eq!((-0.0 as $fty).minimum(-0.0), -0.0);
-                assert!((-0.0 as $fty).minimum(-0.0).is_sign_negative());
-                assert_eq!((9.0 as $fty).minimum(9.0), 9.0);
-                assert_eq!((-9.0 as $fty).minimum(0.0), -9.0);
-                assert_eq!((0.0 as $fty).minimum(9.0), 0.0);
-                assert!((0.0 as $fty).minimum(9.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).minimum(9.0), -0.0);
-                assert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
-                assert_eq!((-0.0 as $fty).minimum(-9.0), -9.0);
-                assert_eq!(($inf as $fty).minimum(9.0), 9.0);
-                assert_eq!((9.0 as $fty).minimum($inf), 9.0);
-                assert_eq!(($inf as $fty).minimum(-9.0), -9.0);
-                assert_eq!((-9.0 as $fty).minimum($inf), -9.0);
-                assert_eq!(($neginf as $fty).minimum(9.0), $neginf);
-                assert_eq!((9.0 as $fty).minimum($neginf), $neginf);
-                assert_eq!(($neginf as $fty).minimum(-9.0), $neginf);
-                assert_eq!((-9.0 as $fty).minimum($neginf), $neginf);
-                assert!(($nan as $fty).minimum(9.0).is_nan());
-                assert!(($nan as $fty).minimum(-9.0).is_nan());
-                assert!((9.0 as $fty).minimum($nan).is_nan());
-                assert!((-9.0 as $fty).minimum($nan).is_nan());
-                assert!(($nan as $fty).minimum($nan).is_nan());
+                $fassert!((0.0 as $fty).minimum(0.0), 0.0);
+                $fassert!((0.0 as $fty).minimum(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).minimum(0.0), -0.0);
+                $fassert!((-0.0 as $fty).minimum(0.0).is_sign_negative());
+                $fassert!((-0.0 as $fty).minimum(-0.0), -0.0);
+                $fassert!((-0.0 as $fty).minimum(-0.0).is_sign_negative());
+                $fassert!((9.0 as $fty).minimum(9.0), 9.0);
+                $fassert!((-9.0 as $fty).minimum(0.0), -9.0);
+                $fassert!((0.0 as $fty).minimum(9.0), 0.0);
+                $fassert!((0.0 as $fty).minimum(9.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).minimum(9.0), -0.0);
+                $fassert!((-0.0 as $fty).minimum(9.0).is_sign_negative());
+                $fassert!((-0.0 as $fty).minimum(-9.0), -9.0);
+                $fassert!(($inf as $fty).minimum(9.0), 9.0);
+                $fassert!((9.0 as $fty).minimum($inf), 9.0);
+                $fassert!(($inf as $fty).minimum(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).minimum($inf), -9.0);
+                $fassert!(($neginf as $fty).minimum(9.0), $neginf);
+                $fassert!((9.0 as $fty).minimum($neginf), $neginf);
+                $fassert!(($neginf as $fty).minimum(-9.0), $neginf);
+                $fassert!((-9.0 as $fty).minimum($neginf), $neginf);
+                $fassert!(($nan as $fty).minimum(9.0).is_nan());
+                $fassert!(($nan as $fty).minimum(-9.0).is_nan());
+                $fassert!((9.0 as $fty).minimum($nan).is_nan());
+                $fassert!((-9.0 as $fty).minimum($nan).is_nan());
+                $fassert!(($nan as $fty).minimum($nan).is_nan());
             }
             #[test]
             fn maximum() {
-                assert_eq!((0.0 as $fty).maximum(0.0), 0.0);
-                assert!((0.0 as $fty).maximum(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).maximum(0.0), 0.0);
-                assert!((-0.0 as $fty).maximum(0.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).maximum(-0.0), -0.0);
-                assert!((-0.0 as $fty).maximum(-0.0).is_sign_negative());
-                assert_eq!((9.0 as $fty).maximum(9.0), 9.0);
-                assert_eq!((-9.0 as $fty).maximum(0.0), 0.0);
-                assert!((-9.0 as $fty).maximum(0.0).is_sign_positive());
-                assert_eq!((-9.0 as $fty).maximum(-0.0), -0.0);
-                assert!((-9.0 as $fty).maximum(-0.0).is_sign_negative());
-                assert_eq!((0.0 as $fty).maximum(9.0), 9.0);
-                assert_eq!((0.0 as $fty).maximum(-9.0), 0.0);
-                assert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
-                assert_eq!((-0.0 as $fty).maximum(-9.0), -0.0);
-                assert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
-                assert_eq!(($inf as $fty).maximum(9.0), $inf);
-                assert_eq!((9.0 as $fty).maximum($inf), $inf);
-                assert_eq!(($inf as $fty).maximum(-9.0), $inf);
-                assert_eq!((-9.0 as $fty).maximum($inf), $inf);
-                assert_eq!(($neginf as $fty).maximum(9.0), 9.0);
-                assert_eq!((9.0 as $fty).maximum($neginf), 9.0);
-                assert_eq!(($neginf as $fty).maximum(-9.0), -9.0);
-                assert_eq!((-9.0 as $fty).maximum($neginf), -9.0);
-                assert!(($nan as $fty).maximum(9.0).is_nan());
-                assert!(($nan as $fty).maximum(-9.0).is_nan());
-                assert!((9.0 as $fty).maximum($nan).is_nan());
-                assert!((-9.0 as $fty).maximum($nan).is_nan());
-                assert!(($nan as $fty).maximum($nan).is_nan());
+                $fassert!((0.0 as $fty).maximum(0.0), 0.0);
+                $fassert!((0.0 as $fty).maximum(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).maximum(0.0), 0.0);
+                $fassert!((-0.0 as $fty).maximum(0.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).maximum(-0.0), -0.0);
+                $fassert!((-0.0 as $fty).maximum(-0.0).is_sign_negative());
+                $fassert!((9.0 as $fty).maximum(9.0), 9.0);
+                $fassert!((-9.0 as $fty).maximum(0.0), 0.0);
+                $fassert!((-9.0 as $fty).maximum(0.0).is_sign_positive());
+                $fassert!((-9.0 as $fty).maximum(-0.0), -0.0);
+                $fassert!((-9.0 as $fty).maximum(-0.0).is_sign_negative());
+                $fassert!((0.0 as $fty).maximum(9.0), 9.0);
+                $fassert!((0.0 as $fty).maximum(-9.0), 0.0);
+                $fassert!((0.0 as $fty).maximum(-9.0).is_sign_positive());
+                $fassert!((-0.0 as $fty).maximum(-9.0), -0.0);
+                $fassert!((-0.0 as $fty).maximum(-9.0).is_sign_negative());
+                $fassert!(($inf as $fty).maximum(9.0), $inf);
+                $fassert!((9.0 as $fty).maximum($inf), $inf);
+                $fassert!(($inf as $fty).maximum(-9.0), $inf);
+                $fassert!((-9.0 as $fty).maximum($inf), $inf);
+                $fassert!(($neginf as $fty).maximum(9.0), 9.0);
+                $fassert!((9.0 as $fty).maximum($neginf), 9.0);
+                $fassert!(($neginf as $fty).maximum(-9.0), -9.0);
+                $fassert!((-9.0 as $fty).maximum($neginf), -9.0);
+                $fassert!(($nan as $fty).maximum(9.0).is_nan());
+                $fassert!(($nan as $fty).maximum(-9.0).is_nan());
+                $fassert!((9.0 as $fty).maximum($nan).is_nan());
+                $fassert!((-9.0 as $fty).maximum($nan).is_nan());
+                $fassert!(($nan as $fty).maximum($nan).is_nan());
             }
             #[test]
             fn midpoint() {
-                assert_eq!((0.5 as $fty).midpoint(0.5), 0.5);
-                assert_eq!((0.5 as $fty).midpoint(2.5), 1.5);
-                assert_eq!((3.0 as $fty).midpoint(4.0), 3.5);
-                assert_eq!((-3.0 as $fty).midpoint(4.0), 0.5);
-                assert_eq!((3.0 as $fty).midpoint(-4.0), -0.5);
-                assert_eq!((-3.0 as $fty).midpoint(-4.0), -3.5);
-                assert_eq!((0.0 as $fty).midpoint(0.0), 0.0);
-                assert_eq!((-0.0 as $fty).midpoint(-0.0), -0.0);
-                assert_eq!((-5.0 as $fty).midpoint(5.0), 0.0);
-                assert_eq!(($max as $fty).midpoint($min), 0.0);
-                assert_eq!(($min as $fty).midpoint($max), -0.0);
-                assert_eq!(($max as $fty).midpoint($min_pos), $max / 2.);
-                assert_eq!((-$max as $fty).midpoint($min_pos), -$max / 2.);
-                assert_eq!(($max as $fty).midpoint(-$min_pos), $max / 2.);
-                assert_eq!((-$max as $fty).midpoint(-$min_pos), -$max / 2.);
-                assert_eq!(($min_pos as $fty).midpoint($max), $max / 2.);
-                assert_eq!(($min_pos as $fty).midpoint(-$max), -$max / 2.);
-                assert_eq!((-$min_pos as $fty).midpoint($max), $max / 2.);
-                assert_eq!((-$min_pos as $fty).midpoint(-$max), -$max / 2.);
-                assert_eq!(($max as $fty).midpoint($max), $max);
-                assert_eq!(($min_pos as $fty).midpoint($min_pos), $min_pos);
-                assert_eq!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos);
-                assert_eq!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5);
-                assert_eq!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5);
-                assert_eq!(($inf as $fty).midpoint($inf), $inf);
-                assert_eq!(($neginf as $fty).midpoint($neginf), $neginf);
-                assert!(($nan as $fty).midpoint(1.0).is_nan());
-                assert!((1.0 as $fty).midpoint($nan).is_nan());
-                assert!(($nan as $fty).midpoint($nan).is_nan());
+                $fassert!((0.5 as $fty).midpoint(0.5), 0.5);
+                $fassert!((0.5 as $fty).midpoint(2.5), 1.5);
+                $fassert!((3.0 as $fty).midpoint(4.0), 3.5);
+                $fassert!((-3.0 as $fty).midpoint(4.0), 0.5);
+                $fassert!((3.0 as $fty).midpoint(-4.0), -0.5);
+                $fassert!((-3.0 as $fty).midpoint(-4.0), -3.5);
+                $fassert!((0.0 as $fty).midpoint(0.0), 0.0);
+                $fassert!((-0.0 as $fty).midpoint(-0.0), -0.0);
+                $fassert!((-5.0 as $fty).midpoint(5.0), 0.0);
+                $fassert!(($max as $fty).midpoint($min), 0.0);
+                $fassert!(($min as $fty).midpoint($max), -0.0);
+                $fassert!(($max as $fty).midpoint($min_pos), $max / 2.);
+                $fassert!((-$max as $fty).midpoint($min_pos), -$max / 2.);
+                $fassert!(($max as $fty).midpoint(-$min_pos), $max / 2.);
+                $fassert!((-$max as $fty).midpoint(-$min_pos), -$max / 2.);
+                $fassert!(($min_pos as $fty).midpoint($max), $max / 2.);
+                $fassert!(($min_pos as $fty).midpoint(-$max), -$max / 2.);
+                $fassert!((-$min_pos as $fty).midpoint($max), $max / 2.);
+                $fassert!((-$min_pos as $fty).midpoint(-$max), -$max / 2.);
+                $fassert!(($max as $fty).midpoint($max), $max);
+                $fassert!(($min_pos as $fty).midpoint($min_pos), $min_pos);
+                $fassert!((-$min_pos as $fty).midpoint(-$min_pos), -$min_pos);
+                $fassert!(($max as $fty).midpoint(5.0), $max / 2.0 + 2.5);
+                $fassert!(($max as $fty).midpoint(-5.0), $max / 2.0 - 2.5);
+                $fassert!(($inf as $fty).midpoint($inf), $inf);
+                $fassert!(($neginf as $fty).midpoint($neginf), $neginf);
+                $fassert!(($nan as $fty).midpoint(1.0).is_nan());
+                $fassert!((1.0 as $fty).midpoint($nan).is_nan());
+                $fassert!(($nan as $fty).midpoint($nan).is_nan());
 
                 // test if large differences in magnitude are still correctly computed.
                 // NOTE: that because of how small x and y are, x + y can never overflow
@@ -907,19 +907,19 @@ macro_rules! test_float {
             }
             #[test]
             fn rem_euclid() {
-                let a: $fty = 42.0;
-                assert!($inf.rem_euclid(a).is_nan());
-                assert_eq!(a.rem_euclid($inf), a);
-                assert!(a.rem_euclid($nan).is_nan());
+                // FIXME: Use $fassert when rem_euclid becomes const
+                assert!($inf.rem_euclid((42.0 as $fty)).is_nan());
+                assert_eq!((42.0 as $fty).rem_euclid($inf), (42.0 as $fty));
+                assert!((42.0 as $fty).rem_euclid($nan).is_nan());
                 assert!($inf.rem_euclid($inf).is_nan());
                 assert!($inf.rem_euclid($nan).is_nan());
                 assert!($nan.rem_euclid($inf).is_nan());
             }
             #[test]
             fn div_euclid() {
-                let a: $fty = 42.0;
-                assert_eq!(a.div_euclid($inf), 0.0);
-                assert!(a.div_euclid($nan).is_nan());
+                // FIXME: Use $fassert when div_euclid becomes const
+                assert_eq!((42.0 as $fty).div_euclid($inf), 0.0);
+                assert!((42.0 as $fty).div_euclid($nan).is_nan());
                 assert!($inf.div_euclid($inf).is_nan());
                 assert!($inf.div_euclid($nan).is_nan());
                 assert!($nan.div_euclid($inf).is_nan());
@@ -928,8 +928,41 @@ macro_rules! test_float {
     };
 }
 
+// Custom assert macro that distribute between assert! and assert_eq! in a non-const context
+macro_rules! float_assert {
+    ($b:expr) => {
+        assert!($b);
+    };
+    ($left:expr, $right:expr) => {
+        assert_eq!($left, $right);
+    };
+}
+
+// Custom assert macro that only uses assert! in a const context
+macro_rules! float_const_assert {
+    ($b:expr) => {
+        assert!(const { $b });
+    };
+    ($left:expr, $right:expr) => {
+        assert!(const { $left == $right });
+    };
+}
+
 test_float!(
     f32,
+    float_assert,
+    f32,
+    f32::INFINITY,
+    f32::NEG_INFINITY,
+    f32::NAN,
+    f32::MIN,
+    f32::MAX,
+    f32::MIN_POSITIVE,
+    f32::MAX_EXP
+);
+test_float!(
+    f32_const,
+    float_const_assert,
     f32,
     f32::INFINITY,
     f32::NEG_INFINITY,
@@ -941,6 +974,19 @@ test_float!(
 );
 test_float!(
     f64,
+    float_assert,
+    f64,
+    f64::INFINITY,
+    f64::NEG_INFINITY,
+    f64::NAN,
+    f64::MIN,
+    f64::MAX,
+    f64::MIN_POSITIVE,
+    f64::MAX_EXP
+);
+test_float!(
+    f64_const,
+    float_const_assert,
     f64,
     f64::INFINITY,
     f64::NEG_INFINITY,
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 94140d01d8b..5210e75ec45 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -46,7 +46,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn floor(self) -> f32 {
-        core::f32::floor(self)
+        core::f32::math::floor(self)
     }
 
     /// Returns the smallest integer greater than or equal to `self`.
@@ -68,7 +68,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn ceil(self) -> f32 {
-        core::f32::ceil(self)
+        core::f32::math::ceil(self)
     }
 
     /// Returns the nearest integer to `self`. If a value is half-way between two
@@ -96,7 +96,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn round(self) -> f32 {
-        core::f32::round(self)
+        core::f32::math::round(self)
     }
 
     /// Returns the nearest integer to a number. Rounds half-way cases to the number
@@ -122,7 +122,7 @@ impl f32 {
     #[stable(feature = "round_ties_even", since = "1.77.0")]
     #[inline]
     pub fn round_ties_even(self) -> f32 {
-        core::f32::round_ties_even(self)
+        core::f32::math::round_ties_even(self)
     }
 
     /// Returns the integer part of `self`.
@@ -147,7 +147,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn trunc(self) -> f32 {
-        core::f32::trunc(self)
+        core::f32::math::trunc(self)
     }
 
     /// Returns the fractional part of `self`.
@@ -170,7 +170,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn fract(self) -> f32 {
-        core::f32::fract(self)
+        core::f32::math::fract(self)
     }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
@@ -212,7 +212,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn mul_add(self, a: f32, b: f32) -> f32 {
-        core::f32::mul_add(self, a, b)
+        core::f32::math::mul_add(self, a, b)
     }
 
     /// Calculates Euclidean division, the matching method for `rem_euclid`.
@@ -242,7 +242,7 @@ impl f32 {
     #[inline]
     #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn div_euclid(self, rhs: f32) -> f32 {
-        core::f32::div_euclid(self, rhs)
+        core::f32::math::div_euclid(self, rhs)
     }
 
     /// Calculates the least nonnegative remainder of `self (mod rhs)`.
@@ -279,7 +279,7 @@ impl f32 {
     #[inline]
     #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn rem_euclid(self, rhs: f32) -> f32 {
-        core::f32::rem_euclid(self, rhs)
+        core::f32::math::rem_euclid(self, rhs)
     }
 
     /// Raises a number to an integer power.
@@ -307,7 +307,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn powi(self, n: i32) -> f32 {
-        core::f32::powi(self, n)
+        core::f32::math::powi(self, n)
     }
 
     /// Raises a number to a floating point power.
@@ -362,7 +362,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn sqrt(self) -> f32 {
-        core::f32::sqrt(self)
+        core::f32::math::sqrt(self)
     }
 
     /// Returns `e^(self)`, (the exponential function).
@@ -595,7 +595,7 @@ impl f32 {
     )]
     pub fn abs_sub(self, other: f32) -> f32 {
         #[allow(deprecated)]
-        core::f32::abs_sub(self, other)
+        core::f32::math::abs_sub(self, other)
     }
 
     /// Returns the cube root of a number.
@@ -622,7 +622,7 @@ impl f32 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn cbrt(self) -> f32 {
-        core::f32::cbrt(self)
+        core::f32::math::cbrt(self)
     }
 
     /// Compute the distance between the origin and a point (`x`, `y`) on the
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 051061ae605..f837800d663 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -46,7 +46,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn floor(self) -> f64 {
-        core::f64::floor(self)
+        core::f64::math::floor(self)
     }
 
     /// Returns the smallest integer greater than or equal to `self`.
@@ -68,7 +68,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn ceil(self) -> f64 {
-        core::f64::ceil(self)
+        core::f64::math::ceil(self)
     }
 
     /// Returns the nearest integer to `self`. If a value is half-way between two
@@ -96,7 +96,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn round(self) -> f64 {
-        core::f64::round(self)
+        core::f64::math::round(self)
     }
 
     /// Returns the nearest integer to a number. Rounds half-way cases to the number
@@ -122,7 +122,7 @@ impl f64 {
     #[stable(feature = "round_ties_even", since = "1.77.0")]
     #[inline]
     pub fn round_ties_even(self) -> f64 {
-        core::f64::round_ties_even(self)
+        core::f64::math::round_ties_even(self)
     }
 
     /// Returns the integer part of `self`.
@@ -147,7 +147,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn trunc(self) -> f64 {
-        core::f64::trunc(self)
+        core::f64::math::trunc(self)
     }
 
     /// Returns the fractional part of `self`.
@@ -170,7 +170,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn fract(self) -> f64 {
-        core::f64::fract(self)
+        core::f64::math::fract(self)
     }
 
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
@@ -212,7 +212,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn mul_add(self, a: f64, b: f64) -> f64 {
-        core::f64::mul_add(self, a, b)
+        core::f64::math::mul_add(self, a, b)
     }
 
     /// Calculates Euclidean division, the matching method for `rem_euclid`.
@@ -242,7 +242,7 @@ impl f64 {
     #[inline]
     #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn div_euclid(self, rhs: f64) -> f64 {
-        core::f64::div_euclid(self, rhs)
+        core::f64::math::div_euclid(self, rhs)
     }
 
     /// Calculates the least nonnegative remainder of `self (mod rhs)`.
@@ -279,7 +279,7 @@ impl f64 {
     #[inline]
     #[stable(feature = "euclidean_division", since = "1.38.0")]
     pub fn rem_euclid(self, rhs: f64) -> f64 {
-        core::f64::rem_euclid(self, rhs)
+        core::f64::math::rem_euclid(self, rhs)
     }
 
     /// Raises a number to an integer power.
@@ -307,7 +307,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn powi(self, n: i32) -> f64 {
-        core::f64::powi(self, n)
+        core::f64::math::powi(self, n)
     }
 
     /// Raises a number to a floating point power.
@@ -362,7 +362,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn sqrt(self) -> f64 {
-        core::f64::sqrt(self)
+        core::f64::math::sqrt(self)
     }
 
     /// Returns `e^(self)`, (the exponential function).
@@ -595,7 +595,7 @@ impl f64 {
     )]
     pub fn abs_sub(self, other: f64) -> f64 {
         #[allow(deprecated)]
-        core::f64::abs_sub(self, other)
+        core::f64::math::abs_sub(self, other)
     }
 
     /// Returns the cube root of a number.
@@ -622,7 +622,7 @@ impl f64 {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn cbrt(self) -> f64 {
-        core::f64::cbrt(self)
+        core::f64::math::cbrt(self)
     }
 
     /// Compute the distance between the origin and a point (`x`, `y`) on the
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 72bdf03ee61..ead48775127 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -1040,7 +1040,7 @@ impl OsStr {
     /// Converts a <code>[Box]<[OsStr]></code> into an [`OsString`] without copying or allocating.
     #[stable(feature = "into_boxed_os_str", since = "1.20.0")]
     #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_os_string(self: Box<OsStr>) -> OsString {
+    pub fn into_os_string(self: Box<Self>) -> OsString {
         let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
         OsString { inner: Buf::from_box(boxed) }
     }
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 11f439b9996..509e673bdb8 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -285,8 +285,7 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
     fn inner(path: &Path) -> io::Result<Vec<u8>> {
         let mut file = File::open(path)?;
         let size = file.metadata().map(|m| m.len() as usize).ok();
-        let mut bytes = Vec::new();
-        bytes.try_reserve_exact(size.unwrap_or(0))?;
+        let mut bytes = Vec::try_with_capacity(size.unwrap_or(0))?;
         io::default_read_to_end(&mut file, &mut bytes, size)?;
         Ok(bytes)
     }
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 96fac4f6bde..03f5f838311 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1214,7 +1214,7 @@ pub trait Read {
     where
         Self: Sized,
     {
-        Take { inner: self, limit }
+        Take { inner: self, len: limit, limit }
     }
 }
 
@@ -2830,6 +2830,7 @@ impl<T, U> SizeHint for Chain<T, U> {
 #[derive(Debug)]
 pub struct Take<T> {
     inner: T,
+    len: u64,
     limit: u64,
 }
 
@@ -2864,6 +2865,12 @@ impl<T> Take<T> {
         self.limit
     }
 
+    /// Returns the number of bytes read so far.
+    #[unstable(feature = "seek_io_take_position", issue = "97227")]
+    pub fn position(&self) -> u64 {
+        self.len - self.limit
+    }
+
     /// Sets the number of bytes that can be read before this instance will
     /// return EOF. This is the same as constructing a new `Take` instance, so
     /// the amount of bytes read and the previous limit value don't matter when
@@ -2889,6 +2896,7 @@ impl<T> Take<T> {
     /// ```
     #[stable(feature = "take_set_limit", since = "1.27.0")]
     pub fn set_limit(&mut self, limit: u64) {
+        self.len = limit;
         self.limit = limit;
     }
 
@@ -3076,6 +3084,49 @@ impl<T> SizeHint for Take<T> {
     }
 }
 
+#[stable(feature = "seek_io_take", since = "CURRENT_RUSTC_VERSION")]
+impl<T: Seek> Seek for Take<T> {
+    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
+        let new_position = match pos {
+            SeekFrom::Start(v) => Some(v),
+            SeekFrom::Current(v) => self.position().checked_add_signed(v),
+            SeekFrom::End(v) => self.len.checked_add_signed(v),
+        };
+        let new_position = match new_position {
+            Some(v) if v <= self.len => v,
+            _ => return Err(ErrorKind::InvalidInput.into()),
+        };
+        while new_position != self.position() {
+            if let Some(offset) = new_position.checked_signed_diff(self.position()) {
+                self.inner.seek_relative(offset)?;
+                self.limit = self.limit.wrapping_sub(offset as u64);
+                break;
+            }
+            let offset = if new_position > self.position() { i64::MAX } else { i64::MIN };
+            self.inner.seek_relative(offset)?;
+            self.limit = self.limit.wrapping_sub(offset as u64);
+        }
+        Ok(new_position)
+    }
+
+    fn stream_len(&mut self) -> Result<u64> {
+        Ok(self.len)
+    }
+
+    fn stream_position(&mut self) -> Result<u64> {
+        Ok(self.position())
+    }
+
+    fn seek_relative(&mut self, offset: i64) -> Result<()> {
+        if !self.position().checked_add_signed(offset).is_some_and(|p| p <= self.len) {
+            return Err(ErrorKind::InvalidInput.into());
+        }
+        self.inner.seek_relative(offset)?;
+        self.limit = self.limit.wrapping_sub(offset as u64);
+        Ok(())
+    }
+}
+
 /// An iterator over `u8` values of a reader.
 ///
 /// This struct is generally created by calling [`bytes`] on a reader.
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index fd962b0415c..b22988d4a8a 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -416,6 +416,126 @@ fn seek_position() -> io::Result<()> {
     Ok(())
 }
 
+#[test]
+fn take_seek() -> io::Result<()> {
+    let mut buf = Cursor::new(b"0123456789");
+    buf.set_position(2);
+    let mut take = buf.by_ref().take(4);
+    let mut buf1 = [0u8; 1];
+    let mut buf2 = [0u8; 2];
+    assert_eq!(take.position(), 0);
+
+    assert_eq!(take.seek(SeekFrom::Start(0))?, 0);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'2', b'3']);
+    assert_eq!(take.seek(SeekFrom::Start(1))?, 1);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'3', b'4']);
+    assert_eq!(take.seek(SeekFrom::Start(2))?, 2);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'4', b'5']);
+    assert_eq!(take.seek(SeekFrom::Start(3))?, 3);
+    take.read_exact(&mut buf1)?;
+    assert_eq!(buf1, [b'5']);
+    assert_eq!(take.seek(SeekFrom::Start(4))?, 4);
+    assert_eq!(take.read(&mut buf1)?, 0);
+
+    assert_eq!(take.seek(SeekFrom::End(0))?, 4);
+    assert_eq!(take.seek(SeekFrom::End(-1))?, 3);
+    take.read_exact(&mut buf1)?;
+    assert_eq!(buf1, [b'5']);
+    assert_eq!(take.seek(SeekFrom::End(-2))?, 2);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'4', b'5']);
+    assert_eq!(take.seek(SeekFrom::End(-3))?, 1);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'3', b'4']);
+    assert_eq!(take.seek(SeekFrom::End(-4))?, 0);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'2', b'3']);
+
+    assert_eq!(take.seek(SeekFrom::Current(0))?, 2);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'4', b'5']);
+
+    assert_eq!(take.seek(SeekFrom::Current(-3))?, 1);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'3', b'4']);
+
+    assert_eq!(take.seek(SeekFrom::Current(-1))?, 2);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'4', b'5']);
+
+    assert_eq!(take.seek(SeekFrom::Current(-4))?, 0);
+    take.read_exact(&mut buf2)?;
+    assert_eq!(buf2, [b'2', b'3']);
+
+    assert_eq!(take.seek(SeekFrom::Current(2))?, 4);
+    assert_eq!(take.read(&mut buf1)?, 0);
+
+    Ok(())
+}
+
+#[test]
+fn take_seek_error() {
+    let buf = Cursor::new(b"0123456789");
+    let mut take = buf.take(2);
+    assert!(take.seek(SeekFrom::Start(3)).is_err());
+    assert!(take.seek(SeekFrom::End(1)).is_err());
+    assert!(take.seek(SeekFrom::End(-3)).is_err());
+    assert!(take.seek(SeekFrom::Current(-1)).is_err());
+    assert!(take.seek(SeekFrom::Current(3)).is_err());
+}
+
+struct ExampleHugeRangeOfZeroes {
+    position: u64,
+}
+
+impl Read for ExampleHugeRangeOfZeroes {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        let max = buf.len().min(usize::MAX);
+        for i in 0..max {
+            if self.position == u64::MAX {
+                return Ok(i);
+            }
+            self.position += 1;
+            buf[i] = 0;
+        }
+        Ok(max)
+    }
+}
+
+impl Seek for ExampleHugeRangeOfZeroes {
+    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
+        match pos {
+            io::SeekFrom::Start(i) => self.position = i,
+            io::SeekFrom::End(i) if i >= 0 => self.position = u64::MAX,
+            io::SeekFrom::End(i) => self.position = self.position - i.unsigned_abs(),
+            io::SeekFrom::Current(i) => {
+                self.position = if i >= 0 {
+                    self.position.saturating_add(i.unsigned_abs())
+                } else {
+                    self.position.saturating_sub(i.unsigned_abs())
+                };
+            }
+        }
+        Ok(self.position)
+    }
+}
+
+#[test]
+fn take_seek_big_offsets() -> io::Result<()> {
+    let inner = ExampleHugeRangeOfZeroes { position: 1 };
+    let mut take = inner.take(u64::MAX - 2);
+    assert_eq!(take.seek(io::SeekFrom::Start(u64::MAX - 2))?, u64::MAX - 2);
+    assert_eq!(take.inner.position, u64::MAX - 1);
+    assert_eq!(take.seek(io::SeekFrom::Start(0))?, 0);
+    assert_eq!(take.inner.position, 1);
+    assert_eq!(take.seek(io::SeekFrom::End(-1))?, u64::MAX - 3);
+    assert_eq!(take.inner.position, u64::MAX - 2);
+    Ok(())
+}
+
 // A simple example reader which uses the default implementation of
 // read_to_end.
 struct ExampleSliceReader<'a> {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 5c1d2deb481..ef41b47384d 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -305,7 +305,6 @@
 #![feature(iter_advance_by)]
 #![feature(iter_next_chunk)]
 #![feature(lang_items)]
-#![feature(let_chains)]
 #![feature(link_cfg)]
 #![feature(linkage)]
 #![feature(macro_metavar_expr_concat)]
@@ -326,6 +325,7 @@
 #![feature(try_blocks)]
 #![feature(try_trait_v2)]
 #![feature(type_alias_impl_trait)]
+#![feature(unsigned_signed_diff)]
 // tidy-alphabetical-end
 //
 // Library features (core):
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 1a4a7aa7448..7959c633858 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -3163,7 +3163,7 @@ impl Path {
     /// allocating.
     #[stable(feature = "into_boxed_path", since = "1.20.0")]
     #[must_use = "`self` will be dropped if the result is not used"]
-    pub fn into_path_buf(self: Box<Path>) -> PathBuf {
+    pub fn into_path_buf(self: Box<Self>) -> PathBuf {
         let rw = Box::into_raw(self) as *mut OsStr;
         let inner = unsafe { Box::from_raw(rw) };
         PathBuf { inner: OsString::from(inner) }
diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs
index 24539d4e830..96a4cf12659 100644
--- a/library/std/src/sync/reentrant_lock.rs
+++ b/library/std/src/sync/reentrant_lock.rs
@@ -136,7 +136,7 @@ cfg_if!(
             // we only ever read from the tid if `tls_addr` matches the current
             // TLS address. In that case, either the tid has been set by
             // the current thread, or by a thread that has terminated before
-            // the current thread was created. In either case, no further
+            // the current thread's `tls_addr` was allocated. In either case, no further
             // synchronization is needed (as per <https://github.com/rust-lang/miri/issues/3450>)
             tls_addr: Atomic<usize>,
             tid: UnsafeCell<u64>,
@@ -154,8 +154,12 @@ cfg_if!(
             // NOTE: This assumes that `owner` is the ID of the current
             // thread, and may spuriously return `false` if that's not the case.
             fn contains(&self, owner: ThreadId) -> bool {
+                // We must call `tls_addr()` *before* doing the load to ensure that if we reuse an
+                // earlier thread's address, the `tls_addr.load()` below happens-after everything
+                // that thread did.
+                let tls_addr = tls_addr();
                 // SAFETY: See the comments in the struct definition.
-                self.tls_addr.load(Ordering::Relaxed) == tls_addr()
+                self.tls_addr.load(Ordering::Relaxed) == tls_addr
                     && unsafe { *self.tid.get() } == owner.as_u64().get()
             }
 
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 8bf6d833515..a3be2cdf738 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -25,15 +25,36 @@ impl Drop for Handler {
     }
 }
 
-#[cfg(any(
-    target_os = "linux",
-    target_os = "freebsd",
-    target_os = "hurd",
-    target_os = "macos",
-    target_os = "netbsd",
-    target_os = "openbsd",
-    target_os = "solaris",
-    target_os = "illumos",
+#[cfg(all(
+    not(miri),
+    any(
+        target_os = "linux",
+        target_os = "freebsd",
+        target_os = "hurd",
+        target_os = "macos",
+        target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "solaris",
+        target_os = "illumos",
+    ),
+))]
+mod thread_info;
+
+// miri doesn't model signals nor stack overflows and this code has some
+// synchronization properties that we don't want to expose to user code,
+// hence we disable it on miri.
+#[cfg(all(
+    not(miri),
+    any(
+        target_os = "linux",
+        target_os = "freebsd",
+        target_os = "hurd",
+        target_os = "macos",
+        target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "solaris",
+        target_os = "illumos",
+    )
 ))]
 mod imp {
     use libc::{
@@ -46,22 +67,13 @@ mod imp {
     use libc::{mmap64, mprotect, munmap};
 
     use super::Handler;
-    use crate::cell::Cell;
+    use super::thread_info::{delete_current_info, set_current_info, with_current_info};
     use crate::ops::Range;
     use crate::sync::OnceLock;
     use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering};
     use crate::sys::pal::unix::os;
-    use crate::{io, mem, ptr, thread};
-
-    // We use a TLS variable to store the address of the guard page. While TLS
-    // variables are not guaranteed to be signal-safe, this works out in practice
-    // since we make sure to write to the variable before the signal stack is
-    // installed, thereby ensuring that the variable is always allocated when
-    // the signal handler is called.
-    thread_local! {
-        // FIXME: use `Range` once that implements `Copy`.
-        static GUARD: Cell<(usize, usize)> = const { Cell::new((0, 0)) };
-    }
+    use crate::thread::with_current_name;
+    use crate::{io, mem, panic, ptr};
 
     // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages
     // (unmapped pages) at the end of every thread's stack, so if a thread ends
@@ -93,29 +105,35 @@ mod imp {
         info: *mut libc::siginfo_t,
         _data: *mut libc::c_void,
     ) {
-        let (start, end) = GUARD.get();
         // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`.
-        let addr = unsafe { (*info).si_addr().addr() };
+        let fault_addr = unsafe { (*info).si_addr().addr() };
+
+        // `with_current_info` expects that the process aborts after it is
+        // called. If the signal was not caused by a memory access, this might
+        // not be true. We detect this by noticing that the `si_addr` field is
+        // zero if the signal is synthetic.
+        if fault_addr != 0 {
+            with_current_info(|thread_info| {
+                // If the faulting address is within the guard page, then we print a
+                // message saying so and abort.
+                if let Some(thread_info) = thread_info
+                    && thread_info.guard_page_range.contains(&fault_addr)
+                {
+                    let name = thread_info.thread_name.as_deref().unwrap_or("<unknown>");
+                    rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
+                    rtabort!("stack overflow");
+                }
+            })
+        }
 
-        // If the faulting address is within the guard page, then we print a
-        // message saying so and abort.
-        if start <= addr && addr < end {
-            thread::with_current_name(|name| {
-                let name = name.unwrap_or("<unknown>");
-                rtprintpanic!("\nthread '{name}' has overflowed its stack\n");
-            });
+        // Unregister ourselves by reverting back to the default behavior.
+        // SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
+        let mut action: sigaction = unsafe { mem::zeroed() };
+        action.sa_sigaction = SIG_DFL;
+        // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction
+        unsafe { sigaction(signum, &action, ptr::null_mut()) };
 
-            rtabort!("stack overflow");
-        } else {
-            // Unregister ourselves by reverting back to the default behavior.
-            // SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
-            let mut action: sigaction = unsafe { mem::zeroed() };
-            action.sa_sigaction = SIG_DFL;
-            // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction
-            unsafe { sigaction(signum, &action, ptr::null_mut()) };
-
-            // See comment above for why this function returns.
-        }
+        // See comment above for why this function returns.
     }
 
     static PAGE_SIZE: Atomic<usize> = AtomicUsize::new(0);
@@ -128,9 +146,7 @@ mod imp {
     pub unsafe fn init() {
         PAGE_SIZE.store(os::page_size(), Ordering::Relaxed);
 
-        // Always write to GUARD to ensure the TLS variable is allocated.
-        let guard = unsafe { install_main_guard().unwrap_or(0..0) };
-        GUARD.set((guard.start, guard.end));
+        let mut guard_page_range = unsafe { install_main_guard() };
 
         // SAFETY: assuming all platforms define struct sigaction as "zero-initializable"
         let mut action: sigaction = unsafe { mem::zeroed() };
@@ -145,7 +161,13 @@ mod imp {
                     let handler = unsafe { make_handler(true) };
                     MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
                     mem::forget(handler);
+
+                    if let Some(guard_page_range) = guard_page_range.take() {
+                        let thread_name = with_current_name(|name| name.map(Box::from));
+                        set_current_info(guard_page_range, thread_name);
+                    }
                 }
+
                 action.sa_flags = SA_SIGINFO | SA_ONSTACK;
                 action.sa_sigaction = signal_handler as sighandler_t;
                 // SAFETY: only overriding signals if the default is set
@@ -214,9 +236,10 @@ mod imp {
         }
 
         if !main_thread {
-            // Always write to GUARD to ensure the TLS variable is allocated.
-            let guard = unsafe { current_guard() }.unwrap_or(0..0);
-            GUARD.set((guard.start, guard.end));
+            if let Some(guard_page_range) = unsafe { current_guard() } {
+                let thread_name = with_current_name(|name| name.map(Box::from));
+                set_current_info(guard_page_range, thread_name);
+            }
         }
 
         // SAFETY: assuming stack_t is zero-initializable
@@ -261,6 +284,8 @@ mod imp {
             // a mapping that started one page earlier, so walk back a page and unmap from there.
             unsafe { munmap(data.sub(page_size), sigstack_size + page_size) };
         }
+
+        delete_current_info();
     }
 
     /// Modern kernels on modern hardware can have dynamic signal stack sizes.
@@ -590,17 +615,20 @@ mod imp {
 // usually have fewer qualms about forwards compatibility, since the runtime
 // is shipped with the OS):
 // <https://github.com/apple/swift/blob/swift-5.10-RELEASE/stdlib/public/runtime/CrashHandlerMacOS.cpp>
-#[cfg(not(any(
-    target_os = "linux",
-    target_os = "freebsd",
-    target_os = "hurd",
-    target_os = "macos",
-    target_os = "netbsd",
-    target_os = "openbsd",
-    target_os = "solaris",
-    target_os = "illumos",
-    target_os = "cygwin",
-)))]
+#[cfg(any(
+    miri,
+    not(any(
+        target_os = "linux",
+        target_os = "freebsd",
+        target_os = "hurd",
+        target_os = "macos",
+        target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "solaris",
+        target_os = "illumos",
+        target_os = "cygwin",
+    ))
+))]
 mod imp {
     pub unsafe fn init() {}
 
diff --git a/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs b/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs
new file mode 100644
index 00000000000..e81429b98a6
--- /dev/null
+++ b/library/std/src/sys/pal/unix/stack_overflow/thread_info.rs
@@ -0,0 +1,129 @@
+//! TLS, but async-signal-safe.
+//!
+//! Unfortunately, because thread local storage isn't async-signal-safe, we
+//! cannot soundly use it in our stack overflow handler. While this works
+//! without problems on most platforms, it can lead to undefined behaviour
+//! on others (such as GNU/Linux). Luckily, the POSIX specification documents
+//! two thread-specific values that can be accessed in asynchronous signal
+//! handlers: the value of `pthread_self()` and the address of `errno`. As
+//! `pthread_t` is an opaque platform-specific type, we use the address of
+//! `errno` here. As it is thread-specific and does not change over the
+//! lifetime of a thread, we can use `&errno` as a key for a `BTreeMap`
+//! that stores thread-specific data.
+//!
+//! Concurrent access to this map is synchronized by two locks – an outer
+//! [`Mutex`] and an inner spin lock that also remembers the identity of
+//! the lock owner:
+//! * The spin lock is the primary means of synchronization: since it only
+//!   uses native atomics, it can be soundly used inside the signal handle
+//!   as opposed to [`Mutex`], which might not be async-signal-safe.
+//! * The [`Mutex`] prevents busy-waiting in the setup logic, as all accesses
+//!   there are performed with the [`Mutex`] held, which makes the spin-lock
+//!   redundant in the common case.
+//! * Finally, by using the `errno` address as the locked value of the spin
+//!   lock, we can detect cases where a SIGSEGV occurred while the thread
+//!   info is being modified.
+
+use crate::collections::BTreeMap;
+use crate::hint::spin_loop;
+use crate::ops::Range;
+use crate::sync::Mutex;
+use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sys::os::errno_location;
+
+pub struct ThreadInfo {
+    pub guard_page_range: Range<usize>,
+    pub thread_name: Option<Box<str>>,
+}
+
+static LOCK: Mutex<()> = Mutex::new(());
+static SPIN_LOCK: AtomicUsize = AtomicUsize::new(0);
+// This uses a `BTreeMap` instead of a hashmap since it supports constant
+// initialization and automatically reduces the amount of memory used when
+// items are removed.
+static mut THREAD_INFO: BTreeMap<usize, ThreadInfo> = BTreeMap::new();
+
+struct UnlockOnDrop;
+
+impl Drop for UnlockOnDrop {
+    fn drop(&mut self) {
+        SPIN_LOCK.store(0, Ordering::Release);
+    }
+}
+
+/// Get the current thread's information, if available.
+///
+/// Calling this function might freeze other threads if they attempt to modify
+/// their thread information. Thus, the caller should ensure that the process
+/// is aborted shortly after this function is called.
+///
+/// This function is guaranteed to be async-signal-safe if `f` is too.
+pub fn with_current_info<R>(f: impl FnOnce(Option<&ThreadInfo>) -> R) -> R {
+    let this = errno_location().addr();
+    let mut attempt = 0;
+    let _guard = loop {
+        // If we are just spinning endlessly, it's very likely that the thread
+        // modifying the thread info map has a lower priority than us and will
+        // not continue until we stop running. Just give up in that case.
+        if attempt == 10_000_000 {
+            rtprintpanic!("deadlock in SIGSEGV handler");
+            return f(None);
+        }
+
+        match SPIN_LOCK.compare_exchange(0, this, Ordering::Acquire, Ordering::Relaxed) {
+            Ok(_) => break UnlockOnDrop,
+            Err(owner) if owner == this => {
+                rtabort!("a thread received SIGSEGV while modifying its stack overflow information")
+            }
+            // Spin until the lock can be acquired – there is nothing better to
+            // do. This is unfortunately a priority hole, but a stack overflow
+            // is a fatal error anyway.
+            Err(_) => {
+                spin_loop();
+                attempt += 1;
+            }
+        }
+    };
+
+    // SAFETY: we own the spin lock, so `THREAD_INFO` cannot not be aliased.
+    let thread_info = unsafe { &*(&raw const THREAD_INFO) };
+    f(thread_info.get(&this))
+}
+
+fn spin_lock_in_setup(this: usize) -> UnlockOnDrop {
+    loop {
+        match SPIN_LOCK.compare_exchange(0, this, Ordering::Acquire, Ordering::Relaxed) {
+            Ok(_) => return UnlockOnDrop,
+            Err(owner) if owner == this => {
+                unreachable!("the thread info setup logic isn't recursive")
+            }
+            // This function is always called with the outer lock held,
+            // meaning the only time locking can fail is if another thread has
+            // encountered a stack overflow. Since that will abort the process,
+            // we just stop the current thread until that time. We use `pause`
+            // instead of spinning to avoid priority inversion.
+            // SAFETY: this doesn't have any safety preconditions.
+            Err(_) => drop(unsafe { libc::pause() }),
+        }
+    }
+}
+
+pub fn set_current_info(guard_page_range: Range<usize>, thread_name: Option<Box<str>>) {
+    let this = errno_location().addr();
+    let _lock_guard = LOCK.lock();
+    let _spin_guard = spin_lock_in_setup(this);
+
+    // SAFETY: we own the spin lock, so `THREAD_INFO` cannot be aliased.
+    let thread_info = unsafe { &mut *(&raw mut THREAD_INFO) };
+    thread_info.insert(this, ThreadInfo { guard_page_range, thread_name });
+}
+
+pub fn delete_current_info() {
+    let this = errno_location().addr();
+    let _lock_guard = LOCK.lock();
+    let _spin_guard = spin_lock_in_setup(this);
+
+    // SAFETY: we own the spin lock, so `THREAD_INFO` cannot not be aliased.
+    let thread_info = unsafe { &mut *(&raw mut THREAD_INFO) };
+    thread_info.remove(&this);
+}
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index f331282d2d7..1ebbbec9e91 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -202,6 +202,8 @@ fn home_dir_crt() -> Option<PathBuf> {
             |buf, mut sz| {
                 // GetUserProfileDirectoryW does not quite use the usual protocol for
                 // negotiating the buffer size, so we have to translate.
+                // FIXME(#141254): We rely on the *undocumented* property that this function will
+                // always set the size, not just on failure.
                 match c::GetUserProfileDirectoryW(
                     ptr::without_provenance_mut(CURRENT_PROCESS_TOKEN),
                     buf,
diff --git a/library/stdarch b/library/stdarch
-Subproject f1c1839c0deb985a9f98cbd6b38a6d43f2df615
+Subproject 1dfaa4db2479753a46a3e90f2c3c89d89d0b21f
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index ff63b8c62d3..d10d2d9bf8c 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -64,7 +64,7 @@ dependencies = [
  "tracing-subscriber",
  "tracing-tree",
  "walkdir",
- "windows 0.57.0",
+ "windows",
  "xz2",
 ]
 
@@ -703,7 +703,7 @@ dependencies = [
  "ntapi",
  "objc2-core-foundation",
  "objc2-io-kit",
- "windows 0.61.1",
+ "windows",
 ]
 
 [[package]]
@@ -918,22 +918,12 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
-dependencies = [
- "windows-core 0.57.0",
- "windows-targets",
-]
-
-[[package]]
-name = "windows"
 version = "0.61.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
 dependencies = [
  "windows-collections",
- "windows-core 0.61.0",
+ "windows-core",
  "windows-future",
  "windows-link",
  "windows-numerics",
@@ -945,19 +935,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
 dependencies = [
- "windows-core 0.61.0",
-]
-
-[[package]]
-name = "windows-core"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
-dependencies = [
- "windows-implement 0.57.0",
- "windows-interface 0.57.0",
- "windows-result 0.1.2",
- "windows-targets",
+ "windows-core",
 ]
 
 [[package]]
@@ -966,10 +944,10 @@ version = "0.61.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
 dependencies = [
- "windows-implement 0.60.0",
- "windows-interface 0.59.1",
+ "windows-implement",
+ "windows-interface",
  "windows-link",
- "windows-result 0.3.2",
+ "windows-result",
  "windows-strings",
 ]
 
@@ -979,23 +957,12 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
 dependencies = [
- "windows-core 0.61.0",
+ "windows-core",
  "windows-link",
 ]
 
 [[package]]
 name = "windows-implement"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "windows-implement"
 version = "0.60.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
@@ -1007,17 +974,6 @@ dependencies = [
 
 [[package]]
 name = "windows-interface"
-version = "0.57.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "windows-interface"
 version = "0.59.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
@@ -1039,21 +995,12 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
 dependencies = [
- "windows-core 0.61.0",
+ "windows-core",
  "windows-link",
 ]
 
 [[package]]
 name = "windows-result"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-result"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index e34de924cc1..9652d18f1a6 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -70,7 +70,7 @@ tracing-tree = { version = "0.4.0", optional = true }
 version = "1.0.0"
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.57"
+version = "0.61"
 features = [
     "Win32_Foundation",
     "Win32_Security",
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index 85c682a46c5..374884d8a9a 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -342,7 +342,7 @@ fn format_rusage_data(child: Child) -> Option<String> {
     use windows::Win32::System::Threading::GetProcessTimes;
     use windows::Win32::System::Time::FileTimeToSystemTime;
 
-    let handle = HANDLE(child.as_raw_handle() as isize);
+    let handle = HANDLE(child.as_raw_handle());
 
     let mut user_filetime = Default::default();
     let mut user_time = Default::default();
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 67daf81ee54..d5ea96b43f5 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1984,17 +1984,20 @@ impl Step for Assemble {
                     trace!("installing `{tool}`");
                     let tool_exe = exe(tool, target_compiler.host);
                     let src_path = llvm_bin_dir.join(&tool_exe);
-                    // When using `download-ci-llvm`, some of the tools
-                    // may not exist, so skip trying to copy them.
-                    if src_path.exists() {
-                        // There is a chance that these tools are being installed from an external LLVM.
-                        // Use `Builder::resolve_symlink_and_copy` instead of `Builder::copy_link` to ensure
-                        // we are copying the original file not the symlinked path, which causes issues for
-                        // tarball distribution.
-                        //
-                        // See https://github.com/rust-lang/rust/issues/135554.
-                        builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
+
+                    // When using `download-ci-llvm`, some of the tools may not exist, so skip trying to copy them.
+                    if !src_path.exists() && builder.config.llvm_from_ci {
+                        eprintln!("{} does not exist; skipping copy", src_path.display());
+                        continue;
                     }
+
+                    // There is a chance that these tools are being installed from an external LLVM.
+                    // Use `Builder::resolve_symlink_and_copy` instead of `Builder::copy_link` to ensure
+                    // we are copying the original file not the symlinked path, which causes issues for
+                    // tarball distribution.
+                    //
+                    // See https://github.com/rust-lang/rust/issues/135554.
+                    builder.resolve_symlink_and_copy(&src_path, &libdir_bin.join(&tool_exe));
                 }
             }
         }
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index aa2c7509c2a..253fa224152 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -2274,9 +2274,9 @@ impl Step for LlvmTools {
 
         let target = self.target;
 
-        /* run only if llvm-config isn't used */
+        // Run only if a custom llvm-config is not used
         if let Some(config) = builder.config.target_config.get(&target) {
-            if let Some(ref _s) = config.llvm_config {
+            if !builder.config.llvm_from_ci && config.llvm_config.is_some() {
                 builder.info(&format!("Skipping LlvmTools ({target}): external LLVM"));
                 return None;
             }
@@ -2294,6 +2294,12 @@ impl Step for LlvmTools {
             let dst_bindir = format!("lib/rustlib/{}/bin", target.triple);
             for tool in tools_to_install(&builder.paths) {
                 let exe = src_bindir.join(exe(tool, target));
+                // When using `download-ci-llvm`, some of the tools may not exist, so skip trying to copy them.
+                if !exe.exists() && builder.config.llvm_from_ci {
+                    eprintln!("{} does not exist; skipping copy", exe.display());
+                    continue;
+                }
+
                 tarball.add_file(&exe, &dst_bindir, FileType::Executable);
             }
         }
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index c31c40e846b..585adf9be16 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -244,7 +244,7 @@ install!((self, builder, _config),
             );
         }
     };
-    LlvmTools, alias = "llvm-tools", Self::should_build(_config), only_hosts: true, {
+    LlvmTools, alias = "llvm-tools", _config.llvm_tools_enabled && _config.llvm_enabled(_config.build), only_hosts: true, {
         if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) {
             install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
         } else {
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index b2dc509ddca..27791825aa0 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -3554,7 +3554,7 @@ impl Step for TestFloatParse {
         builder.ensure(tool::TestFloatParse { host: self.host });
 
         // Run any unit tests in the crate
-        let cargo_test = tool::prepare_tool_cargo(
+        let mut cargo_test = tool::prepare_tool_cargo(
             builder,
             compiler,
             Mode::ToolStd,
@@ -3564,6 +3564,7 @@ impl Step for TestFloatParse {
             SourceType::InTree,
             &[],
         );
+        cargo_test.allow_features(tool::TestFloatParse::ALLOW_FEATURES);
 
         run_cargo_test(cargo_test, &[], &[], crate_name, bootstrap_host, builder);
 
@@ -3578,6 +3579,7 @@ impl Step for TestFloatParse {
             SourceType::InTree,
             &[],
         );
+        cargo_run.allow_features(tool::TestFloatParse::ALLOW_FEATURES);
 
         if !matches!(env::var("FLOAT_PARSE_TESTS_NO_SKIP_HUGE").as_deref(), Ok("1") | Ok("true")) {
             cargo_run.args(["--", "--skip-huge"]);
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index ac568eab2e8..678aa9b01e4 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -1259,6 +1259,10 @@ pub struct TestFloatParse {
     pub host: TargetSelection,
 }
 
+impl TestFloatParse {
+    pub const ALLOW_FEATURES: &'static str = "f16,cfg_target_has_reliable_f16_f128";
+}
+
 impl Step for TestFloatParse {
     type Output = ToolBuildResult;
     const ONLY_HOSTS: bool = true;
@@ -1280,7 +1284,7 @@ impl Step for TestFloatParse {
             path: "src/etc/test-float-parse",
             source_type: SourceType::InTree,
             extra_features: Vec::new(),
-            allow_features: "",
+            allow_features: Self::ALLOW_FEATURES,
             cargo_args: Vec::new(),
             artifact_kind: ToolArtifactKind::Binary,
         })
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index cc4fa953ddc..af3e3cc37b9 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -1388,7 +1388,7 @@ impl<'a> Builder<'a> {
         // Windows doesn't need dylib path munging because the dlls for the
         // compiler live next to the compiler and the system will find them
         // automatically.
-        if cfg!(windows) {
+        if cfg!(any(windows, target_os = "cygwin")) {
             return;
         }
 
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index eb7e3799a68..af4ec679d08 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -13,7 +13,6 @@ use std::ffi::{OsStr, OsString};
 use std::path::PathBuf;
 use std::{env, fs};
 
-use crate::Build;
 #[cfg(not(test))]
 use crate::builder::Builder;
 use crate::builder::Kind;
@@ -21,6 +20,7 @@ use crate::builder::Kind;
 use crate::core::build_steps::tool;
 use crate::core::config::Target;
 use crate::utils::exec::command;
+use crate::{Build, Subcommand};
 
 pub struct Finder {
     cache: HashMap<OsString, Option<PathBuf>>,
@@ -205,6 +205,20 @@ than building it.
     .map(|s| s.to_string())
     .collect();
 
+    // Compiler tools like `cc` and `ar` are not configured for cross-targets on certain subcommands
+    // because they are not needed.
+    //
+    // See `cc_detect::find` for more details.
+    let skip_tools_checks = build.config.dry_run()
+        || matches!(
+            build.config.cmd,
+            Subcommand::Clean { .. }
+                | Subcommand::Check { .. }
+                | Subcommand::Suggest { .. }
+                | Subcommand::Format { .. }
+                | Subcommand::Setup { .. }
+        );
+
     // We're gonna build some custom C code here and there, host triples
     // also build some C++ shims for LLVM so we need a C++ compiler.
     for target in &build.targets {
@@ -278,7 +292,7 @@ than building it.
             }
         }
 
-        if !build.config.dry_run() {
+        if !skip_tools_checks {
             cmd_finder.must_have(build.cc(*target));
             if let Some(ar) = build.ar(*target) {
                 cmd_finder.must_have(ar);
@@ -286,7 +300,7 @@ than building it.
         }
     }
 
-    if !build.config.dry_run() {
+    if !skip_tools_checks {
         for host in &build.hosts {
             cmd_finder.must_have(build.cxx(*host).unwrap());
 
diff --git a/src/bootstrap/src/utils/cache.rs b/src/bootstrap/src/utils/cache.rs
index 1c8cc4025df..46eeffad88c 100644
--- a/src/bootstrap/src/utils/cache.rs
+++ b/src/bootstrap/src/utils/cache.rs
@@ -20,7 +20,6 @@ use std::collections::HashMap;
 use std::hash::{Hash, Hasher};
 use std::marker::PhantomData;
 use std::ops::Deref;
-use std::path::PathBuf;
 use std::sync::{LazyLock, Mutex};
 use std::{fmt, mem};
 
@@ -51,26 +50,11 @@ impl<T> PartialEq for Interned<T> {
 }
 impl<T> Eq for Interned<T> {}
 
-impl PartialEq<str> for Interned<String> {
-    fn eq(&self, other: &str) -> bool {
-        *self == other
-    }
-}
 impl PartialEq<&str> for Interned<String> {
     fn eq(&self, other: &&str) -> bool {
         **self == **other
     }
 }
-impl<T> PartialEq<&Interned<T>> for Interned<T> {
-    fn eq(&self, other: &&Self) -> bool {
-        self.0 == other.0
-    }
-}
-impl<T> PartialEq<Interned<T>> for &Interned<T> {
-    fn eq(&self, other: &Interned<T>) -> bool {
-        self.0 == other.0
-    }
-}
 
 unsafe impl<T> Send for Interned<T> {}
 unsafe impl<T> Sync for Interned<T> {}
@@ -188,8 +172,6 @@ impl<T: Hash + Clone + Eq> TyIntern<T> {
 #[derive(Default)]
 pub struct Interner {
     strs: Mutex<TyIntern<String>>,
-    paths: Mutex<TyIntern<PathBuf>>,
-    lists: Mutex<TyIntern<Vec<String>>>,
 }
 
 /// Defines the behavior required for a type to be internable.
@@ -210,18 +192,6 @@ impl Internable for String {
     }
 }
 
-impl Internable for PathBuf {
-    fn intern_cache() -> &'static Mutex<TyIntern<Self>> {
-        &INTERNER.paths
-    }
-}
-
-impl Internable for Vec<String> {
-    fn intern_cache() -> &'static Mutex<TyIntern<Self>> {
-        &INTERNER.lists
-    }
-}
-
 impl Interner {
     /// Interns a string reference, ensuring it is stored uniquely.
     ///
diff --git a/src/bootstrap/src/utils/cache/tests.rs b/src/bootstrap/src/utils/cache/tests.rs
index 28f5563a589..8562a35b3e0 100644
--- a/src/bootstrap/src/utils/cache/tests.rs
+++ b/src/bootstrap/src/utils/cache/tests.rs
@@ -13,26 +13,6 @@ fn test_string_interning() {
 }
 
 #[test]
-fn test_path_interning() {
-    let p1 = PathBuf::from("/tmp/file").intern();
-    let p2 = PathBuf::from("/tmp/file").intern();
-    let p3 = PathBuf::from("/tmp/other").intern();
-
-    assert_eq!(p1, p2);
-    assert_ne!(p1, p3);
-}
-
-#[test]
-fn test_vec_interning() {
-    let v1 = vec!["a".to_string(), "b".to_string()].intern();
-    let v2 = vec!["a".to_string(), "b".to_string()].intern();
-    let v3 = vec!["c".to_string()].intern();
-
-    assert_eq!(v1, v2);
-    assert_ne!(v1, v3);
-}
-
-#[test]
 fn test_interned_equality() {
     let s1 = INTERNER.intern_str("test");
     let s2 = INTERNER.intern_str("test");
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index b29c1fb3889..f2c3e8c0df4 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -130,7 +130,7 @@ pub fn is_debug_info(name: &str) -> bool {
 /// Returns the corresponding relative library directory that the compiler's
 /// dylibs will be found in.
 pub fn libdir(target: TargetSelection) -> &'static str {
-    if target.is_windows() { "bin" } else { "lib" }
+    if target.is_windows() || target.contains("cygwin") { "bin" } else { "lib" }
 }
 
 /// Adds a list of lookup paths to `cmd`'s dynamic library lookup path.
diff --git a/src/bootstrap/src/utils/job.rs b/src/bootstrap/src/utils/job.rs
index 4949518de79..887deb41ca8 100644
--- a/src/bootstrap/src/utils/job.rs
+++ b/src/bootstrap/src/utils/job.rs
@@ -66,7 +66,6 @@ mod for_windows {
             // Enable the Windows Error Reporting dialog which msys disables,
             // so we can JIT debug rustc
             let mode = SetErrorMode(THREAD_ERROR_MODE::default());
-            let mode = THREAD_ERROR_MODE(mode);
             SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX);
 
             // Create a new job object for us to use
diff --git a/src/bootstrap/src/utils/shared_helpers.rs b/src/bootstrap/src/utils/shared_helpers.rs
index 1297a53d488..08e1c21e58e 100644
--- a/src/bootstrap/src/utils/shared_helpers.rs
+++ b/src/bootstrap/src/utils/shared_helpers.rs
@@ -20,7 +20,7 @@ use std::str::FromStr;
 /// Returns the environment variable which the dynamic library lookup path
 /// resides in for this platform.
 pub fn dylib_path_var() -> &'static str {
-    if cfg!(target_os = "windows") {
+    if cfg!(any(target_os = "windows", target_os = "cygwin")) {
         "PATH"
     } else if cfg!(target_vendor = "apple") {
         "DYLD_LIBRARY_PATH"
diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh
index 5522095e304..a9528e92915 100755
--- a/src/ci/scripts/install-clang.sh
+++ b/src/ci/scripts/install-clang.sh
@@ -10,8 +10,8 @@ IFS=$'\n\t'
 source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
 
 # Update both macOS's and Windows's tarballs when bumping the version here.
-# Try to keep this in sync with src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
-LLVM_VERSION="18.1.4"
+# Try to keep this in sync with src/ci/docker/scripts/build-clang.sh
+LLVM_VERSION="20.1.3"
 
 if isMacOS; then
     # FIXME: This is the latest pre-built version of LLVM that's available for
diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh
index c8c501e646a..ad852071f29 100755
--- a/src/ci/scripts/install-mingw.sh
+++ b/src/ci/scripts/install-mingw.sh
@@ -42,5 +42,5 @@ if isWindows && isKnownToBeMingwBuild; then
 
     curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}"
     7z x -y mingw.7z > /dev/null
-    ciCommandAddPath "$(pwd)/${mingw_dir}/bin"
+    ciCommandAddPath "$(cygpath -m "$(pwd)/${mingw_dir}/bin")"
 fi
diff --git a/src/ci/scripts/install-ninja.sh b/src/ci/scripts/install-ninja.sh
index 23cbc2eb6d1..7ac19173923 100755
--- a/src/ci/scripts/install-ninja.sh
+++ b/src/ci/scripts/install-ninja.sh
@@ -12,7 +12,7 @@ if isWindows; then
     7z x -oninja ninja.zip
     rm ninja.zip
     ciCommandSetEnv "RUST_CONFIGURE_ARGS" "${RUST_CONFIGURE_ARGS} --enable-ninja"
-    ciCommandAddPath "$(pwd)/ninja"
+    ciCommandAddPath "$(cygpath -m "$(pwd)/ninja")"
 elif isMacOS; then
     brew install ninja
 fi
diff --git a/src/ci/scripts/install-sccache.sh b/src/ci/scripts/install-sccache.sh
index b055e76a805..fed06063fa0 100755
--- a/src/ci/scripts/install-sccache.sh
+++ b/src/ci/scripts/install-sccache.sh
@@ -15,7 +15,7 @@ elif isWindows; then
     mkdir -p sccache
     curl -fo sccache/sccache.exe \
       "${MIRRORS_BASE}/2025-02-24-sccache-v0.10.0-x86_64-pc-windows-msvc.exe"
-    ciCommandAddPath "$(pwd)/sccache"
+    ciCommandAddPath "$(cygpath -m "$(pwd)/sccache")"
 fi
 
 # FIXME: we should probably install sccache outside the containers and then
diff --git a/src/doc/book b/src/doc/book
-Subproject d33916341d480caede1d0ae57cbeae23aab23e8
+Subproject 230c68bc1e08f5f3228384a28cc228c81dfbd10
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 387392674d74656f7cb437c05a96f0c52ea8e60
+Subproject acd0231ebc74849f6a8907b5e646ce86721aad7
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 8a8918c698534547fa8a1a693cb3e7277f0bfb2
+Subproject c9d151f9147c4808c77f0375ba3fa5d54443cb9
diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version
index 5e4266f61da..0d889a5d5b9 100644
--- a/src/doc/rustc-dev-guide/rust-version
+++ b/src/doc/rustc-dev-guide/rust-version
@@ -1 +1 @@
-414482f6a0d4e7290f614300581a0b55442552a3
+e42bbfe1f7c26f8760a99c4b1f27d33aba1040bb
diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md
index 31119496e75..a7b76233d19 100644
--- a/src/doc/rustc-dev-guide/src/SUMMARY.md
+++ b/src/doc/rustc-dev-guide/src/SUMMARY.md
@@ -134,9 +134,9 @@
 
 - [Command-line arguments](./cli.md)
 - [rustc_driver and rustc_interface](./rustc-driver/intro.md)
+    - [Remarks on perma-unstable features](./rustc-driver/remarks-on-perma-unstable-features.md)
     - [Example: Type checking](./rustc-driver/interacting-with-the-ast.md)
     - [Example: Getting diagnostics](./rustc-driver/getting-diagnostics.md)
-    - [Remarks on perma-unstable features](./rustc-driver/remarks-on-perma-unstable-features.md)
 - [Errors and lints](diagnostics.md)
     - [Diagnostic and subdiagnostic structs](./diagnostics/diagnostic-structs.md)
     - [Translation](./diagnostics/translation.md)
diff --git a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md
index 513df1650c3..eeb2af5e6bc 100644
--- a/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md
+++ b/src/doc/rustc-dev-guide/src/backend/libs-and-metadata.md
@@ -28,8 +28,8 @@ format is specific to `rustc`, and may change over time. This file contains:
   [`-C embed-bitcode=no`][embed-bitcode] CLI option to improve compile times
   and reduce disk space if LTO is not needed.
 * `rustc` [metadata], in a file named `lib.rmeta`.
-* A symbol table, which is generally a list of symbols with offsets to the
-  object file that contain that symbol. This is pretty standard for archive
+* A symbol table, which is essentially a list of symbols with offsets to the
+  object files that contain that symbol. This is pretty standard for archive
   files.
 
 [archive file]: https://en.wikipedia.org/wiki/Ar_(Unix)
@@ -46,12 +46,11 @@ A `dylib` is a platform-specific shared library. It includes the `rustc`
 
 ### rmeta
 
-An `rmeta` file is custom binary format that contains the [metadata] for the
-crate. This file can be used for fast "checks" of a project by skipping all
-code generation (as is done with `cargo check`), collecting enough information
-for documentation (as is done with `cargo doc`), or for
-[pipelining](#pipelining). This file is created if the
-[`--emit=metadata`][emit] CLI option is used.
+An `rmeta` file is a custom binary format that contains the [metadata] for the
+crate. This file can be used for fast "checks" of a project by skipping all code
+generation (as is done with `cargo check`), collecting enough information for
+documentation (as is done with `cargo doc`), or for [pipelining](#pipelining).
+This file is created if the [`--emit=metadata`][emit] CLI option is used.
 
 `rmeta` files do not support linking, since they do not contain compiled
 object files.
@@ -60,8 +59,8 @@ object files.
 
 ## Metadata
 
-The metadata contains a wide swath of different elements. This guide will not
-go into detail of every field it contains. You are encouraged to browse the
+The metadata contains a wide swath of different elements. This guide will not go
+into detail about every field it contains. You are encouraged to browse the
 [`CrateRoot`] definition to get a sense of the different elements it contains.
 Everything about metadata encoding and decoding is in the [`rustc_metadata`]
 package.
@@ -122,9 +121,9 @@ much more.
 
 By default, all Rust symbols are mangled and incorporate the stable crate id.
 This allows multiple versions of the same crate to be included together. Cargo
-automatically generates `-C metadata` hashes based on a variety of factors,
-like the package version, source, and the target kind (a lib and test can have
-the same crate name, so they need to be disambiguated).
+automatically generates `-C metadata` hashes based on a variety of factors, like
+the package version, source, and target kind (a lib and test can have the same
+crate name, so they need to be disambiguated).
 
 [`StableCrateId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html
 [`StableCrateId::new`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.StableCrateId.html#method.new
@@ -154,7 +153,7 @@ will also look at the [sysroot] to find dependencies.
 
 As crates are loaded, they are kept in the [`CStore`] with the crate metadata
 wrapped in the [`CrateMetadata`] struct. After resolution and expansion, the
-`CStore` will make its way into the [`GlobalCtxt`] for the rest of
+`CStore` will make its way into the [`GlobalCtxt`] for the rest of the
 compilation.
 
 [name resolution]: ../name-resolution.md
diff --git a/src/doc/rustc-dev-guide/src/cli.md b/src/doc/rustc-dev-guide/src/cli.md
index 408ae207004..4c77007ea44 100644
--- a/src/doc/rustc-dev-guide/src/cli.md
+++ b/src/doc/rustc-dev-guide/src/cli.md
@@ -28,6 +28,6 @@ adding a new command-line argument.
   unstable-options` flag.
 
 [cli-docs]: https://doc.rust-lang.org/rustc/command-line-arguments.html
-[forge guide for new options]: https://forge.rust-lang.org/compiler/new_option.html
+[forge guide for new options]: https://forge.rust-lang.org/compiler/proposals-and-stabilization.html#compiler-flags
 [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/
 [`parse_bool`]: https://github.com/rust-lang/rust/blob/e5335592e78354e33d798d20c04bcd677c1df62d/src/librustc_session/options.rs#L307-L313
diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md
index 8bf14bef2a0..0e5b32a06f8 100644
--- a/src/doc/rustc-dev-guide/src/getting-started.md
+++ b/src/doc/rustc-dev-guide/src/getting-started.md
@@ -89,7 +89,7 @@ filtering the search to areas you're interested in. For example:
 Not all important or beginner work has issue labels.
 See below for how to find work that isn't labelled.
 
-[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+
+[help-wanted-search]: https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Arust-lang+no%3Aassignee+label%3AE-easy%2C%22good+first+issue%22%2Cgood-first-issue%2CE-medium%2CEasy%2CE-help-wanted%2CE-mentor+-label%3AS-blocked+-linked:pr+
 [Triage]: ./contributing.md#issue-triage
 
 ### Recurring work
diff --git a/src/doc/rustc-dev-guide/src/notification-groups/rust-for-linux.md b/src/doc/rustc-dev-guide/src/notification-groups/rust-for-linux.md
index 9ba4eff629e..696f2038e1a 100644
--- a/src/doc/rustc-dev-guide/src/notification-groups/rust-for-linux.md
+++ b/src/doc/rustc-dev-guide/src/notification-groups/rust-for-linux.md
@@ -1,9 +1,9 @@
 # Rust for Linux notification group
 
-**Github Label:** [O-rfl] <br>
+**Github Label:** [A-rust-for-linux] <br>
 **Ping command:** `@rustbot ping rfl`
 
-[O-rfl]: https://github.com/rust-lang/rust/labels/O-rfl
+[A-rust-for-linux]: https://github.com/rust-lang/rust/labels/A-rust-for-linux
 
 This list will be used to notify [Rust for Linux (RfL)][rfl] maintainers
 when the compiler or the standard library changes in a way that would
diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md
index 40500e6bc7a..a3684397b29 100644
--- a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md
+++ b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md
@@ -7,8 +7,8 @@ It acts as the glue for running the various phases of the compiler in the correc
 using the interface defined in the [`rustc_interface`] crate. Where possible, using [`rustc_driver`] rather than [`rustc_interface`] is recommended.
 
 The main entry point of [`rustc_driver`] is [`rustc_driver::run_compiler`][rd_rc].
-This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`][cb] and a couple of other optional options.
-[`Callbacks`][cb] is a `trait` that allows for custom compiler configuration,
+This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`] and a couple of other optional options.
+[`Callbacks`] is a `trait` that allows for custom compiler configuration,
 as well as allowing custom code to run after different phases of the compilation.
 
 ## `rustc_interface`
@@ -33,14 +33,8 @@ specifically [`rustc_driver_impl::run_compiler`][rdi_rc]
 [`Compiler`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/struct.Compiler.html
 [`rustc_driver`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/
 [`rustc_interface`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/index.html
-[`Session`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html
-[`SourceMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/source_map/struct.SourceMap.html
-[`TyCtxt`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html
-[Appendix A]: appendix/stupid-stats.html
-[cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html
+[`Callbacks`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html
 [example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-interface-example.rs
 [i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html
 [rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html
 [rdi_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html
-[stupid-stats]: https://github.com/nrc/stupid-stats
-[`nightly-rustc`]: https://doc.rust-lang.org/nightly/nightly-rustc/
diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml
index 167aece0ed6..01f127ad390 100644
--- a/src/doc/rustc/book.toml
+++ b/src/doc/rustc/book.toml
@@ -6,6 +6,8 @@ title = "The rustc book"
 [output.html]
 git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc"
 edit-url-template = "https://github.com/rust-lang/rust/edit/master/src/doc/rustc/{path}"
+additional-css = ["theme/pagetoc.css"]
+additional-js = ["theme/pagetoc.js"]
 
 [output.html.search]
 use-boolean-and = true
diff --git a/src/doc/rustc/theme/pagetoc.css b/src/doc/rustc/theme/pagetoc.css
new file mode 100644
index 00000000000..fa709194f37
--- /dev/null
+++ b/src/doc/rustc/theme/pagetoc.css
@@ -0,0 +1,84 @@
+/* Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL) */
+
+:root {
+    --toc-width: 270px;
+    --center-content-toc-shift: calc(-1 * var(--toc-width) / 2);
+}
+
+.nav-chapters {
+    /* adjust width of buttons that bring to the previous or the next page */
+    min-width: 50px;
+}
+
+@media only screen {
+    @media (max-width: 1179px) {
+        .sidebar-hidden #sidetoc {
+            display: none;
+        }
+    }
+
+    @media (max-width: 1439px) {
+        .sidebar-visible #sidetoc {
+            display: none;
+        }
+    }
+
+    @media (1180px <= width <= 1439px) {
+        .sidebar-hidden main {
+            position: relative;
+            left: var(--center-content-toc-shift);
+        }
+    }
+
+    @media (1440px <= width <= 1700px) {
+        .sidebar-visible main {
+            position: relative;
+            left: var(--center-content-toc-shift);
+        }
+    }
+
+    #sidetoc {
+        margin-left: calc(100% + 20px);
+    }
+    #pagetoc {
+        position: fixed;
+        /* adjust TOC width */
+        width: var(--toc-width);
+        height: calc(100vh - var(--menu-bar-height) - 0.67em * 4);
+        overflow: auto;
+    }
+    #pagetoc a {
+        border-left: 1px solid var(--sidebar-bg);
+        color: var(--fg);
+        display: block;
+        padding-bottom: 5px;
+        padding-top: 5px;
+        padding-left: 10px;
+        text-align: left;
+        text-decoration: none;
+    }
+    #pagetoc a:hover,
+    #pagetoc a.active {
+        background: var(--sidebar-bg);
+        color: var(--sidebar-active) !important;
+    }
+    #pagetoc .active {
+        background: var(--sidebar-bg);
+        color: var(--sidebar-active);
+    }
+    #pagetoc .pagetoc-H2 {
+        padding-left: 20px;
+    }
+    #pagetoc .pagetoc-H3 {
+        padding-left: 40px;
+    }
+    #pagetoc .pagetoc-H4 {
+        padding-left: 60px;
+    }
+}
+
+@media print {
+    #sidetoc {
+        display: none;
+    }
+}
diff --git a/src/doc/rustc/theme/pagetoc.js b/src/doc/rustc/theme/pagetoc.js
new file mode 100644
index 00000000000..927a5b10749
--- /dev/null
+++ b/src/doc/rustc/theme/pagetoc.js
@@ -0,0 +1,104 @@
+// Inspired by https://github.com/JorelAli/mdBook-pagetoc/tree/98ee241 (under WTFPL)
+
+let activeHref = location.href;
+function updatePageToc(elem = undefined) {
+    let selectedPageTocElem = elem;
+    const pagetoc = document.getElementById("pagetoc");
+
+    function getRect(element) {
+        return element.getBoundingClientRect();
+    }
+
+    function overflowTop(container, element) {
+        return getRect(container).top - getRect(element).top;
+    }
+
+    function overflowBottom(container, element) {
+        return getRect(container).bottom - getRect(element).bottom;
+    }
+
+    // We've not selected a heading to highlight, and the URL needs updating
+    // so we need to find a heading based on the URL
+    if (selectedPageTocElem === undefined && location.href !== activeHref) {
+        activeHref = location.href;
+        for (const pageTocElement of pagetoc.children) {
+            if (pageTocElement.href === activeHref) {
+                selectedPageTocElem = pageTocElement;
+            }
+        }
+    }
+
+    // We still don't have a selected heading, let's try and find the most
+    // suitable heading based on the scroll position
+    if (selectedPageTocElem === undefined) {
+        const margin = window.innerHeight / 3;
+
+        const headers = document.getElementsByClassName("header");
+        for (let i = 0; i < headers.length; i++) {
+            const header = headers[i];
+            if (selectedPageTocElem === undefined && getRect(header).top >= 0) {
+                if (getRect(header).top < margin) {
+                    selectedPageTocElem = header;
+                } else {
+                    selectedPageTocElem = headers[Math.max(0, i - 1)];
+                }
+            }
+            // a very long last section's heading is over the screen
+            if (selectedPageTocElem === undefined && i === headers.length - 1) {
+                selectedPageTocElem = header;
+            }
+        }
+    }
+
+    // Remove the active flag from all pagetoc elements
+    for (const pageTocElement of pagetoc.children) {
+        pageTocElement.classList.remove("active");
+    }
+
+    // If we have a selected heading, set it to active and scroll to it
+    if (selectedPageTocElem !== undefined) {
+        for (const pageTocElement of pagetoc.children) {
+            if (selectedPageTocElem.href.localeCompare(pageTocElement.href) === 0) {
+                pageTocElement.classList.add("active");
+                if (overflowTop(pagetoc, pageTocElement) > 0) {
+                    pagetoc.scrollTop = pageTocElement.offsetTop;
+                }
+                if (overflowBottom(pagetoc, pageTocElement) < 0) {
+                    pagetoc.scrollTop -= overflowBottom(pagetoc, pageTocElement);
+                }
+            }
+        }
+    }
+}
+
+if (document.getElementById("sidetoc") === null &&
+    document.getElementsByClassName("header").length > 0) {
+    // The sidetoc element doesn't exist yet, let's create it
+
+    // Create the empty sidetoc and pagetoc elements
+    const sidetoc = document.createElement("div");
+    const pagetoc = document.createElement("div");
+    sidetoc.id = "sidetoc";
+    pagetoc.id = "pagetoc";
+    sidetoc.appendChild(pagetoc);
+
+    // And append them to the current DOM
+    const main = document.querySelector('main');
+    main.insertBefore(sidetoc, main.firstChild);
+
+    // Populate sidebar on load
+    window.addEventListener("load", () => {
+        for (const header of document.getElementsByClassName("header")) {
+            const link = document.createElement("a");
+            link.innerHTML = header.innerHTML;
+            link.href = header.hash;
+            link.classList.add("pagetoc-" + header.parentElement.tagName);
+            document.getElementById("pagetoc").appendChild(link);
+            link.onclick = () => updatePageToc(link);
+        }
+        updatePageToc();
+    });
+
+    // Update page table of contents selected heading on scroll
+    window.addEventListener("scroll", () => updatePageToc());
+}
diff --git a/src/doc/unstable-book/src/language-features/explicit-extern-abis.md b/src/doc/unstable-book/src/language-features/explicit-extern-abis.md
index ba622466ba7..7728f6725b1 100644
--- a/src/doc/unstable-book/src/language-features/explicit-extern-abis.md
+++ b/src/doc/unstable-book/src/language-features/explicit-extern-abis.md
@@ -1,6 +1,6 @@
 # `explicit_extern_abis`
 
-The tracking issue for this feature is: #134986
+The tracking issue for this feature is: [#134986]
 
 ------
 
@@ -21,3 +21,5 @@ extern "C" fn function2() {} // compiles
 
 extern "aapcs" fn function3() {} // compiles
 ```
+
+[#134986]: https://github.com/rust-lang/rust/issues/134986
diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml
index 8a9c5322ef7..e407e322f9e 100644
--- a/src/etc/test-float-parse/Cargo.toml
+++ b/src/etc/test-float-parse/Cargo.toml
@@ -13,3 +13,10 @@ rayon = "1"
 
 [lib]
 name = "test_float_parse"
+
+[lints.rust.unexpected_cfgs]
+level = "warn"
+check-cfg = [
+    # Internal features aren't marked known config by default
+    'cfg(target_has_reliable_f16)',
+]
diff --git a/src/etc/test-float-parse/src/gen_/subnorm.rs b/src/etc/test-float-parse/src/gen_/subnorm.rs
index 4fe3b90a3dd..654f324b9b0 100644
--- a/src/etc/test-float-parse/src/gen_/subnorm.rs
+++ b/src/etc/test-float-parse/src/gen_/subnorm.rs
@@ -1,4 +1,3 @@
-use std::cmp::min;
 use std::fmt::Write;
 use std::ops::RangeInclusive;
 
@@ -83,7 +82,13 @@ where
     }
 
     fn new() -> Self {
-        Self { iter: F::Int::ZERO..=min(F::Int::ONE << 22, F::MAN_BITS.try_into().unwrap()) }
+        let upper_lim = if F::MAN_BITS >= 22 {
+            F::Int::ONE << 22
+        } else {
+            (F::Int::ONE << F::MAN_BITS) - F::Int::ONE
+        };
+
+        Self { iter: F::Int::ZERO..=upper_lim }
     }
 
     fn write_string(s: &mut String, ctx: Self::WriteCtx) {
diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs
index 3c3ef5802b6..0bd4878f9a6 100644
--- a/src/etc/test-float-parse/src/lib.rs
+++ b/src/etc/test-float-parse/src/lib.rs
@@ -1,3 +1,7 @@
+#![feature(f16)]
+#![feature(cfg_target_has_reliable_f16_f128)]
+#![expect(internal_features)] // reliable_f16_f128
+
 mod traits;
 mod ui;
 mod validate;
@@ -114,6 +118,9 @@ pub fn register_tests(cfg: &Config) -> Vec<TestInfo> {
     let mut tests = Vec::new();
 
     // Register normal generators for all floats.
+
+    #[cfg(target_has_reliable_f16)]
+    register_float::<f16>(&mut tests, cfg);
     register_float::<f32>(&mut tests, cfg);
     register_float::<f64>(&mut tests, cfg);
 
diff --git a/src/etc/test-float-parse/src/traits.rs b/src/etc/test-float-parse/src/traits.rs
index 57e702b7d09..65a8721bfa5 100644
--- a/src/etc/test-float-parse/src/traits.rs
+++ b/src/etc/test-float-parse/src/traits.rs
@@ -98,7 +98,7 @@ macro_rules! impl_int {
     }
 }
 
-impl_int!(u32, i32; u64, i64);
+impl_int!(u16, i16; u32, i32; u64, i64);
 
 /// Floating point types.
 pub trait Float:
@@ -170,6 +170,9 @@ macro_rules! impl_float {
 
 impl_float!(f32, u32; f64, u64);
 
+#[cfg(target_has_reliable_f16)]
+impl_float!(f16, u16);
+
 /// A test generator. Should provide an iterator that produces unique patterns to parse.
 ///
 /// The iterator needs to provide a `WriteCtx` (could be anything), which is then used to
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 75f1bc9549c..e45f28444fe 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -5,7 +5,9 @@ use std::{fmt, iter};
 
 use arrayvec::ArrayVec;
 use rustc_abi::{ExternAbi, VariantIdx};
-use rustc_attr_parsing::{AttributeKind, ConstStability, Deprecation, Stability, StableSince};
+use rustc_attr_data_structures::{
+    AttributeKind, ConstStability, Deprecation, Stability, StableSince,
+};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
@@ -403,13 +405,13 @@ impl Item {
             // versions; the paths that are exposed through it are "deprecated" because they
             // were never supposed to work at all.
             let stab = self.stability(tcx)?;
-            if let rustc_attr_parsing::StabilityLevel::Stable {
+            if let rustc_attr_data_structures::StabilityLevel::Stable {
                 allowed_through_unstable_modules: Some(note),
                 ..
             } = stab.level
             {
                 Some(Deprecation {
-                    since: rustc_attr_parsing::DeprecatedSince::Unspecified,
+                    since: rustc_attr_data_structures::DeprecatedSince::Unspecified,
                     note: Some(note),
                     suggestion: None,
                 })
@@ -777,9 +779,9 @@ impl Item {
                             // don't want it it `Item::attrs`.
                             None
                         }
-                        rustc_hir::Attribute::Parsed(rustc_attr_parsing::AttributeKind::Repr(
-                            ..,
-                        )) => {
+                        rustc_hir::Attribute::Parsed(
+                            rustc_attr_data_structures::AttributeKind::Repr(..),
+                        ) => {
                             // We have separate pretty-printing logic for `#[repr(..)]` attributes.
                             // For example, there are circumstances where `#[repr(transparent)]`
                             // is applied but should not be publicly shown in rustdoc
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 19402004ed5..4989bd718c9 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -1,6 +1,6 @@
 use std::mem;
 
-use rustc_attr_parsing::StabilityLevel;
+use rustc_attr_data_structures::StabilityLevel;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet};
 use rustc_middle::ty::{self, TyCtxt};
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 8c7ab640bed..486d4ae932d 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -15,7 +15,7 @@ use std::slice;
 
 use itertools::Either;
 use rustc_abi::ExternAbi;
-use rustc_attr_parsing::{ConstStability, StabilityLevel, StableSince};
+use rustc_attr_data_structures::{ConstStability, StabilityLevel, StableSince};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 44b3be23914..3b5f9b5a458 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -1,4 +1,4 @@
-use std::fmt::{self, Display};
+use std::fmt::Display;
 use std::path::PathBuf;
 
 use askama::Template;
@@ -71,23 +71,6 @@ struct PageLayout<'a> {
 
 pub(crate) use crate::html::render::sidebar::filters;
 
-/// Implements [`Display`] for a function that accepts a mutable reference to a [`String`], and (optionally) writes to it.
-///
-/// The wrapped function will receive an empty string, and can modify it,
-/// and the `Display` implementation will write the contents of the string after the function has finished.
-pub(crate) struct BufDisplay<F>(pub F);
-
-impl<F> Display for BufDisplay<F>
-where
-    F: Fn(&mut String),
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut buf = String::new();
-        self.0(&mut buf);
-        f.write_str(&buf)
-    }
-}
-
 pub(crate) fn render<T: Display, S: Display>(
     layout: &Layout,
     page: &Page<'_>,
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index f22935df96c..1f7201b8ca8 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -28,11 +28,10 @@ use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::html::escape::Escape;
 use crate::html::format::join_with_double_colon;
-use crate::html::layout::{self, BufDisplay};
 use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary};
 use crate::html::render::write_shared::write_shared;
 use crate::html::url_parts_builder::UrlPartsBuilder;
-use crate::html::{sources, static_files};
+use crate::html::{layout, sources, static_files};
 use crate::scrape_examples::AllCallLocations;
 use crate::{DOC_RUST_LANG_ORG_VERSION, try_err};
 
@@ -250,9 +249,7 @@ impl<'tcx> Context<'tcx> {
             layout::render(
                 &self.shared.layout,
                 &page,
-                BufDisplay(|buf: &mut String| {
-                    print_sidebar(self, it, buf);
-                }),
+                fmt::from_fn(|f| print_sidebar(self, it, f)),
                 content,
                 &self.shared.style_files,
             )
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index beaa6497b8c..06cb9269cc8 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -49,7 +49,7 @@ use std::{fs, str};
 
 use askama::Template;
 use itertools::Either;
-use rustc_attr_parsing::{
+use rustc_attr_data_structures::{
     ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince,
 };
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
@@ -538,7 +538,7 @@ fn document(
     }
 
     fmt::from_fn(move |f| {
-        document_item_info(cx, item, parent).render_into(f).unwrap();
+        document_item_info(cx, item, parent).render_into(f)?;
         if parent.is_none() {
             write!(f, "{}", document_full_collapsible(item, cx, heading_offset))
         } else {
@@ -582,7 +582,7 @@ fn document_short(
     show_def_docs: bool,
 ) -> impl fmt::Display {
     fmt::from_fn(move |f| {
-        document_item_info(cx, item, Some(parent)).render_into(f).unwrap();
+        document_item_info(cx, item, Some(parent)).render_into(f)?;
         if !show_def_docs {
             return Ok(());
         }
@@ -661,7 +661,7 @@ fn document_full_inner(
         };
 
         if let clean::ItemKind::FunctionItem(..) | clean::ItemKind::MethodItem(..) = kind {
-            render_call_locations(f, cx, item);
+            render_call_locations(f, cx, item)?;
         }
         Ok(())
     })
@@ -2584,11 +2584,15 @@ const MAX_FULL_EXAMPLES: usize = 5;
 const NUM_VISIBLE_LINES: usize = 10;
 
 /// Generates the HTML for example call locations generated via the --scrape-examples flag.
-fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean::Item) {
+fn render_call_locations<W: fmt::Write>(
+    mut w: W,
+    cx: &Context<'_>,
+    item: &clean::Item,
+) -> fmt::Result {
     let tcx = cx.tcx();
     let def_id = item.item_id.expect_def_id();
     let key = tcx.def_path_hash(def_id);
-    let Some(call_locations) = cx.shared.call_locations.get(&key) else { return };
+    let Some(call_locations) = cx.shared.call_locations.get(&key) else { return Ok(()) };
 
     // Generate a unique ID so users can link to this section for a given method
     let id = cx.derive_id("scraped-examples");
@@ -2602,8 +2606,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean
           </h5>",
         root_path = cx.root_path(),
         id = id
-    )
-    .unwrap();
+    )?;
 
     // Create a URL to a particular location in a reverse-dependency's source file
     let link_to_loc = |call_data: &CallData, loc: &CallLocation| -> (String, String) {
@@ -2705,7 +2708,8 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean
                 title: init_title,
                 locations: locations_encoded,
             }),
-        );
+        )
+        .unwrap();
 
         true
     };
@@ -2761,8 +2765,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean
                   <div class=\"hide-more\">Hide additional examples</div>\
                   <div class=\"more-scraped-examples\">\
                     <div class=\"toggle-line\"><div class=\"toggle-line-inner\"></div></div>"
-        )
-        .unwrap();
+        )?;
 
         // Only generate inline code for MAX_FULL_EXAMPLES number of examples. Otherwise we could
         // make the page arbitrarily huge!
@@ -2774,9 +2777,8 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean
         if it.peek().is_some() {
             w.write_str(
                 r#"<div class="example-links">Additional examples can be found in:<br><ul>"#,
-            )
-            .unwrap();
-            it.for_each(|(_, call_data)| {
+            )?;
+            it.try_for_each(|(_, call_data)| {
                 let (url, _) = link_to_loc(call_data, &call_data.locations[0]);
                 write!(
                     w,
@@ -2784,13 +2786,12 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean
                     url = url,
                     name = call_data.display_name
                 )
-                .unwrap();
-            });
-            w.write_str("</ul></div>").unwrap();
+            })?;
+            w.write_str("</ul></div>")?;
         }
 
-        w.write_str("</div></details>").unwrap();
+        w.write_str("</div></details>")?;
     }
 
-    w.write_str("</div>").unwrap();
+    w.write_str("</div>")
 }
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index cd0c9775f5c..a9029972d96 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 use std::cmp::Ordering;
+use std::fmt;
 
 use askama::Template;
 use rustc_data_structures::fx::FxHashSet;
@@ -135,7 +136,11 @@ pub(crate) mod filters {
     }
 }
 
-pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut String) {
+pub(super) fn print_sidebar(
+    cx: &Context<'_>,
+    it: &clean::Item,
+    mut buffer: impl fmt::Write,
+) -> fmt::Result {
     let mut ids = IdMap::new();
     let mut blocks: Vec<LinkBlock<'_>> = docblock_toc(cx, it, &mut ids).into_iter().collect();
     let deref_id_map = cx.deref_id_map.borrow();
@@ -195,7 +200,8 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Str
         blocks,
         path,
     };
-    sidebar.render_into(buffer).unwrap();
+    sidebar.render_into(&mut buffer)?;
+    Ok(())
 }
 
 fn get_struct_fields_name<'a>(fields: &'a [clean::Item]) -> Vec<Link<'a>> {
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 095795c711d..1fa6b5a60f3 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -11,9 +11,8 @@ use rustc_session::Session;
 use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, sym};
 use tracing::info;
 
-use super::highlight;
-use super::layout::{self, BufDisplay};
 use super::render::Context;
+use super::{highlight, layout};
 use crate::clean;
 use crate::clean::utils::has_doc_flag;
 use crate::docfs::PathError;
@@ -243,16 +242,16 @@ impl SourceCollector<'_, '_> {
             &shared.layout,
             &page,
             "",
-            BufDisplay(|buf: &mut String| {
+            fmt::from_fn(|f| {
                 print_src(
-                    buf,
+                    f,
                     contents,
                     file_span,
                     self.cx,
                     &root_path,
                     &highlight::DecorationInfo::default(),
                     &source_context,
-                );
+                )
             }),
             &shared.style_files,
         );
@@ -331,7 +330,7 @@ pub(crate) fn print_src(
     root_path: &str,
     decoration_info: &highlight::DecorationInfo,
     source_context: &SourceContext<'_>,
-) {
+) -> fmt::Result {
     let mut lines = s.lines().count();
     let line_info = if let SourceContext::Embedded(info) = source_context {
         highlight::LineInfo::new_scraped(lines as u32, info.offset as u32)
@@ -367,12 +366,10 @@ pub(crate) fn print_src(
             },
             max_nb_digits,
         }
-        .render_into(&mut writer)
-        .unwrap(),
+        .render_into(&mut writer),
         SourceContext::Embedded(info) => {
-            ScrapedSource { info, code_html: code, max_nb_digits }
-                .render_into(&mut writer)
-                .unwrap();
+            ScrapedSource { info, code_html: code, max_nb_digits }.render_into(&mut writer)
         }
-    };
+    }?;
+    Ok(())
 }
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index f446c9fbbd8..705f9b2202c 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -6,7 +6,7 @@
 
 use rustc_abi::ExternAbi;
 use rustc_ast::ast;
-use rustc_attr_parsing::DeprecatedSince;
+use rustc_attr_data_structures::{self as attrs, DeprecatedSince};
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::DefId;
 use rustc_metadata::rendered_const;
@@ -153,8 +153,8 @@ where
     }
 }
 
-pub(crate) fn from_deprecation(deprecation: rustc_attr_parsing::Deprecation) -> Deprecation {
-    let rustc_attr_parsing::Deprecation { since, note, suggestion: _ } = deprecation;
+pub(crate) fn from_deprecation(deprecation: attrs::Deprecation) -> Deprecation {
+    let attrs::Deprecation { since, note, suggestion: _ } = deprecation;
     let since = match since {
         DeprecatedSince::RustcVersion(version) => Some(version.to_string()),
         DeprecatedSince::Future => Some("TBD".to_owned()),
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index b4210e7b518..001668c54a7 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -11,7 +11,6 @@
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
 #![feature(iter_intersperse)]
-#![feature(let_chains)]
 #![feature(never_type)]
 #![feature(round_char_boundary)]
 #![feature(test)]
@@ -37,6 +36,7 @@ extern crate pulldown_cmark;
 extern crate rustc_abi;
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
+extern crate rustc_attr_data_structures;
 extern crate rustc_attr_parsing;
 extern crate rustc_data_structures;
 extern crate rustc_driver;
diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs
index fdab2b08779..7b3da8d7c0f 100644
--- a/src/librustdoc/passes/propagate_stability.rs
+++ b/src/librustdoc/passes/propagate_stability.rs
@@ -6,7 +6,7 @@
 //! [`core::error`] module is marked as stable since 1.81.0, so we want to show
 //! [`core::error::Error`] as stable since 1.81.0 as well.
 
-use rustc_attr_parsing::{Stability, StabilityLevel};
+use rustc_attr_data_structures::{Stability, StabilityLevel};
 use rustc_hir::def_id::CRATE_DEF_ID;
 
 use crate::clean::{Crate, Item, ItemId, ItemKind};
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index 9ae746c13b2..852e48cbcae 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -2,7 +2,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::msrvs::{self, Msrv};
 use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
-use rustc_attr_parsing::RustcVersion;
+use rustc_attr_data_structures::RustcVersion;
 use rustc_hir::{HirId, Lit};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
diff --git a/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs
index df01c7fde18..05d8a8c26d1 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/repr_attributes.rs
@@ -1,4 +1,4 @@
-use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr};
+use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr};
 use rustc_hir::Attribute;
 use rustc_lint::LateContext;
 use rustc_span::Span;
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index bc6ba84772b..7c6fd91ca67 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -6,7 +6,7 @@ use clippy_utils::source::SpanRangeExt;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use rustc_ast::ast::LitKind;
-use rustc_attr_parsing::RustcVersion;
+use rustc_attr_data_structures::RustcVersion;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{FnKind, Visitor, walk_expr};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index 7c64bf46e7b..615421f3a40 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use rustc_attr_parsing::{AttributeKind, ReprAttr, find_attr};
+use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr};
 use rustc_hir::{HirId, Item, ItemKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::layout::LayoutOf;
diff --git a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
index 9637546b868..ebfc9972aef 100644
--- a/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/suspicious_doc_comments.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::AttrStyle;
 use rustc_ast::token::CommentKind;
-use rustc_attr_parsing::AttributeKind;
+use rustc_attr_data_structures::AttributeKind;
 use rustc_errors::Applicability;
 use rustc_hir::Attribute;
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
index dc6cbb42543..7f7224ecfc6 100644
--- a/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/too_long_first_doc_paragraph.rs
@@ -1,4 +1,4 @@
-use rustc_attr_parsing::AttributeKind;
+use rustc_attr_data_structures::AttributeKind;
 use rustc_errors::Applicability;
 use rustc_hir::{Attribute, Item, ItemKind};
 use rustc_lint::LateContext;
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 8a3f8e1c587..a26e736c7ae 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -15,7 +15,7 @@ use rustc_ast::{
     FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions,
     FormatPlaceholder, FormatTrait,
 };
-use rustc_attr_parsing::RustcVersion;
+use rustc_attr_data_structures::RustcVersion;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::Applicability;
 use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode};
diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
index e55edb1fcaa..5d0bd3e8ca3 100644
--- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
+++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs
@@ -2,7 +2,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_in_test;
 use clippy_utils::msrvs::Msrv;
-use rustc_attr_parsing::{RustcVersion, StabilityLevel, StableSince};
+use rustc_attr_data_structures::{RustcVersion, StabilityLevel, StableSince};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{Expr, ExprKind, HirId, QPath};
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 006145cc623..ff028713bf0 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -35,7 +35,7 @@ extern crate rustc_abi;
 extern crate rustc_arena;
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
-extern crate rustc_attr_parsing;
+extern crate rustc_attr_data_structures;
 extern crate rustc_data_structures;
 extern crate rustc_driver;
 extern crate rustc_errors;
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index d68ac8bab12..3d39386ecf9 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -2,7 +2,7 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::msrvs::Msrv;
-use rustc_attr_parsing::{StabilityLevel, StableSince};
+use rustc_attr_data_structures::{StabilityLevel, StableSince};
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
diff --git a/src/tools/clippy/clippy_lints_internal/src/lib.rs b/src/tools/clippy/clippy_lints_internal/src/lib.rs
index 43cde86504f..0c94d100c41 100644
--- a/src/tools/clippy/clippy_lints_internal/src/lib.rs
+++ b/src/tools/clippy/clippy_lints_internal/src/lib.rs
@@ -20,6 +20,7 @@
 #![allow(clippy::missing_clippy_version_attribute)]
 
 extern crate rustc_ast;
+extern crate rustc_attr_data_structures;
 extern crate rustc_attr_parsing;
 extern crate rustc_data_structures;
 extern crate rustc_errors;
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 0a9c39c41bd..4fb608a6482 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -27,6 +27,7 @@
 // (Currently there is no way to opt into sysroot crates without `extern crate`.)
 extern crate rustc_abi;
 extern crate rustc_ast;
+extern crate rustc_attr_data_structures;
 extern crate rustc_attr_parsing;
 extern crate rustc_const_eval;
 extern crate rustc_data_structures;
@@ -88,7 +89,7 @@ use std::sync::{Mutex, MutexGuard, OnceLock};
 use itertools::Itertools;
 use rustc_abi::Integer;
 use rustc_ast::ast::{self, LitKind, RangeLimits};
-use rustc_attr_parsing::{AttributeKind, find_attr};
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::packed::Pu128;
 use rustc_data_structures::unhash::UnhashMap;
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 223a8649eb3..599c6f3a4ff 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -1,7 +1,8 @@
 use crate::sym;
 use rustc_ast::Attribute;
 use rustc_ast::attr::AttributeExt;
-use rustc_attr_parsing::{RustcVersion, parse_version};
+use rustc_attr_data_structures::RustcVersion;
+use rustc_attr_parsing::parse_version;
 use rustc_lint::LateContext;
 use rustc_session::Session;
 use rustc_span::Symbol;
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 5d0401010db..45da266fd8a 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -5,7 +5,7 @@
 
 use crate::msrvs::{self, Msrv};
 use hir::LangItem;
-use rustc_attr_parsing::{RustcVersion, StableSince};
+use rustc_attr_data_structures::{RustcVersion, StableSince};
 use rustc_const_eval::check_consts::ConstCx;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -404,7 +404,7 @@ fn is_stable_const_fn(cx: &LateContext<'_>, def_id: DefId, msrv: Msrv) -> bool {
                     .and_then(|trait_def_id| cx.tcx.lookup_const_stability(trait_def_id))
             })
             .is_none_or(|const_stab| {
-                if let rustc_attr_parsing::StabilityLevel::Stable { since, .. } = const_stab.level {
+                if let rustc_attr_data_structures::StabilityLevel::Stable { since, .. } = const_stab.level {
                     // Checking MSRV is manually necessary because `rustc` has no such concept. This entire
                     // function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`.
                     // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262.
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 93f7b1cb7cf..3b544d8b828 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -37,7 +37,7 @@ libc = "0.2"
 miow = "0.6"
 
 [target.'cfg(windows)'.dependencies.windows]
-version = "0.59.0"
+version = "0.61.0"
 features = [
     "Win32_Foundation",
     "Win32_System_Diagnostics_Debug",
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index b692ddab4ff..122438a2509 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -580,6 +580,7 @@ Definite bugs found:
 * [Weak-memory-induced memory leak in Windows thread-local storage](https://github.com/rust-lang/rust/pull/124281)
 * [A bug in the new `RwLock::downgrade` implementation](https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/Miri.20error.20library.20test) (caught by Miri before it landed in the Rust repo)
 * [Mockall reading unintialized memory when mocking `std::io::Read::read`, even if all expectations are satisfied](https://github.com/asomers/mockall/issues/647) (caught by Miri running Tokio's test suite)
+* [`ReentrantLock` not correctly dealing with reuse of addresses for TLS storage of different threads](https://github.com/rust-lang/rust/pull/141248)
 
 Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment):
 
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index 171e157789d..4857f62cd3a 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -176,8 +176,11 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
     // Set `--target-dir` to `miri` inside the original target directory.
     let target_dir = get_target_dir(&metadata);
     cmd.arg("--target-dir").arg(target_dir);
-    // Enable cross-target doctests (for consistency between different cargo versions).
-    cmd.arg("-Zdoctest-xcompile");
+    // Only when running in x.py (where we are running with beta cargo): set `RUSTC_STAGE`.
+    // Will have to be removed on next bootstrap bump. tag: cfg(bootstrap).
+    if env::var_os("RUSTC_STAGE").is_some() {
+        cmd.arg("-Zdoctest-xcompile");
+    }
 
     // *After* we set all the flags that need setting, forward everything else. Make sure to skip
     // `--target-dir` (which would otherwise be set twice).
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 79abbfaeaf1..8b98fe3c4fc 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-a69bc17fb8026bdc0d24bb1896ff95f0eba1da4e
+ac17c3486c6fdfbb0c3c18b99f3d8dfbff625d29
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index d2a73516623..8e7c9edfcc0 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -933,7 +933,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
     }
 
     /// Check that the calling convention is what we expect.
-    fn check_callconv<'a>(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, exp_abi: Conv) -> InterpResult<'a, ()> {
+    fn check_callconv<'a>(
+        &self,
+        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+        exp_abi: Conv,
+    ) -> InterpResult<'a, ()> {
         if fn_abi.conv != exp_abi {
             throw_ub_format!(
                 "calling a function with calling convention {exp_abi} using caller calling convention {}",
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 0b7a067058b..329a7e56bc0 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -60,7 +60,7 @@ extern crate tracing;
 extern crate rustc_abi;
 extern crate rustc_apfloat;
 extern crate rustc_ast;
-extern crate rustc_attr_parsing;
+extern crate rustc_attr_data_structures;
 extern crate rustc_const_eval;
 extern crate rustc_data_structures;
 extern crate rustc_errors;
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index dbde415170c..1c6c7894cb4 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -13,7 +13,7 @@ use rand::rngs::StdRng;
 use rand::{Rng, SeedableRng};
 use rustc_abi::{Align, ExternAbi, Size};
 use rustc_apfloat::{Float, FloatConvert};
-use rustc_attr_parsing::InlineAttr;
+use rustc_attr_data_structures::InlineAttr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 #[allow(unused)]
 use rustc_data_structures::static_assert_size;
diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs
index 0258a76c3e7..1a43e229725 100644
--- a/src/tools/miri/src/shims/native_lib.rs
+++ b/src/tools/miri/src/shims/native_lib.rs
@@ -92,8 +92,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
     fn get_func_ptr_explicitly_from_lib(&mut self, link_name: Symbol) -> Option<CodePtr> {
         let this = self.eval_context_mut();
         // Try getting the function from the shared library.
-        // On windows `_lib_path` will be unused, hence the name starting with `_`.
-        let (lib, _lib_path) = this.machine.native_lib.as_ref().unwrap();
+        let (lib, lib_path) = this.machine.native_lib.as_ref().unwrap();
         let func: libloading::Symbol<'_, unsafe extern "C" fn()> = unsafe {
             match lib.get(link_name.as_str().as_bytes()) {
                 Ok(x) => x,
@@ -114,11 +113,17 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
         // This code is a reimplementation of the mechanism for getting `dli_fname` in `libloading`,
         // from: https://docs.rs/libloading/0.7.3/src/libloading/os/unix/mod.rs.html#411
         // using the `libc` crate where this interface is public.
-        let mut info = std::mem::MaybeUninit::<libc::Dl_info>::uninit();
+        let mut info = std::mem::MaybeUninit::<libc::Dl_info>::zeroed();
         unsafe {
             if libc::dladdr(*func.deref() as *const _, info.as_mut_ptr()) != 0 {
-                if std::ffi::CStr::from_ptr(info.assume_init().dli_fname).to_str().unwrap()
-                    != _lib_path.to_str().unwrap()
+                let info = info.assume_init();
+                #[cfg(target_os = "cygwin")]
+                let fname_ptr = info.dli_fname.as_ptr();
+                #[cfg(not(target_os = "cygwin"))]
+                let fname_ptr = info.dli_fname;
+                assert!(!fname_ptr.is_null());
+                if std::ffi::CStr::from_ptr(fname_ptr).to_str().unwrap()
+                    != lib_path.to_str().unwrap()
                 {
                     return None;
                 }
diff --git a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs
index e6282613df7..ff16ac61d8b 100644
--- a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs
+++ b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs
@@ -1,14 +1,11 @@
-#![feature(intrinsics)]
-
-// Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+#![feature(core_intrinsics)]
 
 fn main() {
     let mut data = [0u8; 16];
     unsafe {
         let a = data.as_mut_ptr();
         let b = a.wrapping_offset(1) as *mut _;
-        copy_nonoverlapping(a, b, 2); //~ ERROR: `copy_nonoverlapping` called on overlapping ranges
+        // Directly call intrinsic to avoid debug assertions in the `std::ptr` version.
+        std::intrinsics::copy_nonoverlapping(a, b, 2); //~ ERROR: `copy_nonoverlapping` called on overlapping ranges
     }
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr
index fef5a0a82a0..9b60a48703b 100644
--- a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
   --> tests/fail/intrinsics/copy_overlapping.rs:LL:CC
    |
-LL |         copy_nonoverlapping(a, b, 2);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
+LL |         std::intrinsics::copy_nonoverlapping(a, b, 2);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs
index ded9d0b669e..311789cdc4b 100644
--- a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs
+++ b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs
@@ -1,14 +1,11 @@
-#![feature(intrinsics)]
-
-// Directly call intrinsic to avoid debug assertions in libstd
-#[rustc_intrinsic]
-unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+#![feature(core_intrinsics)]
 
 fn main() {
     let mut data = [0u16; 8];
     let ptr = (&mut data[0] as *mut u16 as *mut u8).wrapping_add(1) as *mut u16;
     // Even copying 0 elements to something unaligned should error
     unsafe {
-        copy_nonoverlapping(&data[5], ptr, 0); //~ ERROR: accessing memory with alignment 1, but alignment 2 is required
+        // Directly call intrinsic to avoid debug assertions in the `std::ptr` version.
+        std::intrinsics::copy_nonoverlapping(&data[5], ptr, 0); //~ ERROR: accessing memory with alignment 1, but alignment 2 is required
     }
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr
index 2d0edd4e6cb..65dbdb3bbb6 100644
--- a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required
   --> tests/fail/intrinsics/copy_unaligned.rs:LL:CC
    |
-LL |         copy_nonoverlapping(&data[5], ptr, 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
+LL |         std::intrinsics::copy_nonoverlapping(&data[5], ptr, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/many-seeds/reentrant-lock.rs b/src/tools/miri/tests/many-seeds/reentrant-lock.rs
new file mode 100644
index 00000000000..8a363179a9c
--- /dev/null
+++ b/src/tools/miri/tests/many-seeds/reentrant-lock.rs
@@ -0,0 +1,19 @@
+#![feature(reentrant_lock)]
+//! This is a regression test for
+//! <https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/reentrant.20lock.20failure.20on.20musl>.
+
+use std::cell::Cell;
+use std::sync::ReentrantLock;
+use std::thread;
+
+static LOCK: ReentrantLock<Cell<i32>> = ReentrantLock::new(Cell::new(0));
+
+fn main() {
+    for _ in 0..20 {
+        thread::spawn(move || {
+            let val = LOCK.lock();
+            val.set(val.get() + 1);
+            drop(val);
+        });
+    }
+}
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs
index 47f086f7340..48633c0a7fe 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-aes-vaes.rs
@@ -2,7 +2,7 @@
 //@only-target: x86_64 i686
 //@compile-flags: -C target-feature=+aes,+vaes,+avx512f
 
-#![feature(avx512_target_feature, stdarch_x86_avx512)]
+#![feature(stdarch_x86_avx512)]
 
 use core::mem::transmute;
 #[cfg(target_arch = "x86")]
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs
index db593063890..0ec2f679d80 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-avx512.rs
@@ -2,7 +2,6 @@
 //@only-target: x86_64 i686
 //@compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bitalg,+avx512vpopcntdq
 
-#![feature(avx512_target_feature)]
 #![feature(stdarch_x86_avx512)]
 
 #[cfg(target_arch = "x86")]
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
index 882b5e3f795..b58d68e2ef9 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-gfni.rs
@@ -6,7 +6,6 @@
 // be interpreted as integers; signedness does not make sense for them, but
 // __mXXXi happens to be defined in terms of signed integers.
 #![allow(overflowing_literals)]
-#![feature(avx512_target_feature)]
 #![feature(stdarch_x86_avx512)]
 
 #[cfg(target_arch = "x86")]
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs
index 68964728e4e..c7c9eb5e395 100644
--- a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-vpclmulqdq.rs
@@ -8,7 +8,6 @@
 // be interpreted as integers; signedness does not make sense for them, but
 // __mXXXi happens to be defined in terms of signed integers.
 #![allow(overflowing_literals)]
-#![feature(avx512_target_feature)]
 #![feature(stdarch_x86_avx512)]
 
 #[cfg(target_arch = "x86")]
diff --git a/src/tools/opt-dist/src/bolt.rs b/src/tools/opt-dist/src/bolt.rs
index 0f1fda38115..a06e59fcc41 100644
--- a/src/tools/opt-dist/src/bolt.rs
+++ b/src/tools/opt-dist/src/bolt.rs
@@ -80,7 +80,7 @@ pub fn bolt_optimize(
         // Move jump tables to a separate section
         .arg("-jump-tables=move")
         // Fold functions with identical code
-        .arg("-icf=1")
+        .arg("-icf=all")
         // The following flag saves about 50 MiB of libLLVM.so size.
         // However, it succeeds very non-deterministically. To avoid frequent artifact size swings,
         // it is kept disabled for now.
diff --git a/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/config.yml b/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 00000000000..466672e3d48
--- /dev/null
+++ b/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,4 @@
+contact_links:
+  - name: Questions regarding rust-analyzer
+    url: https://github.com/rust-lang/rust-analyzer/discussions
+    about: Please ask and answer questions here instead of opening an issue
diff --git a/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md b/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md
index 23c43443c84..2b44bdc748f 100644
--- a/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md
+++ b/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/critical_nightly_regression.md
@@ -12,5 +12,3 @@ Troubleshooting guide: https://rust-analyzer.github.io/book/troubleshooting.html
 
 Please try to provide information which will help us to fix the issue faster. Minimal reproducible examples with few dependencies are especially lovely <3.
 -->
-
-This is a serious regression in nightly and it's important to fix it before the next release.
diff --git a/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/question.md b/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/question.md
deleted file mode 100644
index a90ade882bd..00000000000
--- a/src/tools/rust-analyzer/.github/ISSUE_TEMPLATE/question.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: Support Question
-about: A question regarding functionality of rust-analyzer.
-title: ''
-labels: 'C-support'
-assignees: ''
-
----
diff --git a/src/tools/rust-analyzer/.github/workflows/metrics.yaml b/src/tools/rust-analyzer/.github/workflows/metrics.yaml
index a4146d60218..dc2f432bbc7 100644
--- a/src/tools/rust-analyzer/.github/workflows/metrics.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/metrics.yaml
@@ -18,9 +18,9 @@ jobs:
     steps:
       - name: Install Rust toolchain
         run: |
-          rustup update --no-self-update stable
-          rustup default stable
-          rustup component add --toolchain stable rust-src
+          rustup update --no-self-update beta
+          rustup default beta
+          rustup component add --toolchain beta rust-src
 
       - name: Checkout repository
         uses: actions/checkout@v4
@@ -61,9 +61,9 @@ jobs:
     steps:
       - name: Install Rust toolchain
         run: |
-          rustup update --no-self-update stable
-          rustup default stable
-          rustup component add --toolchain stable rust-src
+          rustup update --no-self-update beta
+          rustup default beta
+          rustup component add --toolchain beta rust-src
 
       - name: Checkout repository
         uses: actions/checkout@v4
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 8d6c8284e44..bd8146defae 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -61,9 +61,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
 [[package]]
 name = "backtrace"
-version = "0.3.74"
+version = "0.3.75"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
+checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
 dependencies = [
  "addr2line",
  "cfg-if",
@@ -80,6 +80,7 @@ version = "0.0.0"
 dependencies = [
  "cfg",
  "dashmap",
+ "indexmap",
  "intern",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "query-group-macro",
@@ -316,9 +317,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
 
 [[package]]
 name = "ctrlc"
-version = "3.4.5"
+version = "3.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90eeab0aa92f3f9b4e87f258c72b139c207d251f9cbc1080a0086b86a8870dd3"
+checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73"
 dependencies = [
  "nix",
  "windows-sys 0.59.0",
@@ -472,9 +473,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
 
 [[package]]
 name = "flate2"
-version = "1.1.0"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
+checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -1010,9 +1011,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.8.0"
+version = "2.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
+checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
 dependencies = [
  "equivalent",
  "hashbrown 0.15.2",
@@ -1123,12 +1124,12 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
 
 [[package]]
 name = "libloading"
-version = "0.8.6"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
+checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c"
 dependencies = [
  "cfg-if",
- "windows-targets 0.52.6",
+ "windows-targets 0.53.0",
 ]
 
 [[package]]
@@ -1358,9 +1359,9 @@ dependencies = [
 
 [[package]]
 name = "nix"
-version = "0.29.0"
+version = "0.30.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
+checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
 dependencies = [
  "bitflags 2.9.0",
  "cfg-if",
@@ -1640,14 +1641,14 @@ dependencies = [
 
 [[package]]
 name = "process-wrap"
-version = "8.2.0"
+version = "8.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d35f4dc9988d1326b065b4def5e950c3ed727aa03e3151b86cc9e2aec6b03f54"
+checksum = "a3ef4f2f0422f23a82ec9f628ea2acd12871c81a9362b02c43c1aa86acfc3ba1"
 dependencies = [
  "indexmap",
  "nix",
  "tracing",
- "windows 0.59.0",
+ "windows 0.61.1",
 ]
 
 [[package]]
@@ -1749,9 +1750,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.110.0"
+version = "0.113.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "912228bd8ed3beff1f6f9e5e2d4b37c0827ba3e2070060bf3858a311d0e29e30"
+checksum = "c33b8fa229789975647ca5426be432c7c327ebde89ab15889928185dbcee3230"
 dependencies = [
  "bitflags 2.9.0",
  "ra-ap-rustc_hashes",
@@ -1761,18 +1762,18 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_hashes"
-version = "0.110.0"
+version = "0.113.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba520764daf057a9d963fa769f4762eaf87ac5d4900ae76195eeead64cd35afd"
+checksum = "0d68a3e389927002f552938a90b04787f6435f55b46fc5691360470d1cb2e99d"
 dependencies = [
  "rustc-stable-hash",
 ]
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.110.0"
+version = "0.113.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b76b5f9ee55f2d0e5a65bea23f6d738893349ce8d3d17a6720933e647ab04978"
+checksum = "32502273df2838d0ca13f1c67e2a48feef940e591f9771869f07e2db2acede53"
 dependencies = [
  "ra-ap-rustc_index_macros",
  "smallvec",
@@ -1780,9 +1781,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.110.0"
+version = "0.113.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddd972eb1face2fcaa0d94c01d97862fb955b5561d4f5932003bce8a6cadd8c6"
+checksum = "8a32f081864ae34c7ae6634edfa7a95ab9260ba85015e8b1d347580eda79d14f"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1791,9 +1792,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.110.0"
+version = "0.113.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3a9876456fb2521097deef33ddeac1c18260c8eafb68054d986f8b9d6ce9fa"
+checksum = "ed34c51974718c5bd90d876d1364d9725159fc8030c2382b9cb837034152ed68"
 dependencies = [
  "memchr",
  "unicode-properties",
@@ -1802,9 +1803,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.110.0"
+version = "0.113.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e85de58dfcc60a5f9d5ec0157a657e3f84abd8f22c8a0c4d707cfb42c9011f4"
+checksum = "ff0440e5d27facbf4ff13ea651e48c2f6e360b3dbfc56251b41d60719b965fb8"
 dependencies = [
  "ra-ap-rustc_lexer",
  "rustc-literal-escaper",
@@ -1812,9 +1813,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.110.0"
+version = "0.113.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ceadf9db550db67deff7eff2e2765109b860c9d7e5bdfca144863020289c823d"
+checksum = "a6056efa57aba3aa0cc69a0bf1a8281624c23ad25b05748d11ebcd4668037bfc"
 dependencies = [
  "ra-ap-rustc_index",
  "rustc-hash 2.1.1",
@@ -2228,6 +2229,7 @@ version = "0.0.0"
 dependencies = [
  "backtrace",
  "crossbeam-channel",
+ "crossbeam-utils",
  "itertools 0.14.0",
  "jod-thread",
  "libc",
@@ -2750,12 +2752,24 @@ dependencies = [
 
 [[package]]
 name = "windows"
-version = "0.59.0"
+version = "0.61.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1"
+checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419"
 dependencies = [
- "windows-core 0.59.0",
- "windows-targets 0.53.0",
+ "windows-collections",
+ "windows-core 0.61.0",
+ "windows-future",
+ "windows-link",
+ "windows-numerics",
+]
+
+[[package]]
+name = "windows-collections"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
+dependencies = [
+ "windows-core 0.61.0",
 ]
 
 [[package]]
@@ -2773,15 +2787,25 @@ dependencies = [
 
 [[package]]
 name = "windows-core"
-version = "0.59.0"
+version = "0.61.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
+checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980"
 dependencies = [
- "windows-implement 0.59.0",
- "windows-interface 0.59.0",
- "windows-result 0.3.1",
- "windows-strings 0.3.1",
- "windows-targets 0.53.0",
+ "windows-implement 0.60.0",
+ "windows-interface 0.59.1",
+ "windows-link",
+ "windows-result 0.3.2",
+ "windows-strings 0.4.0",
+]
+
+[[package]]
+name = "windows-future"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32"
+dependencies = [
+ "windows-core 0.61.0",
+ "windows-link",
 ]
 
 [[package]]
@@ -2797,9 +2821,9 @@ dependencies = [
 
 [[package]]
 name = "windows-implement"
-version = "0.59.0"
+version = "0.60.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
+checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2819,9 +2843,9 @@ dependencies = [
 
 [[package]]
 name = "windows-interface"
-version = "0.59.0"
+version = "0.59.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2830,9 +2854,19 @@ dependencies = [
 
 [[package]]
 name = "windows-link"
-version = "0.1.0"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
+
+[[package]]
+name = "windows-numerics"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3"
+checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
+dependencies = [
+ "windows-core 0.61.0",
+ "windows-link",
+]
 
 [[package]]
 name = "windows-result"
@@ -2845,9 +2879,9 @@ dependencies = [
 
 [[package]]
 name = "windows-result"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189"
+checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
 dependencies = [
  "windows-link",
 ]
@@ -2864,9 +2898,9 @@ dependencies = [
 
 [[package]]
 name = "windows-strings"
-version = "0.3.1"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
+checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97"
 dependencies = [
  "windows-link",
 ]
@@ -3230,17 +3264,14 @@ dependencies = [
 
 [[package]]
 name = "zip"
-version = "2.4.2"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50"
+checksum = "12598812502ed0105f607f941c386f43d441e00148fce9dec3ca5ffb0bde9308"
 dependencies = [
  "arbitrary",
  "crc32fast",
- "crossbeam-utils",
- "displaydoc",
  "flate2",
  "indexmap",
  "memchr",
- "thiserror 2.0.12",
  "time",
 ]
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index c4c2fdf34ba..07731bae3f3 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -85,11 +85,11 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 edition = { path = "./crates/edition", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.110", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.110", default-features = false }
-ra-ap-rustc_index = { version = "0.110", default-features = false }
-ra-ap-rustc_abi = { version = "0.110", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.110", default-features = false }
+ra-ap-rustc_lexer = { version = "0.113", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.113", default-features = false }
+ra-ap-rustc_index = { version = "0.113", default-features = false }
+ra-ap-rustc_abi = { version = "0.113", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.113", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 
@@ -132,7 +132,10 @@ pulldown-cmark-to-cmark = "10.0.4"
 pulldown-cmark = { version = "0.9.6", default-features = false }
 rayon = "1.10.0"
 rowan = "=0.15.15"
-salsa = { version = "0.21.1", default-features = false, features = ["rayon","salsa_unstable"] }
+salsa = { version = "0.21.1", default-features = false, features = [
+  "rayon",
+  "salsa_unstable",
+] }
 salsa-macros = "0.21.1"
 semver = "1.0.26"
 serde = { version = "1.0.219" }
diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
index e2e3253773f..3b423a86f97 100644
--- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
@@ -21,6 +21,7 @@ rustc-hash.workspace = true
 triomphe.workspace = true
 semver.workspace = true
 tracing.workspace = true
+indexmap.workspace = true
 
 # local deps
 cfg.workspace = true
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 9660e6e87cc..d42d7e5707d 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -14,7 +14,7 @@ use dashmap::DashMap;
 use dashmap::mapref::entry::Entry;
 use intern::Symbol;
 use la_arena::{Arena, Idx, RawIdx};
-use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
+use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet, FxHasher};
 use salsa::{Durability, Setter};
 use span::Edition;
 use triomphe::Arc;
@@ -24,6 +24,8 @@ use crate::{CrateWorkspaceData, EditionedFileId, RootQueryDb};
 
 pub type ProcMacroPaths = FxHashMap<CrateBuilderId, Result<(String, AbsPathBuf), String>>;
 
+type FxIndexSet<T> = indexmap::IndexSet<T, FxBuildHasher>;
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
 pub struct SourceRootId(pub u32);
 
@@ -474,7 +476,9 @@ impl CrateGraphBuilder {
     }
 
     pub fn set_in_db(self, db: &mut dyn RootQueryDb) -> CratesIdMap {
-        let mut all_crates = Vec::with_capacity(self.arena.len());
+        // For some reason in some repositories we have duplicate crates, so we use a set and not `Vec`.
+        // We use an `IndexSet` because the list needs to be topologically sorted.
+        let mut all_crates = FxIndexSet::with_capacity_and_hasher(self.arena.len(), FxBuildHasher);
         let mut visited = FxHashMap::default();
         let mut visited_root_files = FxHashSet::default();
 
@@ -494,9 +498,11 @@ impl CrateGraphBuilder {
             );
         }
 
-        if **old_all_crates != *all_crates {
+        if old_all_crates.len() != all_crates.len()
+            || old_all_crates.iter().any(|&krate| !all_crates.contains(&krate))
+        {
             db.set_all_crates_with_durability(
-                Arc::new(all_crates.into_boxed_slice()),
+                Arc::new(Vec::from_iter(all_crates).into_boxed_slice()),
                 Durability::MEDIUM,
             );
         }
@@ -509,7 +515,7 @@ impl CrateGraphBuilder {
             crates_map: &CratesMap,
             visited: &mut FxHashMap<CrateBuilderId, Crate>,
             visited_root_files: &mut FxHashSet<FileId>,
-            all_crates: &mut Vec<Crate>,
+            all_crates: &mut FxIndexSet<Crate>,
             source: CrateBuilderId,
         ) -> Crate {
             if let Some(&crate_id) = visited.get(&source) {
@@ -597,7 +603,7 @@ impl CrateGraphBuilder {
                     input
                 }
             };
-            all_crates.push(crate_input);
+            all_crates.insert(crate_input);
             visited.insert(source, crate_input);
             crate_input
         }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index 2cbdbe16f9b..4a9a3b12cfa 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -24,8 +24,8 @@ use crate::{
     item_tree::{AttrOwner, ItemTree},
     lang_item::{self, LangItem},
     nameres::{
-        DefMap, LocalDefMap,
         assoc::{ImplItems, TraitItems},
+        crate_def_map,
         diagnostics::DefDiagnostics,
     },
     signatures::{
@@ -111,16 +111,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
     #[salsa::invoke(ItemTree::block_item_tree_query)]
     fn block_item_tree(&self, block_id: BlockId) -> Arc<ItemTree>;
 
-    #[salsa::invoke(DefMap::crate_local_def_map_query)]
-    fn crate_local_def_map(&self, krate: Crate) -> (Arc<DefMap>, Arc<LocalDefMap>);
-
-    #[salsa::invoke(DefMap::crate_def_map_query)]
-    fn crate_def_map(&self, krate: Crate) -> Arc<DefMap>;
-
-    /// Computes the block-level `DefMap`.
-    #[salsa::invoke(DefMap::block_def_map_query)]
-    fn block_def_map(&self, block: BlockId) -> Arc<DefMap>;
-
     /// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution.
     #[salsa::invoke(macro_def)]
     fn macro_def(&self, m: MacroId) -> MacroDefId;
@@ -363,7 +353,7 @@ fn include_macro_invoc(
     db: &dyn DefDatabase,
     krate: Crate,
 ) -> Arc<[(MacroCallId, EditionedFileId)]> {
-    db.crate_def_map(krate)
+    crate_def_map(db, krate)
         .modules
         .values()
         .flat_map(|m| m.scope.iter_macro_invoc())
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs
index e3775c4931a..f617c3225ae 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs
@@ -19,7 +19,6 @@ use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use span::{Edition, SyntaxContext};
 use syntax::{AstPtr, SyntaxNodePtr, ast};
-use triomphe::Arc;
 use tt::TextRange;
 
 use crate::{
@@ -30,7 +29,7 @@ use crate::{
         Array, AsmOperand, Binding, BindingId, Expr, ExprId, ExprOrPatId, Label, LabelId, Pat,
         PatId, RecordFieldPat, Statement,
     },
-    nameres::DefMap,
+    nameres::{DefMap, block_def_map},
     type_ref::{LifetimeRef, LifetimeRefId, PathId, TypeRef, TypeRefId},
 };
 
@@ -225,8 +224,8 @@ impl ExpressionStore {
     pub fn blocks<'a>(
         &'a self,
         db: &'a dyn DefDatabase,
-    ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + 'a {
-        self.block_scopes.iter().map(move |&block| (block, db.block_def_map(block)))
+    ) -> impl Iterator<Item = (BlockId, &'a DefMap)> + 'a {
+        self.block_scopes.iter().map(move |&block| (block, block_def_map(db, block)))
     }
 
     pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
@@ -299,17 +298,16 @@ impl ExpressionStore {
             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::InOut { expr, .. }
+                | AsmOperand::Const(expr)
+                | AsmOperand::Label(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(_) => (),
+                AsmOperand::Out { expr: None, .. } | AsmOperand::Sym(_) => (),
             }),
             Expr::If { condition, then_branch, else_branch } => {
                 f(*condition);
@@ -436,17 +434,16 @@ impl ExpressionStore {
             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::InOut { expr, .. }
+                | AsmOperand::Const(expr)
+                | AsmOperand::Label(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(_) => (),
+                AsmOperand::Out { expr: None, .. } | AsmOperand::Sym(_) => (),
             }),
             Expr::If { condition, then_branch, else_branch } => {
                 f(*condition);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
index 50505d54ba2..29871f5e04d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs
@@ -56,7 +56,7 @@ use crate::{
     item_scope::BuiltinShadowMode,
     item_tree::FieldsShape,
     lang_item::LangItem,
-    nameres::{DefMap, LocalDefMap, MacroSubNs},
+    nameres::{DefMap, LocalDefMap, MacroSubNs, block_def_map},
     type_ref::{
         ArrayType, ConstRef, FnType, LifetimeRef, LifetimeRefId, Mutability, PathId, Rawness,
         RefType, TraitBoundModifier, TraitRef, TypeBound, TypeRef, TypeRefId, UseArgRef,
@@ -436,8 +436,8 @@ pub struct ExprCollector<'db> {
     db: &'db dyn DefDatabase,
     cfg_options: &'db CfgOptions,
     expander: Expander,
-    def_map: Arc<DefMap>,
-    local_def_map: Arc<LocalDefMap>,
+    def_map: &'db DefMap,
+    local_def_map: &'db LocalDefMap,
     module: ModuleId,
     pub store: ExpressionStoreBuilder,
     pub(crate) source_map: ExpressionStoreSourceMap,
@@ -544,7 +544,7 @@ impl ExprCollector<'_> {
         current_file_id: HirFileId,
     ) -> ExprCollector<'_> {
         let (def_map, local_def_map) = module.local_def_map(db);
-        let expander = Expander::new(db, current_file_id, &def_map);
+        let expander = Expander::new(db, current_file_id, def_map);
         ExprCollector {
             db,
             cfg_options: module.krate().cfg_options(db),
@@ -1947,7 +1947,7 @@ impl ExprCollector<'_> {
                 let resolver = |path: &_| {
                     self.def_map
                         .resolve_path(
-                            &self.local_def_map,
+                            self.local_def_map,
                             self.db,
                             module,
                             path,
@@ -2163,12 +2163,12 @@ impl ExprCollector<'_> {
         };
 
         let (module, def_map) =
-            match block_id.map(|block_id| (self.db.block_def_map(block_id), block_id)) {
+            match block_id.map(|block_id| (block_def_map(self.db, block_id), block_id)) {
                 Some((def_map, block_id)) => {
                     self.store.block_scopes.push(block_id);
                     (def_map.module_id(DefMap::ROOT), def_map)
                 }
-                None => (self.module, self.def_map.clone()),
+                None => (self.module, self.def_map),
             };
         let prev_def_map = mem::replace(&mut self.def_map, def_map);
         let prev_local_module = mem::replace(&mut self.module, module);
@@ -2247,7 +2247,7 @@ impl ExprCollector<'_> {
                     // This could also be a single-segment path pattern. To
                     // decide that, we need to try resolving the name.
                     let (resolved, _) = self.def_map.resolve_path(
-                        &self.local_def_map,
+                        self.local_def_map,
                         self.db,
                         self.module.local_id,
                         &name.clone().into(),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs
index 629d1f2ada7..be006c98a58 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path.rs
@@ -232,6 +232,14 @@ pub(super) fn lower_path(
             .with_borrow_mut(|map| map.extend(ast_segments.into_iter().zip(ast_segments_offset..)));
     }
 
+    if let Some(last_segment_args @ Some(GenericArgs { has_self_type: true, .. })) =
+        generic_args.last_mut()
+    {
+        // Well-formed code cannot have `<T as Trait>` without an associated item after,
+        // and this causes panics in hir-ty lowering.
+        *last_segment_args = None;
+    }
+
     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));
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs
index 337cb103bde..8fd81c7b3df 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower/path/tests.rs
@@ -4,7 +4,6 @@ use syntax::ast::{self, make};
 use test_fixture::WithFixture;
 
 use crate::{
-    db::DefDatabase,
     expr_store::{
         ExpressionStore,
         lower::{
@@ -14,13 +13,15 @@ use crate::{
         path::Path,
         pretty,
     },
+    nameres::crate_def_map,
     test_db::TestDB,
 };
 
 fn lower_path(path: ast::Path) -> (TestDB, ExpressionStore, Option<Path>) {
     let (db, file_id) = TestDB::with_single_file("");
     let krate = db.fetch_test_crate();
-    let mut ctx = ExprCollector::new(&db, db.crate_def_map(krate).root_module_id(), file_id.into());
+    let mut ctx =
+        ExprCollector::new(&db, crate_def_map(&db, krate).root_module_id(), file_id.into());
     let lowered_path = ctx.lower_path(path, &mut ExprCollector::impl_trait_allocator);
     let store = ctx.store.finish();
     (db, store, lowered_path)
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs
index 431ea9eb1d4..a46711c67e8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/scope.rs
@@ -324,11 +324,13 @@ mod tests {
     use test_fixture::WithFixture;
     use test_utils::{assert_eq_text, extract_offset};
 
-    use crate::{FunctionId, ModuleDefId, db::DefDatabase, test_db::TestDB};
+    use crate::{
+        FunctionId, ModuleDefId, db::DefDatabase, nameres::crate_def_map, test_db::TestDB,
+    };
 
     fn find_function(db: &TestDB, file_id: FileId) -> FunctionId {
         let krate = db.test_crate();
-        let crate_def_map = db.crate_def_map(krate);
+        let crate_def_map = crate_def_map(db, krate);
 
         let module = crate_def_map.modules_for_file(db, file_id).next().unwrap();
         let (_, def) = crate_def_map[module].scope.entries().next().unwrap();
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs
index d6645dc1d1d..29e249b07a7 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body.rs
@@ -1,9 +1,10 @@
 mod block;
 
-use crate::{DefWithBodyId, ModuleDefId, hir::MatchArm, test_db::TestDB};
+use crate::{DefWithBodyId, ModuleDefId, hir::MatchArm, nameres::crate_def_map, test_db::TestDB};
 use expect_test::{Expect, expect};
 use la_arena::RawIdx;
 use test_fixture::WithFixture;
+use triomphe::Arc;
 
 use super::super::*;
 
@@ -11,7 +12,7 @@ fn lower(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (TestDB, Arc<Body>,
     let db = TestDB::with_files(ra_fixture);
 
     let krate = db.fetch_test_crate();
-    let def_map = db.crate_def_map(krate);
+    let def_map = crate_def_map(&db, krate);
     let mut fn_def = None;
     'outer: for (_, module) in def_map.modules() {
         for decl in module.scope.declarations() {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs
index da3b65d4203..5f7b510bba4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/body/block.rs
@@ -189,8 +189,8 @@ fn f() {
 }
     "#,
         expect![[r#"
-            BlockId(3801) in BlockRelativeModuleId { block: Some(BlockId(3800)), local_id: Idx::<ModuleData>(1) }
-            BlockId(3800) in BlockRelativeModuleId { block: None, local_id: Idx::<ModuleData>(0) }
+            BlockId(3c01) in BlockRelativeModuleId { block: Some(BlockId(3c00)), local_id: Idx::<ModuleData>(1) }
+            BlockId(3c00) in BlockRelativeModuleId { block: None, local_id: Idx::<ModuleData>(0) }
             crate scope
         "#]],
     );
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/signatures.rs
index 80561d64708..efb558a7758 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/signatures.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/tests/signatures.rs
@@ -1,6 +1,7 @@
 use crate::{
     GenericDefId, ModuleDefId,
     expr_store::pretty::{print_function, print_struct},
+    nameres::crate_def_map,
     test_db::TestDB,
 };
 use expect_test::{Expect, expect};
@@ -12,7 +13,7 @@ fn lower_and_print(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expe
     let db = TestDB::with_files(ra_fixture);
 
     let krate = db.fetch_test_crate();
-    let def_map = db.crate_def_map(krate);
+    let def_map = crate_def_map(&db, krate);
     let mut defs = vec![];
     for (_, module) in def_map.modules() {
         for decl in module.scope.declarations() {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
index 9d62d9ce652..bb75621c7e0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
@@ -52,7 +52,7 @@ pub fn find_path(
             ignore_local_imports,
             is_std_item: item_module.krate().data(db).origin.is_lang(),
             from,
-            from_def_map: &from.def_map(db),
+            from_def_map: from.def_map(db),
             fuel: Cell::new(FIND_PATH_FUEL),
         },
         item,
@@ -691,7 +691,7 @@ mod tests {
         let (def_map, local_def_map) = module.local_def_map(&db);
         let resolved = def_map
             .resolve_path(
-                &local_def_map,
+                local_def_map,
                 &db,
                 module.local_id,
                 &mod_path,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs
index f27a4062a63..271484da7b9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs
@@ -297,7 +297,8 @@ pub(crate) fn parse(
                     unfinished_literal.clear();
                 }
 
-                let span = parser.arg_places.get(placeholder_index).and_then(|s| to_span(s.clone()));
+                let span =
+                    parser.arg_places.get(placeholder_index).and_then(|s| to_span(s.clone()));
                 placeholder_index += 1;
 
                 let position_span = to_span(position_span);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
index db571f045d7..a6138fb6821 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
@@ -16,7 +16,7 @@ use crate::{
     AssocItemId, AttrDefId, Complete, FxIndexMap, ModuleDefId, ModuleId, TraitId,
     db::DefDatabase,
     item_scope::{ImportOrExternCrate, ItemInNs},
-    nameres::DefMap,
+    nameres::{DefMap, crate_def_map},
     visibility::Visibility,
 };
 
@@ -129,7 +129,7 @@ impl ImportMap {
     fn collect_import_map(db: &dyn DefDatabase, krate: Crate) -> ImportMapIndex {
         let _p = tracing::info_span!("collect_import_map").entered();
 
-        let def_map = db.crate_def_map(krate);
+        let def_map = crate_def_map(db, krate);
         let mut map = FxIndexMap::default();
 
         // We look only into modules that are public(ly reexported), starting with the crate root.
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 51a833b5f15..59344641f47 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
@@ -10,6 +10,7 @@ use triomphe::Arc;
 use crate::{
     AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId,
     StaticId, StructId, TraitId, TypeAliasId, UnionId, db::DefDatabase, expr_store::path::Path,
+    nameres::crate_def_map,
 };
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -90,7 +91,7 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
 
     let mut lang_items = LangItems::default();
 
-    let crate_def_map = db.crate_def_map(krate);
+    let crate_def_map = crate_def_map(db, krate);
 
     for (_, module_data) in crate_def_map.modules() {
         for impl_def in module_data.scope.impls() {
@@ -209,7 +210,7 @@ pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option
 
     let mut traits = Vec::new();
 
-    let crate_def_map = db.crate_def_map(krate);
+    let crate_def_map = crate_def_map(db, krate);
 
     for (_, module_data) in crate_def_map.modules() {
         for def in module_data.scope.declarations() {
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 28011bda7c5..b41ff026bca 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -92,7 +92,7 @@ use crate::{
         Const, Enum, ExternCrate, Function, Impl, ItemTreeId, ItemTreeNode, Macro2, MacroRules,
         Static, Struct, Trait, TraitAlias, TypeAlias, Union, Use, Variant,
     },
-    nameres::LocalDefMap,
+    nameres::{LocalDefMap, block_def_map, crate_def_map, crate_local_def_map},
     signatures::VariantFields,
 };
 
@@ -324,12 +324,13 @@ pub struct CrateRootModuleId {
 }
 
 impl CrateRootModuleId {
-    pub fn def_map(&self, db: &dyn DefDatabase) -> Arc<DefMap> {
-        db.crate_def_map(self.krate)
+    pub fn def_map(self, db: &dyn DefDatabase) -> &DefMap {
+        crate_def_map(db, self.krate)
     }
 
-    pub(crate) fn local_def_map(&self, db: &dyn DefDatabase) -> (Arc<DefMap>, Arc<LocalDefMap>) {
-        db.crate_local_def_map(self.krate)
+    pub(crate) fn local_def_map(self, db: &dyn DefDatabase) -> (&DefMap, &LocalDefMap) {
+        let def_map = crate_local_def_map(db, self.krate);
+        (def_map.def_map(db), def_map.local(db))
     }
 
     pub fn krate(self) -> Crate {
@@ -390,26 +391,29 @@ pub struct ModuleId {
 }
 
 impl ModuleId {
-    pub fn def_map(self, db: &dyn DefDatabase) -> Arc<DefMap> {
+    pub fn def_map(self, db: &dyn DefDatabase) -> &DefMap {
         match self.block {
-            Some(block) => db.block_def_map(block),
-            None => db.crate_def_map(self.krate),
+            Some(block) => block_def_map(db, block),
+            None => crate_def_map(db, self.krate),
         }
     }
 
-    pub(crate) fn local_def_map(self, db: &dyn DefDatabase) -> (Arc<DefMap>, Arc<LocalDefMap>) {
+    pub(crate) fn local_def_map(self, db: &dyn DefDatabase) -> (&DefMap, &LocalDefMap) {
         match self.block {
-            Some(block) => (db.block_def_map(block), self.only_local_def_map(db)),
-            None => db.crate_local_def_map(self.krate),
+            Some(block) => (block_def_map(db, block), self.only_local_def_map(db)),
+            None => {
+                let def_map = crate_local_def_map(db, self.krate);
+                (def_map.def_map(db), def_map.local(db))
+            }
         }
     }
 
-    pub(crate) fn only_local_def_map(self, db: &dyn DefDatabase) -> Arc<LocalDefMap> {
-        db.crate_local_def_map(self.krate).1
+    pub(crate) fn only_local_def_map(self, db: &dyn DefDatabase) -> &LocalDefMap {
+        crate_local_def_map(db, self.krate).local(db)
     }
 
-    pub fn crate_def_map(self, db: &dyn DefDatabase) -> Arc<DefMap> {
-        db.crate_def_map(self.krate)
+    pub fn crate_def_map(self, db: &dyn DefDatabase) -> &DefMap {
+        crate_def_map(db, self.krate)
     }
 
     pub fn krate(self) -> Crate {
@@ -701,6 +705,16 @@ pub enum AssocItemId {
 // casting them, and somehow making the constructors private, which would be annoying.
 impl_from!(FunctionId, ConstId, TypeAliasId for AssocItemId);
 
+impl From<AssocItemId> for ModuleDefId {
+    fn from(item: AssocItemId) -> Self {
+        match item {
+            AssocItemId::FunctionId(f) => f.into(),
+            AssocItemId::ConstId(c) => c.into(),
+            AssocItemId::TypeAliasId(t) => t.into(),
+        }
+    }
+}
+
 #[derive(Debug, PartialOrd, Ord, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
 pub enum GenericDefId {
     AdtId(AdtId),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index e21d1415aa2..3027aff3163 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -454,13 +454,13 @@ fn test_concat_expand() {
 #[rustc_builtin_macro]
 macro_rules! concat {}
 
-fn main() { concat!("fo", "o", 0, r#""bar""#, "\n", false, '"', '\0'); }
+fn main() { concat!("fo", "o", 0, r#""bar""#, "\n", false, '"', -4, - 4, '\0'); }
 "##,
         expect![[r##"
 #[rustc_builtin_macro]
 macro_rules! concat {}
 
-fn main() { "foo0\"bar\"\nfalse\"\u{0}"; }
+fn main() { "foo0\"bar\"\nfalse\"-4-4\u{0}"; }
 "##]],
     );
 }
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 800c96ebdae..dc4334ee081 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
@@ -39,7 +39,7 @@ use test_fixture::WithFixture;
 use crate::{
     AdtId, Lookup, ModuleDefId,
     db::DefDatabase,
-    nameres::{DefMap, ModuleSource},
+    nameres::{DefMap, ModuleSource, crate_def_map},
     src::HasSource,
     test_db::TestDB,
     tt::TopSubtree,
@@ -49,7 +49,7 @@ use crate::{
 fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
     let db = TestDB::with_files(ra_fixture);
     let krate = db.fetch_test_crate();
-    let def_map = db.crate_def_map(krate);
+    let def_map = crate_def_map(&db, krate);
     let errors = def_map
         .modules()
         .flat_map(|module| module.1.scope.all_macro_calls())
@@ -113,7 +113,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
 
                 let (body, sm) = db.body_with_source_map(body);
                 if let Some(it) =
-                    body.blocks(db).find_map(|block| resolve(db, &block.1, ast_id, ast_ptr))
+                    body.blocks(db).find_map(|block| resolve(db, block.1, ast_id, ast_ptr))
                 {
                     return Some(it);
                 }
@@ -127,7 +127,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.fetch_test_crate();
-    let def_map = db.crate_def_map(krate);
+    let def_map = crate_def_map(&db, krate);
     let local_id = DefMap::ROOT;
     let source = def_map[local_id].definition_source(&db);
     let source_file = match source.value {
@@ -142,7 +142,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
         let ast_id = db.ast_id_map(source.file_id).ast_id(&macro_call_node);
         let ast_id = InFile::new(source.file_id, ast_id);
         let ptr = InFile::new(source.file_id, AstPtr::new(&macro_call_node));
-        let macro_call_id = resolve(&db, &def_map, ast_id, ptr)
+        let macro_call_id = resolve(&db, def_map, ast_id, ptr)
             .unwrap_or_else(|| panic!("unable to find semantic macro call {macro_call_node}"));
         let expansion_result = db.parse_macro_expansion(macro_call_id);
         expansions.push((macro_call_node.clone(), expansion_result));
@@ -380,8 +380,4 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander {
             panic!("got invalid macro input: {:?}", parse.errors());
         }
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index fc66d8e28d8..d4b30a1d3e6 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -112,6 +112,18 @@ pub struct LocalDefMap {
     extern_prelude: FxIndexMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,
 }
 
+impl std::hash::Hash for LocalDefMap {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        let LocalDefMap { extern_prelude } = self;
+        extern_prelude.len().hash(state);
+        for (name, (crate_root, extern_crate)) in extern_prelude {
+            name.hash(state);
+            crate_root.hash(state);
+            extern_crate.hash(state);
+        }
+    }
+}
+
 impl LocalDefMap {
     pub(crate) const EMPTY: &Self =
         &Self { extern_prelude: FxIndexMap::with_hasher(rustc_hash::FxBuildHasher) };
@@ -250,7 +262,7 @@ struct BlockRelativeModuleId {
 }
 
 impl BlockRelativeModuleId {
-    fn def_map(self, db: &dyn DefDatabase, krate: Crate) -> Arc<DefMap> {
+    fn def_map(self, db: &dyn DefDatabase, krate: Crate) -> &DefMap {
         self.into_module(krate).def_map(db)
     }
 
@@ -358,6 +370,87 @@ pub struct ModuleData {
     pub scope: ItemScope,
 }
 
+#[inline]
+pub fn crate_def_map(db: &dyn DefDatabase, crate_id: Crate) -> &DefMap {
+    crate_local_def_map(db, crate_id).def_map(db)
+}
+
+#[allow(unused_lifetimes)]
+mod __ {
+    use super::*;
+    #[salsa_macros::tracked]
+    pub(crate) struct DefMapPair<'db> {
+        #[tracked]
+        #[return_ref]
+        pub(crate) def_map: DefMap,
+        #[return_ref]
+        pub(crate) local: LocalDefMap,
+    }
+}
+pub(crate) use __::DefMapPair;
+
+#[salsa_macros::tracked(return_ref)]
+pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefMapPair<'_> {
+    let krate = crate_id.data(db);
+    let _p = tracing::info_span!(
+        "crate_def_map_query",
+        name=?crate_id
+            .extra_data(db)
+            .display_name
+            .as_ref()
+            .map(|it| it.crate_name().to_smolstr())
+            .unwrap_or_default()
+    )
+    .entered();
+
+    let module_data = ModuleData::new(
+        ModuleOrigin::CrateRoot { definition: krate.root_file_id(db) },
+        Visibility::Public,
+    );
+
+    let def_map =
+        DefMap::empty(crate_id, Arc::new(DefMapCrateData::new(krate.edition)), module_data, None);
+    let (def_map, local_def_map) = collector::collect_defs(
+        db,
+        def_map,
+        TreeId::new(krate.root_file_id(db).into(), None),
+        None,
+    );
+
+    DefMapPair::new(db, def_map, local_def_map)
+}
+
+#[salsa_macros::tracked(return_ref)]
+pub fn block_def_map(db: &dyn DefDatabase, block_id: BlockId) -> DefMap {
+    let BlockLoc { ast_id, module } = block_id.lookup(db);
+
+    let visibility = Visibility::Module(
+        ModuleId { krate: module.krate, local_id: DefMap::ROOT, block: module.block },
+        VisibilityExplicitness::Implicit,
+    );
+    let module_data =
+        ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
+
+    let local_def_map = crate_local_def_map(db, module.krate);
+    let def_map = DefMap::empty(
+        module.krate,
+        local_def_map.def_map(db).data.clone(),
+        module_data,
+        Some(BlockInfo {
+            block: block_id,
+            parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id },
+        }),
+    );
+
+    let (def_map, _) = collector::collect_defs(
+        db,
+        def_map,
+        TreeId::new(ast_id.file_id, Some(block_id)),
+        Some(local_def_map.local(db)),
+    );
+    def_map
+}
+
 impl DefMap {
     /// The module id of a crate or block root.
     pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0));
@@ -366,77 +459,6 @@ impl DefMap {
         self.data.edition
     }
 
-    pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: Crate) -> Arc<DefMap> {
-        db.crate_local_def_map(crate_id).0
-    }
-
-    pub(crate) fn crate_local_def_map_query(
-        db: &dyn DefDatabase,
-        crate_id: Crate,
-    ) -> (Arc<DefMap>, Arc<LocalDefMap>) {
-        let krate = crate_id.data(db);
-        let _p = tracing::info_span!(
-            "crate_def_map_query",
-            name=?crate_id
-                .extra_data(db)
-                .display_name
-                .as_ref()
-                .map(|it| it.crate_name().to_smolstr())
-                .unwrap_or_default()
-        )
-        .entered();
-
-        let module_data = ModuleData::new(
-            ModuleOrigin::CrateRoot { definition: krate.root_file_id(db) },
-            Visibility::Public,
-        );
-
-        let def_map = DefMap::empty(
-            crate_id,
-            Arc::new(DefMapCrateData::new(krate.edition)),
-            module_data,
-            None,
-        );
-        let (def_map, local_def_map) = collector::collect_defs(
-            db,
-            def_map,
-            TreeId::new(krate.root_file_id(db).into(), None),
-            None,
-        );
-
-        (Arc::new(def_map), Arc::new(local_def_map))
-    }
-
-    pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
-        let BlockLoc { ast_id, module } = block_id.lookup(db);
-
-        let visibility = Visibility::Module(
-            ModuleId { krate: module.krate, local_id: Self::ROOT, block: module.block },
-            VisibilityExplicitness::Implicit,
-        );
-        let module_data =
-            ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
-
-        let (crate_map, crate_local_map) = db.crate_local_def_map(module.krate);
-        let def_map = DefMap::empty(
-            module.krate,
-            crate_map.data.clone(),
-            module_data,
-            Some(BlockInfo {
-                block: block_id,
-                parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id },
-            }),
-        );
-
-        let (def_map, _) = collector::collect_defs(
-            db,
-            def_map,
-            TreeId::new(ast_id.file_id, Some(block_id)),
-            Some(crate_local_map),
-        );
-        Arc::new(def_map)
-    }
-
     fn empty(
         krate: Crate,
         crate_data: Arc<DefMapCrateData>,
@@ -595,7 +617,7 @@ impl DefMap {
             go(&mut buf, db, current_map, "block scope", Self::ROOT);
             buf.push('\n');
             arc = block.parent.def_map(db, self.krate);
-            current_map = &arc;
+            current_map = arc;
         }
         go(&mut buf, db, current_map, "crate", Self::ROOT);
         return buf;
@@ -628,7 +650,7 @@ impl DefMap {
         while let Some(block) = current_map.block {
             format_to!(buf, "{:?} in {:?}\n", block.block, block.parent);
             arc = block.parent.def_map(db, self.krate);
-            current_map = &arc;
+            current_map = arc;
         }
 
         format_to!(buf, "crate scope\n");
@@ -708,7 +730,7 @@ impl DefMap {
         let mut block = self.block;
         while let Some(block_info) = block {
             let parent = block_info.parent.def_map(db, self.krate);
-            if let Some(it) = f(&parent, block_info.parent.local_id) {
+            if let Some(it) = f(parent, block_info.parent.local_id) {
                 return Some(it);
             }
             block = parent.block;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
index 448b908936a..d45709b8b90 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/assoc.rs
@@ -66,6 +66,15 @@ impl TraitItems {
         })
     }
 
+    pub fn assoc_item_by_name(&self, name: &Name) -> Option<AssocItemId> {
+        self.items.iter().find_map(|&(ref item_name, item)| match item {
+            AssocItemId::FunctionId(_) if item_name == name => Some(item),
+            AssocItemId::TypeAliasId(_) if item_name == name => Some(item),
+            AssocItemId::ConstId(_) if item_name == name => Some(item),
+            _ => None,
+        })
+    }
+
     pub fn attribute_calls(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
         self.macro_calls.iter().flat_map(|it| it.iter()).copied()
     }
@@ -108,8 +117,8 @@ impl ImplItems {
 struct AssocItemCollector<'a> {
     db: &'a dyn DefDatabase,
     module_id: ModuleId,
-    def_map: Arc<DefMap>,
-    local_def_map: Arc<LocalDefMap>,
+    def_map: &'a DefMap,
+    local_def_map: &'a LocalDefMap,
     diagnostics: Vec<DefDiagnostic>,
     container: ItemContainerId,
 
@@ -174,7 +183,7 @@ impl<'a> AssocItemCollector<'a> {
             let ast_id_with_path = AstIdWithPath { path: attr.path.clone(), ast_id };
 
             match self.def_map.resolve_attr_macro(
-                &self.local_def_map,
+                self.local_def_map,
                 self.db,
                 self.module_id.local_id,
                 ast_id_with_path,
@@ -246,7 +255,7 @@ impl<'a> AssocItemCollector<'a> {
                 let resolver = |path: &_| {
                     self.def_map
                         .resolve_path(
-                            &self.local_def_map,
+                            self.local_def_map,
                             self.db,
                             self.module_id.local_id,
                             path,
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 8df0f092cd0..350c97c3982 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
@@ -26,7 +26,7 @@ use syntax::ast;
 use triomphe::Arc;
 
 use crate::{
-    AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, ExternBlockLoc,
+    AdtId, AssocItemId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, ExternBlockLoc,
     ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId,
     LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId,
     MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc,
@@ -43,9 +43,10 @@ use crate::{
     nameres::{
         BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, ModuleOrigin, ResolveMode,
         attr_resolution::{attr_macro_as_call_id, derive_macro_as_call_id},
+        crate_def_map,
         diagnostics::DefDiagnostic,
         mod_resolution::ModDir,
-        path_resolution::ReachedFixedPoint,
+        path_resolution::{ReachedFixedPoint, ResolvePathResult},
         proc_macro::{ProcMacroDef, ProcMacroKind, parse_macro_name_and_helper_attrs},
         sub_namespace_match,
     },
@@ -61,7 +62,7 @@ pub(super) fn collect_defs(
     db: &dyn DefDatabase,
     def_map: DefMap,
     tree_id: TreeId,
-    crate_local_def_map: Option<Arc<LocalDefMap>>,
+    crate_local_def_map: Option<&LocalDefMap>,
 ) -> (DefMap, LocalDefMap) {
     let krate = &def_map.krate.data(db);
     let cfg_options = def_map.krate.cfg_options(db);
@@ -216,7 +217,7 @@ struct DefCollector<'a> {
     def_map: DefMap,
     local_def_map: LocalDefMap,
     /// Set only in case of blocks.
-    crate_local_def_map: Option<Arc<LocalDefMap>>,
+    crate_local_def_map: Option<&'a LocalDefMap>,
     // The dependencies of the current crate, including optional deps like `test`.
     deps: FxHashMap<Name, BuiltDependency>,
     glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>,
@@ -533,7 +534,7 @@ impl DefCollector<'_> {
         );
 
         let (per_ns, _) = self.def_map.resolve_path(
-            self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
+            self.crate_local_def_map.unwrap_or(&self.local_def_map),
             self.db,
             DefMap::ROOT,
             &path,
@@ -556,7 +557,7 @@ impl DefCollector<'_> {
     }
 
     fn local_def_map(&mut self) -> &LocalDefMap {
-        self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map)
+        self.crate_local_def_map.unwrap_or(&self.local_def_map)
     }
 
     /// Adds a definition of procedural macro `name` to the root module.
@@ -688,7 +689,7 @@ impl DefCollector<'_> {
         let vis = self
             .def_map
             .resolve_visibility(
-                self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
+                self.crate_local_def_map.unwrap_or(&self.local_def_map),
                 self.db,
                 module_id,
                 vis,
@@ -731,7 +732,7 @@ impl DefCollector<'_> {
         names: Option<Vec<Name>>,
         extern_crate: Option<ExternCrateId>,
     ) {
-        let def_map = self.db.crate_def_map(krate);
+        let def_map = crate_def_map(self.db, krate);
         // `#[macro_use]` brings macros into macro_use prelude. Yes, even non-`macro_rules!`
         // macros.
         let root_scope = &def_map[DefMap::ROOT].scope;
@@ -811,32 +812,35 @@ impl DefCollector<'_> {
         let _p = tracing::info_span!("resolve_import", import_path = %import.path.display(self.db, Edition::LATEST))
             .entered();
         tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
-        let res = self.def_map.resolve_path_fp_with_macro(
-            self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
-            self.db,
-            ResolveMode::Import,
-            module_id,
-            &import.path,
-            BuiltinShadowMode::Module,
-            None, // An import may resolve to any kind of macro.
-        );
+        let ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, prefix_info } =
+            self.def_map.resolve_path_fp_with_macro(
+                self.crate_local_def_map.unwrap_or(&self.local_def_map),
+                self.db,
+                ResolveMode::Import,
+                module_id,
+                &import.path,
+                BuiltinShadowMode::Module,
+                None, // An import may resolve to any kind of macro.
+            );
 
-        let def = res.resolved_def;
-        if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
+        if reached_fixedpoint == ReachedFixedPoint::No
+            || resolved_def.is_none()
+            || segment_index.is_some()
+        {
             return PartialResolvedImport::Unresolved;
         }
 
-        if res.prefix_info.differing_crate {
+        if prefix_info.differing_crate {
             return PartialResolvedImport::Resolved(
-                def.filter_visibility(|v| matches!(v, Visibility::Public)),
+                resolved_def.filter_visibility(|v| matches!(v, Visibility::Public)),
             );
         }
 
         // Check whether all namespaces are resolved.
-        if def.is_full() {
-            PartialResolvedImport::Resolved(def)
+        if resolved_def.is_full() {
+            PartialResolvedImport::Resolved(resolved_def)
         } else {
-            PartialResolvedImport::Indeterminate(def)
+            PartialResolvedImport::Indeterminate(resolved_def)
         }
     }
 
@@ -849,7 +853,7 @@ impl DefCollector<'_> {
         let vis = self
             .def_map
             .resolve_visibility(
-                self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
+                self.crate_local_def_map.unwrap_or(&self.local_def_map),
                 self.db,
                 module_id,
                 &directive.import.visibility,
@@ -986,6 +990,43 @@ impl DefCollector<'_> {
                             Some(ImportOrExternCrate::Glob(glob)),
                         );
                     }
+                    Some(ModuleDefId::TraitId(it)) => {
+                        // FIXME: Implement this correctly
+                        // We can't actually call `trait_items`, the reason being that if macro calls
+                        // occur, they will call back into the def map which we might be computing right
+                        // now resulting in a cycle.
+                        // To properly implement this, trait item collection needs to be done in def map
+                        // collection...
+                        let resolutions = if true {
+                            vec![]
+                        } else {
+                            self.db
+                                .trait_items(it)
+                                .items
+                                .iter()
+                                .map(|&(ref name, variant)| {
+                                    let res = match variant {
+                                        AssocItemId::FunctionId(it) => {
+                                            PerNs::values(it.into(), vis, None)
+                                        }
+                                        AssocItemId::ConstId(it) => {
+                                            PerNs::values(it.into(), vis, None)
+                                        }
+                                        AssocItemId::TypeAliasId(it) => {
+                                            PerNs::types(it.into(), vis, None)
+                                        }
+                                    };
+                                    (Some(name.clone()), res)
+                                })
+                                .collect::<Vec<_>>()
+                        };
+                        self.update(
+                            module_id,
+                            &resolutions,
+                            vis,
+                            Some(ImportOrExternCrate::Glob(glob)),
+                        );
+                    }
                     Some(d) => {
                         tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
                     }
@@ -1240,7 +1281,7 @@ impl DefCollector<'_> {
             };
             let resolver = |path: &_| {
                 let resolved_res = self.def_map.resolve_path_fp_with_macro(
-                    self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
+                    self.crate_local_def_map.unwrap_or(&self.local_def_map),
                     self.db,
                     ResolveMode::Other,
                     directive.module_id,
@@ -1307,7 +1348,7 @@ impl DefCollector<'_> {
                         );
                         // Record its helper attributes.
                         if def_id.krate != self.def_map.krate {
-                            let def_map = self.db.crate_def_map(def_id.krate);
+                            let def_map = crate_def_map(self.db, def_id.krate);
                             if let Some(helpers) = def_map.data.exported_derives.get(&def_id) {
                                 self.def_map
                                     .derive_helpers_in_scope
@@ -1553,7 +1594,7 @@ impl DefCollector<'_> {
                         self.def_map.krate,
                         |path| {
                             let resolved_res = self.def_map.resolve_path_fp_with_macro(
-                                self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map),
+                                self.crate_local_def_map.unwrap_or(&self.local_def_map),
                                 self.db,
                                 ResolveMode::Other,
                                 directive.module_id,
@@ -1702,11 +1743,8 @@ impl ModCollector<'_, '_> {
 
             let module = self.def_collector.def_map.module_id(module_id);
             let def_map = &mut self.def_collector.def_map;
-            let local_def_map = self
-                .def_collector
-                .crate_local_def_map
-                .as_deref()
-                .unwrap_or(&self.def_collector.local_def_map);
+            let local_def_map =
+                self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map);
 
             match item {
                 ModItem::Mod(m) => self.collect_module(m, &attrs),
@@ -2133,10 +2171,7 @@ impl ModCollector<'_, '_> {
         let def_map = &mut self.def_collector.def_map;
         let vis = def_map
             .resolve_visibility(
-                self.def_collector
-                    .crate_local_def_map
-                    .as_deref()
-                    .unwrap_or(&self.def_collector.local_def_map),
+                self.def_collector.crate_local_def_map.unwrap_or(&self.def_collector.local_def_map),
                 self.def_collector.db,
                 self.module_id,
                 visibility,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
index a49155d878c..74ce33a6419 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
@@ -17,14 +17,17 @@ use hir_expand::{
     name::Name,
 };
 use span::Edition;
-use triomphe::Arc;
+use stdx::TupleExt;
 
 use crate::{
     AdtId, LocalModuleId, ModuleDefId,
     db::DefDatabase,
     item_scope::{BUILTIN_SCOPE, ImportOrExternCrate},
     item_tree::FieldsShape,
-    nameres::{BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, sub_namespace_match},
+    nameres::{
+        BlockInfo, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, crate_def_map,
+        sub_namespace_match,
+    },
     per_ns::PerNs,
     visibility::{RawVisibility, Visibility},
 };
@@ -44,6 +47,7 @@ pub(super) enum ReachedFixedPoint {
 #[derive(Debug, Clone)]
 pub(super) struct ResolvePathResult {
     pub(super) resolved_def: PerNs,
+    /// The index of the last resolved segment, or `None` if the full path has been resolved.
     pub(super) segment_index: Option<usize>,
     pub(super) reached_fixedpoint: ReachedFixedPoint,
     pub(super) prefix_info: ResolvePathResultPrefixInfo,
@@ -173,7 +177,6 @@ impl DefMap {
             return result;
         }
 
-        let mut arc;
         let mut current_map = self;
 
         let mut merge = |new: ResolvePathResult| {
@@ -195,8 +198,7 @@ impl DefMap {
                 Some(block) if original_module == Self::ROOT => {
                     // Block modules "inherit" names from its parent module.
                     original_module = block.parent.local_id;
-                    arc = block.parent.def_map(db, current_map.krate);
-                    current_map = &arc;
+                    current_map = block.parent.def_map(db, current_map.krate);
                 }
                 // Proper (non-block) modules, including those in block `DefMap`s, don't.
                 _ => {
@@ -204,8 +206,7 @@ impl DefMap {
                         // A module inside a block. Do not resolve items declared in upper blocks, but we do need to get
                         // the prelude items (which are not inserted into blocks because they can be overridden there).
                         original_module = Self::ROOT;
-                        arc = db.crate_def_map(self.krate);
-                        current_map = &arc;
+                        current_map = crate_def_map(db, self.krate);
 
                         let new = current_map.resolve_path_fp_in_all_preludes(
                             local_def_map,
@@ -253,7 +254,7 @@ impl DefMap {
                     cov_mark::hit!(macro_dollar_crate_self);
                     PerNs::types(self.crate_root().into(), Visibility::Public, None)
                 } else {
-                    let def_map = db.crate_def_map(krate);
+                    let def_map = crate_def_map(db, krate);
                     let module = def_map.module_id(Self::ROOT);
                     cov_mark::hit!(macro_dollar_crate_other);
                     PerNs::types(module.into(), Visibility::Public, None)
@@ -312,7 +313,7 @@ impl DefMap {
                 // Adjust `local_id` to `self`, i.e. the nearest non-block module.
                 if def_map.module_id(local_id).is_block_module() {
                     (ext, local_id) = adjust_to_nearest_non_block_module(db, def_map, local_id);
-                    def_map = &ext;
+                    def_map = ext;
                 }
 
                 // Go up the module tree but skip block modules as `super` always refers to the
@@ -325,7 +326,7 @@ impl DefMap {
                         if def_map.module_id(local_id).is_block_module() {
                             (ext, local_id) =
                                 adjust_to_nearest_non_block_module(db, def_map, local_id);
-                            def_map = &ext;
+                            def_map = ext;
                         }
                     } else {
                         stdx::always!(def_map.block.is_none());
@@ -364,7 +365,15 @@ impl DefMap {
             },
         };
 
-        self.resolve_remaining_segments(segments, curr_per_ns, path, db, shadow, original_module)
+        self.resolve_remaining_segments(
+            db,
+            mode,
+            segments,
+            curr_per_ns,
+            path,
+            shadow,
+            original_module,
+        )
     }
 
     /// Resolves a path only in the preludes, without accounting for item scopes.
@@ -413,7 +422,15 @@ impl DefMap {
             }
         };
 
-        self.resolve_remaining_segments(segments, curr_per_ns, path, db, shadow, original_module)
+        self.resolve_remaining_segments(
+            db,
+            mode,
+            segments,
+            curr_per_ns,
+            path,
+            shadow,
+            original_module,
+        )
     }
 
     /// 2018-style absolute path -- only extern prelude
@@ -441,10 +458,11 @@ impl DefMap {
 
     fn resolve_remaining_segments<'a>(
         &self,
+        db: &dyn DefDatabase,
+        mode: ResolveMode,
         mut segments: impl Iterator<Item = (usize, &'a Name)>,
         mut curr_per_ns: PerNs,
         path: &ModPath,
-        db: &dyn DefDatabase,
         shadow: BuiltinShadowMode,
         original_module: LocalModuleId,
     ) -> ResolvePathResult {
@@ -465,6 +483,7 @@ impl DefMap {
             curr_per_ns = match curr.def {
                 ModuleDefId::ModuleId(module) => {
                     if module.krate != self.krate {
+                        // FIXME: Inefficient
                         let path = ModPath::from_segments(
                             PathKind::SELF,
                             path.segments()[i..].iter().cloned(),
@@ -478,7 +497,7 @@ impl DefMap {
                         let resolution = defp_map.resolve_path_fp_with_macro(
                             LocalDefMap::EMPTY,
                             db,
-                            ResolveMode::Other,
+                            mode,
                             module.local_id,
                             &path,
                             shadow,
@@ -553,6 +572,44 @@ impl DefMap {
                         ),
                     };
                 }
+                def @ ModuleDefId::TraitId(t) if mode == ResolveMode::Import => {
+                    // FIXME: Implement this correctly
+                    // We can't actually call `trait_items`, the reason being that if macro calls
+                    // occur, they will call back into the def map which we might be computing right
+                    // now resulting in a cycle.
+                    // To properly implement this, trait item collection needs to be done in def map
+                    // collection...
+                    let item =
+                        if true { None } else { db.trait_items(t).assoc_item_by_name(segment) };
+                    return match item {
+                        Some(item) => ResolvePathResult::new(
+                            match item {
+                                crate::AssocItemId::FunctionId(function_id) => PerNs::values(
+                                    function_id.into(),
+                                    curr.vis,
+                                    curr.import.and_then(|it| it.import_or_glob()),
+                                ),
+                                crate::AssocItemId::ConstId(const_id) => PerNs::values(
+                                    const_id.into(),
+                                    curr.vis,
+                                    curr.import.and_then(|it| it.import_or_glob()),
+                                ),
+                                crate::AssocItemId::TypeAliasId(type_alias_id) => {
+                                    PerNs::types(type_alias_id.into(), curr.vis, curr.import)
+                                }
+                            },
+                            ReachedFixedPoint::Yes,
+                            segments.next().map(TupleExt::head),
+                            ResolvePathResultPrefixInfo::default(),
+                        ),
+                        None => ResolvePathResult::new(
+                            PerNs::types(def, curr.vis, curr.import),
+                            ReachedFixedPoint::Yes,
+                            Some(i),
+                            ResolvePathResultPrefixInfo::default(),
+                        ),
+                    };
+                }
                 s => {
                     // could be an inherent method call in UFCS form
                     // (`Struct::method`), or some other kind of associated item
@@ -715,7 +772,7 @@ impl DefMap {
             } else {
                 // Extend lifetime
                 keep = prelude.def_map(db);
-                &keep
+                keep
             };
             def_map[prelude.local_id].scope.get(name)
         } else {
@@ -725,25 +782,23 @@ impl DefMap {
 }
 
 /// Given a block module, returns its nearest non-block module and the `DefMap` it belongs to.
-fn adjust_to_nearest_non_block_module(
-    db: &dyn DefDatabase,
-    def_map: &DefMap,
+fn adjust_to_nearest_non_block_module<'db>(
+    db: &'db dyn DefDatabase,
+    def_map: &'db DefMap,
     mut local_id: LocalModuleId,
-) -> (Arc<DefMap>, LocalModuleId) {
+) -> (&'db DefMap, LocalModuleId) {
     // INVARIANT: `local_id` in `def_map` must be a block module.
     stdx::always!(def_map.module_id(local_id).is_block_module());
 
-    let mut ext;
     // This needs to be a local variable due to our mighty lifetime.
     let mut def_map = def_map;
     loop {
         let BlockInfo { parent, .. } = def_map.block.expect("block module without parent module");
 
-        ext = parent.def_map(db, def_map.krate);
-        def_map = &ext;
+        def_map = parent.def_map(db, def_map.krate);
         local_id = parent.local_id;
         if !parent.is_block_module() {
-            return (ext, local_id);
+            return (def_map, local_id);
         }
     }
 }
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 3fd095a9a98..4a7974c4fa1 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
@@ -7,20 +7,25 @@ mod primitives;
 use base_db::RootQueryDb;
 use expect_test::{Expect, expect};
 use test_fixture::WithFixture;
-use triomphe::Arc;
 
-use crate::{db::DefDatabase, nameres::DefMap, test_db::TestDB};
+use crate::{
+    nameres::{DefMap, crate_def_map},
+    test_db::TestDB,
+};
 
-fn compute_crate_def_map(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> Arc<DefMap> {
+fn compute_crate_def_map(
+    #[rust_analyzer::rust_fixture] ra_fixture: &str,
+    cb: impl FnOnce(&DefMap),
+) {
     let db = TestDB::with_files(ra_fixture);
     let krate = db.fetch_test_crate();
-    db.crate_def_map(krate)
+    cb(crate_def_map(&db, krate));
 }
 
 fn render_crate_def_map(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String {
     let db = TestDB::with_files(ra_fixture);
     let krate = db.fetch_test_crate();
-    db.crate_def_map(krate).dump(&db)
+    crate_def_map(&db, krate).dump(&db)
 }
 
 fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
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 179a9c8fec2..948e8bed66d 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
@@ -7,24 +7,37 @@ use span::Edition;
 use test_fixture::WithFixture;
 use triomphe::Arc;
 
-use crate::{AdtId, ModuleDefId, db::DefDatabase, nameres::tests::TestDB};
+use crate::{
+    AdtId, ModuleDefId,
+    db::DefDatabase,
+    nameres::{crate_def_map, tests::TestDB},
+};
 
-fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: &str) {
+fn check_def_map_is_not_recomputed(
+    #[rust_analyzer::rust_fixture] ra_fixture_initial: &str,
+    #[rust_analyzer::rust_fixture] ra_fixture_change: &str,
+) {
     let (mut db, pos) = TestDB::with_position(ra_fixture_initial);
     let krate = db.fetch_test_crate();
     {
         let events = db.log_executed(|| {
-            db.crate_def_map(krate);
+            crate_def_map(&db, krate);
         });
-        assert!(format!("{events:?}").contains("crate_def_map"), "{events:#?}")
+        assert!(
+            format!("{events:?}").contains("crate_local_def_map"),
+            "no crate def map computed:\n{events:#?}",
+        )
     }
     db.set_file_text(pos.file_id.file_id(&db), ra_fixture_change);
 
     {
         let events = db.log_executed(|| {
-            db.crate_def_map(krate);
+            crate_def_map(&db, krate);
         });
-        assert!(!format!("{events:?}").contains("crate_def_map"), "{events:#?}")
+        assert!(
+            !format!("{events:?}").contains("crate_local_def_map"),
+            "crate def map invalidated:\n{events:#?}",
+        )
     }
 }
 
@@ -44,7 +57,7 @@ pub const BAZ: u32 = 0;
     );
 
     for &krate in db.all_crates().iter() {
-        db.crate_def_map(krate);
+        crate_def_map(&db, krate);
     }
 
     let all_crates_before = db.all_crates();
@@ -94,11 +107,11 @@ pub const BAZ: u32 = 0;
 
     let events = db.log_executed(|| {
         for &krate in db.all_crates().iter() {
-            db.crate_def_map(krate);
+            crate_def_map(&db, krate);
         }
     });
     let invalidated_def_maps =
-        events.iter().filter(|event| event.contains("crate_def_map")).count();
+        events.iter().filter(|event| event.contains("crate_local_def_map")).count();
     assert_eq!(invalidated_def_maps, 1, "{events:#?}")
 }
 
@@ -330,7 +343,7 @@ m!(Z);
     let krate = db.test_crate();
     {
         let events = db.log_executed(|| {
-            let crate_def_map = db.crate_def_map(krate);
+            let crate_def_map = crate_def_map(&db, krate);
             let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
             assert_eq!(module_data.scope.resolutions().count(), 4);
         });
@@ -352,7 +365,7 @@ m!(Z);
 
     {
         let events = db.log_executed(|| {
-            let crate_def_map = db.crate_def_map(krate);
+            let crate_def_map = crate_def_map(&db, krate);
             let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
             assert_eq!(module_data.scope.resolutions().count(), 4);
         });
@@ -403,7 +416,7 @@ pub type Ty = ();
 
     {
         let events = db.log_executed(|| {
-            let crate_def_map = db.crate_def_map(krate);
+            let crate_def_map = crate_def_map(&db, krate);
             let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
             assert_eq!(module_data.scope.resolutions().count(), 8);
             assert_eq!(module_data.scope.impls().count(), 1);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
index 5f8a01523d8..3cba88ec2f1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
@@ -736,7 +736,7 @@ pub struct bar;
 
 #[test]
 fn macro_dollar_crate_is_correct_in_derive_meta() {
-    let map = compute_crate_def_map(
+    compute_crate_def_map(
         r#"
 //- minicore: derive, clone
 //- /main.rs crate:main deps:lib
@@ -753,13 +753,13 @@ macro_rules! foo {
 
 pub use core::clone::Clone;
 "#,
+        |map| assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1),
     );
-    assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1);
 }
 
 #[test]
 fn expand_derive() {
-    let map = compute_crate_def_map(
+    compute_crate_def_map(
         r#"
 //- /main.rs crate:main deps:core
 use core::Copy;
@@ -775,8 +775,8 @@ pub macro Copy {}
 #[rustc_builtin_macro]
 pub macro Clone {}
 "#,
+        |map| assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 2),
     );
-    assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 2);
 }
 
 #[test]
@@ -803,7 +803,7 @@ pub trait Clone {}
 fn builtin_derive_with_unresolved_attributes_fall_back() {
     // Tests that we still resolve derives after ignoring an unresolved attribute.
     cov_mark::check!(unresolved_attribute_fallback);
-    let map = compute_crate_def_map(
+    compute_crate_def_map(
         r#"
 //- /main.rs crate:main deps:core
 use core::{Clone, derive};
@@ -818,8 +818,8 @@ pub macro derive($item:item) {}
 #[rustc_builtin_macro]
 pub macro Clone {}
 "#,
+        |map| assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1),
     );
-    assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1);
 }
 
 #[test]
@@ -1096,7 +1096,7 @@ pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
 "#,
     );
     let krate = *db.all_crates().last().expect("no crate graph present");
-    let def_map = db.crate_def_map(krate);
+    let def_map = crate_def_map(&db, krate);
 
     assert_eq!(def_map.data.exported_derives.len(), 1);
     match def_map.data.exported_derives.values().next() {
@@ -1446,7 +1446,7 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
     "#,
     );
     let krate = *db.all_crates().last().expect("no crate graph present");
-    let def_map = db.crate_def_map(krate);
+    let def_map = crate_def_map(&db, krate);
 
     let root_module = &def_map[DefMap::ROOT].scope;
     assert!(
@@ -1544,7 +1544,7 @@ macro_rules! mk_foo {
 
 #[test]
 fn macro_sub_namespace() {
-    let map = compute_crate_def_map(
+    compute_crate_def_map(
         r#"
 //- minicore: derive, clone
 macro_rules! Clone { () => {} }
@@ -1553,8 +1553,8 @@ macro_rules! derive { () => {} }
 #[derive(Clone)]
 struct S;
     "#,
+        |map| assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1),
     );
-    assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1);
 }
 
 #[test]
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs
index 071b55c83d8..9c97e42f4fd 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs
@@ -839,6 +839,7 @@ mod foo;
 #[path = "./foo.rs"]
 mod foo;
 "#,
+        |_| (),
     );
 
     compute_crate_def_map(
@@ -852,6 +853,7 @@ mod bar;
 #[path = "./foo.rs"]
 mod foo;
 "#,
+        |_| (),
     );
 }
 
@@ -894,3 +896,149 @@ struct AlsoShouldNotAppear;
         "#]],
     )
 }
+
+#[test]
+fn invalid_imports() {
+    check(
+        r#"
+//- /main.rs
+mod module;
+
+use self::module::S::new;
+use self::module::unresolved;
+use self::module::C::const_based;
+use self::module::Enum::Variant::NoAssoc;
+
+//- /module.rs
+pub struct S;
+impl S {
+    pub fn new() {}
+}
+pub const C: () = ();
+pub enum Enum {
+    Variant,
+}
+        "#,
+        expect![[r#"
+            crate
+            NoAssoc: _
+            const_based: _
+            module: t
+            new: _
+            unresolved: _
+
+            crate::module
+            C: v
+            Enum: t
+            S: t v
+        "#]],
+    );
+}
+
+#[test]
+fn trait_item_imports_same_crate() {
+    check(
+        r#"
+//- /main.rs
+mod module;
+
+use self::module::Trait::{AssocType, ASSOC_CONST, MACRO_CONST, method};
+
+//- /module.rs
+macro_rules! m {
+    ($name:ident) => { const $name: () = (); };
+}
+pub trait Trait {
+    type AssocType;
+    const ASSOC_CONST: ();
+    fn method(&self);
+    m!(MACRO_CONST);
+}
+        "#,
+        expect![[r#"
+            crate
+            ASSOC_CONST: _
+            AssocType: _
+            MACRO_CONST: _
+            method: _
+            module: t
+
+            crate::module
+            Trait: t
+        "#]],
+    );
+    check(
+        r#"
+//- /main.rs
+mod module;
+
+use self::module::Trait::*;
+
+//- /module.rs
+macro_rules! m {
+    ($name:ident) => { const $name: () = (); };
+}
+pub trait Trait {
+    type AssocType;
+    const ASSOC_CONST: ();
+    fn method(&self);
+    m!(MACRO_CONST);
+}
+        "#,
+        expect![[r#"
+            crate
+            module: t
+
+            crate::module
+            Trait: t
+        "#]],
+    );
+}
+
+#[test]
+fn trait_item_imports_differing_crate() {
+    check(
+        r#"
+//- /main.rs deps:lib crate:main
+use lib::Trait::{AssocType, ASSOC_CONST, MACRO_CONST, method};
+
+//- /lib.rs crate:lib
+macro_rules! m {
+    ($name:ident) => { const $name: () = (); };
+}
+pub trait Trait {
+    type AssocType;
+    const ASSOC_CONST: ();
+    fn method(&self);
+    m!(MACRO_CONST);
+}
+        "#,
+        expect![[r#"
+            crate
+            ASSOC_CONST: _
+            AssocType: _
+            MACRO_CONST: _
+            method: _
+        "#]],
+    );
+    check(
+        r#"
+//- /main.rs deps:lib crate:main
+use lib::Trait::*;
+
+//- /lib.rs crate:lib
+macro_rules! m {
+    ($name:ident) => { const $name: () = (); };
+}
+pub trait Trait {
+    type AssocType;
+    const ASSOC_CONST: ();
+    fn method(&self);
+    m!(MACRO_CONST);
+}
+        "#,
+        expect![[r#"
+            crate
+        "#]],
+    );
+}
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 8a8d17018c1..16988ddf04b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -34,30 +34,30 @@ use crate::{
     item_scope::{BUILTIN_SCOPE, BuiltinShadowMode, ImportOrExternCrate, ImportOrGlob, ItemScope},
     item_tree::ImportAlias,
     lang_item::LangItemTarget,
-    nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo},
+    nameres::{DefMap, LocalDefMap, MacroSubNs, ResolvePathResultPrefixInfo, block_def_map},
     per_ns::PerNs,
     type_ref::LifetimeRef,
     visibility::{RawVisibility, Visibility},
 };
 
 #[derive(Debug, Clone)]
-pub struct Resolver {
+pub struct Resolver<'db> {
     /// The stack of scopes, where the inner-most scope is the last item.
     ///
     /// When using, you generally want to process the scopes in reverse order,
     /// there's `scopes` *method* for that.
-    scopes: Vec<Scope>,
-    module_scope: ModuleItemMap,
+    scopes: Vec<Scope<'db>>,
+    module_scope: ModuleItemMap<'db>,
 }
 
 #[derive(Clone)]
-struct ModuleItemMap {
-    def_map: Arc<DefMap>,
-    local_def_map: Arc<LocalDefMap>,
+struct ModuleItemMap<'db> {
+    def_map: &'db DefMap,
+    local_def_map: &'db LocalDefMap,
     module_id: LocalModuleId,
 }
 
-impl fmt::Debug for ModuleItemMap {
+impl fmt::Debug for ModuleItemMap<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("ModuleItemMap").field("module_id", &self.module_id).finish()
     }
@@ -80,9 +80,9 @@ impl fmt::Debug for ExprScope {
 }
 
 #[derive(Debug, Clone)]
-enum Scope {
+enum Scope<'db> {
     /// All the items and imported names of a module
-    BlockScope(ModuleItemMap),
+    BlockScope(ModuleItemMap<'db>),
     /// Brings the generic parameters of an item into scope as well as the `Self` type alias /
     /// generic for ADTs and impls.
     GenericParams { def: GenericDefId, params: Arc<GenericParams> },
@@ -133,7 +133,7 @@ pub enum LifetimeNs {
     LifetimeParam(LifetimeParamId),
 }
 
-impl Resolver {
+impl<'db> Resolver<'db> {
     /// Resolve known trait from std, like `std::futures::Future`
     pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> {
         let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?;
@@ -580,7 +580,7 @@ impl Resolver {
         for scope in self.scopes() {
             scope.process_names(&mut res, db);
         }
-        let ModuleItemMap { ref def_map, module_id, ref local_def_map } = self.module_scope;
+        let ModuleItemMap { def_map, module_id, local_def_map } = self.module_scope;
         // FIXME: should we provide `self` here?
         // f(
         //     Name::self_param(),
@@ -842,14 +842,14 @@ impl Resolver {
     #[must_use]
     pub fn update_to_inner_scope(
         &mut self,
-        db: &dyn DefDatabase,
+        db: &'db dyn DefDatabase,
         owner: DefWithBodyId,
         expr_id: ExprId,
     ) -> UpdateGuard {
         #[inline(always)]
-        fn append_expr_scope(
-            db: &dyn DefDatabase,
-            resolver: &mut Resolver,
+        fn append_expr_scope<'db>(
+            db: &'db dyn DefDatabase,
+            resolver: &mut Resolver<'db>,
             owner: DefWithBodyId,
             expr_scopes: &Arc<ExprScopes>,
             scope_id: ScopeId,
@@ -863,7 +863,7 @@ impl Resolver {
                 scope_id,
             }));
             if let Some(block) = expr_scopes.block(scope_id) {
-                let def_map = db.block_def_map(block);
+                let def_map = block_def_map(db, block);
                 let local_def_map = block.lookup(db).module.only_local_def_map(db);
                 resolver.scopes.push(Scope::BlockScope(ModuleItemMap {
                     def_map,
@@ -945,8 +945,8 @@ fn hygiene_info(
 
 pub struct UpdateGuard(usize);
 
-impl Resolver {
-    fn scopes(&self) -> impl Iterator<Item = &Scope> {
+impl<'db> Resolver<'db> {
+    fn scopes(&self) -> impl Iterator<Item = &Scope<'db>> {
         self.scopes.iter().rev()
     }
 
@@ -970,12 +970,12 @@ impl Resolver {
     fn item_scope_(&self) -> (&DefMap, &LocalDefMap, LocalModuleId) {
         self.scopes()
             .find_map(|scope| match scope {
-                Scope::BlockScope(m) => Some((&*m.def_map, &*m.local_def_map, m.module_id)),
+                Scope::BlockScope(m) => Some((m.def_map, m.local_def_map, m.module_id)),
                 _ => None,
             })
             .unwrap_or((
-                &self.module_scope.def_map,
-                &self.module_scope.local_def_map,
+                self.module_scope.def_map,
+                self.module_scope.local_def_map,
                 self.module_scope.module_id,
             ))
     }
@@ -992,8 +992,8 @@ pub enum ScopeDef {
     Label(LabelId),
 }
 
-impl Scope {
-    fn process_names(&self, acc: &mut ScopeNames, db: &dyn DefDatabase) {
+impl<'db> Scope<'db> {
+    fn process_names(&self, acc: &mut ScopeNames, db: &'db dyn DefDatabase) {
         match self {
             Scope::BlockScope(m) => {
                 m.def_map[m.module_id].scope.entries().for_each(|(name, def)| {
@@ -1047,7 +1047,11 @@ impl Scope {
     }
 }
 
-pub fn resolver_for_expr(db: &dyn DefDatabase, owner: DefWithBodyId, expr_id: ExprId) -> Resolver {
+pub fn resolver_for_expr(
+    db: &dyn DefDatabase,
+    owner: DefWithBodyId,
+    expr_id: ExprId,
+) -> Resolver<'_> {
     let r = owner.resolver(db);
     let scopes = db.expr_scopes(owner);
     let scope_id = scopes.scope_for(expr_id);
@@ -1058,25 +1062,25 @@ pub fn resolver_for_scope(
     db: &dyn DefDatabase,
     owner: DefWithBodyId,
     scope_id: Option<ScopeId>,
-) -> Resolver {
+) -> Resolver<'_> {
     let r = owner.resolver(db);
     let scopes = db.expr_scopes(owner);
     resolver_for_scope_(db, scopes, scope_id, r, owner)
 }
 
-fn resolver_for_scope_(
-    db: &dyn DefDatabase,
+fn resolver_for_scope_<'db>(
+    db: &'db dyn DefDatabase,
     scopes: Arc<ExprScopes>,
     scope_id: Option<ScopeId>,
-    mut r: Resolver,
+    mut r: Resolver<'db>,
     owner: DefWithBodyId,
-) -> Resolver {
+) -> Resolver<'db> {
     let scope_chain = scopes.scope_chain(scope_id).collect::<Vec<_>>();
     r.scopes.reserve(scope_chain.len());
 
     for scope in scope_chain.into_iter().rev() {
         if let Some(block) = scopes.block(scope) {
-            let def_map = db.block_def_map(block);
+            let def_map = block_def_map(db, block);
             let local_def_map = block.lookup(db).module.only_local_def_map(db);
             r = r.push_block_scope(def_map, local_def_map);
             // FIXME: This adds as many module scopes as there are blocks, but resolving in each
@@ -1092,18 +1096,26 @@ fn resolver_for_scope_(
     r
 }
 
-impl Resolver {
-    fn push_scope(mut self, scope: Scope) -> Resolver {
+impl<'db> Resolver<'db> {
+    fn push_scope(mut self, scope: Scope<'db>) -> Resolver<'db> {
         self.scopes.push(scope);
         self
     }
 
-    fn push_generic_params_scope(self, db: &dyn DefDatabase, def: GenericDefId) -> Resolver {
+    fn push_generic_params_scope(
+        self,
+        db: &'db dyn DefDatabase,
+        def: GenericDefId,
+    ) -> Resolver<'db> {
         let params = db.generic_params(def);
         self.push_scope(Scope::GenericParams { def, params })
     }
 
-    fn push_block_scope(self, def_map: Arc<DefMap>, local_def_map: Arc<LocalDefMap>) -> Resolver {
+    fn push_block_scope(
+        self,
+        def_map: &'db DefMap,
+        local_def_map: &'db LocalDefMap,
+    ) -> Resolver<'db> {
         self.push_scope(Scope::BlockScope(ModuleItemMap {
             def_map,
             local_def_map,
@@ -1116,19 +1128,19 @@ impl Resolver {
         owner: DefWithBodyId,
         expr_scopes: Arc<ExprScopes>,
         scope_id: ScopeId,
-    ) -> Resolver {
+    ) -> Resolver<'db> {
         self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id }))
     }
 }
 
-impl ModuleItemMap {
+impl<'db> ModuleItemMap<'db> {
     fn resolve_path_in_value_ns(
         &self,
-        db: &dyn DefDatabase,
+        db: &'db dyn DefDatabase,
         path: &ModPath,
     ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> {
         let (module_def, unresolved_idx, prefix_info) = self.def_map.resolve_path_locally(
-            &self.local_def_map,
+            self.local_def_map,
             db,
             self.module_id,
             path,
@@ -1167,7 +1179,7 @@ impl ModuleItemMap {
     ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)>
     {
         let (module_def, idx, prefix_info) = self.def_map.resolve_path_locally(
-            &self.local_def_map,
+            self.local_def_map,
             db,
             self.module_id,
             path,
@@ -1263,11 +1275,11 @@ impl ScopeNames {
 
 pub trait HasResolver: Copy {
     /// Builds a resolver for type references inside this def.
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver;
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_>;
 }
 
 impl HasResolver for ModuleId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         let (mut def_map, local_def_map) = self.local_def_map(db);
         let mut module_id = self.local_id;
 
@@ -1289,21 +1301,17 @@ impl HasResolver for ModuleId {
         }
         let mut resolver = Resolver {
             scopes: Vec::with_capacity(modules.len()),
-            module_scope: ModuleItemMap {
-                def_map,
-                local_def_map: local_def_map.clone(),
-                module_id,
-            },
+            module_scope: ModuleItemMap { def_map, local_def_map, module_id },
         };
         for def_map in modules.into_iter().rev() {
-            resolver = resolver.push_block_scope(def_map, local_def_map.clone());
+            resolver = resolver.push_block_scope(def_map, local_def_map);
         }
         resolver
     }
 }
 
 impl HasResolver for CrateRootModuleId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         let (def_map, local_def_map) = self.local_def_map(db);
         Resolver {
             scopes: vec![],
@@ -1313,75 +1321,75 @@ impl HasResolver for CrateRootModuleId {
 }
 
 impl HasResolver for TraitId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self).push_generic_params_scope(db, self.into())
     }
 }
 
 impl HasResolver for TraitAliasId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self).push_generic_params_scope(db, self.into())
     }
 }
 
 impl<T: Into<AdtId> + Copy> HasResolver for T {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         let def = self.into();
         def.module(db).resolver(db).push_generic_params_scope(db, def.into())
     }
 }
 
 impl HasResolver for FunctionId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self).push_generic_params_scope(db, self.into())
     }
 }
 
 impl HasResolver for ConstId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self)
     }
 }
 
 impl HasResolver for StaticId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self)
     }
 }
 
 impl HasResolver for TypeAliasId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self).push_generic_params_scope(db, self.into())
     }
 }
 
 impl HasResolver for ImplId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into())
     }
 }
 
 impl HasResolver for ExternBlockId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         // Same as parent's
         lookup_resolver(db, self)
     }
 }
 
 impl HasResolver for ExternCrateId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self)
     }
 }
 
 impl HasResolver for UseId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self)
     }
 }
 
 impl HasResolver for DefWithBodyId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         match self {
             DefWithBodyId::ConstId(c) => c.resolver(db),
             DefWithBodyId::FunctionId(f) => f.resolver(db),
@@ -1392,7 +1400,7 @@ impl HasResolver for DefWithBodyId {
 }
 
 impl HasResolver for ItemContainerId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         match self {
             ItemContainerId::ModuleId(it) => it.resolver(db),
             ItemContainerId::TraitId(it) => it.resolver(db),
@@ -1403,7 +1411,7 @@ impl HasResolver for ItemContainerId {
 }
 
 impl HasResolver for GenericDefId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         match self {
             GenericDefId::FunctionId(inner) => inner.resolver(db),
             GenericDefId::AdtId(adt) => adt.resolver(db),
@@ -1418,13 +1426,13 @@ impl HasResolver for GenericDefId {
 }
 
 impl HasResolver for EnumVariantId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         self.lookup(db).parent.resolver(db)
     }
 }
 
 impl HasResolver for VariantId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         match self {
             VariantId::EnumVariantId(it) => it.resolver(db),
             VariantId::StructId(it) => it.resolver(db),
@@ -1434,7 +1442,7 @@ impl HasResolver for VariantId {
 }
 
 impl HasResolver for MacroId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         match self {
             MacroId::Macro2Id(it) => it.resolver(db),
             MacroId::MacroRulesId(it) => it.resolver(db),
@@ -1444,29 +1452,29 @@ impl HasResolver for MacroId {
 }
 
 impl HasResolver for Macro2Id {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self)
     }
 }
 
 impl HasResolver for ProcMacroId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self)
     }
 }
 
 impl HasResolver for MacroRulesId {
-    fn resolver(self, db: &dyn DefDatabase) -> Resolver {
+    fn resolver(self, db: &dyn DefDatabase) -> Resolver<'_> {
         lookup_resolver(db, self)
     }
 }
 
-fn lookup_resolver<'db>(
-    db: &(dyn DefDatabase + 'db),
+fn lookup_resolver(
+    db: &dyn DefDatabase,
     lookup: impl Lookup<
         Database = dyn DefDatabase,
         Data = impl ItemTreeLoc<Container = impl HasResolver>,
     >,
-) -> Resolver {
+) -> Resolver<'_> {
     lookup.lookup(db).container().resolver(db)
 }
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 47097548295..6c995ab6c23 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
@@ -15,7 +15,7 @@ use triomphe::Arc;
 use crate::{
     LocalModuleId, Lookup, ModuleDefId, ModuleId,
     db::DefDatabase,
-    nameres::{DefMap, ModuleSource},
+    nameres::{DefMap, ModuleSource, block_def_map, crate_def_map},
     src::HasSource,
 };
 
@@ -133,7 +133,7 @@ impl TestDB {
 
     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);
+            let crate_def_map = crate_def_map(self, krate);
             for (local_id, data) in crate_def_map.modules() {
                 if data.origin.file_id().map(|file_id| file_id.file_id(self)) == Some(file_id) {
                     return crate_def_map.module_id(local_id);
@@ -146,16 +146,16 @@ impl TestDB {
     pub(crate) fn module_at_position(&self, position: FilePosition) -> ModuleId {
         let file_module = self.module_for_file(position.file_id.file_id(self));
         let mut def_map = file_module.def_map(self);
-        let module = self.mod_at_position(&def_map, position);
+        let module = self.mod_at_position(def_map, position);
 
-        def_map = match self.block_at_position(&def_map, position) {
+        def_map = match self.block_at_position(def_map, position) {
             Some(it) => it,
             None => return def_map.module_id(module),
         };
         loop {
-            let new_map = self.block_at_position(&def_map, position);
+            let new_map = self.block_at_position(def_map, position);
             match new_map {
-                Some(new_block) if !Arc::ptr_eq(&new_block, &def_map) => {
+                Some(new_block) if !std::ptr::eq(&new_block, &def_map) => {
                     def_map = new_block;
                 }
                 _ => {
@@ -206,7 +206,7 @@ impl TestDB {
         res
     }
 
-    fn block_at_position(&self, def_map: &DefMap, position: FilePosition) -> Option<Arc<DefMap>> {
+    fn block_at_position(&self, def_map: &DefMap, position: FilePosition) -> Option<&DefMap> {
         // Find the smallest (innermost) function in `def_map` containing the cursor.
         let mut size = None;
         let mut fn_def = None;
@@ -263,7 +263,7 @@ impl TestDB {
             let mut containing_blocks =
                 scopes.scope_chain(Some(scope)).filter_map(|scope| scopes.block(scope));
 
-            if let Some(block) = containing_blocks.next().map(|block| self.block_def_map(block)) {
+            if let Some(block) = containing_blocks.next().map(|block| block_def_map(self, block)) {
                 return Some(block);
             }
         }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
index b42c8d383d4..3c67ee9fe5b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
@@ -28,7 +28,7 @@ pub enum Visibility {
 impl Visibility {
     pub fn resolve(
         db: &dyn DefDatabase,
-        resolver: &crate::resolver::Resolver,
+        resolver: &crate::resolver::Resolver<'_>,
         raw_vis: &RawVisibility,
     ) -> Self {
         // we fall back to public visibility (i.e. fail open) if the path can't be resolved
@@ -50,7 +50,7 @@ impl Visibility {
             return false;
         }
         let def_map = from_module.def_map(db);
-        Self::is_visible_from_def_map_(db, &def_map, to_module, from_module.local_id)
+        Self::is_visible_from_def_map_(db, def_map, to_module, from_module.local_id)
     }
 
     pub(crate) fn is_visible_from_def_map(
@@ -116,7 +116,7 @@ impl Visibility {
                     match def_map.parent() {
                         Some(module) => {
                             parent_arc = module.def_map(db);
-                            def_map = &*parent_arc;
+                            def_map = parent_arc;
                             from_module = module.local_id;
                         }
                         // Reached the root module, nothing left to check.
@@ -257,7 +257,7 @@ pub(crate) fn type_alias_visibility_query(db: &dyn DefDatabase, def: TypeAliasId
 }
 
 #[inline]
-fn trait_vis(db: &dyn DefDatabase, resolver: &Resolver, trait_id: TraitId) -> Visibility {
+fn trait_vis(db: &dyn DefDatabase, resolver: &Resolver<'_>, trait_id: TraitId) -> Visibility {
     let ItemLoc { id: tree_id, .. } = trait_id.lookup(db);
     let item_tree = tree_id.item_tree(db);
     let tr_def = &item_tree[tree_id.value];
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
index bb17eb06276..94c97713f06 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
@@ -1,4 +1,5 @@
 //! A higher level attributes based on TokenTree, with also some shortcuts.
+use std::iter;
 use std::{borrow::Cow, fmt, ops};
 
 use base_db::Crate;
@@ -122,16 +123,15 @@ impl RawAttrs {
             (None, entries @ Some(_)) => Self { entries },
             (Some(entries), None) => Self { entries: Some(entries.clone()) },
             (Some(a), Some(b)) => {
-                let last_ast_index = a.slice.last().map_or(0, |it| it.id.ast_index() + 1) as u32;
+                let last_ast_index = a.slice.last().map_or(0, |it| it.id.ast_index() + 1);
                 let items = a
                     .slice
                     .iter()
                     .cloned()
                     .chain(b.slice.iter().map(|it| {
                         let mut it = it.clone();
-                        it.id.id = (it.id.ast_index() as u32 + last_ast_index)
-                            | ((it.id.cfg_attr_index().unwrap_or(0) as u32)
-                                << AttrId::AST_INDEX_BITS);
+                        let id = it.id.ast_index() + last_ast_index;
+                        it.id = AttrId::new(id, it.id.is_inner_attr());
                         it
                     }))
                     .collect::<Vec<_>>();
@@ -175,25 +175,20 @@ pub struct AttrId {
 // FIXME: This only handles a single level of cfg_attr nesting
 // that is `#[cfg_attr(all(), cfg_attr(all(), cfg(any())))]` breaks again
 impl AttrId {
-    const CFG_ATTR_BITS: usize = 7;
-    const AST_INDEX_MASK: usize = 0x00FF_FFFF;
-    const AST_INDEX_BITS: usize = Self::AST_INDEX_MASK.count_ones() as usize;
-    const CFG_ATTR_SET_BITS: u32 = 1 << 31;
+    const INNER_ATTR_SET_BIT: u32 = 1 << 31;
 
-    pub fn ast_index(&self) -> usize {
-        self.id as usize & Self::AST_INDEX_MASK
+    pub fn new(id: usize, is_inner: bool) -> Self {
+        assert!(id <= !Self::INNER_ATTR_SET_BIT as usize);
+        let id = id as u32;
+        Self { id: if is_inner { id | Self::INNER_ATTR_SET_BIT } else { id } }
     }
 
-    pub fn cfg_attr_index(&self) -> Option<usize> {
-        if self.id & Self::CFG_ATTR_SET_BITS == 0 {
-            None
-        } else {
-            Some(self.id as usize >> Self::AST_INDEX_BITS)
-        }
+    pub fn ast_index(&self) -> usize {
+        (self.id & !Self::INNER_ATTR_SET_BIT) as usize
     }
 
-    pub fn with_cfg_attr(self, idx: usize) -> AttrId {
-        AttrId { id: self.id | ((idx as u32) << Self::AST_INDEX_BITS) | Self::CFG_ATTR_SET_BITS }
+    pub fn is_inner_attr(&self) -> bool {
+        self.id & Self::INNER_ATTR_SET_BIT != 0
     }
 }
 
@@ -333,10 +328,7 @@ impl Attr {
             None => return smallvec![self.clone()],
         };
         let index = self.id;
-        let attrs = parts
-            .enumerate()
-            .take(1 << AttrId::CFG_ATTR_BITS)
-            .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)));
+        let attrs = parts.filter_map(|attr| Attr::from_tt(db, attr, index));
 
         let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg);
         let cfg = CfgExpr::parse(&cfg);
@@ -467,13 +459,18 @@ fn unescape(s: &str) -> Option<Cow<'_, str>> {
 pub fn collect_attrs(
     owner: &dyn ast::HasAttrs,
 ) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> {
-    let inner_attrs = inner_attributes(owner.syntax()).into_iter().flatten();
-    let outer_attrs =
-        ast::AttrDocCommentIter::from_syntax_node(owner.syntax()).filter(|el| match el {
+    let inner_attrs =
+        inner_attributes(owner.syntax()).into_iter().flatten().zip(iter::repeat(true));
+    let outer_attrs = ast::AttrDocCommentIter::from_syntax_node(owner.syntax())
+        .filter(|el| match el {
             Either::Left(attr) => attr.kind().is_outer(),
             Either::Right(comment) => comment.is_outer(),
-        });
-    outer_attrs.chain(inner_attrs).enumerate().map(|(id, attr)| (AttrId { id: id as u32 }, attr))
+        })
+        .zip(iter::repeat(false));
+    outer_attrs
+        .chain(inner_attrs)
+        .enumerate()
+        .map(|(id, (attr, is_inner))| (AttrId::new(id, is_inner), attr))
 }
 
 fn inner_attributes(
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
index 68283b916d7..d135584a080 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
@@ -1,5 +1,6 @@
 //! Builtin derives.
 
+use either::Either;
 use intern::sym;
 use itertools::{Itertools, izip};
 use parser::SyntaxKind;
@@ -1179,10 +1180,10 @@ fn coerce_pointee_expand(
                 };
                 new_predicates.push(
                     make::where_pred(
-                        make::ty_path(make::path_from_segments(
+                        Either::Right(make::ty_path(make::path_from_segments(
                             [make::path_segment(new_bounds_target)],
                             false,
-                        )),
+                        ))),
                         new_bounds,
                     )
                     .clone_for_update(),
@@ -1245,7 +1246,9 @@ fn coerce_pointee_expand(
                             substitute_type_in_bound(ty, &pointee_param_name.text(), ADDED_PARAM)
                         })
                     });
-                new_predicates.push(make::where_pred(pred_target, new_bounds).clone_for_update());
+                new_predicates.push(
+                    make::where_pred(Either::Right(pred_target), new_bounds).clone_for_update(),
+                );
             }
         }
 
@@ -1260,10 +1263,10 @@ fn coerce_pointee_expand(
         // Find the `#[pointee]` parameter and add an `Unsize<__S>` bound to it.
         where_clause.add_predicate(
             make::where_pred(
-                make::ty_path(make::path_from_segments(
+                Either::Right(make::ty_path(make::path_from_segments(
                     [make::path_segment(make::name_ref(&pointee_param_name.text()))],
                     false,
-                )),
+                ))),
                 [make::type_bound(make::ty_path(make::path_from_segments(
                     [
                         make::path_segment(make::name_ref("core")),
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
index 621e174cac9..539c7277284 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs
@@ -452,7 +452,10 @@ fn concat_expand(
         Some(_) => (),
         None => span = Some(s),
     };
-    for (i, mut t) in tt.iter().enumerate() {
+
+    let mut i = 0;
+    let mut iter = tt.iter();
+    while let Some(mut t) = iter.next() {
         // FIXME: hack on top of a hack: `$e:expr` captures get surrounded in parentheses
         // to ensure the right parsing order, so skip the parentheses here. Ideally we'd
         // implement rustc's model. cc https://github.com/rust-lang/rust-analyzer/pull/10623
@@ -504,10 +507,40 @@ fn concat_expand(
                 record_span(id.span);
             }
             TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
+            // handle negative numbers
+            TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 0 && punct.char == '-' => {
+                let t = match iter.next() {
+                    Some(t) => t,
+                    None => {
+                        err.get_or_insert(ExpandError::other(
+                            call_site,
+                            "unexpected end of input after '-'",
+                        ));
+                        break;
+                    }
+                };
+
+                match t {
+                    TtElement::Leaf(tt::Leaf::Literal(it))
+                        if matches!(it.kind, tt::LitKind::Integer | tt::LitKind::Float) =>
+                    {
+                        format_to!(text, "-{}", it.symbol.as_str());
+                        record_span(punct.span.cover(it.span));
+                    }
+                    _ => {
+                        err.get_or_insert(ExpandError::other(
+                            call_site,
+                            "expected integer or floating pointer number after '-'",
+                        ));
+                        break;
+                    }
+                }
+            }
             _ => {
                 err.get_or_insert(ExpandError::other(call_site, "unexpected token"));
             }
         }
+        i += 1;
     }
     let span = span.unwrap_or_else(|| tt.top_subtree().delimiter.open);
     ExpandResult { value: quote!(span =>#text), err }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
index 8a1a33d7e3b..1cd975b980d 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
@@ -19,18 +19,8 @@ pub enum ProcMacroKind {
     Attr,
 }
 
-pub trait AsAny: Any {
-    fn as_any(&self) -> &dyn Any;
-}
-
-impl<T: Any> AsAny for T {
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-}
-
 /// A proc-macro expander implementation.
-pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe + AsAny {
+pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe + Any {
     /// Run the expander with the given input subtree, optional attribute input subtree (for
     /// [`ProcMacroKind::Attr`]), environment variables, and span information.
     fn expand(
@@ -44,7 +34,9 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe + AsAny {
         current_dir: String,
     ) -> Result<tt::TopSubtree, ProcMacroExpansionError>;
 
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool;
+    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
+        other.type_id() == self.type_id()
+    }
 }
 
 impl PartialEq for dyn ProcMacroExpander {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
index d1a1e135fff..f903b06d65e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
@@ -91,7 +91,7 @@ impl From<MirEvalError> for ConstEvalError {
 
 pub(crate) fn path_to_const<'g>(
     db: &dyn HirDatabase,
-    resolver: &Resolver,
+    resolver: &Resolver<'_>,
     path: &Path,
     mode: ParamLoweringMode,
     args: impl FnOnce() -> &'g Generics,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index 57106412765..e4a23cbbacf 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -480,7 +480,7 @@ struct FilterMapNextChecker {
 }
 
 impl FilterMapNextChecker {
-    fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self {
+    fn new(resolver: &hir_def::resolver::Resolver<'_>, db: &dyn HirDatabase) -> Self {
         // Find and store the FunctionIds for Iterator::filter_map and Iterator::next
         let (next_function_id, filter_map_function_id) = match LangItem::IteratorNext
             .resolve_function(db, resolver.krate())
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 068fc22f2ca..785277d70c6 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
@@ -73,7 +73,7 @@ pub(crate) struct MatchCheckCtx<'db> {
 
 impl<'db> MatchCheckCtx<'db> {
     pub(crate) fn new(module: ModuleId, body: DefWithBodyId, db: &'db dyn HirDatabase) -> Self {
-        let def_map = db.crate_def_map(module.krate());
+        let def_map = module.crate_def_map(db);
         let exhaustive_patterns = def_map.is_unstable_feature_enabled(&sym::exhaustive_patterns);
         Self { module, body, db, exhaustive_patterns }
     }
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 73b99db7268..20cf3c78115 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
@@ -7,7 +7,7 @@ use either::Either;
 use hir_def::{
     AdtId, DefWithBodyId, FieldId, FunctionId, VariantId,
     expr_store::{Body, path::Path},
-    hir::{Expr, ExprId, ExprOrPatId, Pat, PatId, Statement, UnaryOp},
+    hir::{AsmOperand, Expr, ExprId, ExprOrPatId, Pat, PatId, Statement, UnaryOp},
     resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
     signatures::StaticFlags,
     type_ref::Rawness,
@@ -131,28 +131,28 @@ pub fn unsafe_operations(
     visitor.walk_expr(current);
 }
 
-struct UnsafeVisitor<'a> {
-    db: &'a dyn HirDatabase,
-    infer: &'a InferenceResult,
-    body: &'a Body,
-    resolver: Resolver,
+struct UnsafeVisitor<'db> {
+    db: &'db dyn HirDatabase,
+    infer: &'db InferenceResult,
+    body: &'db Body,
+    resolver: Resolver<'db>,
     def: DefWithBodyId,
     inside_unsafe_block: InsideUnsafeBlock,
     inside_assignment: bool,
     inside_union_destructure: bool,
-    callback: &'a mut dyn FnMut(UnsafeDiagnostic),
+    callback: &'db mut dyn FnMut(UnsafeDiagnostic),
     def_target_features: TargetFeatures,
     // FIXME: This needs to be the edition of the span of each call.
     edition: Edition,
 }
 
-impl<'a> UnsafeVisitor<'a> {
+impl<'db> UnsafeVisitor<'db> {
     fn new(
-        db: &'a dyn HirDatabase,
-        infer: &'a InferenceResult,
-        body: &'a Body,
+        db: &'db dyn HirDatabase,
+        infer: &'db InferenceResult,
+        body: &'db Body,
         def: DefWithBodyId,
-        unsafe_expr_cb: &'a mut dyn FnMut(UnsafeDiagnostic),
+        unsafe_expr_cb: &'db mut dyn FnMut(UnsafeDiagnostic),
     ) -> Self {
         let resolver = def.resolver(db);
         let def_target_features = match def {
@@ -199,6 +199,17 @@ impl<'a> UnsafeVisitor<'a> {
         }
     }
 
+    fn with_inside_unsafe_block<R>(
+        &mut self,
+        inside_unsafe_block: InsideUnsafeBlock,
+        f: impl FnOnce(&mut Self) -> R,
+    ) -> R {
+        let old = mem::replace(&mut self.inside_unsafe_block, inside_unsafe_block);
+        let result = f(self);
+        self.inside_unsafe_block = old;
+        result
+    }
+
     fn walk_pats_top(&mut self, pats: impl Iterator<Item = PatId>, parent_expr: ExprId) {
         let guard = self.resolver.update_to_inner_scope(self.db, self.def, parent_expr);
         pats.for_each(|pat| self.walk_pat(pat));
@@ -303,7 +314,29 @@ impl<'a> UnsafeVisitor<'a> {
                 self.walk_pats_top(std::iter::once(target), current);
                 self.inside_assignment = old_inside_assignment;
             }
-            Expr::InlineAsm(_) => self.on_unsafe_op(current.into(), UnsafetyReason::InlineAsm),
+            Expr::InlineAsm(asm) => {
+                self.on_unsafe_op(current.into(), UnsafetyReason::InlineAsm);
+                asm.operands.iter().for_each(|(_, op)| match op {
+                    AsmOperand::In { expr, .. }
+                    | AsmOperand::Out { expr: Some(expr), .. }
+                    | AsmOperand::InOut { expr, .. }
+                    | AsmOperand::Const(expr) => self.walk_expr(*expr),
+                    AsmOperand::SplitInOut { in_expr, out_expr, .. } => {
+                        self.walk_expr(*in_expr);
+                        if let Some(out_expr) = out_expr {
+                            self.walk_expr(*out_expr);
+                        }
+                    }
+                    AsmOperand::Out { expr: None, .. } | AsmOperand::Sym(_) => (),
+                    AsmOperand::Label(expr) => {
+                        // Inline asm labels are considered safe even when inside unsafe blocks.
+                        self.with_inside_unsafe_block(InsideUnsafeBlock::No, |this| {
+                            this.walk_expr(*expr)
+                        });
+                    }
+                });
+                return;
+            }
             // rustc allows union assignment to propagate through field accesses and casts.
             Expr::Cast { .. } => self.inside_assignment = inside_assignment,
             Expr::Field { .. } => {
@@ -317,17 +350,16 @@ impl<'a> UnsafeVisitor<'a> {
                 }
             }
             Expr::Unsafe { statements, .. } => {
-                let old_inside_unsafe_block =
-                    mem::replace(&mut self.inside_unsafe_block, InsideUnsafeBlock::Yes);
-                self.walk_pats_top(
-                    statements.iter().filter_map(|statement| match statement {
-                        &Statement::Let { pat, .. } => Some(pat),
-                        _ => None,
-                    }),
-                    current,
-                );
-                self.body.walk_child_exprs_without_pats(current, |child| self.walk_expr(child));
-                self.inside_unsafe_block = old_inside_unsafe_block;
+                self.with_inside_unsafe_block(InsideUnsafeBlock::Yes, |this| {
+                    this.walk_pats_top(
+                        statements.iter().filter_map(|statement| match statement {
+                            &Statement::Let { pat, .. } => Some(pat),
+                            _ => None,
+                        }),
+                        current,
+                    );
+                    this.body.walk_child_exprs_without_pats(current, |child| this.walk_expr(child));
+                });
                 return;
             }
             Expr::Block { statements, .. } | Expr::Async { statements, .. } => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index 106b996b13e..ed8d8dc2624 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -9,8 +9,8 @@ use chalk_ir::{
 };
 use chalk_solve::rust_ir::InlineBound;
 use hir_def::{
-    AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId, TypeAliasId,
-    lang_item::LangItem, signatures::TraitFlags,
+    AssocItemId, ConstId, CrateRootModuleId, FunctionId, GenericDefId, HasModule, TraitId,
+    TypeAliasId, lang_item::LangItem, signatures::TraitFlags,
 };
 use rustc_hash::FxHashSet;
 use smallvec::SmallVec;
@@ -343,7 +343,7 @@ where
             })
         }
         AssocItemId::TypeAliasId(it) => {
-            let def_map = db.crate_def_map(trait_.krate(db));
+            let def_map = CrateRootModuleId::from(trait_.krate(db)).def_map(db);
             if def_map.is_unstable_feature_enabled(&intern::sym::generic_associated_type_extended) {
                 ControlFlow::Continue(())
             } else {
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 f0ec31db8bb..e698fb201cb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -594,16 +594,16 @@ impl Index<BindingId> for InferenceResult {
 
 /// The inference context contains all information needed during type inference.
 #[derive(Clone, Debug)]
-pub(crate) struct InferenceContext<'a> {
-    pub(crate) db: &'a dyn HirDatabase,
+pub(crate) struct InferenceContext<'db> {
+    pub(crate) db: &'db dyn HirDatabase,
     pub(crate) owner: DefWithBodyId,
-    pub(crate) body: &'a Body,
+    pub(crate) body: &'db Body,
     /// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext
     /// and resolve the path via its methods. This will ensure proper error reporting.
-    pub(crate) resolver: Resolver,
+    pub(crate) resolver: Resolver<'db>,
     generic_def: GenericDefId,
     generics: OnceCell<Generics>,
-    table: unify::InferenceTable<'a>,
+    table: unify::InferenceTable<'db>,
     /// The traits in scope, disregarding block modules. This is used for caching purposes.
     traits_in_scope: FxHashSet<TraitId>,
     pub(crate) result: InferenceResult,
@@ -695,12 +695,12 @@ enum ImplTraitReplacingMode {
     TypeAlias,
 }
 
-impl<'a> InferenceContext<'a> {
+impl<'db> InferenceContext<'db> {
     fn new(
-        db: &'a dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         owner: DefWithBodyId,
-        body: &'a Body,
-        resolver: Resolver,
+        body: &'db Body,
+        resolver: Resolver<'db>,
     ) -> Self {
         let trait_env = db.trait_environment_for_body(owner);
         InferenceContext {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs
index e3c4f5562d5..003364d4336 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs
@@ -61,7 +61,7 @@ impl<'a> InferenceTyLoweringContext<'a> {
     #[inline]
     pub(super) fn new(
         db: &'a dyn HirDatabase,
-        resolver: &'a Resolver,
+        resolver: &'a Resolver<'_>,
         store: &'a ExpressionStore,
         diagnostics: &'a Diagnostics,
         source: InferenceTyDiagnosticSource,
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 8084b394d04..87b7f3406ff 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
@@ -959,8 +959,8 @@ impl InferenceContext<'_> {
             }
             Expr::OffsetOf(_) => TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
             Expr::InlineAsm(asm) => {
-                let mut check_expr_asm_operand = |expr, is_input: bool| {
-                    let ty = self.infer_expr_no_expect(expr, ExprIsRead::Yes);
+                let check_expr_asm_operand = |this: &mut Self, expr, is_input: bool| {
+                    let ty = this.infer_expr_no_expect(expr, ExprIsRead::Yes);
 
                     // If this is an input value, we require its type to be fully resolved
                     // at this point. This allows us to provide helpful coercions which help
@@ -970,18 +970,18 @@ impl InferenceContext<'_> {
                     // allows them to be inferred based on how they are used later in the
                     // function.
                     if is_input {
-                        let ty = self.resolve_ty_shallow(&ty);
+                        let ty = this.resolve_ty_shallow(&ty);
                         match ty.kind(Interner) {
                             TyKind::FnDef(def, parameters) => {
                                 let fnptr_ty = TyKind::Function(
-                                    CallableSig::from_def(self.db, *def, parameters).to_fn_ptr(),
+                                    CallableSig::from_def(this.db, *def, parameters).to_fn_ptr(),
                                 )
                                 .intern(Interner);
-                                _ = self.coerce(Some(expr), &ty, &fnptr_ty, CoerceNever::Yes);
+                                _ = this.coerce(Some(expr), &ty, &fnptr_ty, CoerceNever::Yes);
                             }
                             TyKind::Ref(mutbl, _, base_ty) => {
                                 let ptr_ty = TyKind::Raw(*mutbl, base_ty.clone()).intern(Interner);
-                                _ = self.coerce(Some(expr), &ty, &ptr_ty, CoerceNever::Yes);
+                                _ = this.coerce(Some(expr), &ty, &ptr_ty, CoerceNever::Yes);
                             }
                             _ => {}
                         }
@@ -990,22 +990,28 @@ impl InferenceContext<'_> {
 
                 let diverge = asm.options.contains(AsmOptions::NORETURN);
                 asm.operands.iter().for_each(|(_, operand)| match *operand {
-                    AsmOperand::In { expr, .. } => check_expr_asm_operand(expr, true),
+                    AsmOperand::In { expr, .. } => check_expr_asm_operand(self, expr, true),
                     AsmOperand::Out { expr: Some(expr), .. } | AsmOperand::InOut { expr, .. } => {
-                        check_expr_asm_operand(expr, false)
+                        check_expr_asm_operand(self, expr, false)
                     }
                     AsmOperand::Out { expr: None, .. } => (),
                     AsmOperand::SplitInOut { in_expr, out_expr, .. } => {
-                        check_expr_asm_operand(in_expr, true);
+                        check_expr_asm_operand(self, in_expr, true);
                         if let Some(out_expr) = out_expr {
-                            check_expr_asm_operand(out_expr, false);
+                            check_expr_asm_operand(self, out_expr, false);
                         }
                     }
-                    // FIXME
-                    AsmOperand::Label(_) => (),
-                    // FIXME
-                    AsmOperand::Const(_) => (),
-                    // FIXME
+                    AsmOperand::Label(expr) => {
+                        self.infer_expr(
+                            expr,
+                            &Expectation::HasType(self.result.standard_types.unit.clone()),
+                            ExprIsRead::No,
+                        );
+                    }
+                    AsmOperand::Const(expr) => {
+                        self.infer_expr(expr, &Expectation::None, ExprIsRead::No);
+                    }
+                    // FIXME: `sym` should report for things that are not functions or statics.
                     AsmOperand::Sym(_) => (),
                 });
                 if diverge {
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 9def39d5f97..ea8e7cc2be9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -42,7 +42,6 @@ use hir_def::{
 use hir_expand::name::Name;
 use la_arena::{Arena, ArenaMap};
 use rustc_hash::FxHashSet;
-use rustc_pattern_analysis::Captures;
 use stdx::{impl_from, never};
 use triomphe::{Arc, ThinArc};
 
@@ -151,10 +150,10 @@ impl LifetimeElisionKind {
 }
 
 #[derive(Debug)]
-pub struct TyLoweringContext<'a> {
-    pub db: &'a dyn HirDatabase,
-    resolver: &'a Resolver,
-    store: &'a ExpressionStore,
+pub struct TyLoweringContext<'db> {
+    pub db: &'db dyn HirDatabase,
+    resolver: &'db Resolver<'db>,
+    store: &'db ExpressionStore,
     def: GenericDefId,
     generics: OnceCell<Generics>,
     in_binders: DebruijnIndex,
@@ -170,11 +169,11 @@ pub struct TyLoweringContext<'a> {
     lifetime_elision: LifetimeElisionKind,
 }
 
-impl<'a> TyLoweringContext<'a> {
+impl<'db> TyLoweringContext<'db> {
     pub fn new(
-        db: &'a dyn HirDatabase,
-        resolver: &'a Resolver,
-        store: &'a ExpressionStore,
+        db: &'db dyn HirDatabase,
+        resolver: &'db Resolver<'db>,
+        store: &'db ExpressionStore,
         def: GenericDefId,
         lifetime_elision: LifetimeElisionKind,
     ) -> Self {
@@ -1176,13 +1175,13 @@ where
 
 /// Generate implicit `: Sized` predicates for all generics that has no `?Sized` bound.
 /// Exception is Self of a trait def.
-fn implicitly_sized_clauses<'a, 'subst: 'a>(
-    db: &dyn HirDatabase,
+fn implicitly_sized_clauses<'db, 'a, 'subst: 'a>(
+    db: &'db dyn HirDatabase,
     def: GenericDefId,
     explicitly_unsized_tys: &'a FxHashSet<Ty>,
     substitution: &'subst Substitution,
-    resolver: &Resolver,
-) -> Option<impl Iterator<Item = WhereClause> + Captures<'a> + Captures<'subst>> {
+    resolver: &Resolver<'db>,
+) -> Option<impl Iterator<Item = WhereClause>> {
     let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id)?;
 
     let trait_self_idx = trait_self_param_idx(db, def);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index 8e549ca0cbd..3b295d41e6e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -10,7 +10,7 @@ use chalk_ir::{UniverseIndex, WithKind, cast::Cast};
 use hir_def::{
     AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup,
     ModuleId, TraitId,
-    nameres::{DefMap, assoc::ImplItems},
+    nameres::{DefMap, assoc::ImplItems, block_def_map, crate_def_map},
     signatures::{ConstFlags, EnumFlags, FnFlags, StructFlags, TraitFlags, TypeAliasFlags},
 };
 use hir_expand::name::Name;
@@ -152,7 +152,7 @@ impl TraitImpls {
         let _p = tracing::info_span!("trait_impls_in_crate_query", ?krate).entered();
         let mut impls = FxHashMap::default();
 
-        Self::collect_def_map(db, &mut impls, &db.crate_def_map(krate));
+        Self::collect_def_map(db, &mut impls, crate_def_map(db, krate));
 
         Arc::new(Self::finish(impls))
     }
@@ -164,7 +164,7 @@ impl TraitImpls {
         let _p = tracing::info_span!("trait_impls_in_block_query").entered();
         let mut impls = FxHashMap::default();
 
-        Self::collect_def_map(db, &mut impls, &db.block_def_map(block));
+        Self::collect_def_map(db, &mut impls, block_def_map(db, block));
 
         if impls.is_empty() { None } else { Some(Arc::new(Self::finish(impls))) }
     }
@@ -214,7 +214,7 @@ impl TraitImpls {
             for konst in module_data.scope.unnamed_consts() {
                 let body = db.body(konst.into());
                 for (_, block_def_map) in body.blocks(db) {
-                    Self::collect_def_map(db, map, &block_def_map);
+                    Self::collect_def_map(db, map, block_def_map);
                 }
             }
         }
@@ -280,8 +280,8 @@ impl InherentImpls {
         let _p = tracing::info_span!("inherent_impls_in_crate_query", ?krate).entered();
         let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
 
-        let crate_def_map = db.crate_def_map(krate);
-        impls.collect_def_map(db, &crate_def_map);
+        let crate_def_map = crate_def_map(db, krate);
+        impls.collect_def_map(db, crate_def_map);
         impls.shrink_to_fit();
 
         Arc::new(impls)
@@ -294,8 +294,8 @@ impl InherentImpls {
         let _p = tracing::info_span!("inherent_impls_in_block_query").entered();
         let mut impls = Self { map: FxHashMap::default(), invalid_impls: Vec::default() };
 
-        let block_def_map = db.block_def_map(block);
-        impls.collect_def_map(db, &block_def_map);
+        let block_def_map = block_def_map(db, block);
+        impls.collect_def_map(db, block_def_map);
         impls.shrink_to_fit();
 
         if impls.map.is_empty() && impls.invalid_impls.is_empty() {
@@ -337,7 +337,7 @@ impl InherentImpls {
             for konst in module_data.scope.unnamed_consts() {
                 let body = db.body(konst.into());
                 for (_, block_def_map) in body.blocks(db) {
-                    self.collect_def_map(db, &block_def_map);
+                    self.collect_def_map(db, block_def_map);
                 }
             }
         }
@@ -1399,7 +1399,7 @@ fn iterate_inherent_methods(
             )?;
         }
 
-        block = db.block_def_map(block_id).parent().and_then(|module| module.containing_block());
+        block = block_def_map(db, block_id).parent().and_then(|module| module.containing_block());
     }
 
     for krate in def_crates {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index 26ef95d264b..7cf948b178e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -5,6 +5,7 @@ use std::cmp::{self, Ordering};
 
 use chalk_ir::TyKind;
 use hir_def::{
+    CrateRootModuleId,
     builtin_type::{BuiltinInt, BuiltinUint},
     resolver::HasResolver,
 };
@@ -153,7 +154,7 @@ impl Evaluator<'_> {
     ) -> Result<Option<FunctionId>> {
         // `PanicFmt` is redirected to `ConstPanicFmt`
         if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
-            let resolver = self.db.crate_def_map(self.crate_id).crate_root().resolver(self.db);
+            let resolver = CrateRootModuleId::from(self.crate_id).resolver(self.db);
 
             let Some(const_panic_fmt) =
                 LangItem::ConstPanicFmt.resolve_function(self.db, resolver.krate())
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 7b48b15d9ea..7fcc89e5183 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
@@ -68,16 +68,16 @@ struct DropScope {
     locals: Vec<LocalId>,
 }
 
-struct MirLowerCtx<'a> {
+struct MirLowerCtx<'db> {
     result: MirBody,
     owner: DefWithBodyId,
     current_loop_blocks: Option<LoopBlocks>,
     labeled_loop_blocks: FxHashMap<LabelId, LoopBlocks>,
     discr_temp: Option<Place>,
-    db: &'a dyn HirDatabase,
-    body: &'a Body,
-    infer: &'a InferenceResult,
-    resolver: Resolver,
+    db: &'db dyn HirDatabase,
+    body: &'db Body,
+    infer: &'db InferenceResult,
+    resolver: Resolver<'db>,
     drop_scopes: Vec<DropScope>,
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
index bcd8aa6c4e9..8f0d17c9dc4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/test_db.rs
@@ -7,7 +7,7 @@ use base_db::{
     SourceRoot, SourceRootId, SourceRootInput,
 };
 
-use hir_def::{ModuleId, db::DefDatabase};
+use hir_def::{ModuleId, db::DefDatabase, nameres::crate_def_map};
 use hir_expand::EditionedFileId;
 use rustc_hash::FxHashMap;
 use salsa::{AsDynDatabase, Durability};
@@ -118,7 +118,7 @@ impl TestDB {
     pub(crate) fn module_for_file_opt(&self, file_id: impl Into<FileId>) -> Option<ModuleId> {
         let file_id = file_id.into();
         for &krate in self.relevant_crates(file_id).iter() {
-            let crate_def_map = self.crate_def_map(krate);
+            let crate_def_map = crate_def_map(self, krate);
             for (local_id, data) in crate_def_map.modules() {
                 if data.origin.file_id().map(|file_id| file_id.file_id(self)) == Some(file_id) {
                     return Some(crate_def_map.module_id(local_id));
@@ -137,7 +137,7 @@ impl TestDB {
     ) -> FxHashMap<EditionedFileId, Vec<(TextRange, String)>> {
         let mut files = Vec::new();
         for &krate in self.all_crates().iter() {
-            let crate_def_map = self.crate_def_map(krate);
+            let crate_def_map = crate_def_map(self, krate);
             for (module_id, _) in crate_def_map.modules() {
                 let file_id = crate_def_map[module_id].origin.file_id();
                 files.extend(file_id)
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 cc37f65c26c..2b75bd6f160 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
@@ -132,7 +132,7 @@ fn check_impl(
             None => continue,
         };
         let def_map = module.def_map(&db);
-        visit_module(&db, &def_map, module.local_id, &mut |it| {
+        visit_module(&db, def_map, module.local_id, &mut |it| {
             let def = match it {
                 ModuleDefId::FunctionId(it) => it.into(),
                 ModuleDefId::EnumVariantId(it) => it.into(),
@@ -391,7 +391,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
     let def_map = module.def_map(&db);
 
     let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new();
-    visit_module(&db, &def_map, module.local_id, &mut |it| {
+    visit_module(&db, def_map, module.local_id, &mut |it| {
         let def = match it {
             ModuleDefId::FunctionId(it) => it.into(),
             ModuleDefId::EnumVariantId(it) => it.into(),
@@ -504,7 +504,7 @@ pub(crate) fn visit_module(
     fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(ModuleDefId)) {
         for (_, def_map) in body.blocks(db) {
             for (mod_id, _) in def_map.modules() {
-                visit_module(db, &def_map, mod_id, cb);
+                visit_module(db, def_map, mod_id, cb);
             }
         }
     }
@@ -570,7 +570,7 @@ fn salsa_bug() {
 
     let module = db.module_for_file(pos.file_id.file_id(&db));
     let crate_def_map = module.def_map(&db);
-    visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
+    visit_module(&db, crate_def_map, module.local_id, &mut |def| {
         db.infer(match def {
             ModuleDefId::FunctionId(it) => it.into(),
             ModuleDefId::EnumVariantId(it) => it.into(),
@@ -609,7 +609,7 @@ fn salsa_bug() {
 
     let module = db.module_for_file(pos.file_id.file_id(&db));
     let crate_def_map = module.def_map(&db);
-    visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
+    visit_module(&db, crate_def_map, module.local_id, &mut |def| {
         db.infer(match def {
             ModuleDefId::FunctionId(it) => it.into(),
             ModuleDefId::EnumVariantId(it) => it.into(),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs
index 73f1ae56457..88d21be81ea 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs
@@ -20,7 +20,7 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
     let def_map = module.def_map(&db);
 
     let mut defs = Vec::new();
-    visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it));
+    visit_module(&db, def_map, module.local_id, &mut |it| defs.push(it));
 
     let mut captures_info = Vec::new();
     for def in defs {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
index 0542be0ba89..48474d2d26d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
@@ -19,7 +19,7 @@ fn foo() -> i32 {
         let events = db.log_executed(|| {
             let module = db.module_for_file(pos.file_id.file_id(&db));
             let crate_def_map = module.def_map(&db);
-            visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
+            visit_module(&db, crate_def_map, module.local_id, &mut |def| {
                 if let ModuleDefId::FunctionId(it) = def {
                     db.infer(it.into());
                 }
@@ -41,7 +41,7 @@ fn foo() -> i32 {
         let events = db.log_executed(|| {
             let module = db.module_for_file(pos.file_id.file_id(&db));
             let crate_def_map = module.def_map(&db);
-            visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
+            visit_module(&db, crate_def_map, module.local_id, &mut |def| {
                 if let ModuleDefId::FunctionId(it) = def {
                     db.infer(it.into());
                 }
@@ -70,7 +70,7 @@ fn baz() -> i32 {
         let events = db.log_executed(|| {
             let module = db.module_for_file(pos.file_id.file_id(&db));
             let crate_def_map = module.def_map(&db);
-            visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
+            visit_module(&db, crate_def_map, module.local_id, &mut |def| {
                 if let ModuleDefId::FunctionId(it) = def {
                     db.infer(it.into());
                 }
@@ -97,7 +97,7 @@ fn baz() -> i32 {
         let events = db.log_executed(|| {
             let module = db.module_for_file(pos.file_id.file_id(&db));
             let crate_def_map = module.def_map(&db);
-            visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
+            visit_module(&db, crate_def_map, module.local_id, &mut |def| {
                 if let ModuleDefId::FunctionId(it) = def {
                     db.infer(it.into());
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs
index 446f0b21a2a..ea7a113cae3 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/macros.rs
@@ -1505,6 +1505,10 @@ fn main() {
             !119..120 'o': i32
             293..294 'o': i32
             308..317 'thread_id': usize
+            !314..320 'OffPtr': usize
+            !333..338 'OffFn': usize
+            !354..355 '0': i32
+            !371..382 'MEM_RELEASE': usize
         "#]],
     )
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
index eeebe38f182..cf51671afb2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
@@ -3902,3 +3902,66 @@ fn main() {
         "#]],
     );
 }
+
+#[test]
+fn regression_19734() {
+    check_infer(
+        r#"
+trait Foo {
+    type Gat<'o>;
+}
+
+trait Bar {
+    fn baz() -> <Self::Xyz as Foo::Gat<'_>>;
+}
+
+fn foo<T: Bar>() {
+    T::baz();
+}
+    "#,
+        expect![[r#"
+            110..127 '{     ...z(); }': ()
+            116..122 'T::baz': fn baz<T>() -> <{unknown} as Foo>::Gat<'?>
+            116..124 'T::baz()': Foo::Gat<'?, {unknown}>
+        "#]],
+    );
+}
+
+#[test]
+fn asm_const_label() {
+    check_infer(
+        r#"
+//- minicore: asm
+const fn bar() -> i32 { 123 }
+fn baz(s: &str) {}
+
+fn foo() {
+    unsafe {
+        core::arch::asm!(
+            "mov eax, {}",
+            "jmp {}",
+            const bar(),
+            label {
+                baz("hello");
+            },
+        );
+    }
+}
+    "#,
+        expect![[r#"
+            22..29 '{ 123 }': i32
+            24..27 '123': i32
+            37..38 's': &'? str
+            46..48 '{}': ()
+            !0..68 'builti...");},)': ()
+            !40..43 'bar': fn bar() -> i32
+            !40..45 'bar()': i32
+            !51..66 '{baz("hello");}': ()
+            !52..55 'baz': fn baz(&'? str)
+            !52..64 'baz("hello")': ()
+            !56..63 '"hello"': &'static str
+            59..257 '{     ...   } }': ()
+            65..255 'unsafe...     }': ()
+        "#]],
+    );
+}
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 14137605c9f..2b527a4ae12 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
@@ -4884,3 +4884,22 @@ async fn baz<T: AsyncFnOnce(u32) -> i32>(c: T) {
         "#]],
     );
 }
+
+#[test]
+fn import_trait_items() {
+    check_infer(
+        r#"
+//- minicore: default
+use core::default::Default::default;
+fn main() {
+    let a: i32 = default();
+}
+    "#,
+        expect![[r#"
+            47..78 '{     ...t(); }': ()
+            57..58 'a': i32
+            66..73 'default': {unknown}
+            66..75 'default()': i32
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
index 6e1cd9a310f..d6b43aeed4d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
@@ -984,7 +984,7 @@ struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
         let mut defs: Vec<GenericDefId> = Vec::new();
         let module = db.module_for_file_opt(file_id.file_id(&db)).unwrap();
         let def_map = module.def_map(&db);
-        crate::tests::visit_module(&db, &def_map, module.local_id, &mut |it| {
+        crate::tests::visit_module(&db, def_map, module.local_id, &mut |it| {
             defs.push(match it {
                 ModuleDefId::FunctionId(it) => it.into(),
                 ModuleDefId::AdtId(it) => it.into(),
diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
index b1c478d1bf4..b1cf30b98f5 100644
--- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
@@ -105,11 +105,12 @@ impl HasAttrs for crate::Crate {
 /// Resolves the item `link` points to in the scope of `def`.
 pub fn resolve_doc_path_on(
     db: &dyn HirDatabase,
-    def: impl HasAttrs,
+    def: impl HasAttrs + Copy,
     link: &str,
     ns: Option<Namespace>,
+    is_inner_doc: bool,
 ) -> Option<DocLinkDef> {
-    resolve_doc_path_on_(db, link, def.attr_id(), ns)
+    resolve_doc_path_on_(db, link, def.attr_id(), ns, is_inner_doc)
 }
 
 fn resolve_doc_path_on_(
@@ -117,9 +118,18 @@ fn resolve_doc_path_on_(
     link: &str,
     attr_id: AttrDefId,
     ns: Option<Namespace>,
+    is_inner_doc: bool,
 ) -> Option<DocLinkDef> {
     let resolver = match attr_id {
-        AttrDefId::ModuleId(it) => it.resolver(db),
+        AttrDefId::ModuleId(it) => {
+            if is_inner_doc {
+                it.resolver(db)
+            } else if let Some(parent) = Module::from(it).parent(db) {
+                parent.id.resolver(db)
+            } else {
+                it.resolver(db)
+            }
+        }
         AttrDefId::FieldId(it) => it.parent.resolver(db),
         AttrDefId::AdtId(it) => it.resolver(db),
         AttrDefId::FunctionId(it) => it.resolver(db),
@@ -160,7 +170,7 @@ fn resolve_doc_path_on_(
 
 fn resolve_assoc_or_field(
     db: &dyn HirDatabase,
-    resolver: Resolver,
+    resolver: Resolver<'_>,
     path: ModPath,
     name: Name,
     ns: Option<Namespace>,
@@ -248,7 +258,7 @@ fn resolve_assoc_item(
 
 fn resolve_impl_trait_item(
     db: &dyn HirDatabase,
-    resolver: Resolver,
+    resolver: Resolver<'_>,
     ty: &Type,
     name: &Name,
     ns: Option<Namespace>,
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 3f1d5bb01f2..3a91050d15f 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -97,7 +97,8 @@ pub use crate::{
     diagnostics::*,
     has_source::HasSource,
     semantics::{
-        PathResolution, Semantics, SemanticsImpl, SemanticsScope, TypeInfo, VisibleTraits,
+        PathResolution, PathResolutionPerNs, Semantics, SemanticsImpl, SemanticsScope, TypeInfo,
+        VisibleTraits,
     },
 };
 
@@ -119,7 +120,7 @@ pub use {
         find_path::PrefixKind,
         import_map,
         lang_item::LangItem,
-        nameres::{DefMap, ModuleSource},
+        nameres::{DefMap, ModuleSource, crate_def_map},
         per_ns::Namespace,
         type_ref::{Mutability, TypeRef},
         visibility::Visibility,
@@ -227,7 +228,7 @@ impl Crate {
     }
 
     pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
-        let def_map = db.crate_def_map(self.id);
+        let def_map = crate_def_map(db, self.id);
         def_map.modules().map(|(id, _)| def_map.module_id(id).into()).collect()
     }
 
@@ -528,7 +529,7 @@ impl Module {
     /// might be missing `krate`. This can happen if a module's file is not included
     /// in the module tree of any target in `Cargo.toml`.
     pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
-        let def_map = db.crate_def_map(self.id.krate());
+        let def_map = crate_def_map(db, self.id.krate());
         Module { id: def_map.crate_root().into() }
     }
 
@@ -2468,7 +2469,7 @@ impl Function {
         {
             return None;
         }
-        let def_map = db.crate_def_map(HasModule::krate(&self.id, db));
+        let def_map = crate_def_map(db, HasModule::krate(&self.id, db));
         def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() })
     }
 
@@ -4015,8 +4016,7 @@ impl BuiltinAttr {
         if let builtin @ Some(_) = Self::builtin(name) {
             return builtin;
         }
-        let idx = db
-            .crate_def_map(krate.id)
+        let idx = crate_def_map(db, krate.id)
             .registered_attrs()
             .iter()
             .position(|it| it.as_str() == name)? as u32;
@@ -4031,7 +4031,7 @@ impl BuiltinAttr {
     pub fn name(&self, db: &dyn HirDatabase) -> Name {
         match self.krate {
             Some(krate) => Name::new_symbol_root(
-                db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(),
+                crate_def_map(db, krate).registered_attrs()[self.idx as usize].clone(),
             ),
             None => Name::new_symbol_root(Symbol::intern(
                 hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name,
@@ -4059,14 +4059,14 @@ impl ToolModule {
     pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
         let krate = krate.id;
         let idx =
-            db.crate_def_map(krate).registered_tools().iter().position(|it| it.as_str() == name)?
+            crate_def_map(db, krate).registered_tools().iter().position(|it| it.as_str() == name)?
                 as u32;
         Some(ToolModule { krate, idx })
     }
 
     pub fn name(&self, db: &dyn HirDatabase) -> Name {
         Name::new_symbol_root(
-            db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone(),
+            crate_def_map(db, self.krate).registered_tools()[self.idx as usize].clone(),
         )
     }
 
@@ -4488,7 +4488,7 @@ impl Impl {
             MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
                 let module_id = self.id.lookup(db).container;
                 (
-                    db.crate_def_map(module_id.krate())[module_id.local_id]
+                    crate_def_map(db, module_id.krate())[module_id.local_id]
                         .scope
                         .derive_macro_invoc(ast_id, derive_attr_index)?,
                     derive_index,
@@ -4530,7 +4530,7 @@ pub struct TraitRef {
 impl TraitRef {
     pub(crate) fn new_with_resolver(
         db: &dyn HirDatabase,
-        resolver: &Resolver,
+        resolver: &Resolver<'_>,
         trait_ref: hir_ty::TraitRef,
     ) -> TraitRef {
         let env = resolver
@@ -4752,13 +4752,13 @@ pub struct Type {
 }
 
 impl Type {
-    pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver, ty: Ty) -> Type {
+    pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver<'_>, ty: Ty) -> Type {
         Type::new_with_resolver_inner(db, resolver, ty)
     }
 
     pub(crate) fn new_with_resolver_inner(
         db: &dyn HirDatabase,
-        resolver: &Resolver,
+        resolver: &Resolver<'_>,
         ty: Ty,
     ) -> Type {
         let environment = resolver
@@ -6400,7 +6400,7 @@ pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>(
                 })
                 .filter_map(|&krate| {
                     let segments = segments.clone();
-                    let mut def_map = db.crate_def_map(krate);
+                    let mut def_map = crate_def_map(db, krate);
                     let mut module = &def_map[DefMap::ROOT];
                     let mut segments = segments.with_position().peekable();
                     while let Some((_, segment)) = segments.next_if(|&(position, _)| {
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 4d092c1f0bb..caa6700de9f 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -15,7 +15,7 @@ use hir_def::{
     DefWithBodyId, FunctionId, MacroId, StructId, TraitId, VariantId,
     expr_store::{Body, ExprOrPatSource, path::Path},
     hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat},
-    nameres::ModuleOrigin,
+    nameres::{ModuleOrigin, crate_def_map},
     resolver::{self, HasResolver, Resolver, TypeNs},
     type_ref::Mutability,
 };
@@ -103,6 +103,26 @@ impl PathResolution {
     }
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct PathResolutionPerNs {
+    pub type_ns: Option<PathResolution>,
+    pub value_ns: Option<PathResolution>,
+    pub macro_ns: Option<PathResolution>,
+}
+
+impl PathResolutionPerNs {
+    pub fn new(
+        type_ns: Option<PathResolution>,
+        value_ns: Option<PathResolution>,
+        macro_ns: Option<PathResolution>,
+    ) -> Self {
+        PathResolutionPerNs { type_ns, value_ns, macro_ns }
+    }
+    pub fn any(&self) -> Option<PathResolution> {
+        self.type_ns.or(self.value_ns).or(self.macro_ns)
+    }
+}
+
 #[derive(Debug)]
 pub struct TypeInfo {
     /// The original type of the expression or pattern.
@@ -341,7 +361,7 @@ impl<'db> SemanticsImpl<'db> {
         match file_id {
             HirFileId::FileId(file_id) => {
                 let module = self.file_to_module_defs(file_id.file_id(self.db)).next()?;
-                let def_map = self.db.crate_def_map(module.krate().id);
+                let def_map = crate_def_map(self.db, module.krate().id);
                 match def_map[module.id.local_id].origin {
                     ModuleOrigin::CrateRoot { .. } => None,
                     ModuleOrigin::File { declaration, declaration_tree_id, .. } => {
@@ -1606,6 +1626,10 @@ impl<'db> SemanticsImpl<'db> {
         self.resolve_path_with_subst(path).map(|(it, _)| it)
     }
 
+    pub fn resolve_path_per_ns(&self, path: &ast::Path) -> Option<PathResolutionPerNs> {
+        self.analyze(path.syntax())?.resolve_hir_path_per_ns(self.db, path)
+    }
+
     pub fn resolve_path_with_subst(
         &self,
         path: &ast::Path,
@@ -1711,13 +1735,13 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     /// Returns none if the file of the node is not part of a crate.
-    fn analyze(&self, node: &SyntaxNode) -> Option<SourceAnalyzer> {
+    fn analyze(&self, node: &SyntaxNode) -> Option<SourceAnalyzer<'db>> {
         let node = self.find_file(node);
         self.analyze_impl(node, None, true)
     }
 
     /// Returns none if the file of the node is not part of a crate.
-    fn analyze_no_infer(&self, node: &SyntaxNode) -> Option<SourceAnalyzer> {
+    fn analyze_no_infer(&self, node: &SyntaxNode) -> Option<SourceAnalyzer<'db>> {
         let node = self.find_file(node);
         self.analyze_impl(node, None, false)
     }
@@ -1726,7 +1750,7 @@ impl<'db> SemanticsImpl<'db> {
         &self,
         node: &SyntaxNode,
         offset: TextSize,
-    ) -> Option<SourceAnalyzer> {
+    ) -> Option<SourceAnalyzer<'db>> {
         let node = self.find_file(node);
         self.analyze_impl(node, Some(offset), false)
     }
@@ -1737,7 +1761,7 @@ impl<'db> SemanticsImpl<'db> {
         offset: Option<TextSize>,
         // replace this, just make the inference result a `LazyCell`
         infer_body: bool,
-    ) -> Option<SourceAnalyzer> {
+    ) -> Option<SourceAnalyzer<'db>> {
         let _p = tracing::info_span!("SemanticsImpl::analyze_impl").entered();
 
         let container = self.with_ctx(|ctx| ctx.find_container(node))?;
@@ -1984,13 +2008,13 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode {
 /// Note that if you are wondering "what does this specific existing name mean?",
 /// you'd better use the `resolve_` family of methods.
 #[derive(Debug)]
-pub struct SemanticsScope<'a> {
-    pub db: &'a dyn HirDatabase,
+pub struct SemanticsScope<'db> {
+    pub db: &'db dyn HirDatabase,
     file_id: HirFileId,
-    resolver: Resolver,
+    resolver: Resolver<'db>,
 }
 
-impl SemanticsScope<'_> {
+impl<'db> SemanticsScope<'db> {
     pub fn module(&self) -> Module {
         Module { id: self.resolver.module() }
     }
@@ -2006,7 +2030,7 @@ impl SemanticsScope<'_> {
         })
     }
 
-    pub(crate) fn resolver(&self) -> &Resolver {
+    pub(crate) fn resolver(&self) -> &Resolver<'db> {
         &self.resolver
     }
 
@@ -2133,7 +2157,7 @@ impl ops::Deref for VisibleTraits {
 struct RenameConflictsVisitor<'a> {
     db: &'a dyn HirDatabase,
     owner: DefWithBodyId,
-    resolver: Resolver,
+    resolver: Resolver<'a>,
     body: &'a Body,
     to_be_renamed: BindingId,
     new_name: Symbol,
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index 587c51d8cc9..172af456d92 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -96,6 +96,7 @@ use hir_def::{
         keys::{self, Key},
     },
     hir::{BindingId, Expr, LabelId},
+    nameres::{block_def_map, crate_def_map},
 };
 use hir_expand::{
     EditionedFileId, ExpansionInfo, HirFileId, InMacroFile, MacroCallId, attrs::AttrId,
@@ -180,7 +181,7 @@ impl SourceToDefCtx<'_, '_> {
 
             for &crate_id in self.db.relevant_crates(file).iter() {
                 // Note: `mod` declarations in block modules cannot be supported here
-                let crate_def_map = self.db.crate_def_map(crate_id);
+                let crate_def_map = crate_def_map(self.db, crate_id);
                 let n_mods = mods.len();
                 let modules = |file| {
                     crate_def_map
@@ -226,7 +227,7 @@ impl SourceToDefCtx<'_, '_> {
         let parent_module = match parent_declaration {
             Some(Either::Right(parent_block)) => self
                 .block_to_def(parent_block.as_ref())
-                .map(|block| self.db.block_def_map(block).root_module_id()),
+                .map(|block| block_def_map(self.db, block).root_module_id()),
             Some(Either::Left(parent_declaration)) => {
                 self.module_to_def(parent_declaration.as_ref())
             }
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 c1a75ce7e57..ea21546f9d7 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -10,7 +10,9 @@ use std::iter::{self, once};
 use crate::{
     Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field,
     Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait,
-    TraitAlias, TupleField, Type, TypeAlias, Variant, db::HirDatabase, semantics::PathResolution,
+    TraitAlias, TupleField, Type, TypeAlias, Variant,
+    db::HirDatabase,
+    semantics::{PathResolution, PathResolutionPerNs},
 };
 use either::Either;
 use hir_def::{
@@ -24,7 +26,7 @@ use hir_def::{
     },
     hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat},
     lang_item::LangItem,
-    nameres::MacroSubNs,
+    nameres::{MacroSubNs, crate_def_map},
     resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope},
     type_ref::{Mutability, TypeRefId},
 };
@@ -57,9 +59,9 @@ use triomphe::Arc;
 /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
 /// original source files. It should not be used inside the HIR itself.
 #[derive(Debug)]
-pub(crate) struct SourceAnalyzer {
+pub(crate) struct SourceAnalyzer<'db> {
     pub(crate) file_id: HirFileId,
-    pub(crate) resolver: Resolver,
+    pub(crate) resolver: Resolver<'db>,
     pub(crate) body_or_sig: Option<BodyOrSig>,
 }
 
@@ -85,32 +87,32 @@ pub(crate) enum BodyOrSig {
     },
 }
 
-impl SourceAnalyzer {
+impl<'db> SourceAnalyzer<'db> {
     pub(crate) fn new_for_body(
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         def: DefWithBodyId,
         node: InFile<&SyntaxNode>,
         offset: Option<TextSize>,
-    ) -> SourceAnalyzer {
+    ) -> SourceAnalyzer<'db> {
         Self::new_for_body_(db, def, node, offset, Some(db.infer(def)))
     }
 
     pub(crate) fn new_for_body_no_infer(
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         def: DefWithBodyId,
         node: InFile<&SyntaxNode>,
         offset: Option<TextSize>,
-    ) -> SourceAnalyzer {
+    ) -> SourceAnalyzer<'db> {
         Self::new_for_body_(db, def, node, offset, None)
     }
 
     pub(crate) fn new_for_body_(
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         def: DefWithBodyId,
         node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
         offset: Option<TextSize>,
         infer: Option<Arc<InferenceResult>>,
-    ) -> SourceAnalyzer {
+    ) -> SourceAnalyzer<'db> {
         let (body, source_map) = db.body_with_source_map(def);
         let scopes = db.expr_scopes(def);
         let scope = match offset {
@@ -134,11 +136,11 @@ impl SourceAnalyzer {
     }
 
     pub(crate) fn new_generic_def(
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         def: GenericDefId,
         InFile { file_id, .. }: InFile<&SyntaxNode>,
         _offset: Option<TextSize>,
-    ) -> SourceAnalyzer {
+    ) -> SourceAnalyzer<'db> {
         let (_params, store, source_map) = db.generic_params_and_store_and_source_map(def);
         let resolver = def.resolver(db);
         SourceAnalyzer {
@@ -149,11 +151,11 @@ impl SourceAnalyzer {
     }
 
     pub(crate) fn new_variant_body(
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         def: VariantId,
         InFile { file_id, .. }: InFile<&SyntaxNode>,
         _offset: Option<TextSize>,
-    ) -> SourceAnalyzer {
+    ) -> SourceAnalyzer<'db> {
         let (fields, source_map) = db.variant_fields_with_source_map(def);
         let resolver = def.resolver(db);
         SourceAnalyzer {
@@ -168,9 +170,9 @@ impl SourceAnalyzer {
     }
 
     pub(crate) fn new_for_resolver(
-        resolver: Resolver,
+        resolver: Resolver<'db>,
         node: InFile<&SyntaxNode>,
-    ) -> SourceAnalyzer {
+    ) -> SourceAnalyzer<'db> {
         SourceAnalyzer { resolver, body_or_sig: None, file_id: node.file_id }
     }
 
@@ -220,7 +222,7 @@ impl SourceAnalyzer {
         self.store_sm()?.expansion(node)
     }
 
-    fn trait_environment(&self, db: &dyn HirDatabase) -> Arc<TraitEnvironment> {
+    fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc<TraitEnvironment> {
         self.body_().map(|(def, ..)| def).map_or_else(
             || TraitEnvironment::empty(self.resolver.krate()),
             |def| db.trait_environment_for_body(def),
@@ -259,7 +261,7 @@ impl SourceAnalyzer {
         infer.expr_adjustments.get(&expr_id).map(|v| &**v)
     }
 
-    pub(crate) fn type_of_type(&self, db: &dyn HirDatabase, ty: &ast::Type) -> Option<Type> {
+    pub(crate) fn type_of_type(&self, db: &'db dyn HirDatabase, ty: &ast::Type) -> Option<Type> {
         let type_ref = self.type_id(ty)?;
         let ty = TyLoweringContext::new(
             db,
@@ -277,7 +279,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn type_of_expr(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         expr: &ast::Expr,
     ) -> Option<(Type, Option<Type>)> {
         let expr_id = self.expr_id(expr.clone())?;
@@ -293,7 +295,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn type_of_pat(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         pat: &ast::Pat,
     ) -> Option<(Type, Option<Type>)> {
         let expr_or_pat_id = self.pat_id(pat)?;
@@ -316,7 +318,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn type_of_binding_in_pat(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         pat: &ast::IdentPat,
     ) -> Option<Type> {
         let binding_id = self.binding_id_of_pat(pat)?;
@@ -328,7 +330,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn type_of_self(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         _param: &ast::SelfParam,
     ) -> Option<Type> {
         let binding = self.body()?.self_param?;
@@ -338,7 +340,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn binding_mode_of_pat(
         &self,
-        _db: &dyn HirDatabase,
+        _db: &'db dyn HirDatabase,
         pat: &ast::IdentPat,
     ) -> Option<BindingMode> {
         let id = self.pat_id(&pat.clone().into())?;
@@ -353,7 +355,7 @@ impl SourceAnalyzer {
     }
     pub(crate) fn pattern_adjustments(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         pat: &ast::Pat,
     ) -> Option<SmallVec<[Type; 1]>> {
         let pat_id = self.pat_id(pat)?;
@@ -370,7 +372,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_method_call_as_callable(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         call: &ast::MethodCallExpr,
     ) -> Option<Callable> {
         let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
@@ -384,7 +386,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_method_call(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         call: &ast::MethodCallExpr,
     ) -> Option<Function> {
         let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
@@ -395,7 +397,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_method_call_fallback(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         call: &ast::MethodCallExpr,
     ) -> Option<(Either<Function, Field>, Option<GenericSubstitution>)> {
         let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
@@ -419,7 +421,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_expr_as_callable(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         call: &ast::Expr,
     ) -> Option<Callable> {
         let (orig, adjusted) = self.type_of_expr(db, &call.clone())?;
@@ -441,7 +443,7 @@ impl SourceAnalyzer {
         &self,
         field_expr: ExprId,
         infer: &InferenceResult,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
     ) -> Option<GenericSubstitution> {
         let body = self.store()?;
         if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] {
@@ -457,7 +459,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_field_fallback(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         field: &ast::FieldExpr,
     ) -> Option<(Either<Either<Field, TupleField>, Function>, Option<GenericSubstitution>)> {
         let (def, ..) = self.body_()?;
@@ -490,7 +492,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_range_pat(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         range_pat: &ast::RangePat,
     ) -> Option<StructId> {
         let path: ModPath = match (range_pat.op_kind()?, range_pat.start(), range_pat.end()) {
@@ -509,7 +511,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_range_expr(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         range_expr: &ast::RangeExpr,
     ) -> Option<StructId> {
         let path: ModPath = match (range_expr.op_kind()?, range_expr.start(), range_expr.end()) {
@@ -529,7 +531,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_await_to_poll(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         await_expr: &ast::AwaitExpr,
     ) -> Option<FunctionId> {
         let mut ty = self.ty_of_expr(await_expr.expr()?)?.clone();
@@ -566,7 +568,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_prefix_expr(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         prefix_expr: &ast::PrefixExpr,
     ) -> Option<FunctionId> {
         let (op_trait, op_fn) = match prefix_expr.op_kind()? {
@@ -608,7 +610,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_index_expr(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         index_expr: &ast::IndexExpr,
     ) -> Option<FunctionId> {
         let base_ty = self.ty_of_expr(index_expr.base()?)?;
@@ -640,7 +642,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_bin_expr(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         binop_expr: &ast::BinExpr,
     ) -> Option<FunctionId> {
         let op = binop_expr.op_kind()?;
@@ -661,7 +663,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_try_expr(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         try_expr: &ast::TryExpr,
     ) -> Option<FunctionId> {
         let ty = self.ty_of_expr(try_expr.expr()?)?;
@@ -680,7 +682,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_record_field(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         field: &ast::RecordExprField,
     ) -> Option<(Field, Option<Local>, Type, GenericSubstitution)> {
         let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
@@ -724,7 +726,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_record_pat_field(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         field: &ast::RecordPatField,
     ) -> Option<(Field, Type, GenericSubstitution)> {
         let field_name = field.field_name()?.as_name();
@@ -745,14 +747,14 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_macro_call(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         macro_call: InFile<&ast::MacroCall>,
     ) -> Option<Macro> {
         let bs = self.store_sm()?;
         bs.expansion(macro_call).and_then(|it| {
             // FIXME: Block def maps
             let def = it.lookup(db).def;
-            db.crate_def_map(def.krate)
+            crate_def_map(db, def.krate)
                 .macro_def_to_macro_id
                 .get(&def.kind.erased_ast_id())
                 .map(|it| (*it).into())
@@ -761,7 +763,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_bind_pat_to_const(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         pat: &ast::IdentPat,
     ) -> Option<ModuleDef> {
         let expr_or_pat_id = self.pat_id(&pat.clone().into())?;
@@ -795,7 +797,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_offset_of_field(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         name_ref: &ast::NameRef,
     ) -> Option<(Either<crate::Variant, crate::Field>, GenericSubstitution)> {
         let offset_of_expr = ast::OffsetOfExpr::cast(name_ref.syntax().parent()?)?;
@@ -867,7 +869,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_path(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         path: &ast::Path,
     ) -> Option<(PathResolution, Option<GenericSubstitution>)> {
         let parent = path.syntax().parent();
@@ -1159,7 +1161,9 @@ impl SourceAnalyzer {
                 prefer_value_ns,
                 name_hygiene(db, InFile::new(self.file_id, path.syntax())),
                 Some(&store),
-            )?;
+                false,
+            )
+            .any()?;
             let subst = (|| {
                 let parent = parent()?;
                 let ty = if let Some(expr) = ast::Expr::cast(parent.clone()) {
@@ -1209,9 +1213,29 @@ impl SourceAnalyzer {
         }
     }
 
-    pub(crate) fn record_literal_missing_fields(
+    pub(crate) fn resolve_hir_path_per_ns(
         &self,
         db: &dyn HirDatabase,
+        path: &ast::Path,
+    ) -> Option<PathResolutionPerNs> {
+        let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
+        let hir_path =
+            collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
+        let store = collector.store.finish();
+        Some(resolve_hir_path_(
+            db,
+            &self.resolver,
+            &hir_path,
+            false,
+            name_hygiene(db, InFile::new(self.file_id, path.syntax())),
+            Some(&store),
+            true,
+        ))
+    }
+
+    pub(crate) fn record_literal_missing_fields(
+        &self,
+        db: &'db dyn HirDatabase,
         literal: &ast::RecordExpr,
     ) -> Option<Vec<(Field, Type)>> {
         let body = self.store()?;
@@ -1234,7 +1258,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn record_pattern_missing_fields(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         pattern: &ast::RecordPat,
     ) -> Option<Vec<(Field, Type)>> {
         let body = self.store()?;
@@ -1251,7 +1275,7 @@ impl SourceAnalyzer {
 
     fn missing_fields(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         substs: &Substitution,
         variant: VariantId,
         missing_fields: Vec<LocalFieldId>,
@@ -1270,7 +1294,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn expand(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         macro_call: InFile<&ast::MacroCall>,
     ) -> Option<MacroCallId> {
         self.store_sm().and_then(|bs| bs.expansion(macro_call)).or_else(|| {
@@ -1288,7 +1312,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn is_unsafe_macro_call_expr(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         macro_expr: InFile<&ast::MacroExpr>,
     ) -> bool {
         if let Some((def, body, sm, Some(infer))) = self.body_() {
@@ -1313,7 +1337,7 @@ impl SourceAnalyzer {
 
     pub(crate) fn resolve_offset_in_format_args(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         format_args: InFile<&ast::FormatArgsExpr>,
         offset: TextSize,
     ) -> Option<(TextRange, Option<PathResolution>)> {
@@ -1384,7 +1408,7 @@ impl SourceAnalyzer {
 
     fn resolve_impl_method_or_trait_def(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         func: FunctionId,
         substs: Substitution,
     ) -> FunctionId {
@@ -1393,7 +1417,7 @@ impl SourceAnalyzer {
 
     fn resolve_impl_method_or_trait_def_with_subst(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         func: FunctionId,
         substs: Substitution,
     ) -> (FunctionId, Substitution) {
@@ -1407,7 +1431,7 @@ impl SourceAnalyzer {
 
     fn resolve_impl_const_or_trait_def_with_subst(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         const_id: ConstId,
         subs: Substitution,
     ) -> (ConstId, Substitution) {
@@ -1421,7 +1445,7 @@ impl SourceAnalyzer {
 
     fn lang_trait_fn(
         &self,
-        db: &dyn HirDatabase,
+        db: &'db dyn HirDatabase,
         lang_trait: LangItem,
         method_name: &Name,
     ) -> Option<(TraitId, FunctionId)> {
@@ -1527,18 +1551,18 @@ fn adjust(
 #[inline]
 pub(crate) fn resolve_hir_path(
     db: &dyn HirDatabase,
-    resolver: &Resolver,
+    resolver: &Resolver<'_>,
     path: &Path,
     hygiene: HygieneId,
     store: Option<&ExpressionStore>,
 ) -> Option<PathResolution> {
-    resolve_hir_path_(db, resolver, path, false, hygiene, store)
+    resolve_hir_path_(db, resolver, path, false, hygiene, store, false).any()
 }
 
 #[inline]
 pub(crate) fn resolve_hir_path_as_attr_macro(
     db: &dyn HirDatabase,
-    resolver: &Resolver,
+    resolver: &Resolver<'_>,
     path: &Path,
 ) -> Option<Macro> {
     resolver
@@ -1549,12 +1573,13 @@ pub(crate) fn resolve_hir_path_as_attr_macro(
 
 fn resolve_hir_path_(
     db: &dyn HirDatabase,
-    resolver: &Resolver,
+    resolver: &Resolver<'_>,
     path: &Path,
     prefer_value_ns: bool,
     hygiene: HygieneId,
     store: Option<&ExpressionStore>,
-) -> Option<PathResolution> {
+    resolve_per_ns: bool,
+) -> PathResolutionPerNs {
     let types = || {
         let (ty, unresolved) = match path.type_anchor() {
             Some(type_ref) => resolver.generic_def().and_then(|def| {
@@ -1635,14 +1660,36 @@ fn resolve_hir_path_(
             .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into())))
     };
 
-    if prefer_value_ns { values().or_else(types) } else { types().or_else(values) }
-        .or_else(items)
-        .or_else(macros)
+    if resolve_per_ns {
+        PathResolutionPerNs {
+            type_ns: types().or_else(items),
+            value_ns: values(),
+            macro_ns: macros(),
+        }
+    } else {
+        let res = if prefer_value_ns {
+            values()
+                .map(|value_ns| PathResolutionPerNs::new(None, Some(value_ns), None))
+                .unwrap_or_else(|| PathResolutionPerNs::new(types(), None, None))
+        } else {
+            types()
+                .map(|type_ns| PathResolutionPerNs::new(Some(type_ns), None, None))
+                .unwrap_or_else(|| PathResolutionPerNs::new(None, values(), None))
+        };
+
+        if res.any().is_some() {
+            res
+        } else if let Some(type_ns) = items() {
+            PathResolutionPerNs::new(Some(type_ns), None, None)
+        } else {
+            PathResolutionPerNs::new(None, None, macros())
+        }
+    }
 }
 
 fn resolve_hir_value_path(
     db: &dyn HirDatabase,
-    resolver: &Resolver,
+    resolver: &Resolver<'_>,
     body_owner: Option<DefWithBodyId>,
     path: &Path,
     hygiene: HygieneId,
@@ -1680,7 +1727,7 @@ fn resolve_hir_value_path(
 /// then we know that `foo` in `my::foo::Bar` refers to the module, not the function.
 fn resolve_hir_path_qualifier(
     db: &dyn HirDatabase,
-    resolver: &Resolver,
+    resolver: &Resolver<'_>,
     path: &Path,
     store: &ExpressionStore,
 ) -> Option<PathResolution> {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs
index 7e8735bd7a2..a9df6f6fc36 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs
@@ -1,3 +1,4 @@
+use either::Either;
 use syntax::{
     ast::{
         self, AstNode, HasName, HasTypeBounds,
@@ -30,10 +31,11 @@ pub(crate) fn move_bounds_to_where_clause(
 ) -> Option<()> {
     let type_param_list = ctx.find_node_at_offset::<ast::GenericParamList>()?;
 
-    let mut type_params = type_param_list.type_or_const_params();
+    let mut type_params = type_param_list.generic_params();
     if type_params.all(|p| match p {
-        ast::TypeOrConstParam::Type(t) => t.type_bound_list().is_none(),
-        ast::TypeOrConstParam::Const(_) => true,
+        ast::GenericParam::TypeParam(t) => t.type_bound_list().is_none(),
+        ast::GenericParam::LifetimeParam(l) => l.type_bound_list().is_none(),
+        ast::GenericParam::ConstParam(_) => true,
     }) {
         return None;
     }
@@ -53,20 +55,23 @@ pub(crate) fn move_bounds_to_where_clause(
                 match parent {
                     ast::Fn(it) => it.get_or_create_where_clause(),
                     ast::Trait(it) => it.get_or_create_where_clause(),
+                    ast::TraitAlias(it) => it.get_or_create_where_clause(),
                     ast::Impl(it) => it.get_or_create_where_clause(),
                     ast::Enum(it) => it.get_or_create_where_clause(),
                     ast::Struct(it) => it.get_or_create_where_clause(),
+                    ast::TypeAlias(it) => it.get_or_create_where_clause(),
                     _ => return,
                 }
             };
 
-            for toc_param in type_param_list.type_or_const_params() {
-                let type_param = match toc_param {
-                    ast::TypeOrConstParam::Type(x) => x,
-                    ast::TypeOrConstParam::Const(_) => continue,
+            for generic_param in type_param_list.generic_params() {
+                let param: &dyn HasTypeBounds = match &generic_param {
+                    ast::GenericParam::TypeParam(t) => t,
+                    ast::GenericParam::LifetimeParam(l) => l,
+                    ast::GenericParam::ConstParam(_) => continue,
                 };
-                if let Some(tbl) = type_param.type_bound_list() {
-                    if let Some(predicate) = build_predicate(type_param) {
+                if let Some(tbl) = param.type_bound_list() {
+                    if let Some(predicate) = build_predicate(generic_param) {
                         where_clause.add_predicate(predicate)
                     }
                     tbl.remove()
@@ -76,9 +81,23 @@ pub(crate) fn move_bounds_to_where_clause(
     )
 }
 
-fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> {
-    let path = make::ext::ident_path(&param.name()?.syntax().to_string());
-    let predicate = make::where_pred(make::ty_path(path), param.type_bound_list()?.bounds());
+fn build_predicate(param: ast::GenericParam) -> Option<ast::WherePred> {
+    let target = match &param {
+        ast::GenericParam::TypeParam(t) => {
+            Either::Right(make::ty_path(make::ext::ident_path(&t.name()?.to_string())))
+        }
+        ast::GenericParam::LifetimeParam(l) => Either::Left(l.lifetime()?),
+        ast::GenericParam::ConstParam(_) => return None,
+    };
+    let predicate = make::where_pred(
+        target,
+        match param {
+            ast::GenericParam::TypeParam(t) => t.type_bound_list()?,
+            ast::GenericParam::LifetimeParam(l) => l.type_bound_list()?,
+            ast::GenericParam::ConstParam(_) => return None,
+        }
+        .bounds(),
+    );
     Some(predicate.clone_for_update())
 }
 
@@ -123,4 +142,13 @@ mod tests {
             r#"struct Pair<T>(T, T) where T: u32;"#,
         );
     }
+
+    #[test]
+    fn move_bounds_to_where_clause_trait() {
+        check_assist(
+            move_bounds_to_where_clause,
+            r#"trait T<'a: 'static, $0T: u32> {}"#,
+            r#"trait T<'a, T> where 'a: 'static, T: u32 {}"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs
index 1baf814ca68..16debc4d728 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs
@@ -1,6 +1,9 @@
 use std::collections::hash_map::Entry;
 
-use hir::{FileRange, InFile, InRealFile, Module, ModuleSource};
+use hir::{
+    FileRange, InFile, InRealFile, Module, ModuleDef, ModuleSource, PathResolution,
+    PathResolutionPerNs,
+};
 use ide_db::text_edit::TextRange;
 use ide_db::{
     FxHashMap, RootDatabase,
@@ -77,22 +80,17 @@ pub(crate) fn remove_unused_imports(acc: &mut Assists, ctx: &AssistContext<'_>)
             };
 
             // Get the actual definition associated with this use item.
-            let res = match ctx.sema.resolve_path(&path) {
-                Some(x) => x,
-                None => {
+            let res = match ctx.sema.resolve_path_per_ns(&path) {
+                Some(x) if x.any().is_some() => x,
+                Some(_) | None => {
                     return None;
                 }
             };
 
-            let def = match res {
-                hir::PathResolution::Def(d) => Definition::from(d),
-                _ => return None,
-            };
-
             if u.star_token().is_some() {
                 // Check if any of the children of this module are used
-                let def_mod = match def {
-                    Definition::Module(module) => module,
+                let def_mod = match res.type_ns {
+                    Some(PathResolution::Def(ModuleDef::Module(module))) => module,
                     _ => return None,
                 };
 
@@ -105,21 +103,13 @@ pub(crate) fn remove_unused_imports(acc: &mut Assists, ctx: &AssistContext<'_>)
                     })
                     .any(|d| used_once_in_scope(ctx, d, u.rename(), scope))
                 {
-                    return Some(u);
-                }
-            } else if let Definition::Trait(ref t) = def {
-                // If the trait or any item is used.
-                if !std::iter::once((def, u.rename()))
-                    .chain(t.items(ctx.db()).into_iter().map(|item| (item.into(), None)))
-                    .any(|(d, rename)| used_once_in_scope(ctx, d, rename, scope))
-                {
-                    return Some(u);
+                    Some(u)
+                } else {
+                    None
                 }
-            } else if !used_once_in_scope(ctx, def, u.rename(), scope) {
-                return Some(u);
+            } else {
+                is_path_per_ns_unused_in_scope(ctx, &u, scope, &res).then_some(u)
             }
-
-            None
         })
         .peekable();
 
@@ -141,6 +131,52 @@ pub(crate) fn remove_unused_imports(acc: &mut Assists, ctx: &AssistContext<'_>)
     }
 }
 
+fn is_path_per_ns_unused_in_scope(
+    ctx: &AssistContext<'_>,
+    u: &ast::UseTree,
+    scope: &mut Vec<SearchScope>,
+    path: &PathResolutionPerNs,
+) -> bool {
+    if let Some(PathResolution::Def(ModuleDef::Trait(ref t))) = path.type_ns {
+        if is_trait_unused_in_scope(ctx, u, scope, t) {
+            let path = [path.value_ns, path.macro_ns];
+            is_path_unused_in_scope(ctx, u, scope, &path)
+        } else {
+            false
+        }
+    } else {
+        let path = [path.type_ns, path.value_ns, path.macro_ns];
+        is_path_unused_in_scope(ctx, u, scope, &path)
+    }
+}
+
+fn is_path_unused_in_scope(
+    ctx: &AssistContext<'_>,
+    u: &ast::UseTree,
+    scope: &mut Vec<SearchScope>,
+    path: &[Option<PathResolution>],
+) -> bool {
+    !path
+        .iter()
+        .filter_map(|path| *path)
+        .filter_map(|res| match res {
+            PathResolution::Def(d) => Some(Definition::from(d)),
+            _ => None,
+        })
+        .any(|def| used_once_in_scope(ctx, def, u.rename(), scope))
+}
+
+fn is_trait_unused_in_scope(
+    ctx: &AssistContext<'_>,
+    u: &ast::UseTree,
+    scope: &mut Vec<SearchScope>,
+    t: &hir::Trait,
+) -> bool {
+    !std::iter::once((Definition::Trait(*t), u.rename()))
+        .chain(t.items(ctx.db()).into_iter().map(|item| (item.into(), None)))
+        .any(|(d, rename)| used_once_in_scope(ctx, d, rename, scope))
+}
+
 fn used_once_in_scope(
     ctx: &AssistContext<'_>,
     def: Definition,
@@ -1012,4 +1048,110 @@ fn test(_: Bar) {
 "#,
         );
     }
+
+    #[test]
+    fn test_unused_macro() {
+        check_assist(
+            remove_unused_imports,
+            r#"
+//- /foo.rs crate:foo
+#[macro_export]
+macro_rules! m { () => {} }
+
+//- /main.rs crate:main deps:foo
+use foo::m;$0
+fn main() {}
+"#,
+            r#"
+fn main() {}
+"#,
+        );
+
+        check_assist_not_applicable(
+            remove_unused_imports,
+            r#"
+//- /foo.rs crate:foo
+#[macro_export]
+macro_rules! m { () => {} }
+
+//- /main.rs crate:main deps:foo
+use foo::m;$0
+fn main() {
+    m!();
+}
+"#,
+        );
+
+        check_assist_not_applicable(
+            remove_unused_imports,
+            r#"
+//- /foo.rs crate:foo
+#[macro_export]
+macro_rules! m { () => {} }
+
+//- /bar.rs crate:bar deps:foo
+pub use foo::m;
+fn m() {}
+
+
+//- /main.rs crate:main deps:bar
+use bar::m;$0
+fn main() {
+    m!();
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_conflict_derive_macro() {
+        check_assist_not_applicable(
+            remove_unused_imports,
+            r#"
+//- proc_macros: derive_identity
+//- minicore: derive
+//- /bar.rs crate:bar
+pub use proc_macros::DeriveIdentity;
+pub trait DeriveIdentity {}
+
+//- /main.rs crate:main deps:bar
+$0use bar::DeriveIdentity;$0
+#[derive(DeriveIdentity)]
+struct S;
+"#,
+        );
+
+        check_assist_not_applicable(
+            remove_unused_imports,
+            r#"
+//- proc_macros: derive_identity
+//- minicore: derive
+//- /bar.rs crate:bar
+pub use proc_macros::DeriveIdentity;
+pub fn DeriveIdentity() {}
+
+//- /main.rs crate:main deps:bar
+$0use bar::DeriveIdentity;$0
+#[derive(DeriveIdentity)]
+struct S;
+"#,
+        );
+
+        check_assist_not_applicable(
+            remove_unused_imports,
+            r#"
+//- proc_macros: derive_identity
+//- minicore: derive
+//- /bar.rs crate:bar
+pub use proc_macros::DeriveIdentity;
+pub fn DeriveIdentity() {}
+
+//- /main.rs crate:main deps:bar
+$0use bar::DeriveIdentity;$0
+fn main() {
+    DeriveIdentity();
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_type_to_generic_arg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_type_to_generic_arg.rs
new file mode 100644
index 00000000000..7b5adc1858b
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_type_to_generic_arg.rs
@@ -0,0 +1,156 @@
+use ide_db::assists::AssistId;
+use syntax::{
+    AstNode,
+    ast::{self, GenericArg, HasGenericArgs},
+};
+
+use crate::{AssistContext, Assists};
+
+// Assist: unwrap_type_to_generic_arg
+//
+// This assist unwraps a type into its generic type argument.
+//
+// ```
+// fn foo() -> $0Option<i32> {
+//     todo!()
+// }
+// ```
+// ->
+// ```
+// fn foo() -> i32 {
+//     todo!()
+// }
+// ```
+pub(crate) fn unwrap_type_to_generic_arg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    let path_type = ctx.find_node_at_offset::<ast::PathType>()?;
+    let path = path_type.path()?;
+    let segment = path.segment()?;
+    let args_list = segment.generic_arg_list()?;
+
+    let mut generic_arg = None;
+
+    for arg in args_list.generic_args() {
+        match arg {
+            GenericArg::ConstArg(_) | GenericArg::LifetimeArg(_) => (),
+            GenericArg::TypeArg(arg) if generic_arg.is_none() => {
+                generic_arg = Some(arg);
+            }
+            _ => return None,
+        }
+    }
+
+    let generic_arg = generic_arg?;
+
+    acc.add(
+        AssistId::refactor_extract("unwrap_type_to_generic_arg"),
+        format!("Unwrap type to type argument {generic_arg}"),
+        path_type.syntax().text_range(),
+        |builder| {
+            let mut editor = builder.make_editor(path_type.syntax());
+            editor.replace(path_type.syntax(), generic_arg.syntax());
+
+            builder.add_file_edits(ctx.vfs_file_id(), editor);
+        },
+    )
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::tests::{check_assist, check_assist_not_applicable};
+
+    #[test]
+    fn test_unwrap_type_to_generic_arg() {
+        check_assist(
+            unwrap_type_to_generic_arg,
+            r#"
+//- minicore: option
+fn foo() -> $0Option<i32> {
+    todo!()
+}
+"#,
+            r#"
+fn foo() -> i32 {
+    todo!()
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_type_to_generic_arg_not_applicable_for_non_generic_arg_list() {
+        check_assist_not_applicable(
+            unwrap_type_to_generic_arg,
+            r#"
+fn foo() -> $0i32 {}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_type_to_generic_arg_not_applicable_for_multiple_generic_args() {
+        check_assist_not_applicable(
+            unwrap_type_to_generic_arg,
+            r#"
+//- minicore: result
+fn foo() -> $0Result<i32, ()> {
+    todo!()
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_type_to_generic_arg_with_lifetime_and_const() {
+        check_assist(
+            unwrap_type_to_generic_arg,
+            r#"
+enum Foo<'a, T, const N: usize> {
+    Bar(T),
+    Baz(&'a [T; N]),
+}
+
+fn test<'a>() -> $0Foo<'a, i32, 3> {
+    todo!()
+}
+"#,
+            r#"
+enum Foo<'a, T, const N: usize> {
+    Bar(T),
+    Baz(&'a [T; N]),
+}
+
+fn test<'a>() -> i32 {
+    todo!()
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn unwrap_type_to_generic_arg_in_let_stmt() {
+        check_assist(
+            unwrap_type_to_generic_arg,
+            r#"
+enum Foo<T> {
+    Bar(T),
+    Baz,
+}
+
+fn test() {
+    let foo: $0Foo<i32> = todo!();
+}
+"#,
+            r#"
+enum Foo<T> {
+    Bar(T),
+    Baz,
+}
+
+fn test() {
+    let foo: i32 = todo!();
+}
+"#,
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
index 627ed37b04e..2395091b6f2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -229,6 +229,7 @@ mod handlers {
     mod unwrap_block;
     mod unwrap_return_type;
     mod unwrap_tuple;
+    mod unwrap_type_to_generic_arg;
     mod wrap_return_type;
     mod wrap_unwrap_cfg_attr;
 
@@ -369,6 +370,7 @@ mod handlers {
             unwrap_block::unwrap_block,
             unwrap_return_type::unwrap_return_type,
             unwrap_tuple::unwrap_tuple,
+            unwrap_type_to_generic_arg::unwrap_type_to_generic_arg,
             wrap_return_type::wrap_return_type,
             wrap_unwrap_cfg_attr::wrap_unwrap_cfg_attr,
 
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 01ab0be34b2..76134acb36e 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
@@ -3482,6 +3482,23 @@ fn main() {
 }
 
 #[test]
+fn doctest_unwrap_type_to_generic_arg() {
+    check_doc_test(
+        "unwrap_type_to_generic_arg",
+        r#####"
+fn foo() -> $0Option<i32> {
+    todo!()
+}
+"#####,
+        r#####"
+fn foo() -> i32 {
+    todo!()
+}
+"#####,
+    )
+}
+
+#[test]
 fn doctest_wrap_return_type_in_option() {
     check_doc_test(
         "wrap_return_type_in_option",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
index cd18b3dcfdc..92cbf411c1e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
@@ -13,6 +13,7 @@ use crate::{
 const CARGO_DEFINED_VARS: &[(&str, &str)] = &[
     ("CARGO", "Path to the cargo binary performing the build"),
     ("CARGO_MANIFEST_DIR", "The directory containing the manifest of your package"),
+    ("CARGO_MANIFEST_PATH", "The path to the manifest of your package"),
     ("CARGO_PKG_VERSION", "The full version of your package"),
     ("CARGO_PKG_VERSION_MAJOR", "The major version of your package"),
     ("CARGO_PKG_VERSION_MINOR", "The minor version of your package"),
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
index 54be7d2fbc3..3cdf2112835 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
@@ -311,6 +311,8 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) {
 
     let mut prefix = String::new();
 
+    let mut found_ref_or_deref = false;
+
     while let Some(parent_deref_element) =
         resulting_element.syntax().parent().and_then(ast::PrefixExpr::cast)
     {
@@ -318,27 +320,26 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, String) {
             break;
         }
 
+        found_ref_or_deref = true;
         resulting_element = ast::Expr::from(parent_deref_element);
 
         prefix.insert(0, '*');
     }
 
-    if let Some(first_ref_expr) = resulting_element.syntax().parent().and_then(ast::RefExpr::cast) {
-        if let Some(expr) = first_ref_expr.expr() {
-            resulting_element = expr;
-        }
+    while let Some(parent_ref_element) =
+        resulting_element.syntax().parent().and_then(ast::RefExpr::cast)
+    {
+        found_ref_or_deref = true;
+        let exclusive = parent_ref_element.mut_token().is_some();
+        resulting_element = ast::Expr::from(parent_ref_element);
 
-        while let Some(parent_ref_element) =
-            resulting_element.syntax().parent().and_then(ast::RefExpr::cast)
-        {
-            let exclusive = parent_ref_element.mut_token().is_some();
-            resulting_element = ast::Expr::from(parent_ref_element);
+        prefix.insert_str(0, if exclusive { "&mut " } else { "&" });
+    }
 
-            prefix.insert_str(0, if exclusive { "&mut " } else { "&" });
-        }
-    } else {
-        // If we do not find any ref expressions, restore
+    if !found_ref_or_deref {
+        // If we do not find any ref/deref expressions, restore
         // all the progress of tree climbing
+        prefix.clear();
         resulting_element = initial_element.clone();
     }
 
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 391e2379dcd..284876ffc88 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
@@ -883,9 +883,10 @@ fn classify_name_ref(
             },
             ast::MethodCallExpr(method) => {
                 let receiver = find_opt_node_in_file(original_file, method.receiver());
+                let has_parens = has_parens(&method);
                 let kind = NameRefKind::DotAccess(DotAccess {
                     receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
-                    kind: DotAccessKind::Method { has_parens: method.arg_list().is_some_and(|it| it.l_paren_token().is_some()) },
+                    kind: DotAccessKind::Method { has_parens },
                     receiver,
                     ctx: DotAccessExprCtx { in_block_expr: is_in_block(method.syntax()), in_breakable: is_in_breakable(method.syntax()) }
                 });
@@ -1372,7 +1373,7 @@ fn classify_name_ref(
                         }
                     }
 
-                    path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::can_cast(it.kind()));
+                    path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::cast(it).is_some_and(|it| has_parens(&it)));
 
                     make_path_kind_expr(it.into())
                 },
@@ -1401,7 +1402,7 @@ fn classify_name_ref(
                         match parent {
                             ast::PathType(it) => make_path_kind_type(it.into()),
                             ast::PathExpr(it) => {
-                                path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::can_cast(it.kind()));
+                                path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::cast(it).is_some_and(|it| has_parens(&it)));
 
                                 make_path_kind_expr(it.into())
                             },
@@ -1559,6 +1560,30 @@ fn classify_name_ref(
     Some((NameRefContext { nameref, kind: NameRefKind::Path(path_ctx) }, qualifier_ctx))
 }
 
+/// When writing in the middle of some code the following situation commonly occurs (`|` denotes the cursor):
+/// ```ignore
+/// value.method|
+/// (1, 2, 3)
+/// ```
+/// Here, we want to complete the method parentheses & arguments (if the corresponding settings are on),
+/// but the thing is parsed as a method call with parentheses. Therefore we use heuristics: if the parentheses
+/// are on the next line, consider them non-existent.
+fn has_parens(node: &dyn HasArgList) -> bool {
+    let Some(arg_list) = node.arg_list() else { return false };
+    if arg_list.l_paren_token().is_none() {
+        return false;
+    }
+    let prev_siblings = iter::successors(arg_list.syntax().prev_sibling_or_token(), |it| {
+        it.prev_sibling_or_token()
+    });
+    prev_siblings
+        .take_while(|syntax| syntax.kind().is_trivia())
+        .filter_map(|syntax| {
+            syntax.into_token().filter(|token| token.kind() == SyntaxKind::WHITESPACE)
+        })
+        .all(|whitespace| !whitespace.text().contains('\n'))
+}
+
 fn pattern_context_for(
     sema: &Semantics<'_, RootDatabase>,
     original_file: &SyntaxNode,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index d5137949d42..e5467767d42 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -2126,3 +2126,70 @@ fn main() {
         "#]],
     );
 }
+
+#[test]
+fn call_parens_with_newline() {
+    check_edit(
+        "foo",
+        r#"
+fn foo(v: i32) {}
+
+fn bar() {
+    foo$0
+    ()
+}
+    "#,
+        r#"
+fn foo(v: i32) {}
+
+fn bar() {
+    foo(${1:v});$0
+    ()
+}
+    "#,
+    );
+    check_edit(
+        "foo",
+        r#"
+struct Foo;
+impl Foo {
+    fn foo(&self, v: i32) {}
+}
+
+fn bar() {
+    Foo.foo$0
+    ()
+}
+    "#,
+        r#"
+struct Foo;
+impl Foo {
+    fn foo(&self, v: i32) {}
+}
+
+fn bar() {
+    Foo.foo(${1:v});$0
+    ()
+}
+    "#,
+    );
+}
+
+#[test]
+fn dbg_too_many_asterisks() {
+    check_edit(
+        "dbg",
+        r#"
+fn main() {
+    let x = &42;
+    let y = *x.$0;
+}
+    "#,
+        r#"
+fn main() {
+    let x = &42;
+    let y = dbg!(*x);
+}
+    "#,
+    );
+}
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 bf4f541ff54..d5db1c481b6 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
@@ -6,7 +6,7 @@
 // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06).
 
 use crate::RootDatabase;
-use crate::documentation::{Documentation, HasDocs};
+use crate::documentation::{DocsRangeMap, Documentation, HasDocs};
 use crate::famous_defs::FamousDefs;
 use arrayvec::ArrayVec;
 use either::Either;
@@ -21,7 +21,7 @@ use hir::{
 use span::Edition;
 use stdx::{format_to, impl_from};
 use syntax::{
-    SyntaxKind, SyntaxNode, SyntaxToken,
+    SyntaxKind, SyntaxNode, SyntaxToken, TextSize,
     ast::{self, AstNode},
     match_ast,
 };
@@ -210,29 +210,40 @@ impl Definition {
         famous_defs: Option<&FamousDefs<'_, '_>>,
         display_target: DisplayTarget,
     ) -> Option<Documentation> {
+        self.docs_with_rangemap(db, famous_defs, display_target).map(|(docs, _)| docs)
+    }
+
+    pub fn docs_with_rangemap(
+        &self,
+        db: &RootDatabase,
+        famous_defs: Option<&FamousDefs<'_, '_>>,
+        display_target: DisplayTarget,
+    ) -> Option<(Documentation, Option<DocsRangeMap>)> {
         let docs = match self {
-            Definition::Macro(it) => it.docs(db),
-            Definition::Field(it) => it.docs(db),
-            Definition::Module(it) => it.docs(db),
-            Definition::Crate(it) => it.docs(db),
-            Definition::Function(it) => it.docs(db),
-            Definition::Adt(it) => it.docs(db),
-            Definition::Variant(it) => it.docs(db),
-            Definition::Const(it) => it.docs(db),
-            Definition::Static(it) => it.docs(db),
-            Definition::Trait(it) => it.docs(db),
-            Definition::TraitAlias(it) => it.docs(db),
+            Definition::Macro(it) => it.docs_with_rangemap(db),
+            Definition::Field(it) => it.docs_with_rangemap(db),
+            Definition::Module(it) => it.docs_with_rangemap(db),
+            Definition::Crate(it) => it.docs_with_rangemap(db),
+            Definition::Function(it) => it.docs_with_rangemap(db),
+            Definition::Adt(it) => it.docs_with_rangemap(db),
+            Definition::Variant(it) => it.docs_with_rangemap(db),
+            Definition::Const(it) => it.docs_with_rangemap(db),
+            Definition::Static(it) => it.docs_with_rangemap(db),
+            Definition::Trait(it) => it.docs_with_rangemap(db),
+            Definition::TraitAlias(it) => it.docs_with_rangemap(db),
             Definition::TypeAlias(it) => {
-                it.docs(db).or_else(|| {
+                it.docs_with_rangemap(db).or_else(|| {
                     // docs are missing, try to fall back to the docs of the aliased item.
                     let adt = it.ty(db).as_adt()?;
-                    let docs = adt.docs(db)?;
-                    let docs = format!(
-                        "*This is the documentation for* `{}`\n\n{}",
-                        adt.display(db, display_target),
-                        docs.as_str()
+                    let (docs, range_map) = adt.docs_with_rangemap(db)?;
+                    let header_docs = format!(
+                        "*This is the documentation for* `{}`\n\n",
+                        adt.display(db, display_target)
                     );
-                    Some(Documentation::new(docs))
+                    let offset = TextSize::new(header_docs.len() as u32);
+                    let range_map = range_map.shift_docstring_line_range(offset);
+                    let docs = header_docs + docs.as_str();
+                    Some((Documentation::new(docs), range_map))
                 })
             }
             Definition::BuiltinType(it) => {
@@ -241,17 +252,17 @@ impl Definition {
                     let primitive_mod =
                         format!("prim_{}", it.name().display(fd.0.db, display_target.edition));
                     let doc_owner = find_std_module(fd, &primitive_mod, display_target.edition)?;
-                    doc_owner.docs(fd.0.db)
+                    doc_owner.docs_with_rangemap(fd.0.db)
                 })
             }
             Definition::BuiltinLifetime(StaticLifetime) => None,
             Definition::Local(_) => None,
             Definition::SelfType(impl_def) => {
-                impl_def.self_ty(db).as_adt().map(|adt| adt.docs(db))?
+                impl_def.self_ty(db).as_adt().map(|adt| adt.docs_with_rangemap(db))?
             }
             Definition::GenericParam(_) => None,
             Definition::Label(_) => None,
-            Definition::ExternCrateDecl(it) => it.docs(db),
+            Definition::ExternCrateDecl(it) => it.docs_with_rangemap(db),
 
             Definition::BuiltinAttr(it) => {
                 let name = it.name(db);
@@ -276,7 +287,8 @@ impl Definition {
                         name_value_str
                     );
                 }
-                Some(Documentation::new(docs.replace('*', "\\*")))
+
+                return Some((Documentation::new(docs.replace('*', "\\*")), None));
             }
             Definition::ToolModule(_) => None,
             Definition::DeriveHelper(_) => None,
@@ -291,8 +303,9 @@ impl Definition {
             let trait_ = assoc.implemented_trait(db)?;
             let name = Some(assoc.name(db)?);
             let item = trait_.items(db).into_iter().find(|it| it.name(db) == name)?;
-            item.docs(db)
+            item.docs_with_rangemap(db)
         })
+        .map(|(docs, range_map)| (docs, Some(range_map)))
     }
 
     pub fn label(&self, db: &RootDatabase, display_target: DisplayTarget) -> String {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs
index ef2c83992c0..30c355f8b3f 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs
@@ -34,11 +34,13 @@ impl From<Documentation> for String {
 
 pub trait HasDocs: HasAttrs {
     fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>;
+    fn docs_with_rangemap(self, db: &dyn HirDatabase) -> Option<(Documentation, DocsRangeMap)>;
     fn resolve_doc_path(
         self,
         db: &dyn HirDatabase,
         link: &str,
         ns: Option<hir::Namespace>,
+        is_inner_doc: bool,
     ) -> Option<hir::DocLinkDef>;
 }
 /// A struct to map text ranges from [`Documentation`] back to TextRanges in the syntax tree.
@@ -53,7 +55,7 @@ pub struct DocsRangeMap {
 
 impl DocsRangeMap {
     /// Maps a [`TextRange`] relative to the documentation string back to its AST range
-    pub fn map(&self, range: TextRange) -> Option<InFile<TextRange>> {
+    pub fn map(&self, range: TextRange) -> Option<(InFile<TextRange>, AttrId)> {
         let found = self.mapping.binary_search_by(|(probe, ..)| probe.ordering(range)).ok()?;
         let (line_docs_range, idx, original_line_src_range) = self.mapping[found];
         if !line_docs_range.contains_range(range) {
@@ -71,7 +73,7 @@ impl DocsRangeMap {
                     text_range.end() + original_line_src_range.start() + relative_range.start(),
                     string.syntax().text_range().len().min(range.len()),
                 );
-                Some(InFile { file_id, value: range })
+                Some((InFile { file_id, value: range }, idx))
             }
             Either::Right(comment) => {
                 let text_range = comment.syntax().text_range();
@@ -82,10 +84,22 @@ impl DocsRangeMap {
                         + relative_range.start(),
                     text_range.len().min(range.len()),
                 );
-                Some(InFile { file_id, value: range })
+                Some((InFile { file_id, value: range }, idx))
             }
         }
     }
+
+    pub fn shift_docstring_line_range(self, offset: TextSize) -> DocsRangeMap {
+        let mapping = self
+            .mapping
+            .into_iter()
+            .map(|(buf_offset, id, base_offset)| {
+                let buf_offset = buf_offset.checked_add(offset).unwrap();
+                (buf_offset, id, base_offset)
+            })
+            .collect_vec();
+        DocsRangeMap { source_map: self.source_map, mapping }
+    }
 }
 
 pub fn docs_with_rangemap(
@@ -161,13 +175,20 @@ macro_rules! impl_has_docs {
             fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
                 docs_from_attrs(&self.attrs(db)).map(Documentation)
             }
+            fn docs_with_rangemap(
+                self,
+                db: &dyn HirDatabase,
+            ) -> Option<(Documentation, DocsRangeMap)> {
+                docs_with_rangemap(db, &self.attrs(db))
+            }
             fn resolve_doc_path(
                 self,
                 db: &dyn HirDatabase,
                 link: &str,
-                ns: Option<hir::Namespace>
+                ns: Option<hir::Namespace>,
+                is_inner_doc: bool,
             ) -> Option<hir::DocLinkDef> {
-                resolve_doc_path_on(db, self, link, ns)
+                resolve_doc_path_on(db, self, link, ns, is_inner_doc)
             }
         }
     )*};
@@ -184,13 +205,21 @@ macro_rules! impl_has_docs_enum {
             fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
                 hir::$enum::$variant(self).docs(db)
             }
+
+            fn docs_with_rangemap(
+                self,
+                db: &dyn HirDatabase,
+            ) -> Option<(Documentation, DocsRangeMap)> {
+                hir::$enum::$variant(self).docs_with_rangemap(db)
+            }
             fn resolve_doc_path(
                 self,
                 db: &dyn HirDatabase,
                 link: &str,
-                ns: Option<hir::Namespace>
+                ns: Option<hir::Namespace>,
+                is_inner_doc: bool,
             ) -> Option<hir::DocLinkDef> {
-                hir::$enum::$variant(self).resolve_doc_path(db, link, ns)
+                hir::$enum::$variant(self).resolve_doc_path(db, link, ns, is_inner_doc)
             }
         }
     )*};
@@ -207,16 +236,25 @@ impl HasDocs for hir::AssocItem {
         }
     }
 
+    fn docs_with_rangemap(self, db: &dyn HirDatabase) -> Option<(Documentation, DocsRangeMap)> {
+        match self {
+            hir::AssocItem::Function(it) => it.docs_with_rangemap(db),
+            hir::AssocItem::Const(it) => it.docs_with_rangemap(db),
+            hir::AssocItem::TypeAlias(it) => it.docs_with_rangemap(db),
+        }
+    }
+
     fn resolve_doc_path(
         self,
         db: &dyn HirDatabase,
         link: &str,
         ns: Option<hir::Namespace>,
+        is_inner_doc: bool,
     ) -> Option<hir::DocLinkDef> {
         match self {
-            hir::AssocItem::Function(it) => it.resolve_doc_path(db, link, ns),
-            hir::AssocItem::Const(it) => it.resolve_doc_path(db, link, ns),
-            hir::AssocItem::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
+            hir::AssocItem::Function(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+            hir::AssocItem::Const(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+            hir::AssocItem::TypeAlias(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
         }
     }
 }
@@ -238,13 +276,36 @@ impl HasDocs for hir::ExternCrateDecl {
         }
         .map(Documentation::new)
     }
+
+    fn docs_with_rangemap(self, db: &dyn HirDatabase) -> Option<(Documentation, DocsRangeMap)> {
+        let crate_docs = docs_with_rangemap(db, &self.resolved_crate(db)?.root_module().attrs(db));
+        let decl_docs = docs_with_rangemap(db, &self.attrs(db));
+        match (decl_docs, crate_docs) {
+            (None, None) => None,
+            (Some(decl_docs), None) => Some(decl_docs),
+            (None, Some(crate_docs)) => Some(crate_docs),
+            (
+                Some((Documentation(mut decl_docs), mut decl_range_map)),
+                Some((Documentation(crate_docs), crate_range_map)),
+            ) => {
+                decl_docs.push('\n');
+                decl_docs.push('\n');
+                let offset = TextSize::new(decl_docs.len() as u32);
+                decl_docs += &crate_docs;
+                let crate_range_map = crate_range_map.shift_docstring_line_range(offset);
+                decl_range_map.mapping.extend(crate_range_map.mapping);
+                Some((Documentation(decl_docs), decl_range_map))
+            }
+        }
+    }
     fn resolve_doc_path(
         self,
         db: &dyn HirDatabase,
         link: &str,
         ns: Option<hir::Namespace>,
+        is_inner_doc: bool,
     ) -> Option<hir::DocLinkDef> {
-        resolve_doc_path_on(db, self, link, ns)
+        resolve_doc_path_on(db, self, link, ns, is_inner_doc)
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs
index cbe31405ab7..5356614dce5 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs
@@ -2,12 +2,10 @@
 //! sometimes is counter productive when, for example, the first goto definition
 //! request takes longer to compute. This module implements prepopulation of
 //! various caches, it's not really advanced at the moment.
-mod topologic_sort;
-
-use std::time::Duration;
+use std::panic::AssertUnwindSafe;
 
 use hir::{Symbol, db::DefDatabase};
-use itertools::Itertools;
+use rustc_hash::FxHashMap;
 use salsa::{Cancelled, Database};
 
 use crate::{
@@ -35,59 +33,114 @@ pub fn parallel_prime_caches(
 ) {
     let _p = tracing::info_span!("parallel_prime_caches").entered();
 
-    let mut crates_to_prime = {
-        // FIXME: We already have the crate list topologically sorted (but without the things
-        // `TopologicalSortIter` gives us). Maybe there is a way to avoid using it and rip it out
-        // of the codebase?
-        let mut builder = topologic_sort::TopologicalSortIter::builder();
-
-        for &crate_id in db.all_crates().iter() {
-            builder.add(crate_id, crate_id.data(db).dependencies.iter().map(|d| d.crate_id));
-        }
-
-        builder.build()
-    };
-
     enum ParallelPrimeCacheWorkerProgress {
-        BeginCrate { crate_id: Crate, crate_name: Symbol },
-        EndCrate { crate_id: Crate },
+        BeginCrateDefMap { crate_id: Crate, crate_name: Symbol },
+        EndCrateDefMap { crate_id: Crate },
+        EndCrateImportMap,
+        EndModuleSymbols,
         Cancelled(Cancelled),
     }
 
-    // We split off def map computation from other work,
-    // as the def map is the relevant one. Once the defmaps are computed
-    // the project is ready to go, the other indices are just nice to have for some IDE features.
-    #[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone)]
-    enum PrimingPhase {
-        DefMap,
-        ImportMap,
-        CrateSymbols,
-    }
+    // The setup here is a bit complicated. We try to make best use of compute resources.
+    // The idea is that if we have a def map available to compute, we should do that first.
+    // This is because def map is a dependency of both import map and symbols. So if we have
+    // e.g. a def map and a symbols, if we compute the def map we can, after it completes,
+    // compute the def maps of dependencies, the existing symbols and the symbols of the
+    // new crate, all in parallel. But if we compute the symbols, after that we will only
+    // have the def map to compute, and the rest of the CPU cores will rest, which is not
+    // good.
+    // However, it's better to compute symbols/import map than to compute a def map that
+    // isn't ready yet, because one of its dependencies hasn't yet completed its def map.
+    // Such def map will just block on the dependency, which is just wasted time. So better
+    // to compute the symbols/import map of an already computed def map in that time.
+
+    let (reverse_deps, mut to_be_done_deps) = {
+        let all_crates = db.all_crates();
+        let to_be_done_deps = all_crates
+            .iter()
+            .map(|&krate| (krate, krate.data(db).dependencies.len() as u32))
+            .collect::<FxHashMap<_, _>>();
+        let mut reverse_deps =
+            all_crates.iter().map(|&krate| (krate, Vec::new())).collect::<FxHashMap<_, _>>();
+        for &krate in &*all_crates {
+            for dep in &krate.data(db).dependencies {
+                reverse_deps.get_mut(&dep.crate_id).unwrap().push(krate);
+            }
+        }
+        (reverse_deps, to_be_done_deps)
+    };
 
-    let (work_sender, progress_receiver) = {
+    let (def_map_work_sender, import_map_work_sender, symbols_work_sender, progress_receiver) = {
         let (progress_sender, progress_receiver) = crossbeam_channel::unbounded();
-        let (work_sender, work_receiver) = crossbeam_channel::unbounded();
-        let prime_caches_worker = move |db: RootDatabase| {
-            while let Ok((crate_id, crate_name, kind)) = work_receiver.recv() {
-                progress_sender
-                    .send(ParallelPrimeCacheWorkerProgress::BeginCrate { crate_id, crate_name })?;
-
-                let cancelled = Cancelled::catch(|| match kind {
-                    PrimingPhase::DefMap => _ = db.crate_def_map(crate_id),
-                    PrimingPhase::ImportMap => _ = db.import_map(crate_id),
-                    PrimingPhase::CrateSymbols => _ = db.crate_symbols(crate_id.into()),
-                });
+        let (def_map_work_sender, def_map_work_receiver) = crossbeam_channel::unbounded();
+        let (import_map_work_sender, import_map_work_receiver) = crossbeam_channel::unbounded();
+        let (symbols_work_sender, symbols_work_receiver) = crossbeam_channel::unbounded();
+        let prime_caches_worker =
+            move |db: RootDatabase| {
+                let handle_def_map = |crate_id, crate_name| {
+                    progress_sender.send(ParallelPrimeCacheWorkerProgress::BeginCrateDefMap {
+                        crate_id,
+                        crate_name,
+                    })?;
 
-                match cancelled {
-                    Ok(()) => progress_sender
-                        .send(ParallelPrimeCacheWorkerProgress::EndCrate { crate_id })?,
-                    Err(cancelled) => progress_sender
-                        .send(ParallelPrimeCacheWorkerProgress::Cancelled(cancelled))?,
-                }
-            }
+                    let cancelled = Cancelled::catch(|| _ = hir::crate_def_map(&db, crate_id));
 
-            Ok::<_, crossbeam_channel::SendError<_>>(())
-        };
+                    match cancelled {
+                        Ok(()) => progress_sender
+                            .send(ParallelPrimeCacheWorkerProgress::EndCrateDefMap { crate_id })?,
+                        Err(cancelled) => progress_sender
+                            .send(ParallelPrimeCacheWorkerProgress::Cancelled(cancelled))?,
+                    }
+
+                    Ok::<_, crossbeam_channel::SendError<_>>(())
+                };
+                let handle_import_map = |crate_id| {
+                    let cancelled = Cancelled::catch(|| _ = db.import_map(crate_id));
+
+                    match cancelled {
+                        Ok(()) => progress_sender
+                            .send(ParallelPrimeCacheWorkerProgress::EndCrateImportMap)?,
+                        Err(cancelled) => progress_sender
+                            .send(ParallelPrimeCacheWorkerProgress::Cancelled(cancelled))?,
+                    }
+
+                    Ok::<_, crossbeam_channel::SendError<_>>(())
+                };
+                let handle_symbols = |module| {
+                    let cancelled =
+                        Cancelled::catch(AssertUnwindSafe(|| _ = db.module_symbols(module)));
+
+                    match cancelled {
+                        Ok(()) => progress_sender
+                            .send(ParallelPrimeCacheWorkerProgress::EndModuleSymbols)?,
+                        Err(cancelled) => progress_sender
+                            .send(ParallelPrimeCacheWorkerProgress::Cancelled(cancelled))?,
+                    }
+
+                    Ok::<_, crossbeam_channel::SendError<_>>(())
+                };
+
+                loop {
+                    db.unwind_if_revision_cancelled();
+
+                    // Biased because we want to prefer def maps.
+                    crossbeam_channel::select_biased! {
+                        recv(def_map_work_receiver) -> work => {
+                            let Ok((crate_id, crate_name)) = work else { break };
+                            handle_def_map(crate_id, crate_name)?;
+                        }
+                        recv(import_map_work_receiver) -> work => {
+                            let Ok(crate_id) = work else { break };
+                            handle_import_map(crate_id)?;
+                        }
+                        recv(symbols_work_receiver) -> work => {
+                            let Ok(module) = work else { break };
+                            handle_symbols(module)?;
+                        }
+                    }
+                }
+                Ok::<_, crossbeam_channel::SendError<_>>(())
+            };
 
         for id in 0..num_worker_threads {
             stdx::thread::Builder::new(
@@ -103,138 +156,121 @@ pub fn parallel_prime_caches(
             .expect("failed to spawn thread");
         }
 
-        (work_sender, progress_receiver)
+        (def_map_work_sender, import_map_work_sender, symbols_work_sender, progress_receiver)
     };
 
-    let crates_total = crates_to_prime.pending();
-    let mut crates_done = 0;
+    let crate_def_maps_total = db.all_crates().len();
+    let mut crate_def_maps_done = 0;
+    let (mut crate_import_maps_total, mut crate_import_maps_done) = (0usize, 0usize);
+    let (mut module_symbols_total, mut module_symbols_done) = (0usize, 0usize);
 
     // an index map is used to preserve ordering so we can sort the progress report in order of
     // "longest crate to index" first
     let mut crates_currently_indexing =
         FxIndexMap::with_capacity_and_hasher(num_worker_threads, Default::default());
 
-    let mut additional_phases = vec![];
-
-    while crates_done < crates_total {
-        db.unwind_if_revision_cancelled();
-
-        for krate in &mut crates_to_prime {
-            let name = krate.extra_data(db).display_name.as_deref().cloned().unwrap_or_else(|| {
-                Symbol::integer(salsa::plumbing::AsId::as_id(&krate).as_u32() as usize)
-            });
-            let origin = &krate.data(db).origin;
-            if origin.is_lang() {
-                additional_phases.push((krate, name.clone(), PrimingPhase::ImportMap));
-            } else if origin.is_local() {
-                // Compute the symbol search index.
-                // This primes the cache for `ide_db::symbol_index::world_symbols()`.
-                //
-                // We do this for workspace crates only (members of local_roots), because doing it
-                // for all dependencies could be *very* unnecessarily slow in a large project.
-                //
-                // FIXME: We should do it unconditionally if the configuration is set to default to
-                // searching dependencies (rust-analyzer.workspace.symbol.search.scope), but we
-                // would need to pipe that configuration information down here.
-                additional_phases.push((krate, name.clone(), PrimingPhase::CrateSymbols));
-            }
-
-            work_sender.send((krate, name, PrimingPhase::DefMap)).ok();
+    for (&krate, &to_be_done_deps) in &to_be_done_deps {
+        if to_be_done_deps != 0 {
+            continue;
         }
 
-        // recv_timeout is somewhat a hack, we need a way to from this thread check to see if the current salsa revision
-        // is cancelled on a regular basis. workers will only exit if they are processing a task that is cancelled, or
-        // if this thread exits, and closes the work channel.
-        let worker_progress = match progress_receiver.recv_timeout(Duration::from_millis(10)) {
-            Ok(p) => p,
-            Err(crossbeam_channel::RecvTimeoutError::Timeout) => {
-                continue;
-            }
-            Err(crossbeam_channel::RecvTimeoutError::Disconnected) => {
-                // all our workers have exited, mark us as finished and exit
-                cb(ParallelPrimeCachesProgress {
-                    crates_currently_indexing: vec![],
-                    crates_done,
-                    crates_total: crates_done,
-                    work_type: "Indexing",
-                });
-                return;
-            }
-        };
-        match worker_progress {
-            ParallelPrimeCacheWorkerProgress::BeginCrate { crate_id, crate_name } => {
-                crates_currently_indexing.insert(crate_id, crate_name);
-            }
-            ParallelPrimeCacheWorkerProgress::EndCrate { crate_id } => {
-                crates_currently_indexing.swap_remove(&crate_id);
-                crates_to_prime.mark_done(crate_id);
-                crates_done += 1;
-            }
-            ParallelPrimeCacheWorkerProgress::Cancelled(cancelled) => {
-                // Cancelled::throw should probably be public
-                std::panic::resume_unwind(Box::new(cancelled));
-            }
-        };
+        let name = crate_name(db, krate);
+        def_map_work_sender.send((krate, name)).ok();
+    }
+
+    while crate_def_maps_done < crate_def_maps_total
+        || crate_import_maps_done < crate_import_maps_total
+        || module_symbols_done < module_symbols_total
+    {
+        db.unwind_if_revision_cancelled();
 
         let progress = ParallelPrimeCachesProgress {
             crates_currently_indexing: crates_currently_indexing.values().cloned().collect(),
-            crates_done,
-            crates_total,
+            crates_done: crate_def_maps_done,
+            crates_total: crate_def_maps_total,
             work_type: "Indexing",
         };
 
         cb(progress);
-    }
-
-    let mut crates_done = 0;
-    let crates_total = additional_phases.len();
-    for w in additional_phases.into_iter().sorted_by_key(|&(_, _, phase)| phase) {
-        work_sender.send(w).ok();
-    }
-
-    while crates_done < crates_total {
-        db.unwind_if_revision_cancelled();
 
-        // recv_timeout is somewhat a hack, we need a way to from this thread check to see if the current salsa revision
-        // is cancelled on a regular basis. workers will only exit if they are processing a task that is cancelled, or
-        // if this thread exits, and closes the work channel.
-        let worker_progress = match progress_receiver.recv_timeout(Duration::from_millis(10)) {
+        // Biased to prefer progress updates (and because it's faster).
+        let progress = match progress_receiver.recv() {
             Ok(p) => p,
-            Err(crossbeam_channel::RecvTimeoutError::Timeout) => {
-                continue;
-            }
-            Err(crossbeam_channel::RecvTimeoutError::Disconnected) => {
+            Err(crossbeam_channel::RecvError) => {
                 // all our workers have exited, mark us as finished and exit
                 cb(ParallelPrimeCachesProgress {
                     crates_currently_indexing: vec![],
-                    crates_done,
-                    crates_total: crates_done,
-                    work_type: "Populating symbols",
+                    crates_done: crate_def_maps_done,
+                    crates_total: crate_def_maps_done,
+                    work_type: "Done",
                 });
                 return;
             }
         };
-        match worker_progress {
-            ParallelPrimeCacheWorkerProgress::BeginCrate { crate_id, crate_name } => {
+
+        match progress {
+            ParallelPrimeCacheWorkerProgress::BeginCrateDefMap { crate_id, crate_name } => {
                 crates_currently_indexing.insert(crate_id, crate_name);
             }
-            ParallelPrimeCacheWorkerProgress::EndCrate { crate_id } => {
+            ParallelPrimeCacheWorkerProgress::EndCrateDefMap { crate_id } => {
                 crates_currently_indexing.swap_remove(&crate_id);
-                crates_done += 1;
+                crate_def_maps_done += 1;
+
+                // Fire ready dependencies.
+                for &dep in &reverse_deps[&crate_id] {
+                    let to_be_done = to_be_done_deps.get_mut(&dep).unwrap();
+                    *to_be_done -= 1;
+                    if *to_be_done == 0 {
+                        let dep_name = crate_name(db, dep);
+                        def_map_work_sender.send((dep, dep_name)).ok();
+                    }
+                }
+
+                if crate_def_maps_done == crate_def_maps_total {
+                    cb(ParallelPrimeCachesProgress {
+                        crates_currently_indexing: vec![],
+                        crates_done: crate_def_maps_done,
+                        crates_total: crate_def_maps_done,
+                        work_type: "Collecting Symbols",
+                    });
+                }
+
+                let origin = &crate_id.data(db).origin;
+                if origin.is_lang() {
+                    crate_import_maps_total += 1;
+                    import_map_work_sender.send(crate_id).ok();
+                } else if origin.is_local() {
+                    // Compute the symbol search index.
+                    // This primes the cache for `ide_db::symbol_index::world_symbols()`.
+                    //
+                    // We do this for workspace crates only (members of local_roots), because doing it
+                    // for all dependencies could be *very* unnecessarily slow in a large project.
+                    //
+                    // FIXME: We should do it unconditionally if the configuration is set to default to
+                    // searching dependencies (rust-analyzer.workspace.symbol.search.scope), but we
+                    // would need to pipe that configuration information down here.
+                    let modules = hir::Crate::from(crate_id).modules(db);
+                    module_symbols_total += modules.len();
+                    for module in modules {
+                        symbols_work_sender.send(module).ok();
+                    }
+                }
             }
+            ParallelPrimeCacheWorkerProgress::EndCrateImportMap => crate_import_maps_done += 1,
+            ParallelPrimeCacheWorkerProgress::EndModuleSymbols => module_symbols_done += 1,
             ParallelPrimeCacheWorkerProgress::Cancelled(cancelled) => {
                 // Cancelled::throw should probably be public
                 std::panic::resume_unwind(Box::new(cancelled));
             }
-        };
-
-        let progress = ParallelPrimeCachesProgress {
-            crates_currently_indexing: crates_currently_indexing.values().cloned().collect(),
-            crates_done,
-            crates_total,
-            work_type: "Populating symbols",
-        };
-
-        cb(progress);
+        }
     }
 }
+
+fn crate_name(db: &RootDatabase, krate: Crate) -> Symbol {
+    krate
+        .extra_data(db)
+        .display_name
+        .as_deref()
+        .cloned()
+        .unwrap_or_else(|| Symbol::integer(salsa::plumbing::AsId::as_id(&krate).as_u32() as usize))
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches/topologic_sort.rs b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches/topologic_sort.rs
deleted file mode 100644
index c8a03863103..00000000000
--- a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches/topologic_sort.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-//! helper data structure to schedule work for parallel prime caches.
-use std::{collections::VecDeque, hash::Hash};
-
-use crate::FxHashMap;
-
-pub(crate) struct TopologicSortIterBuilder<T> {
-    nodes: FxHashMap<T, Entry<T>>,
-}
-
-// this implementation has different bounds on T than would be implied by #[derive(Default)]
-impl<T> Default for TopologicSortIterBuilder<T>
-where
-    T: Copy + Eq + PartialEq + Hash,
-{
-    fn default() -> Self {
-        Self { nodes: Default::default() }
-    }
-}
-
-impl<T> TopologicSortIterBuilder<T>
-where
-    T: Copy + Eq + PartialEq + Hash,
-{
-    fn get_or_create_entry(&mut self, item: T) -> &mut Entry<T> {
-        self.nodes.entry(item).or_default()
-    }
-
-    pub(crate) fn add(&mut self, item: T, predecessors: impl IntoIterator<Item = T>) {
-        let mut num_predecessors = 0;
-
-        for predecessor in predecessors.into_iter() {
-            self.get_or_create_entry(predecessor).successors.push(item);
-            num_predecessors += 1;
-        }
-
-        let entry = self.get_or_create_entry(item);
-        entry.num_predecessors += num_predecessors;
-    }
-
-    pub(crate) fn build(self) -> TopologicalSortIter<T> {
-        let ready = self
-            .nodes
-            .iter()
-            .filter_map(
-                |(item, entry)| if entry.num_predecessors == 0 { Some(*item) } else { None },
-            )
-            .collect();
-
-        TopologicalSortIter { nodes: self.nodes, ready }
-    }
-}
-
-pub(crate) struct TopologicalSortIter<T> {
-    ready: VecDeque<T>,
-    nodes: FxHashMap<T, Entry<T>>,
-}
-
-impl<T> TopologicalSortIter<T>
-where
-    T: Copy + Eq + PartialEq + Hash,
-{
-    pub(crate) fn builder() -> TopologicSortIterBuilder<T> {
-        TopologicSortIterBuilder::default()
-    }
-
-    pub(crate) fn pending(&self) -> usize {
-        self.nodes.len()
-    }
-
-    pub(crate) fn mark_done(&mut self, item: T) {
-        let entry = self.nodes.remove(&item).expect("invariant: unknown item marked as done");
-
-        for successor in entry.successors {
-            let succ_entry = self
-                .nodes
-                .get_mut(&successor)
-                .expect("invariant: unknown successor referenced by entry");
-
-            succ_entry.num_predecessors -= 1;
-            if succ_entry.num_predecessors == 0 {
-                self.ready.push_back(successor);
-            }
-        }
-    }
-}
-
-impl<T> Iterator for TopologicalSortIter<T> {
-    type Item = T;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        self.ready.pop_front()
-    }
-}
-
-struct Entry<T> {
-    successors: Vec<T>,
-    num_predecessors: usize,
-}
-
-impl<T> Default for Entry<T> {
-    fn default() -> Self {
-        Self { successors: Default::default(), num_predecessors: 0 }
-    }
-}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs
index b8119e1aab3..fa2a46a0f7c 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs
@@ -390,11 +390,6 @@ pub fn source_edit_from_references(
     let mut edited_ranges = Vec::new();
     for &FileReference { range, ref name, .. } in references {
         let name_range = name.text_range();
-        if name_range.len() != range.len() {
-            // This usage comes from a different token kind that was downmapped to a NameLike in a macro
-            // Renaming this will most likely break things syntax-wise
-            continue;
-        }
         let has_emitted_edit = match name {
             // if the ranges differ then the node is inside a macro call, we can't really attempt
             // to make special rewrites like shorthand syntax and such, so just rename the node in
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/await_outside_of_async.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/await_outside_of_async.rs
index 92ca7a74184..2a7b0098edf 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/await_outside_of_async.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/await_outside_of_async.rs
@@ -14,6 +14,7 @@ pub(crate) fn await_outside_of_async(
         format!("`await` is used inside {}, which is not an `async` context", d.location),
         display_range,
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/bad_rtn.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/bad_rtn.rs
index 9ed85f9f208..ae42a88c313 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/bad_rtn.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/bad_rtn.rs
@@ -12,6 +12,7 @@ pub(crate) fn bad_rtn(ctx: &DiagnosticsContext<'_>, d: &hir::BadRtn) -> Diagnost
         "return type notation not allowed in this position yet",
         d.rtn.map(Into::into),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs
index c25b0a7bf7d..cbcaab6c747 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/break_outside_of_loop.rs
@@ -19,6 +19,7 @@ pub(crate) fn break_outside_of_loop(
         message,
         d.expr.map(|it| it.into()),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs
index 438dd2fdcb6..b284d9b3510 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/elided_lifetimes_in_path.rs
@@ -15,7 +15,6 @@ pub(crate) fn elided_lifetimes_in_path(
             "implicit elided lifetime not allowed here",
             d.generics_or_segment.map(Into::into),
         )
-        .experimental()
     } else {
         Diagnostic::new_with_syntax_node_ptr(
             ctx,
@@ -23,7 +22,6 @@ pub(crate) fn elided_lifetimes_in_path(
             "hidden lifetime parameters in types are deprecated",
             d.generics_or_segment.map(Into::into),
         )
-        .experimental()
     }
 }
 
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 a6da0fd9c5e..7d2ac373dc0 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
@@ -15,7 +15,6 @@ pub(crate) fn expected_function(
         format!("expected function, found {}", d.found.display(ctx.sema.db, ctx.display_target)),
         d.call.map(|it| it.into()),
     )
-    .experimental()
 }
 
 #[cfg(test)]
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
index b617c094983..9ae6f013c70 100644
--- 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
@@ -21,6 +21,7 @@ pub(crate) fn generic_args_prohibited(
         describe_reason(d.reason),
         d.args.map(Into::into),
     )
+    .stable()
     .with_fixes(fixes(ctx, d))
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs
index 47e1c84fecd..8611ef653b0 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs
@@ -33,6 +33,7 @@ pub(crate) fn inactive_code(
         message,
         ctx.sema.diagnostics_display_range(d.node),
     )
+    .stable()
     .with_unused(true);
     Some(res)
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs
index 0b9a2ec9db3..a0c364b0010 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incoherent_impl.rs
@@ -19,6 +19,7 @@ pub(crate) fn incoherent_impl(ctx: &DiagnosticsContext<'_>, d: &hir::IncoherentI
         "cannot define inherent `impl` for foreign type".to_owned(),
         display_range,
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs
index 289a0765732..38f10c778d6 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_case.rs
@@ -29,6 +29,7 @@ pub(crate) fn incorrect_case(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCas
         ),
         InFile::new(d.file, d.ident.into()),
     )
+    .stable()
     .with_fixes(fixes(ctx, d))
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs
index 17c7f75880c..06f35759420 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs
@@ -28,7 +28,6 @@ pub(crate) fn incorrect_generics_len(
         message,
         d.generics_or_segment.map(Into::into),
     )
-    .experimental()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_order.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_order.rs
index 84496df2d7c..b71586d6be0 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_order.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/incorrect_generics_order.rs
@@ -28,6 +28,7 @@ pub(crate) fn incorrect_generics_order(
         message,
         d.provided_arg.map(Into::into),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs
index d72b21099ce..7a6e98fe1b5 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_cast.rs
@@ -100,7 +100,7 @@ pub(crate) fn invalid_cast(ctx: &DiagnosticsContext<'_>, d: &hir::InvalidCast) -
         //     "cannot cast to a pointer of an unknown kind".to_owned(),
         // ),
     };
-    Diagnostic::new(code, message, display_range)
+    Diagnostic::new(code, message, display_range).stable()
 }
 
 // Diagnostic: cast-to-unsized
@@ -113,6 +113,7 @@ pub(crate) fn cast_to_unsized(ctx: &DiagnosticsContext<'_>, d: &hir::CastToUnsiz
         format_ty!(ctx, "cast to unsized type: `{}`", d.cast_ty),
         display_range,
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_derive_target.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_derive_target.rs
index ab0f5139f10..8b708f229d0 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_derive_target.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/invalid_derive_target.rs
@@ -15,6 +15,7 @@ pub(crate) fn invalid_derive_target(
         "`derive` may only be applied to `struct`s, `enum`s and `union`s",
         display_range,
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
index a2648a1995d..546512a6cf9 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs
@@ -19,6 +19,7 @@ pub(crate) fn macro_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroError) ->
         d.message.clone(),
         display_range,
     )
+    .stable()
 }
 
 // Diagnostic: macro-def-error
@@ -33,6 +34,7 @@ pub(crate) fn macro_def_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroDefErr
         d.message.clone(),
         display_range,
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/malformed_derive.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/malformed_derive.rs
index 0e47fff6f93..701b30b9b59 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/malformed_derive.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/malformed_derive.rs
@@ -14,6 +14,7 @@ pub(crate) fn malformed_derive(
         "malformed derive input, derive attributes are of the form `#[derive(Derive1, Derive2, ...)]`",
         display_range,
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs
index 63fd9b4e3f0..25c1e633ba3 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mismatched_arg_count.rs
@@ -26,6 +26,7 @@ pub(crate) fn mismatched_tuple_struct_pat_arg_count(
         message,
         invalid_args_range(ctx, d.expr_or_pat, d.expected, d.found),
     )
+    .stable()
 }
 
 // Diagnostic: mismatched-arg-count
@@ -42,6 +43,7 @@ pub(crate) fn mismatched_arg_count(
         message,
         invalid_args_range(ctx, d.call_expr, d.expected, d.found),
     )
+    .stable()
 }
 
 fn invalid_args_range(
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
index a354d123f5a..2b76efb1965 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -47,6 +47,7 @@ pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingField
     );
 
     Diagnostic::new_with_syntax_node_ptr(ctx, DiagnosticCode::RustcHardError("E0063"), message, ptr)
+        .stable()
         .with_fixes(fixes(ctx, d))
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_lifetime.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
index 8cdbb6384ff..76b30745a04 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_lifetime.rs
@@ -13,7 +13,6 @@ pub(crate) fn missing_lifetime(
         "missing lifetime specifier",
         d.generics_or_segment.map(Into::into),
     )
-    .experimental()
 }
 
 #[cfg(test)]
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 d3d3c3aa38d..1fc96b78eda 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
@@ -13,6 +13,7 @@ pub(crate) fn missing_match_arms(
         format!("missing match arm: {}", d.uncovered_patterns),
         d.scrutinee_expr.map(Into::into),
     )
+    .stable()
 }
 
 #[cfg(test)]
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 3c36b455ca9..364bead34ef 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
@@ -23,6 +23,7 @@ pub(crate) fn missing_unsafe(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsaf
         format!("{operation} is unsafe and requires an unsafe function or block"),
         d.node.map(|it| it.into()),
     )
+    .stable()
     .with_fixes(fixes(ctx, d))
 }
 
@@ -893,4 +894,25 @@ fn main() {
         "#,
         );
     }
+
+    #[test]
+    fn asm_label() {
+        check_diagnostics(
+            r#"
+//- minicore: asm
+fn foo() {
+    unsafe {
+        core::arch::asm!(
+            "jmp {}",
+            label {
+                let p = 0xDEADBEAF as *mut u8;
+                *p = 3;
+             // ^^ error: dereference of raw pointer is unsafe and requires an unsafe function or block
+            },
+        );
+    }
+}
+            "#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
index 780271361d7..01cf5e8fa52 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/moved_out_of_ref.rs
@@ -11,7 +11,7 @@ pub(crate) fn moved_out_of_ref(ctx: &DiagnosticsContext<'_>, d: &hir::MovedOutOf
         format!("cannot move `{}` out of reference", d.ty.display(ctx.sema.db, ctx.display_target)),
         d.span,
     )
-    .experimental() // spans are broken, and I'm not sure how precise we can detect copy types
+    // spans are broken, and I'm not sure how precise we can detect copy types
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 5d25f2c6a90..8831efa3117 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -55,6 +55,7 @@ pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_>, d: &hir::NeedMut) -> Option
             ),
             span,
         )
+        .stable()
         .with_fixes(fixes),
     )
 }
@@ -94,7 +95,7 @@ pub(crate) fn unused_mut(ctx: &DiagnosticsContext<'_>, d: &hir::UnusedMut) -> Op
             "variable does not need to be mutable",
             ast,
         )
-        .experimental() // Not supporting `#[allow(unused_mut)]` in proc macros leads to false positive.
+        // Not supporting `#[allow(unused_mut)]` in proc macros leads to false positive, hence not stable.
         .with_fixes(fixes),
     )
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs
index fa3347aa12e..84fb467a5ce 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs
@@ -22,6 +22,7 @@ pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField)
             "field is private",
             node,
         )
+        .stable()
     } else {
         Diagnostic::new_with_syntax_node_ptr(
             ctx,
@@ -32,6 +33,7 @@ pub(crate) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField)
             "no such field",
             node,
         )
+        .stable()
         .with_fixes(fixes(ctx, d))
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs
index ff1eeb0516a..35cefd23975 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/non_exhaustive_let.rs
@@ -14,6 +14,7 @@ pub(crate) fn non_exhaustive_let(
         format!("non-exhaustive pattern: {}", d.uncovered_patterns),
         d.pat.map(Into::into),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/parenthesized_generic_args_without_fn_trait.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/parenthesized_generic_args_without_fn_trait.rs
index ccf51723418..68f2b196570 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/parenthesized_generic_args_without_fn_trait.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/parenthesized_generic_args_without_fn_trait.rs
@@ -14,6 +14,7 @@ pub(crate) fn parenthesized_generic_args_without_fn_trait(
         "parenthesized type parameters may only be used with a `Fn` trait",
         d.args.map(Into::into),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
index fe32c590492..6d33ae0cf9b 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_assoc_item.rs
@@ -28,6 +28,7 @@ pub(crate) fn private_assoc_item(
         ),
         d.expr_or_pat.map(Into::into),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_field.rs
index 237a9b87871..5b4273a5a62 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_field.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/private_field.rs
@@ -15,6 +15,7 @@ pub(crate) fn private_field(ctx: &DiagnosticsContext<'_>, d: &hir::PrivateField)
         ),
         d.expr.map(|it| it.into()),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs
index 6b786450026..dec7be8b742 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs
@@ -31,6 +31,7 @@ pub(crate) fn remove_trailing_return(
             "replace return <expr>; with <expr>",
             display_range,
         )
+        .stable()
         .with_fixes(fixes(ctx, d)),
     )
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
index 8d717b9093b..7dc5b5b45e5 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
@@ -36,7 +36,6 @@ pub(crate) fn remove_unnecessary_else(
             "remove unnecessary else block",
             display_range,
         )
-        .experimental()
         .with_fixes(fixes(ctx, d)),
     )
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
index 6b335c52de7..37ce5f583f9 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs
@@ -21,6 +21,7 @@ pub(crate) fn replace_filter_map_next_with_find_map(
         "replace filter_map(..).next() with find_map(..)",
         InFile::new(d.file, d.next_expr.into()),
     )
+    .stable()
     .with_fixes(fixes(ctx, d))
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs
index 19ee1caa3e6..dd142db8590 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_incorrect_safety.rs
@@ -33,6 +33,7 @@ pub(crate) fn trait_impl_incorrect_safety(
             },
         ),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
index 2d7d78f5d7b..fa7ba90a756 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_missing_assoc_item.rs
@@ -29,6 +29,7 @@ pub(crate) fn trait_impl_missing_assoc_item(
             &|impl_| impl_.trait_().map(|t| t.syntax().text_range()),
         ),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs
index 35dc9b0fac8..96911d4781b 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_orphan.rs
@@ -16,8 +16,6 @@ pub(crate) fn trait_impl_orphan(
             .to_owned(),
         InFile::new(d.file_id, d.impl_.into()),
     )
-    // Not yet checked for false positives
-    .experimental()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
index d5c4bcf768a..4327b12dce7 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
@@ -61,6 +61,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
         format!("{redundant_item_name} is not a member of trait `{trait_name}`"),
         ide_db::FileRange { file_id: file_id.file_id(ctx.sema.db), range },
     )
+    .stable()
     .with_fixes(quickfix_for_redundant_assoc_item(
         ctx,
         d,
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 500c5de791d..5253734867e 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
@@ -53,8 +53,8 @@ pub(crate) fn type_mismatch(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch)
         display_range,
     )
     .with_fixes(fixes(ctx, d));
-    if diag.fixes.is_none() {
-        diag.experimental = true;
+    if diag.fixes.is_some() {
+        diag.experimental = false;
     }
     diag
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
index a933f1b4261..1915a88dd00 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/typed_hole.rs
@@ -37,6 +37,7 @@ pub(crate) fn typed_hole(ctx: &DiagnosticsContext<'_>, d: &hir::TypedHole) -> Di
     };
 
     Diagnostic::new(DiagnosticCode::RustcHardError("typed-hole"), message, display_range)
+        .stable()
         .with_fixes(fixes)
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/undeclared_label.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/undeclared_label.rs
index d16bfb80024..f81d34377da 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/undeclared_label.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/undeclared_label.rs
@@ -12,6 +12,7 @@ pub(crate) fn undeclared_label(
         format!("use of undeclared label `{}`", name.display(ctx.sema.db, ctx.edition)),
         d.node.map(|it| it.into()),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unimplemented_builtin_macro.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unimplemented_builtin_macro.rs
index 06f176f86f4..5627393f318 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unimplemented_builtin_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unimplemented_builtin_macro.rs
@@ -13,4 +13,5 @@ pub(crate) fn unimplemented_builtin_macro(
         "unimplemented built-in macro".to_owned(),
         d.node,
     )
+    .stable()
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
index 47fa3059362..af9126c8933 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
@@ -2,7 +2,8 @@
 
 use std::iter;
 
-use hir::{DefMap, InFile, ModuleSource, db::DefDatabase};
+use hir::crate_def_map;
+use hir::{DefMap, InFile, ModuleSource};
 use ide_db::base_db::RootQueryDb;
 use ide_db::text_edit::TextEdit;
 use ide_db::{
@@ -101,7 +102,8 @@ fn fixes(
     // check crate roots, i.e. main.rs, lib.rs, ...
     let relevant_crates = db.relevant_crates(file_id);
     'crates: for &krate in &*relevant_crates {
-        let crate_def_map = ctx.sema.db.crate_def_map(krate);
+        // FIXME: This shouldnt need to access the crate def map directly
+        let crate_def_map = crate_def_map(ctx.sema.db, krate);
 
         let root_module = &crate_def_map[DefMap::ROOT];
         let Some(root_file_id) = root_module.origin.file_id() else { continue };
@@ -156,7 +158,7 @@ fn fixes(
     stack.pop();
     let relevant_crates = db.relevant_crates(parent_id);
     'crates: for &krate in relevant_crates.iter() {
-        let crate_def_map = ctx.sema.db.crate_def_map(krate);
+        let crate_def_map = crate_def_map(ctx.sema.db, krate);
         let Some((_, module)) = crate_def_map.modules().find(|(_, module)| {
             module.origin.file_id().map(|file_id| file_id.file_id(ctx.sema.db)) == Some(parent_id)
                 && !module.origin.is_inline()
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unreachable_label.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unreachable_label.rs
index bdff2417ca1..0c9e0d6ce44 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unreachable_label.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unreachable_label.rs
@@ -12,6 +12,7 @@ pub(crate) fn unreachable_label(
         format!("use of unreachable label `{}`", name.display(ctx.sema.db, ctx.edition)),
         d.node.map(|it| it.into()),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs
index 614057ab52b..4ae528bf9f2 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_assoc_item.rs
@@ -13,7 +13,6 @@ pub(crate) fn unresolved_assoc_item(
         "no such associated item",
         d.expr_or_pat.map(Into::into),
     )
-    .experimental()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_extern_crate.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_extern_crate.rs
index 4cd73d46d5f..7c3eacf7e3a 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_extern_crate.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_extern_crate.rs
@@ -13,6 +13,7 @@ pub(crate) fn unresolved_extern_crate(
         "unresolved extern crate",
         d.decl.map(|it| it.into()),
     )
+    .stable()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs
index a4f4813cf5b..0649c97f820 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_field.rs
@@ -52,7 +52,6 @@ pub(crate) fn unresolved_field(
         }),
     )
     .with_fixes(fixes(ctx, d))
-    .experimental()
 }
 
 fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<Vec<Assist>> {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_ident.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_ident.rs
index 4f64dabeb52..801023dabd9 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_ident.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_ident.rs
@@ -13,7 +13,6 @@ pub(crate) fn unresolved_ident(
         range.range = in_node_range + range.range.start();
     }
     Diagnostic::new(DiagnosticCode::RustcHardError("E0425"), "no such value in this scope", range)
-        .experimental()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_import.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_import.rs
index 67c7e76a3bc..0da535d11b4 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_import.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_import.rs
@@ -18,7 +18,6 @@ pub(crate) fn unresolved_import(
     // - `cfg_if!`-generated code in libstd (we don't load the sysroot correctly)
     // - `core::arch` (we don't handle `#[path = "../<path>"]` correctly)
     // - proc macros and/or proc macro generated code
-    .experimental()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs
index 0d1c9775062..a87b8c42ac1 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_macro_call.rs
@@ -16,7 +16,6 @@ pub(crate) fn unresolved_macro_call(
         format!("unresolved macro `{}{bang}`", d.path.display(ctx.sema.db, ctx.edition)),
         display_range,
     )
-    .experimental()
 }
 
 #[cfg(test)]
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 7f07009dc56..00c2a8c4c46 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
@@ -47,7 +47,6 @@ pub(crate) fn unresolved_method(
         }),
     )
     .with_fixes(fixes(ctx, d))
-    .experimental()
 }
 
 fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -> Option<Vec<Assist>> {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_module.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_module.rs
index 599cabe3e4f..1a409d7e76a 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_module.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unresolved_module.rs
@@ -28,6 +28,7 @@ pub(crate) fn unresolved_module(
         },
         d.decl.map(|it| it.into()),
     )
+    .stable()
     .with_fixes(fixes(ctx, d))
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs
index 77b1075ea53..e6bbff05f7e 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs
@@ -50,8 +50,7 @@ pub(crate) fn unused_variables(
                 ast.file_id.is_macro(),
                 ctx.edition,
             )
-        }))
-        .experimental(),
+        })),
     )
 }
 
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 607721d611d..2af14ca949b 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -182,7 +182,7 @@ impl Diagnostic {
                 DiagnosticCode::Ra(_, s) => s,
             },
             unused: false,
-            experimental: false,
+            experimental: true,
             fixes: None,
             main_node: None,
         }
@@ -198,8 +198,8 @@ impl Diagnostic {
             .with_main_node(node)
     }
 
-    fn experimental(mut self) -> Diagnostic {
-        self.experimental = true;
+    fn stable(mut self) -> Diagnostic {
+        self.experimental = false;
         self
     }
 
@@ -424,14 +424,11 @@ pub fn semantic_diagnostics(
             AnyDiagnostic::MacroExpansionParseError(d) => {
                 // FIXME: Point to the correct error span here, not just the macro-call name
                 res.extend(d.errors.iter().take(16).map(|err| {
-                    {
                         Diagnostic::new(
                             DiagnosticCode::SyntaxError,
                             format!("Syntax Error in Expansion: {err}"),
                             ctx.resolve_precise_location(&d.node.clone(), d.precise_location),
                         )
-                    }
-                    .experimental()
                 }));
                 continue;
             },
@@ -485,12 +482,8 @@ pub fn semantic_diagnostics(
                 Some(it) => it,
                 None => continue,
             },
-            AnyDiagnostic::GenericArgsProhibited(d) => {
-                handlers::generic_args_prohibited::generic_args_prohibited(&ctx, &d)
-            }
-            AnyDiagnostic::ParenthesizedGenericArgsWithoutFnTrait(d) => {
-                handlers::parenthesized_generic_args_without_fn_trait::parenthesized_generic_args_without_fn_trait(&ctx, &d)
-            }
+            AnyDiagnostic::GenericArgsProhibited(d) => handlers::generic_args_prohibited::generic_args_prohibited(&ctx, &d),
+            AnyDiagnostic::ParenthesizedGenericArgsWithoutFnTrait(d) => handlers::parenthesized_generic_args_without_fn_trait::parenthesized_generic_args_without_fn_trait(&ctx, &d),
             AnyDiagnostic::BadRtn(d) => handlers::bad_rtn::bad_rtn(&ctx, &d),
             AnyDiagnostic::IncorrectGenericsLen(d) => handlers::incorrect_generics_len::incorrect_generics_len(&ctx, &d),
             AnyDiagnostic::IncorrectGenericsOrder(d) => handlers::incorrect_generics_order::incorrect_generics_order(&ctx, &d),
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
index f0247f32d7e..2c983287d89 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -5,17 +5,21 @@ mod tests;
 
 mod intra_doc_links;
 
+use std::ops::Range;
+
 use pulldown_cmark::{BrokenLink, CowStr, Event, InlineStr, LinkType, Options, Parser, Tag};
 use pulldown_cmark_to_cmark::{Options as CMarkOptions, cmark_resume_with_options};
 use stdx::format_to;
 use url::Url;
 
-use hir::{Adt, AsAssocItem, AssocItem, AssocItemContainer, HasAttrs, db::HirDatabase, sym};
+use hir::{
+    Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrsWithOwner, HasAttrs, db::HirDatabase, sym,
+};
 use ide_db::{
     RootDatabase,
     base_db::{CrateOrigin, LangCrateOrigin, ReleaseChannel, RootQueryDb},
     defs::{Definition, NameClass, NameRefClass},
-    documentation::{Documentation, HasDocs, docs_with_rangemap},
+    documentation::{DocsRangeMap, Documentation, HasDocs, docs_with_rangemap},
     helpers::pick_best_token,
 };
 use syntax::{
@@ -46,11 +50,17 @@ const MARKDOWN_OPTIONS: Options =
     Options::ENABLE_FOOTNOTES.union(Options::ENABLE_TABLES).union(Options::ENABLE_TASKLISTS);
 
 /// Rewrite documentation links in markdown to point to an online host (e.g. docs.rs)
-pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: Definition) -> String {
+pub(crate) fn rewrite_links(
+    db: &RootDatabase,
+    markdown: &str,
+    definition: Definition,
+    range_map: Option<DocsRangeMap>,
+) -> String {
     let mut cb = broken_link_clone_cb;
-    let doc = Parser::new_with_broken_link_callback(markdown, MARKDOWN_OPTIONS, Some(&mut cb));
+    let doc = Parser::new_with_broken_link_callback(markdown, MARKDOWN_OPTIONS, Some(&mut cb))
+        .into_offset_iter();
 
-    let doc = map_links(doc, |target, title| {
+    let doc = map_links(doc, |target, title, range| {
         // This check is imperfect, there's some overlap between valid intra-doc links
         // and valid URLs so we choose to be too eager to try to resolve what might be
         // a URL.
@@ -60,7 +70,16 @@ pub(crate) fn rewrite_links(db: &RootDatabase, markdown: &str, definition: Defin
             // Two possibilities:
             // * path-based links: `../../module/struct.MyStruct.html`
             // * module-based links (AKA intra-doc links): `super::super::module::MyStruct`
-            if let Some((target, title)) = rewrite_intra_doc_link(db, definition, target, title) {
+            let text_range =
+                TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
+            let is_inner_doc = range_map
+                .as_ref()
+                .and_then(|range_map| range_map.map(text_range))
+                .map(|(_, attr_id)| attr_id.is_inner_attr())
+                .unwrap_or(false);
+            if let Some((target, title)) =
+                rewrite_intra_doc_link(db, definition, target, title, is_inner_doc)
+            {
                 (None, target, title)
             } else if let Some(target) = rewrite_url_link(db, definition, target) {
                 (Some(LinkType::Inline), target, title.to_owned())
@@ -195,22 +214,23 @@ pub(crate) fn resolve_doc_path_for_def(
     def: Definition,
     link: &str,
     ns: Option<hir::Namespace>,
+    is_inner_doc: bool,
 ) -> Option<Definition> {
     match def {
-        Definition::Module(it) => it.resolve_doc_path(db, link, ns),
-        Definition::Crate(it) => it.resolve_doc_path(db, link, ns),
-        Definition::Function(it) => it.resolve_doc_path(db, link, ns),
-        Definition::Adt(it) => it.resolve_doc_path(db, link, ns),
-        Definition::Variant(it) => it.resolve_doc_path(db, link, ns),
-        Definition::Const(it) => it.resolve_doc_path(db, link, ns),
-        Definition::Static(it) => it.resolve_doc_path(db, link, ns),
-        Definition::Trait(it) => it.resolve_doc_path(db, link, ns),
-        Definition::TraitAlias(it) => it.resolve_doc_path(db, link, ns),
-        Definition::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
-        Definition::Macro(it) => it.resolve_doc_path(db, link, ns),
-        Definition::Field(it) => it.resolve_doc_path(db, link, ns),
-        Definition::SelfType(it) => it.resolve_doc_path(db, link, ns),
-        Definition::ExternCrateDecl(it) => it.resolve_doc_path(db, link, ns),
+        Definition::Module(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::Crate(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::Function(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::Adt(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::Variant(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::Const(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::Static(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::Trait(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::TraitAlias(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::TypeAlias(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::Macro(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::Field(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::SelfType(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
+        Definition::ExternCrateDecl(it) => it.resolve_doc_path(db, link, ns, is_inner_doc),
         Definition::BuiltinAttr(_)
         | Definition::BuiltinType(_)
         | Definition::BuiltinLifetime(_)
@@ -289,31 +309,58 @@ impl DocCommentToken {
         let relative_comment_offset = offset - original_start - prefix_len;
 
         sema.descend_into_macros(doc_token).into_iter().find_map(|t| {
-            let (node, descended_prefix_len) = match_ast! {
+            let (node, descended_prefix_len, is_inner) = match_ast!{
                 match t {
-                    ast::Comment(comment) => (t.parent()?, TextSize::try_from(comment.prefix().len()).ok()?),
-                    ast::String(string) => (t.parent_ancestors().skip_while(|n| n.kind() != ATTR).nth(1)?, string.open_quote_text_range()?.len()),
+                    ast::Comment(comment) => {
+                        (t.parent()?, TextSize::try_from(comment.prefix().len()).ok()?, comment.is_inner())
+                    },
+                    ast::String(string) => {
+                        let attr = t.parent_ancestors().find_map(ast::Attr::cast)?;
+                        let attr_is_inner = attr.excl_token().map(|excl| excl.kind() == BANG).unwrap_or(false);
+                        (attr.syntax().parent()?, string.open_quote_text_range()?.len(), attr_is_inner)
+                    },
                     _ => return None,
                 }
             };
             let token_start = t.text_range().start();
             let abs_in_expansion_offset = token_start + relative_comment_offset + descended_prefix_len;
-
-            let (attributes, def) = doc_attributes(sema, &node)?;
+            let (attributes, def) = Self::doc_attributes(sema, &node, is_inner)?;
             let (docs, doc_mapping) = docs_with_rangemap(sema.db, &attributes)?;
-            let (in_expansion_range, link, ns) =
+            let (in_expansion_range, link, ns, is_inner) =
                 extract_definitions_from_docs(&docs).into_iter().find_map(|(range, link, ns)| {
-                    let mapped = doc_mapping.map(range)?;
-                    (mapped.value.contains(abs_in_expansion_offset)).then_some((mapped.value, link, ns))
+                    let (mapped, idx) = doc_mapping.map(range)?;
+                    (mapped.value.contains(abs_in_expansion_offset)).then_some((mapped.value, link, ns, idx.is_inner_attr()))
                 })?;
             // get the relative range to the doc/attribute in the expansion
             let in_expansion_relative_range = in_expansion_range - descended_prefix_len - token_start;
             // Apply relative range to the original input comment
             let absolute_range = in_expansion_relative_range + original_start + prefix_len;
-            let def = resolve_doc_path_for_def(sema.db, def, &link, ns)?;
+            let def = resolve_doc_path_for_def(sema.db, def, &link, ns, is_inner)?;
             cb(def, node, absolute_range)
         })
     }
+
+    /// When we hover a inner doc item, this find a attached definition.
+    /// ```
+    /// // node == ITEM_LIST
+    /// // node.parent == EXPR_BLOCK
+    /// // node.parent().parent() == FN
+    /// fn f() {
+    ///    //! [`S$0`]
+    /// }
+    /// ```
+    fn doc_attributes(
+        sema: &Semantics<'_, RootDatabase>,
+        node: &SyntaxNode,
+        is_inner_doc: bool,
+    ) -> Option<(AttrsWithOwner, Definition)> {
+        if is_inner_doc && node.kind() != SOURCE_FILE {
+            let parent = node.parent()?;
+            doc_attributes(sema, &parent).or(doc_attributes(sema, &parent.parent()?))
+        } else {
+            doc_attributes(sema, node)
+        }
+    }
 }
 
 fn broken_link_clone_cb(link: BrokenLink<'_>) -> Option<(CowStr<'_>, CowStr<'_>)> {
@@ -369,6 +416,7 @@ fn rewrite_intra_doc_link(
     def: Definition,
     target: &str,
     title: &str,
+    is_inner_doc: bool,
 ) -> Option<(String, String)> {
     let (link, ns) = parse_intra_doc_link(target);
 
@@ -377,7 +425,7 @@ fn rewrite_intra_doc_link(
         None => (link, None),
     };
 
-    let resolved = resolve_doc_path_for_def(db, def, link, ns)?;
+    let resolved = resolve_doc_path_for_def(db, def, link, ns, is_inner_doc)?;
     let mut url = get_doc_base_urls(db, resolved, None, None).0?;
 
     let (_, file, frag) = filename_and_frag_for_def(db, resolved)?;
@@ -421,8 +469,8 @@ fn mod_path_of_def(db: &RootDatabase, def: Definition) -> Option<String> {
 
 /// Rewrites a markdown document, applying 'callback' to each link.
 fn map_links<'e>(
-    events: impl Iterator<Item = Event<'e>>,
-    callback: impl Fn(&str, &str) -> (Option<LinkType>, String, String),
+    events: impl Iterator<Item = (Event<'e>, Range<usize>)>,
+    callback: impl Fn(&str, &str, Range<usize>) -> (Option<LinkType>, String, String),
 ) -> impl Iterator<Item = Event<'e>> {
     let mut in_link = false;
     // holds the origin link target on start event and the rewritten one on end event
@@ -432,7 +480,7 @@ fn map_links<'e>(
     // `Shortcut` type parsed from Start/End tags doesn't make sense for url links
     let mut end_link_type: Option<LinkType> = None;
 
-    events.map(move |evt| match evt {
+    events.map(move |(evt, range)| match evt {
         Event::Start(Tag::Link(link_type, ref target, _)) => {
             in_link = true;
             end_link_target = Some(target.clone());
@@ -449,7 +497,7 @@ fn map_links<'e>(
         }
         Event::Text(s) if in_link => {
             let (link_type, link_target_s, link_name) =
-                callback(&end_link_target.take().unwrap(), &s);
+                callback(&end_link_target.take().unwrap(), &s, range);
             end_link_target = Some(CowStr::Boxed(link_target_s.into()));
             if !matches!(end_link_type, Some(LinkType::Autolink)) {
                 end_link_type = link_type;
@@ -458,7 +506,7 @@ fn map_links<'e>(
         }
         Event::Code(s) if in_link => {
             let (link_type, link_target_s, link_name) =
-                callback(&end_link_target.take().unwrap(), &s);
+                callback(&end_link_target.take().unwrap(), &s, range);
             end_link_target = Some(CowStr::Boxed(link_target_s.into()));
             if !matches!(end_link_type, Some(LinkType::Autolink)) {
                 end_link_type = link_type;
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
index 91785be8d8b..6af156fa668 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
@@ -5,7 +5,7 @@ use hir::Semantics;
 use ide_db::{
     FilePosition, FileRange, RootDatabase,
     defs::Definition,
-    documentation::{Documentation, HasDocs},
+    documentation::{DocsRangeMap, Documentation, HasDocs},
 };
 use itertools::Itertools;
 use syntax::{AstNode, SyntaxNode, ast, match_ast};
@@ -45,8 +45,8 @@ fn check_external_docs(
 fn check_rewrite(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
     let (analysis, position) = fixture::position(ra_fixture);
     let sema = &Semantics::new(&analysis.db);
-    let (cursor_def, docs) = def_under_cursor(sema, &position);
-    let res = rewrite_links(sema.db, docs.as_str(), cursor_def);
+    let (cursor_def, docs, range) = def_under_cursor(sema, &position);
+    let res = rewrite_links(sema.db, docs.as_str(), cursor_def, Some(range));
     expect.assert_eq(&res)
 }
 
@@ -56,12 +56,14 @@ fn check_doc_links(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
     let (analysis, position, mut expected) = fixture::annotations(ra_fixture);
     expected.sort_by_key(key_fn);
     let sema = &Semantics::new(&analysis.db);
-    let (cursor_def, docs) = def_under_cursor(sema, &position);
+    let (cursor_def, docs, range) = def_under_cursor(sema, &position);
     let defs = extract_definitions_from_docs(&docs);
     let actual: Vec<_> = defs
         .into_iter()
-        .flat_map(|(_, link, ns)| {
-            let def = resolve_doc_path_for_def(sema.db, cursor_def, &link, ns)
+        .flat_map(|(text_range, link, ns)| {
+            let attr = range.map(text_range);
+            let is_inner_attr = attr.map(|(_file, attr)| attr.is_inner_attr()).unwrap_or(false);
+            let def = resolve_doc_path_for_def(sema.db, cursor_def, &link, ns, is_inner_attr)
                 .unwrap_or_else(|| panic!("Failed to resolve {link}"));
             def.try_to_nav(sema.db).unwrap().into_iter().zip(iter::repeat(link))
         })
@@ -78,7 +80,7 @@ fn check_doc_links(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
 fn def_under_cursor(
     sema: &Semantics<'_, RootDatabase>,
     position: &FilePosition,
-) -> (Definition, Documentation) {
+) -> (Definition, Documentation, DocsRangeMap) {
     let (docs, def) = sema
         .parse_guess_edition(position.file_id)
         .syntax()
@@ -89,31 +91,31 @@ fn def_under_cursor(
         .find_map(|it| node_to_def(sema, &it))
         .expect("no def found")
         .unwrap();
-    let docs = docs.expect("no docs found for cursor def");
-    (def, docs)
+    let (docs, range) = docs.expect("no docs found for cursor def");
+    (def, docs, range)
 }
 
 fn node_to_def(
     sema: &Semantics<'_, RootDatabase>,
     node: &SyntaxNode,
-) -> Option<Option<(Option<Documentation>, Definition)>> {
+) -> Option<Option<(Option<(Documentation, DocsRangeMap)>, Definition)>> {
     Some(match_ast! {
         match node {
-            ast::SourceFile(it)  => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Module(def))),
-            ast::Module(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Module(def))),
-            ast::Fn(it)          => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Function(def))),
-            ast::Struct(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Struct(def)))),
-            ast::Union(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Union(def)))),
-            ast::Enum(it)        => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Adt(hir::Adt::Enum(def)))),
-            ast::Variant(it)     => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Variant(def))),
-            ast::Trait(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Trait(def))),
-            ast::Static(it)      => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Static(def))),
-            ast::Const(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Const(def))),
-            ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::TypeAlias(def))),
-            ast::Impl(it)        => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::SelfType(def))),
-            ast::RecordField(it) => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Field(def))),
-            ast::TupleField(it)  => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Field(def))),
-            ast::Macro(it)       => sema.to_def(&it).map(|def| (def.docs(sema.db), Definition::Macro(def))),
+            ast::SourceFile(it)  => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Module(def))),
+            ast::Module(it)      => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Module(def))),
+            ast::Fn(it)          => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Function(def))),
+            ast::Struct(it)      => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Adt(hir::Adt::Struct(def)))),
+            ast::Union(it)       => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Adt(hir::Adt::Union(def)))),
+            ast::Enum(it)        => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Adt(hir::Adt::Enum(def)))),
+            ast::Variant(it)     => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Variant(def))),
+            ast::Trait(it)       => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Trait(def))),
+            ast::Static(it)      => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Static(def))),
+            ast::Const(it)       => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Const(def))),
+            ast::TypeAlias(it)   => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::TypeAlias(def))),
+            ast::Impl(it)        => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::SelfType(def))),
+            ast::RecordField(it) => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Field(def))),
+            ast::TupleField(it)  => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Field(def))),
+            ast::Macro(it)       => sema.to_def(&it).map(|def| (def.docs_with_rangemap(sema.db), Definition::Macro(def))),
             // ast::Use(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))),
             _ => return None,
         }
@@ -576,6 +578,40 @@ struct S$0(i32);
 }
 
 #[test]
+fn doc_links_module() {
+    check_doc_links(
+        r#"
+/// [`M`]
+/// [`M::f`]
+mod M$0 {
+  //^ M
+  #![doc = "inner_item[`S`]"]
+
+    pub fn f() {}
+         //^ M::f
+    pub struct S;
+             //^ S
+}
+"#,
+    );
+
+    check_doc_links(
+        r#"
+mod M$0 {
+  //^ super::M
+    //! [`super::M`]
+    //! [`super::M::f`]
+    //! [`super::M::S`]
+    pub fn f() {}
+         //^ super::M::f
+    pub struct S;
+             //^ super::M::S
+}
+"#,
+    );
+}
+
+#[test]
 fn rewrite_html_root_url() {
     check_rewrite(
         r#"
@@ -691,6 +727,29 @@ fn rewrite_intra_doc_link_with_anchor() {
 }
 
 #[test]
+fn rewrite_module() {
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+/// [Foo]
+pub mod $0Foo{
+};
+"#,
+        expect![[r#"[Foo](https://docs.rs/foo/*/foo/Foo/index.html)"#]],
+    );
+
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+pub mod $0Foo{
+    //! [super::Foo]
+};
+"#,
+        expect![[r#"[super::Foo](https://docs.rs/foo/*/foo/Foo/index.html)"#]],
+    );
+}
+
+#[test]
 fn rewrite_intra_doc_link_to_associated_item() {
     check_rewrite(
         r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index b894e857522..c60ca3562f6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -1923,6 +1923,74 @@ pub fn foo() { }
     }
 
     #[test]
+    fn goto_def_for_intra_doc_link_outer_same_file() {
+        check(
+            r#"
+/// [`S$0`]
+mod m {
+    //! [`super::S`]
+}
+struct S;
+     //^
+            "#,
+        );
+
+        check(
+            r#"
+/// [`S$0`]
+mod m {}
+struct S;
+     //^
+            "#,
+        );
+
+        check(
+            r#"
+/// [`S$0`]
+fn f() {
+    //! [`S`]
+}
+struct S;
+     //^
+            "#,
+        );
+    }
+
+    #[test]
+    fn goto_def_for_intra_doc_link_inner_same_file() {
+        check(
+            r#"
+/// [`S`]
+mod m {
+    //! [`super::S$0`]
+}
+struct S;
+     //^
+            "#,
+        );
+
+        check(
+            r#"
+mod m {
+    //! [`super::S$0`]
+}
+struct S;
+     //^
+            "#,
+        );
+
+        check(
+            r#"
+fn f() {
+    //! [`S$0`]
+}
+struct S;
+     //^
+            "#,
+        );
+    }
+
+    #[test]
     fn goto_def_for_intra_doc_link_inner() {
         check(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
index 80624eeae80..fb8dbcfc735 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -89,6 +89,9 @@ pub(crate) fn highlight_related(
         T![break] | T![loop] | T![while] | T![continue] if config.break_points => {
             highlight_break_points(sema, token).remove(&file_id)
         }
+        T![unsafe] if token.parent().and_then(ast::BlockExpr::cast).is_some() => {
+            highlight_unsafe_points(sema, token).remove(&file_id)
+        }
         T![|] if config.closure_captures => {
             highlight_closure_captures(sema, token, file_id, span_file_id.file_id())
         }
@@ -706,6 +709,44 @@ impl<'a> WalkExpandedExprCtx<'a> {
     }
 }
 
+pub(crate) fn highlight_unsafe_points(
+    sema: &Semantics<'_, RootDatabase>,
+    token: SyntaxToken,
+) -> FxHashMap<EditionedFileId, Vec<HighlightedRange>> {
+    fn hl(
+        sema: &Semantics<'_, RootDatabase>,
+        unsafe_token: &SyntaxToken,
+        block_expr: Option<ast::BlockExpr>,
+    ) -> Option<FxHashMap<EditionedFileId, Vec<HighlightedRange>>> {
+        let mut highlights: FxHashMap<EditionedFileId, Vec<_>> = FxHashMap::default();
+
+        let mut push_to_highlights = |file_id, range| {
+            if let Some(FileRange { file_id, range }) = original_frange(sema.db, file_id, range) {
+                let hrange = HighlightedRange { category: ReferenceCategory::empty(), range };
+                highlights.entry(file_id).or_default().push(hrange);
+            }
+        };
+
+        // highlight unsafe keyword itself
+        let unsafe_token_file_id = sema.hir_file_for(&unsafe_token.parent()?);
+        push_to_highlights(unsafe_token_file_id, Some(unsafe_token.text_range()));
+
+        // highlight unsafe operations
+        if let Some(block) = block_expr {
+            if let Some(body) = sema.body_for(InFile::new(unsafe_token_file_id, block.syntax())) {
+                let unsafe_ops = sema.get_unsafe_ops(body);
+                for unsafe_op in unsafe_ops {
+                    push_to_highlights(unsafe_op.file_id, Some(unsafe_op.value.text_range()));
+                }
+            }
+        }
+
+        Some(highlights)
+    }
+
+    hl(sema, &token, token.parent().and_then(ast::BlockExpr::cast)).unwrap_or_default()
+}
+
 #[cfg(test)]
 mod tests {
     use itertools::Itertools;
@@ -755,6 +796,32 @@ mod tests {
     }
 
     #[test]
+    fn test_hl_unsafe_block() {
+        check(
+            r#"
+fn foo() {
+    unsafe fn this_is_unsafe_function() {}
+
+    unsa$0fe {
+  //^^^^^^
+        let raw_ptr = &42 as *const i32;
+        let val = *raw_ptr;
+                //^^^^^^^^
+
+        let mut_ptr = &mut 5 as *mut i32;
+        *mut_ptr = 10;
+      //^^^^^^^^
+
+        this_is_unsafe_function();
+      //^^^^^^^^^^^^^^^^^^^^^^^^^
+    }
+
+}
+"#,
+        );
+    }
+
+    #[test]
     fn test_hl_tuple_fields() {
         check(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 075afcec019..873e31b4a33 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -456,7 +456,7 @@ pub(crate) fn hover_for_definition(
     let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default();
     let subst_types = subst.map(|subst| subst.types(db));
 
-    let markup = render::definition(
+    let (markup, range_map) = render::definition(
         sema.db,
         def,
         famous_defs.as_ref(),
@@ -469,7 +469,7 @@ pub(crate) fn hover_for_definition(
         display_target,
     );
     HoverResult {
-        markup: render::process_markup(sema.db, def, &markup, config),
+        markup: render::process_markup(sema.db, def, &markup, range_map, config),
         actions: [
             show_fn_references_action(sema.db, def),
             show_implementations_action(sema.db, def),
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index 69b83f3b12d..ad720c8a627 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -11,7 +11,7 @@ use hir::{
 use ide_db::{
     RootDatabase,
     defs::Definition,
-    documentation::HasDocs,
+    documentation::{DocsRangeMap, HasDocs},
     famous_defs::FamousDefs,
     generated::lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES},
     syntax_helpers::prettify_macro_expansion,
@@ -21,7 +21,7 @@ use rustc_apfloat::{
     Float,
     ieee::{Half as f16, Quad as f128},
 };
-use span::Edition;
+use span::{Edition, TextSize};
 use stdx::format_to;
 use syntax::{AstNode, AstToken, Direction, SyntaxToken, T, algo, ast, match_ast};
 
@@ -276,13 +276,10 @@ pub(super) fn keyword(
         keyword_hints(sema, token, parent, edition, display_target);
 
     let doc_owner = find_std_module(&famous_defs, &keyword_mod, edition)?;
-    let docs = doc_owner.docs(sema.db)?;
-    let markup = process_markup(
-        sema.db,
-        Definition::Module(doc_owner),
-        &markup(Some(docs.into()), description, None, None, String::new()),
-        config,
-    );
+    let (docs, range_map) = doc_owner.docs_with_rangemap(sema.db)?;
+    let (markup, range_map) =
+        markup(Some(docs.into()), Some(range_map), description, None, None, String::new());
+    let markup = process_markup(sema.db, Definition::Module(doc_owner), &markup, range_map, config);
     Some(HoverResult { markup, actions })
 }
 
@@ -371,11 +368,15 @@ pub(super) fn process_markup(
     db: &RootDatabase,
     def: Definition,
     markup: &Markup,
+    markup_range_map: Option<DocsRangeMap>,
     config: &HoverConfig,
 ) -> Markup {
     let markup = markup.as_str();
-    let markup =
-        if config.links_in_hover { rewrite_links(db, markup, def) } else { remove_links(markup) };
+    let markup = if config.links_in_hover {
+        rewrite_links(db, markup, def, markup_range_map)
+    } else {
+        remove_links(markup)
+    };
     Markup::from(markup)
 }
 
@@ -482,7 +483,7 @@ pub(super) fn definition(
     config: &HoverConfig,
     edition: Edition,
     display_target: DisplayTarget,
-) -> Markup {
+) -> (Markup, Option<DocsRangeMap>) {
     let mod_path = definition_path(db, &def, edition);
     let label = match def {
         Definition::Trait(trait_) => trait_
@@ -518,7 +519,12 @@ pub(super) fn definition(
         }
         _ => def.label(db, display_target),
     };
-    let docs = def.docs(db, famous_defs, display_target);
+    let (docs, range_map) =
+        if let Some((docs, doc_range)) = def.docs_with_rangemap(db, famous_defs, display_target) {
+            (Some(docs), doc_range)
+        } else {
+            (None, None)
+        };
     let value = || match def {
         Definition::Variant(it) => {
             if !it.parent_enum(db).is_data_carrying(db) {
@@ -807,6 +813,7 @@ pub(super) fn definition(
 
     markup(
         docs.map(Into::into),
+        range_map,
         desc,
         extra.is_empty().not().then_some(extra),
         mod_path,
@@ -1083,11 +1090,12 @@ fn definition_path(db: &RootDatabase, &def: &Definition, edition: Edition) -> Op
 
 fn markup(
     docs: Option<String>,
+    range_map: Option<DocsRangeMap>,
     rust: String,
     extra: Option<String>,
     mod_path: Option<String>,
     subst_types: String,
-) -> Markup {
+) -> (Markup, Option<DocsRangeMap>) {
     let mut buf = String::new();
 
     if let Some(mod_path) = mod_path {
@@ -1106,9 +1114,15 @@ fn markup(
     }
 
     if let Some(doc) = docs {
-        format_to!(buf, "\n___\n\n{}", doc);
+        format_to!(buf, "\n___\n\n");
+        let offset = TextSize::new(buf.len() as u32);
+        let buf_range_map = range_map.map(|range_map| range_map.shift_docstring_line_range(offset));
+        format_to!(buf, "{}", doc);
+
+        (buf.into(), buf_range_map)
+    } else {
+        (buf.into(), None)
     }
-    buf.into()
 }
 
 fn find_std_module(
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 7b7eef9d579..06ca24c3ec3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -7375,6 +7375,128 @@ pub struct Foo(i32);
 }
 
 #[test]
+fn hover_intra_inner_attr() {
+    check(
+        r#"
+/// outer comment for [`Foo`]
+#[doc = "Doc outer comment for [`Foo`]"]
+pub fn Foo {
+    //! inner comment for [`Foo$0`]
+    #![doc = "Doc inner comment for [`Foo`]"]
+}
+"#,
+        expect![[r#"
+            *[`Foo`]*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            pub fn Foo()
+            ```
+
+            ---
+
+            outer comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/fn.Foo.html)
+            Doc outer comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/fn.Foo.html)
+            inner comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/fn.Foo.html)
+            Doc inner comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/fn.Foo.html)
+        "#]],
+    );
+
+    check(
+        r#"
+/// outer comment for [`Foo`]
+#[doc = "Doc outer comment for [`Foo`]"]
+pub mod Foo {
+    //! inner comment for [`super::Foo$0`]
+    #![doc = "Doc inner comment for [`super::Foo`]"]
+}
+"#,
+        expect![[r#"
+            *[`super::Foo`]*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            pub mod Foo
+            ```
+
+            ---
+
+            outer comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/Foo/index.html)
+            Doc outer comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/Foo/index.html)
+            inner comment for [`super::Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/Foo/index.html)
+            Doc inner comment for [`super::Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/Foo/index.html)
+        "#]],
+    );
+}
+
+#[test]
+fn hover_intra_outer_attr() {
+    check(
+        r#"
+/// outer comment for [`Foo$0`]
+#[doc = "Doc outer comment for [`Foo`]"]
+pub fn Foo() {
+    //! inner comment for [`Foo`]
+    #![doc = "Doc inner comment for [`Foo`]"]
+}
+"#,
+        expect![[r#"
+            *[`Foo`]*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            pub fn Foo()
+            ```
+
+            ---
+
+            outer comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/fn.Foo.html)
+            Doc outer comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/fn.Foo.html)
+            inner comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/fn.Foo.html)
+            Doc inner comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/fn.Foo.html)
+        "#]],
+    );
+
+    check(
+        r#"
+/// outer comment for [`Foo$0`]
+#[doc = "Doc outer comment for [`Foo`]"]
+pub mod Foo {
+    //! inner comment for [`super::Foo`]
+    #![doc = "Doc inner comment for [`super::Foo`]"]
+}
+"#,
+        expect![[r#"
+            *[`Foo`]*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            pub mod Foo
+            ```
+
+            ---
+
+            outer comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/Foo/index.html)
+            Doc outer comment for [`Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/Foo/index.html)
+            inner comment for [`super::Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/Foo/index.html)
+            Doc inner comment for [`super::Foo`](https://docs.rs/ra_test_fixture/*/ra_test_fixture/Foo/index.html)
+        "#]],
+    );
+}
+
+#[test]
 fn hover_intra_generics() {
     check(
         r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index aa525a86123..d649dffbd90 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -62,7 +62,7 @@ use std::panic::{AssertUnwindSafe, UnwindSafe};
 
 use cfg::CfgOptions;
 use fetch_crates::CrateInfo;
-use hir::{ChangeWithProcMacros, EditionedFileId, sym};
+use hir::{ChangeWithProcMacros, EditionedFileId, crate_def_map, sym};
 use ide_db::{
     FxHashMap, FxIndexSet, LineIndexDatabase,
     base_db::{
@@ -627,7 +627,7 @@ impl Analysis {
 
     /// Returns true if this crate has `no_std` or `no_core` specified.
     pub fn is_crate_no_std(&self, crate_id: Crate) -> Cancellable<bool> {
-        self.with_db(|db| hir::db::DefDatabase::crate_def_map(db, crate_id).is_no_std())
+        self.with_db(|db| crate_def_map(db, crate_id).is_no_std())
     }
 
     /// Returns the root file of the given crate.
diff --git a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
index 6dc01c45063..50219cee57d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
@@ -1,4 +1,4 @@
-use hir::{Semantics, db::DefDatabase};
+use hir::{Semantics, crate_def_map};
 use ide_db::{
     FileId, FilePosition, RootDatabase,
     base_db::{Crate, RootQueryDb},
@@ -58,7 +58,7 @@ pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec<Crate> {
         .iter()
         .copied()
         .filter(|&crate_id| {
-            db.crate_def_map(crate_id).modules_for_file(db, file_id).next().is_some()
+            crate_def_map(db, crate_id).modules_for_file(db, file_id).next().is_some()
         })
         .sorted()
         .collect()
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
index 0998e14c87b..7f5c2c1ec84 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
@@ -129,11 +129,18 @@ pub(super) fn doc_comment(
         extract_definitions_from_docs(&docs)
             .into_iter()
             .filter_map(|(range, link, ns)| {
-                doc_mapping.map(range).filter(|mapping| mapping.file_id == src_file_id).and_then(
-                    |InFile { value: mapped_range, .. }| {
-                        Some(mapped_range).zip(resolve_doc_path_for_def(sema.db, def, &link, ns))
-                    },
-                )
+                doc_mapping
+                    .map(range)
+                    .filter(|(mapping, _)| mapping.file_id == src_file_id)
+                    .and_then(|(InFile { value: mapped_range, .. }, attr_id)| {
+                        Some(mapped_range).zip(resolve_doc_path_for_def(
+                            sema.db,
+                            def,
+                            &link,
+                            ns,
+                            attr_id.is_inner_attr(),
+                        ))
+                    })
             })
             .for_each(|(range, def)| {
                 hl.add(HlRange {
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 2686a75c7c8..30e2d5416cf 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -512,10 +512,6 @@ impl ProcMacroExpander for Expander {
             Err(err) => Err(ProcMacroExpansionError::System(err.to_string())),
         }
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().downcast_ref::<Self>().is_some_and(|other| self == other)
-    }
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/mbe/src/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/tests.rs
index a5672e4e050..3369dfff281 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/tests.rs
@@ -356,3 +356,120 @@ fn expr_2021() {
             ;"#]],
     );
 }
+
+#[test]
+fn minus_belongs_to_literal() {
+    let decl = r#"
+(-1) => {-1};
+(- 2) => {- 2};
+(- 3.0) => {- 3.0};
+(@$lit:literal) => {$lit}
+"#;
+    let check = |args, expect| check(Edition::CURRENT, Edition::CURRENT, decl, args, expect);
+    check(
+        "-1",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..2#ROOT2024 1:0@0..2#ROOT2024
+              PUNCH   - [alone] 0:0@10..11#ROOT2024
+              LITERAL Integer 1 0:0@11..12#ROOT2024
+
+            -1"#]],
+    );
+    check(
+        "- 1",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..3#ROOT2024 1:0@0..3#ROOT2024
+              PUNCH   - [alone] 0:0@10..11#ROOT2024
+              LITERAL Integer 1 0:0@11..12#ROOT2024
+
+            -1"#]],
+    );
+    check(
+        "-2",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..2#ROOT2024 1:0@0..2#ROOT2024
+              PUNCH   - [alone] 0:0@25..26#ROOT2024
+              LITERAL Integer 2 0:0@27..28#ROOT2024
+
+            -2"#]],
+    );
+    check(
+        "- 2",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..3#ROOT2024 1:0@0..3#ROOT2024
+              PUNCH   - [alone] 0:0@25..26#ROOT2024
+              LITERAL Integer 2 0:0@27..28#ROOT2024
+
+            -2"#]],
+    );
+    check(
+        "-3.0",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..4#ROOT2024 1:0@0..4#ROOT2024
+              PUNCH   - [alone] 0:0@43..44#ROOT2024
+              LITERAL Float 3.0 0:0@45..48#ROOT2024
+
+            -3.0"#]],
+    );
+    check(
+        "- 3.0",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..5#ROOT2024 1:0@0..5#ROOT2024
+              PUNCH   - [alone] 0:0@43..44#ROOT2024
+              LITERAL Float 3.0 0:0@45..48#ROOT2024
+
+            -3.0"#]],
+    );
+    check(
+        "@1",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..2#ROOT2024 1:0@0..2#ROOT2024
+              LITERAL Integer 1 1:0@1..2#ROOT2024
+
+            1"#]],
+    );
+    check(
+        "@-1",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..3#ROOT2024 1:0@0..3#ROOT2024
+              PUNCH   - [alone] 1:0@1..2#ROOT2024
+              LITERAL Integer 1 1:0@2..3#ROOT2024
+
+            -1"#]],
+    );
+    check(
+        "@1.0",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..4#ROOT2024 1:0@0..4#ROOT2024
+              LITERAL Float 1.0 1:0@1..4#ROOT2024
+
+            1.0"#]],
+    );
+    check(
+        "@-1.0",
+        expect![[r#"
+            SUBTREE $$ 1:0@0..5#ROOT2024 1:0@0..5#ROOT2024
+              PUNCH   - [alone] 1:0@1..2#ROOT2024
+              LITERAL Float 1.0 1:0@2..5#ROOT2024
+
+            -1.0"#]],
+    );
+    check(
+        "@--1.0",
+        expect![[r#"
+            ExpandError {
+                inner: (
+                    1:0@1..2#ROOT2024,
+                    BindingError(
+                        "expected literal",
+                    ),
+                ),
+            }
+
+            SUBTREE $$ 1:0@0..6#ROOT2024 1:0@0..6#ROOT2024
+              PUNCH   - [joint] 1:0@1..2#ROOT2024
+              PUNCH   - [alone] 1:0@2..3#ROOT2024
+
+            --"#]],
+    );
+}
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 5faf6fc2759..8cc332d4633 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
@@ -381,10 +381,14 @@ fn parse_asm_expr(p: &mut Parser<'_>, m: Marker) -> Option<CompletedMarker> {
             op.complete(p, ASM_REG_OPERAND);
             op_n.complete(p, ASM_OPERAND_NAMED);
         } else if p.eat_contextual_kw(T![label]) {
+            // test asm_label
+            // fn foo() {
+            //     builtin#asm("", label {});
+            // }
             dir_spec.abandon(p);
             block_expr(p);
-            op.complete(p, ASM_OPERAND_NAMED);
-            op_n.complete(p, ASM_LABEL);
+            op.complete(p, ASM_LABEL);
+            op_n.complete(p, ASM_OPERAND_NAMED);
         } else if p.eat(T![const]) {
             dir_spec.abandon(p);
             expr(p);
diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
index 0a5c16dc4c4..0fa9a264545 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
@@ -179,7 +179,10 @@ impl<'a> Converter<'a> {
                     COMMENT
                 }
 
-                rustc_lexer::TokenKind::Frontmatter  { has_invalid_preceding_whitespace, invalid_infostring } => {
+                rustc_lexer::TokenKind::Frontmatter {
+                    has_invalid_preceding_whitespace,
+                    invalid_infostring,
+                } => {
                     if *has_invalid_preceding_whitespace {
                         err = "invalid preceding whitespace for frontmatter opening"
                     } else if *invalid_infostring {
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 24db9478ee5..030d8e0f04d 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
@@ -21,6 +21,8 @@ mod ok {
     #[test]
     fn asm_expr() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_expr.rs"); }
     #[test]
+    fn asm_label() { run_and_expect_no_errors("test_data/parser/inline/ok/asm_label.rs"); }
+    #[test]
     fn assoc_const_eq() {
         run_and_expect_no_errors("test_data/parser/inline/ok/assoc_const_eq.rs");
     }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_label.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_label.rast
new file mode 100644
index 00000000000..38999c9cd34
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_label.rast
@@ -0,0 +1,37 @@
+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 "("
+            LITERAL
+              STRING "\"\""
+            COMMA ","
+            WHITESPACE " "
+            ASM_OPERAND_NAMED
+              ASM_LABEL
+                LABEL_KW "label"
+                WHITESPACE " "
+                BLOCK_EXPR
+                  STMT_LIST
+                    L_CURLY "{"
+                    R_CURLY "}"
+            R_PAREN ")"
+          SEMICOLON ";"
+        WHITESPACE "\n"
+        R_CURLY "}"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_label.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_label.rs
new file mode 100644
index 00000000000..996c1c8477b
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/asm_label.rs
@@ -0,0 +1,3 @@
+fn foo() {
+    builtin#asm("", label {});
+}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs
index dfdbb4c95fc..6820e4b3353 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs
@@ -31,12 +31,17 @@ pub fn fn_like_mk_literals(_args: TokenStream) -> TokenStream {
         TokenTree::from(Literal::byte_string(b"byte_string")),
         TokenTree::from(Literal::character('c')),
         TokenTree::from(Literal::string("string")),
+        TokenTree::from(Literal::c_string(c"cstring")),
         // as of 2022-07-21, there's no method on `Literal` to build a raw
         // string or a raw byte string
         TokenTree::from(Literal::f64_suffixed(3.14)),
+        TokenTree::from(Literal::f64_suffixed(-3.14)),
         TokenTree::from(Literal::f64_unsuffixed(3.14)),
+        TokenTree::from(Literal::f64_unsuffixed(-3.14)),
         TokenTree::from(Literal::i64_suffixed(123)),
+        TokenTree::from(Literal::i64_suffixed(-123)),
         TokenTree::from(Literal::i64_unsuffixed(123)),
+        TokenTree::from(Literal::i64_unsuffixed(-123)),
     ];
     TokenStream::from_iter(trees)
 }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs
index 3d999421794..11dbd920091 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs
@@ -16,9 +16,8 @@ mod token_stream;
 pub use token_stream::TokenStream;
 
 pub mod rust_analyzer_span;
-// mod symbol;
 pub mod token_id;
-// pub use symbol::*;
+
 use tt::Spacing;
 
 #[derive(Clone)]
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
index 47555a5db2f..64b40e7b943 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
@@ -168,16 +168,38 @@ impl server::TokenStream for RaSpanServer {
             }
 
             bridge::TokenTree::Literal(literal) => {
-                let literal = tt::Literal {
-                    symbol: literal.symbol,
-                    suffix: literal.suffix,
-                    span: literal.span,
-                    kind: literal_kind_to_internal(literal.kind),
-                };
-
-                let leaf: tt::Leaf = tt::Leaf::from(literal);
-                let tree = tt::TokenTree::from(leaf);
-                TokenStream { token_trees: vec![tree] }
+                let token_trees =
+                    if let Some((_minus, symbol)) = literal.symbol.as_str().split_once('-') {
+                        let punct = tt::Punct {
+                            spacing: tt::Spacing::Alone,
+                            span: literal.span,
+                            char: '-' as char,
+                        };
+                        let leaf: tt::Leaf = tt::Leaf::from(punct);
+                        let minus_tree = tt::TokenTree::from(leaf);
+
+                        let literal = tt::Literal {
+                            symbol: Symbol::intern(symbol),
+                            suffix: literal.suffix,
+                            span: literal.span,
+                            kind: literal_kind_to_internal(literal.kind),
+                        };
+                        let leaf: tt::Leaf = tt::Leaf::from(literal);
+                        let tree = tt::TokenTree::from(leaf);
+                        vec![minus_tree, tree]
+                    } else {
+                        let literal = tt::Literal {
+                            symbol: literal.symbol,
+                            suffix: literal.suffix,
+                            span: literal.span,
+                            kind: literal_kind_to_internal(literal.kind),
+                        };
+
+                        let leaf: tt::Leaf = tt::Leaf::from(literal);
+                        let tree = tt::TokenTree::from(leaf);
+                        vec![tree]
+                    };
+                TokenStream { token_trees }
             }
 
             bridge::TokenTree::Punct(p) => {
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/symbol.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/symbol.rs
deleted file mode 100644
index 6863ce95997..00000000000
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/symbol.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-//! Symbol interner for proc-macro-srv
-
-use std::{cell::RefCell, collections::HashMap, thread::LocalKey};
-
-thread_local! {
-    pub(crate) static SYMBOL_INTERNER: RefCell<SymbolInterner> = Default::default();
-}
-
-// ID for an interned symbol.
-#[derive(Hash, Eq, PartialEq, Copy, Clone)]
-pub struct Symbol(u32);
-
-pub(crate) type SymbolInternerRef = &'static LocalKey<RefCell<SymbolInterner>>;
-
-impl Symbol {
-    pub(super) fn intern(interner: SymbolInternerRef, data: &str) -> Symbol {
-        interner.with(|i| i.borrow_mut().intern(data))
-    }
-
-    pub(super) fn text(&self, interner: SymbolInternerRef) -> SmolStr {
-        interner.with(|i| i.borrow().get(self).clone())
-    }
-}
-
-#[derive(Default)]
-pub(crate) struct SymbolInterner {
-    idents: HashMap<SmolStr, u32>,
-    ident_data: Vec<SmolStr>,
-}
-
-impl SymbolInterner {
-    fn intern(&mut self, data: &str) -> Symbol {
-        if let Some(index) = self.idents.get(data) {
-            return Symbol(*index);
-        }
-
-        let index = self.idents.len() as u32;
-        let data = SmolStr::from(data);
-        self.ident_data.push(data.clone());
-        self.idents.insert(data, index);
-        Symbol(index)
-    }
-
-    fn get(&self, sym: &Symbol) -> &SmolStr {
-        &self.ident_data[sym.0 as usize]
-    }
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
index c002be4be6f..24a67bf45c8 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
@@ -153,16 +153,38 @@ impl server::TokenStream for TokenIdServer {
             }
 
             bridge::TokenTree::Literal(literal) => {
-                let literal = Literal {
-                    symbol: literal.symbol,
-                    suffix: literal.suffix,
-                    span: literal.span,
-                    kind: literal_kind_to_internal(literal.kind),
-                };
-
-                let leaf = tt::Leaf::from(literal);
-                let tree = TokenTree::from(leaf);
-                TokenStream { token_trees: vec![tree] }
+                let token_trees =
+                    if let Some((_minus, symbol)) = literal.symbol.as_str().split_once('-') {
+                        let punct = tt::Punct {
+                            spacing: tt::Spacing::Alone,
+                            span: literal.span,
+                            char: '-' as char,
+                        };
+                        let leaf: tt::Leaf = tt::Leaf::from(punct);
+                        let minus_tree = tt::TokenTree::from(leaf);
+
+                        let literal = Literal {
+                            symbol: Symbol::intern(symbol),
+                            suffix: literal.suffix,
+                            span: literal.span,
+                            kind: literal_kind_to_internal(literal.kind),
+                        };
+                        let leaf: tt::Leaf = tt::Leaf::from(literal);
+                        let tree = tt::TokenTree::from(leaf);
+                        vec![minus_tree, tree]
+                    } else {
+                        let literal = Literal {
+                            symbol: literal.symbol,
+                            suffix: literal.suffix,
+                            span: literal.span,
+                            kind: literal_kind_to_internal(literal.kind),
+                        };
+
+                        let leaf: tt::Leaf = tt::Leaf::from(literal);
+                        let tree = tt::TokenTree::from(leaf);
+                        vec![tree]
+                    };
+                TokenStream { token_trees }
             }
 
             bridge::TokenTree::Punct(p) => {
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
index 4946a4f2a62..072557913c2 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
@@ -68,6 +68,11 @@ impl<S: Copy> TokenStream<S> {
                         span: ident.span,
                     }))
                 }
+                // Note, we do not have to assemble our `-` punct and literal split into a single
+                // negative bridge literal here. As the proc-macro docs state
+                // > Literals created from negative numbers might not survive round-trips through
+                // > TokenStream or strings and may be broken into two tokens (- and positive
+                // > literal).
                 tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
                     result.push(bridge::TokenTree::Literal(bridge::Literal {
                         span: lit.span,
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
index a81fea7bec6..3868fee40fb 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
@@ -11,8 +11,24 @@ fn test_derive_empty() {
     assert_expand(
         "DeriveEmpty",
         r#"struct S;"#,
-        expect!["SUBTREE $$ 1 1"],
-        expect!["SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024"],
+        expect![[r#"
+            SUBTREE $$ 1 1
+              IDENT   struct 1
+              IDENT   S 1
+              PUNCH   ; [alone] 1
+
+
+
+            SUBTREE $$ 1 1"#]],
+        expect![[r#"
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              IDENT   struct 42:2@0..6#ROOT2024
+              IDENT   S 42:2@7..8#ROOT2024
+              PUNCH   ; [alone] 42:2@8..9#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024"#]],
     );
 }
 
@@ -23,6 +39,13 @@ fn test_derive_error() {
         r#"struct S;"#,
         expect![[r#"
             SUBTREE $$ 1 1
+              IDENT   struct 1
+              IDENT   S 1
+              PUNCH   ; [alone] 1
+
+
+
+            SUBTREE $$ 1 1
               IDENT   compile_error 1
               PUNCH   ! [alone] 1
               SUBTREE () 1 1
@@ -30,6 +53,13 @@ fn test_derive_error() {
               PUNCH   ; [alone] 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              IDENT   struct 42:2@0..6#ROOT2024
+              IDENT   S 42:2@7..8#ROOT2024
+              PUNCH   ; [alone] 42:2@8..9#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
               IDENT   compile_error 42:2@0..100#ROOT2024
               PUNCH   ! [alone] 42:2@0..100#ROOT2024
               SUBTREE () 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
@@ -51,6 +81,17 @@ fn test_fn_like_macro_noop() {
               PUNCH   , [alone] 1
               LITERAL Integer 1 1
               PUNCH   , [alone] 1
+              SUBTREE [] 1 1
+
+
+
+            SUBTREE $$ 1 1
+              IDENT   ident 1
+              PUNCH   , [alone] 1
+              LITERAL Integer 0 1
+              PUNCH   , [alone] 1
+              LITERAL Integer 1 1
+              PUNCH   , [alone] 1
               SUBTREE [] 1 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
@@ -60,6 +101,17 @@ fn test_fn_like_macro_noop() {
               PUNCH   , [alone] 42:2@8..9#ROOT2024
               LITERAL Integer 1 42:2@10..11#ROOT2024
               PUNCH   , [alone] 42:2@11..12#ROOT2024
+              SUBTREE [] 42:2@13..14#ROOT2024 42:2@14..15#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              IDENT   ident 42:2@0..5#ROOT2024
+              PUNCH   , [alone] 42:2@5..6#ROOT2024
+              LITERAL Integer 0 42:2@7..8#ROOT2024
+              PUNCH   , [alone] 42:2@8..9#ROOT2024
+              LITERAL Integer 1 42:2@10..11#ROOT2024
+              PUNCH   , [alone] 42:2@11..12#ROOT2024
               SUBTREE [] 42:2@13..14#ROOT2024 42:2@14..15#ROOT2024"#]],
     );
 }
@@ -73,11 +125,25 @@ fn test_fn_like_macro_clone_ident_subtree() {
             SUBTREE $$ 1 1
               IDENT   ident 1
               PUNCH   , [alone] 1
+              SUBTREE [] 1 1
+
+
+
+            SUBTREE $$ 1 1
+              IDENT   ident 1
+              PUNCH   , [alone] 1
               SUBTREE [] 1 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
               IDENT   ident 42:2@0..5#ROOT2024
               PUNCH   , [alone] 42:2@5..6#ROOT2024
+              SUBTREE [] 42:2@7..8#ROOT2024 42:2@8..9#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              IDENT   ident 42:2@0..5#ROOT2024
+              PUNCH   , [alone] 42:2@5..6#ROOT2024
               SUBTREE [] 42:2@7..8#ROOT2024 42:2@7..8#ROOT2024"#]],
     );
 }
@@ -89,9 +155,19 @@ fn test_fn_like_macro_clone_raw_ident() {
         "r#async",
         expect![[r#"
             SUBTREE $$ 1 1
+              IDENT   r#async 1
+
+
+
+            SUBTREE $$ 1 1
               IDENT   r#async 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              IDENT   r#async 42:2@0..7#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
               IDENT   r#async 42:2@0..7#ROOT2024"#]],
     );
 }
@@ -103,9 +179,21 @@ fn test_fn_like_fn_like_span_join() {
         "foo     bar",
         expect![[r#"
             SUBTREE $$ 1 1
+              IDENT   foo 1
+              IDENT   bar 1
+
+
+
+            SUBTREE $$ 1 1
               IDENT   r#joined 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              IDENT   foo 42:2@0..3#ROOT2024
+              IDENT   bar 42:2@8..11#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
               IDENT   r#joined 42:2@0..11#ROOT2024"#]],
     );
 }
@@ -117,11 +205,25 @@ fn test_fn_like_fn_like_span_ops() {
         "set_def_site resolved_at_def_site start_span",
         expect![[r#"
             SUBTREE $$ 1 1
+              IDENT   set_def_site 1
+              IDENT   resolved_at_def_site 1
+              IDENT   start_span 1
+
+
+
+            SUBTREE $$ 1 1
               IDENT   set_def_site 0
               IDENT   resolved_at_def_site 1
               IDENT   start_span 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              IDENT   set_def_site 42:2@0..12#ROOT2024
+              IDENT   resolved_at_def_site 42:2@13..33#ROOT2024
+              IDENT   start_span 42:2@34..44#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
               IDENT   set_def_site 41:1@0..150#ROOT2024
               IDENT   resolved_at_def_site 42:2@13..33#ROOT2024
               IDENT   start_span 42:2@34..34#ROOT2024"#]],
@@ -135,21 +237,47 @@ fn test_fn_like_mk_literals() {
         r#""#,
         expect![[r#"
             SUBTREE $$ 1 1
+
+
+
+            SUBTREE $$ 1 1
               LITERAL ByteStr byte_string 1
               LITERAL Char c 1
               LITERAL Str string 1
+              LITERAL CStr cstring 1
               LITERAL Float 3.14f64 1
+              PUNCH   - [alone] 1
+              LITERAL Float 3.14f64 1
+              LITERAL Float 3.14 1
+              PUNCH   - [alone] 1
               LITERAL Float 3.14 1
               LITERAL Integer 123i64 1
+              PUNCH   - [alone] 1
+              LITERAL Integer 123i64 1
+              LITERAL Integer 123 1
+              PUNCH   - [alone] 1
               LITERAL Integer 123 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
               LITERAL ByteStr byte_string 42:2@0..100#ROOT2024
               LITERAL Char c 42:2@0..100#ROOT2024
               LITERAL Str string 42:2@0..100#ROOT2024
+              LITERAL CStr cstring 42:2@0..100#ROOT2024
+              LITERAL Float 3.14f64 42:2@0..100#ROOT2024
+              PUNCH   - [alone] 42:2@0..100#ROOT2024
               LITERAL Float 3.14f64 42:2@0..100#ROOT2024
               LITERAL Float 3.14 42:2@0..100#ROOT2024
+              PUNCH   - [alone] 42:2@0..100#ROOT2024
+              LITERAL Float 3.14 42:2@0..100#ROOT2024
+              LITERAL Integer 123i64 42:2@0..100#ROOT2024
+              PUNCH   - [alone] 42:2@0..100#ROOT2024
               LITERAL Integer 123i64 42:2@0..100#ROOT2024
+              LITERAL Integer 123 42:2@0..100#ROOT2024
+              PUNCH   - [alone] 42:2@0..100#ROOT2024
               LITERAL Integer 123 42:2@0..100#ROOT2024"#]],
     );
 }
@@ -161,10 +289,18 @@ fn test_fn_like_mk_idents() {
         r#""#,
         expect![[r#"
             SUBTREE $$ 1 1
+
+
+
+            SUBTREE $$ 1 1
               IDENT   standard 1
               IDENT   r#raw 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
               IDENT   standard 42:2@0..100#ROOT2024
               IDENT   r#raw 42:2@0..100#ROOT2024"#]],
     );
@@ -196,6 +332,30 @@ fn test_fn_like_macro_clone_literals() {
               PUNCH   , [alone] 1
               LITERAL Byte b 1
               PUNCH   , [alone] 1
+              LITERAL CStr null 1
+
+
+
+            SUBTREE $$ 1 1
+              LITERAL Integer 1u16 1
+              PUNCH   , [alone] 1
+              LITERAL Integer 2_u32 1
+              PUNCH   , [alone] 1
+              PUNCH   - [alone] 1
+              LITERAL Integer 4i64 1
+              PUNCH   , [alone] 1
+              LITERAL Float 3.14f32 1
+              PUNCH   , [alone] 1
+              LITERAL Str hello bridge 1
+              PUNCH   , [alone] 1
+              LITERAL Str suffixedsuffix 1
+              PUNCH   , [alone] 1
+              LITERAL StrRaw(2) raw 1
+              PUNCH   , [alone] 1
+              LITERAL Char a 1
+              PUNCH   , [alone] 1
+              LITERAL Byte b 1
+              PUNCH   , [alone] 1
               LITERAL CStr null 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
@@ -218,11 +378,99 @@ fn test_fn_like_macro_clone_literals() {
               PUNCH   , [alone] 42:2@78..79#ROOT2024
               LITERAL Byte b 42:2@80..84#ROOT2024
               PUNCH   , [alone] 42:2@84..85#ROOT2024
+              LITERAL CStr null 42:2@86..93#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              LITERAL Integer 1u16 42:2@0..4#ROOT2024
+              PUNCH   , [alone] 42:2@4..5#ROOT2024
+              LITERAL Integer 2_u32 42:2@6..11#ROOT2024
+              PUNCH   , [alone] 42:2@11..12#ROOT2024
+              PUNCH   - [alone] 42:2@13..14#ROOT2024
+              LITERAL Integer 4i64 42:2@14..18#ROOT2024
+              PUNCH   , [alone] 42:2@18..19#ROOT2024
+              LITERAL Float 3.14f32 42:2@20..27#ROOT2024
+              PUNCH   , [alone] 42:2@27..28#ROOT2024
+              LITERAL Str hello bridge 42:2@29..43#ROOT2024
+              PUNCH   , [alone] 42:2@43..44#ROOT2024
+              LITERAL Str suffixedsuffix 42:2@45..61#ROOT2024
+              PUNCH   , [alone] 42:2@61..62#ROOT2024
+              LITERAL StrRaw(2) raw 42:2@63..73#ROOT2024
+              PUNCH   , [alone] 42:2@73..74#ROOT2024
+              LITERAL Char a 42:2@75..78#ROOT2024
+              PUNCH   , [alone] 42:2@78..79#ROOT2024
+              LITERAL Byte b 42:2@80..84#ROOT2024
+              PUNCH   , [alone] 42:2@84..85#ROOT2024
               LITERAL CStr null 42:2@86..93#ROOT2024"#]],
     );
 }
 
 #[test]
+fn test_fn_like_macro_negative_literals() {
+    assert_expand(
+        "fn_like_clone_tokens",
+        r###"-1u16, - 2_u32, -3.14f32, - 2.7"###,
+        expect![[r#"
+            SUBTREE $$ 1 1
+              PUNCH   - [alone] 1
+              LITERAL Integer 1u16 1
+              PUNCH   , [alone] 1
+              PUNCH   - [alone] 1
+              LITERAL Integer 2_u32 1
+              PUNCH   , [alone] 1
+              PUNCH   - [alone] 1
+              LITERAL Float 3.14f32 1
+              PUNCH   , [alone] 1
+              PUNCH   - [alone] 1
+              LITERAL Float 2.7 1
+
+
+
+            SUBTREE $$ 1 1
+              PUNCH   - [alone] 1
+              LITERAL Integer 1u16 1
+              PUNCH   , [alone] 1
+              PUNCH   - [alone] 1
+              LITERAL Integer 2_u32 1
+              PUNCH   , [alone] 1
+              PUNCH   - [alone] 1
+              LITERAL Float 3.14f32 1
+              PUNCH   , [alone] 1
+              PUNCH   - [alone] 1
+              LITERAL Float 2.7 1"#]],
+        expect![[r#"
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              PUNCH   - [alone] 42:2@0..1#ROOT2024
+              LITERAL Integer 1u16 42:2@1..5#ROOT2024
+              PUNCH   , [alone] 42:2@5..6#ROOT2024
+              PUNCH   - [alone] 42:2@7..8#ROOT2024
+              LITERAL Integer 2_u32 42:2@9..14#ROOT2024
+              PUNCH   , [alone] 42:2@14..15#ROOT2024
+              PUNCH   - [alone] 42:2@16..17#ROOT2024
+              LITERAL Float 3.14f32 42:2@17..24#ROOT2024
+              PUNCH   , [alone] 42:2@24..25#ROOT2024
+              PUNCH   - [alone] 42:2@26..27#ROOT2024
+              LITERAL Float 2.7 42:2@28..31#ROOT2024
+
+
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              PUNCH   - [alone] 42:2@0..1#ROOT2024
+              LITERAL Integer 1u16 42:2@1..5#ROOT2024
+              PUNCH   , [alone] 42:2@5..6#ROOT2024
+              PUNCH   - [alone] 42:2@7..8#ROOT2024
+              LITERAL Integer 2_u32 42:2@9..14#ROOT2024
+              PUNCH   , [alone] 42:2@14..15#ROOT2024
+              PUNCH   - [alone] 42:2@16..17#ROOT2024
+              LITERAL Float 3.14f32 42:2@17..24#ROOT2024
+              PUNCH   , [alone] 42:2@24..25#ROOT2024
+              PUNCH   - [alone] 42:2@26..27#ROOT2024
+              LITERAL Float 2.7 42:2@28..31#ROOT2024"#]],
+    );
+}
+
+#[test]
 fn test_attr_macro() {
     // Corresponds to
     //    #[proc_macro_test::attr_error(some arguments)]
@@ -233,6 +481,15 @@ fn test_attr_macro() {
         r#"some arguments"#,
         expect![[r#"
             SUBTREE $$ 1 1
+              IDENT   mod 1
+              IDENT   m 1
+              SUBTREE {} 1 1
+
+            SUBTREE $$ 1 1
+              IDENT   some 1
+              IDENT   arguments 1
+
+            SUBTREE $$ 1 1
               IDENT   compile_error 1
               PUNCH   ! [alone] 1
               SUBTREE () 1 1
@@ -240,6 +497,15 @@ fn test_attr_macro() {
               PUNCH   ; [alone] 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              IDENT   mod 42:2@0..3#ROOT2024
+              IDENT   m 42:2@4..5#ROOT2024
+              SUBTREE {} 42:2@6..7#ROOT2024 42:2@7..8#ROOT2024
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
+              IDENT   some 42:2@0..4#ROOT2024
+              IDENT   arguments 42:2@5..14#ROOT2024
+
+            SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
               IDENT   compile_error 42:2@0..100#ROOT2024
               PUNCH   ! [alone] 42:2@0..100#ROOT2024
               SUBTREE () 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
index a476a70a740..a0a45b269e4 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
@@ -32,9 +32,9 @@ pub fn assert_expand(
     macro_name: &str,
     #[rust_analyzer::rust_fixture] ra_fixture: &str,
     expect: Expect,
-    expect_s: Expect,
+    expect_spanned: Expect,
 ) {
-    assert_expand_impl(macro_name, ra_fixture, None, expect, expect_s);
+    assert_expand_impl(macro_name, ra_fixture, None, expect, expect_spanned);
 }
 
 pub fn assert_expand_attr(
@@ -42,9 +42,9 @@ pub fn assert_expand_attr(
     #[rust_analyzer::rust_fixture] ra_fixture: &str,
     attr_args: &str,
     expect: Expect,
-    expect_s: Expect,
+    expect_spanned: Expect,
 ) {
-    assert_expand_impl(macro_name, ra_fixture, Some(attr_args), expect, expect_s);
+    assert_expand_impl(macro_name, ra_fixture, Some(attr_args), expect, expect_spanned);
 }
 
 fn assert_expand_impl(
@@ -52,7 +52,7 @@ fn assert_expand_impl(
     input: &str,
     attr: Option<&str>,
     expect: Expect,
-    expect_s: Expect,
+    expect_spanned: Expect,
 ) {
     let path = proc_macro_test_dylib_path();
     let expander = dylib::Expander::new(&path).unwrap();
@@ -60,20 +60,17 @@ fn assert_expand_impl(
     let def_site = TokenId(0);
     let call_site = TokenId(1);
     let mixed_site = TokenId(2);
-    let input_ts = parse_string(call_site, input);
+    let input_ts = parse_string(call_site, input).into_subtree(call_site);
     let attr_ts = attr.map(|attr| parse_string(call_site, attr).into_subtree(call_site));
+    let input_ts_string = format!("{input_ts:?}");
+    let attr_ts_string = attr_ts.as_ref().map(|it| format!("{it:?}"));
 
-    let res = expander
-        .expand(
-            macro_name,
-            input_ts.into_subtree(call_site),
-            attr_ts,
-            def_site,
-            call_site,
-            mixed_site,
-        )
-        .unwrap();
-    expect.assert_eq(&format!("{res:?}"));
+    let res =
+        expander.expand(macro_name, input_ts, attr_ts, def_site, call_site, mixed_site).unwrap();
+    expect.assert_eq(&format!(
+        "{input_ts_string}\n\n{}\n\n{res:?}",
+        attr_ts_string.unwrap_or_default()
+    ));
 
     let def_site = Span {
         range: TextRange::new(0.into(), 150.into()),
@@ -93,15 +90,17 @@ fn assert_expand_impl(
     };
     let mixed_site = call_site;
 
-    let fixture = parse_string_spanned(call_site.anchor, call_site.ctx, input);
+    let fixture =
+        parse_string_spanned(call_site.anchor, call_site.ctx, input).into_subtree(call_site);
     let attr = attr.map(|attr| {
         parse_string_spanned(call_site.anchor, call_site.ctx, attr).into_subtree(call_site)
     });
+    let fixture_string = format!("{fixture:?}");
+    let attr_string = attr.as_ref().map(|it| format!("{it:?}"));
 
-    let res = expander
-        .expand(macro_name, fixture.into_subtree(call_site), attr, def_site, call_site, mixed_site)
-        .unwrap();
-    expect_s.assert_eq(&format!("{res:#?}"));
+    let res = expander.expand(macro_name, fixture, attr, def_site, call_site, mixed_site).unwrap();
+    expect_spanned
+        .assert_eq(&format!("{fixture_string}\n\n{}\n\n{res:#?}", attr_string.unwrap_or_default()));
 }
 
 pub(crate) fn list() -> Vec<String> {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/env.rs b/src/tools/rust-analyzer/crates/project-model/src/env.rs
index e7293b0b2ef..450def5461d 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/env.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/env.rs
@@ -18,6 +18,7 @@ pub(crate) fn inject_cargo_package_env(env: &mut Env, package: &PackageData) {
 
     let manifest_dir = package.manifest.parent();
     env.set("CARGO_MANIFEST_DIR", manifest_dir.as_str());
+    env.set("CARGO_MANIFEST_PATH", package.manifest.as_str());
 
     env.set("CARGO_PKG_VERSION", package.version.to_string());
     env.set("CARGO_PKG_VERSION_MAJOR", package.version.major.to_string());
diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
index c7c1b043186..d4055d9a0af 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
@@ -137,7 +137,12 @@ impl Sysroot {
                 }
 
                 let mut cmd = toolchain::command(tool.prefer_proxy(), current_dir, envs);
-                cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(root));
+                if !envs.contains_key("RUSTUP_TOOLCHAIN")
+                    && std::env::var_os("RUSTUP_TOOLCHAIN").is_none()
+                {
+                    cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(root));
+                }
+
                 cmd
             }
             _ => toolchain::command(tool.path(), current_dir, envs),
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
index 4ef9d816119..3722e2c7216 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model.txt
@@ -52,6 +52,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -136,6 +137,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -220,6 +222,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "an_example",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -304,6 +307,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "it",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -384,6 +388,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "libc",
                 "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
+                "CARGO_MANIFEST_PATH": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "The Rust Project Developers",
                 "CARGO_PKG_DESCRIPTION": "Raw FFI bindings to platform libraries like libc.\n",
                 "CARGO_PKG_HOMEPAGE": "https://github.com/rust-lang/libc",
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
index 4ef9d816119..3722e2c7216 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_selective_overrides.txt
@@ -52,6 +52,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -136,6 +137,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -220,6 +222,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "an_example",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -304,6 +307,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "it",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -384,6 +388,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "libc",
                 "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
+                "CARGO_MANIFEST_PATH": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "The Rust Project Developers",
                 "CARGO_PKG_DESCRIPTION": "Raw FFI bindings to platform libraries like libc.\n",
                 "CARGO_PKG_HOMEPAGE": "https://github.com/rust-lang/libc",
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
index 52089d1dbc2..7b156ea63a5 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/cargo_hello_world_project_model_with_wildcard_overrides.txt
@@ -51,6 +51,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -134,6 +135,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "hello_world",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -217,6 +219,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "an_example",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -300,6 +303,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "it",
                 "CARGO_MANIFEST_DIR": "$ROOT$hello-world",
+                "CARGO_MANIFEST_PATH": "$ROOT$hello-world/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "",
                 "CARGO_PKG_DESCRIPTION": "",
                 "CARGO_PKG_HOMEPAGE": "",
@@ -380,6 +384,7 @@
                 "CARGO": "$CARGO$",
                 "CARGO_CRATE_NAME": "libc",
                 "CARGO_MANIFEST_DIR": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98",
+                "CARGO_MANIFEST_PATH": "$ROOT$.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.98/Cargo.toml",
                 "CARGO_PKG_AUTHORS": "The Rust Project Developers",
                 "CARGO_PKG_DESCRIPTION": "Raw FFI bindings to platform libraries like libc.\n",
                 "CARGO_PKG_HOMEPAGE": "https://github.com/rust-lang/libc",
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 a1e4adf0844..671e838421f 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
@@ -4,6 +4,7 @@
 use std::{
     env, fmt,
     ops::AddAssign,
+    panic::{AssertUnwindSafe, catch_unwind},
     time::{SystemTime, UNIX_EPOCH},
 };
 
@@ -721,6 +722,7 @@ impl flags::AnalysisStats {
         let mut num_pats_unknown = 0;
         let mut num_pats_partially_unknown = 0;
         let mut num_pat_type_mismatches = 0;
+        let mut panics = 0;
         for &body_id in bodies {
             let name = body_id.name(db).unwrap_or_else(Name::missing);
             let module = body_id.module(db);
@@ -774,7 +776,20 @@ impl flags::AnalysisStats {
             }
             bar.set_message(msg);
             let body = db.body(body_id.into());
-            let inference_result = db.infer(body_id.into());
+            let inference_result = catch_unwind(AssertUnwindSafe(|| db.infer(body_id.into())));
+            let inference_result = match inference_result {
+                Ok(inference_result) => inference_result,
+                Err(p) => {
+                    if let Some(s) = p.downcast_ref::<&str>() {
+                        eprintln!("infer panicked for {}: {}", full_name(), s);
+                    } else if let Some(s) = p.downcast_ref::<String>() {
+                        eprintln!("infer panicked for {}: {}", full_name(), s);
+                    }
+                    panics += 1;
+                    bar.inc(1);
+                    continue;
+                }
+            };
             // This query is LRU'd, so actually calling it will skew the timing results.
             let sm = || db.body_with_source_map(body_id.into()).1;
 
@@ -1008,6 +1023,7 @@ impl flags::AnalysisStats {
             percentage(num_pats_partially_unknown, num_pats),
             num_pat_type_mismatches
         );
+        eprintln!("  panics: {}", panics);
         eprintln!("{:<20} {}", "Inference:", inference_time);
         report_metric("unknown type", num_exprs_unknown, "#");
         report_metric("type mismatches", num_expr_type_mismatches, "#");
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
index 57f95d114d9..16f351272b6 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
@@ -150,8 +150,8 @@ xflags::xflags! {
             optional --disable-proc-macros
             /// Run the proc-macro-srv binary at the specified path.
             optional --proc-macro-srv path: PathBuf
-            /// Run cache priming in parallel.
-            optional --parallel
+            /// The number of threads to use. Defaults to the number of physical cores.
+            optional --num-threads num_threads: usize
         }
 
         cmd ssr {
@@ -299,7 +299,7 @@ pub struct PrimeCaches {
     pub disable_build_scripts: bool,
     pub disable_proc_macros: bool,
     pub proc_macro_srv: Option<PathBuf>,
-    pub parallel: bool,
+    pub num_threads: Option<usize>,
 }
 
 #[derive(Debug)]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/prime_caches.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/prime_caches.rs
index 46fb701ab42..467d8a53884 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/prime_caches.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/prime_caches.rs
@@ -52,7 +52,7 @@ impl flags::PrimeCaches {
             elapsed.memory.allocated.megabytes() as u64
         );
 
-        let threads = if self.parallel { num_cpus::get() } else { 1 };
+        let threads = self.num_threads.unwrap_or_else(num_cpus::get_physical);
         ide_db::prime_caches::parallel_prime_caches(&db, threads, &|_| ());
 
         let elapsed = stop_watch.elapsed();
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
index fc312439d58..0e418240db0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
@@ -470,7 +470,11 @@ impl FlycheckActor {
                 let mut cmd =
                     toolchain::command(Tool::Cargo.path(), &*self.root, &options.extra_env);
                 if let Some(sysroot_root) = &self.sysroot_root {
-                    cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(sysroot_root));
+                    if !options.extra_env.contains_key("RUSTUP_TOOLCHAIN")
+                        && std::env::var_os("RUSTUP_TOOLCHAIN").is_none()
+                    {
+                        cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(sysroot_root));
+                    }
                 }
                 cmd.arg(command);
 
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 3b3b9c87975..a870232d4a0 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
@@ -3,7 +3,11 @@
 //!
 //! Each tick provides an immutable snapshot of the state as `WorldSnapshot`.
 
-use std::{ops::Not as _, time::Instant};
+use std::{
+    ops::Not as _,
+    panic::AssertUnwindSafe,
+    time::{Duration, Instant},
+};
 
 use crossbeam_channel::{Receiver, Sender, unbounded};
 use hir::ChangeWithProcMacros;
@@ -19,6 +23,7 @@ use parking_lot::{
 use proc_macro_api::ProcMacroClient;
 use project_model::{ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, WorkspaceBuildScripts};
 use rustc_hash::{FxHashMap, FxHashSet};
+use stdx::thread;
 use tracing::{Level, span, trace};
 use triomphe::Arc;
 use vfs::{AbsPathBuf, AnchoredPathBuf, ChangeKind, Vfs, VfsPath};
@@ -40,6 +45,7 @@ use crate::{
     test_runner::{CargoTestHandle, CargoTestMessage},
 };
 
+#[derive(Debug)]
 pub(crate) struct FetchWorkspaceRequest {
     pub(crate) path: Option<AbsPathBuf>,
     pub(crate) force_crate_graph_reload: bool,
@@ -78,6 +84,7 @@ pub(crate) struct GlobalState {
 
     pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>,
     pub(crate) fmt_pool: Handle<TaskPool<Task>, Receiver<Task>>,
+    pub(crate) cancellation_pool: thread::Pool,
 
     pub(crate) config: Arc<Config>,
     pub(crate) config_errors: Option<ConfigErrors>,
@@ -114,6 +121,11 @@ pub(crate) struct GlobalState {
     pub(crate) discover_sender: Sender<discover::DiscoverProjectMessage>,
     pub(crate) discover_receiver: Receiver<discover::DiscoverProjectMessage>,
 
+    // Debouncing channel for fetching the workspace
+    // we want to delay it until the VFS looks stable-ish (and thus is not currently in the middle
+    // of a VCS operation like `git switch`)
+    pub(crate) fetch_ws_receiver: Option<(Receiver<Instant>, FetchWorkspaceRequest)>,
+
     // VFS
     pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
     pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
@@ -210,6 +222,7 @@ impl GlobalState {
             let handle = TaskPool::new_with_threads(sender, 1);
             Handle { handle, receiver }
         };
+        let cancellation_pool = thread::Pool::new(1);
 
         let task_queue = {
             let (sender, receiver) = unbounded();
@@ -230,6 +243,7 @@ impl GlobalState {
             req_queue: ReqQueue::default(),
             task_pool,
             fmt_pool,
+            cancellation_pool,
             loader,
             config: Arc::new(config.clone()),
             analysis_host,
@@ -264,6 +278,8 @@ impl GlobalState {
             discover_sender,
             discover_receiver,
 
+            fetch_ws_receiver: None,
+
             vfs: Arc::new(RwLock::new((vfs::Vfs::default(), Default::default()))),
             vfs_config_version: 0,
             vfs_progress_config_version: 0,
@@ -290,7 +306,6 @@ impl GlobalState {
 
     pub(crate) fn process_changes(&mut self) -> bool {
         let _p = span!(Level::INFO, "GlobalState::process_changes").entered();
-
         // We cannot directly resolve a change in a ratoml file to a format
         // that can be used by the config module because config talks
         // in `SourceRootId`s instead of `FileId`s and `FileId` -> `SourceRootId`
@@ -298,66 +313,75 @@ impl GlobalState {
         let mut modified_ratoml_files: FxHashMap<FileId, (ChangeKind, vfs::VfsPath)> =
             FxHashMap::default();
 
-        let (change, modified_rust_files, workspace_structure_change) = {
-            let mut change = ChangeWithProcMacros::default();
-            let mut guard = self.vfs.write();
-            let changed_files = guard.0.take_changes();
-            if changed_files.is_empty() {
-                return false;
-            }
+        let mut change = ChangeWithProcMacros::default();
+        let mut guard = self.vfs.write();
+        let changed_files = guard.0.take_changes();
+        if changed_files.is_empty() {
+            return false;
+        }
 
-            // downgrade to read lock to allow more readers while we are normalizing text
-            let guard = RwLockWriteGuard::downgrade_to_upgradable(guard);
-            let vfs: &Vfs = &guard.0;
-
-            let mut workspace_structure_change = None;
-            // A file was added or deleted
-            let mut has_structure_changes = false;
-            let mut bytes = vec![];
-            let mut modified_rust_files = vec![];
-            for file in changed_files.into_values() {
-                let vfs_path = vfs.file_path(file.file_id);
-                if let Some(("rust-analyzer", Some("toml"))) = vfs_path.name_and_extension() {
-                    // Remember ids to use them after `apply_changes`
-                    modified_ratoml_files.insert(file.file_id, (file.kind(), vfs_path.clone()));
-                }
+        let (change, modified_rust_files, workspace_structure_change) =
+            self.cancellation_pool.scoped(|s| {
+                // start cancellation in parallel, this will kick off lru eviction
+                // allowing us to do meaningful work while waiting
+                let analysis_host = AssertUnwindSafe(&mut self.analysis_host);
+                s.spawn(thread::ThreadIntent::LatencySensitive, || {
+                    { analysis_host }.0.request_cancellation()
+                });
+
+                // downgrade to read lock to allow more readers while we are normalizing text
+                let guard = RwLockWriteGuard::downgrade_to_upgradable(guard);
+                let vfs: &Vfs = &guard.0;
+
+                let mut workspace_structure_change = None;
+                // A file was added or deleted
+                let mut has_structure_changes = false;
+                let mut bytes = vec![];
+                let mut modified_rust_files = vec![];
+                for file in changed_files.into_values() {
+                    let vfs_path = vfs.file_path(file.file_id);
+                    if let Some(("rust-analyzer", Some("toml"))) = vfs_path.name_and_extension() {
+                        // Remember ids to use them after `apply_changes`
+                        modified_ratoml_files.insert(file.file_id, (file.kind(), vfs_path.clone()));
+                    }
 
-                if let Some(path) = vfs_path.as_path() {
-                    has_structure_changes |= file.is_created_or_deleted();
+                    if let Some(path) = vfs_path.as_path() {
+                        has_structure_changes |= file.is_created_or_deleted();
 
-                    if file.is_modified() && path.extension() == Some("rs") {
-                        modified_rust_files.push(file.file_id);
-                    }
+                        if file.is_modified() && path.extension() == Some("rs") {
+                            modified_rust_files.push(file.file_id);
+                        }
 
-                    let additional_files = self
-                        .config
-                        .discover_workspace_config()
-                        .map(|cfg| {
-                            cfg.files_to_watch.iter().map(String::as_str).collect::<Vec<&str>>()
-                        })
-                        .unwrap_or_default();
-
-                    let path = path.to_path_buf();
-                    if file.is_created_or_deleted() {
-                        workspace_structure_change.get_or_insert((path, false)).1 |=
-                            self.crate_graph_file_dependencies.contains(vfs_path);
-                    } else if reload::should_refresh_for_change(
-                        &path,
-                        file.kind(),
-                        &additional_files,
-                    ) {
-                        trace!(?path, kind = ?file.kind(), "refreshing for a change");
-                        workspace_structure_change.get_or_insert((path.clone(), false));
+                        let additional_files = self
+                            .config
+                            .discover_workspace_config()
+                            .map(|cfg| {
+                                cfg.files_to_watch.iter().map(String::as_str).collect::<Vec<&str>>()
+                            })
+                            .unwrap_or_default();
+
+                        let path = path.to_path_buf();
+                        if file.is_created_or_deleted() {
+                            workspace_structure_change.get_or_insert((path, false)).1 |=
+                                self.crate_graph_file_dependencies.contains(vfs_path);
+                        } else if reload::should_refresh_for_change(
+                            &path,
+                            file.kind(),
+                            &additional_files,
+                        ) {
+                            trace!(?path, kind = ?file.kind(), "refreshing for a change");
+                            workspace_structure_change.get_or_insert((path.clone(), false));
+                        }
                     }
-                }
 
-                // Clear native diagnostics when their file gets deleted
-                if !file.exists() {
-                    self.diagnostics.clear_native_for(file.file_id);
-                }
+                    // Clear native diagnostics when their file gets deleted
+                    if !file.exists() {
+                        self.diagnostics.clear_native_for(file.file_id);
+                    }
 
-                let text =
-                    if let vfs::Change::Create(v, _) | vfs::Change::Modify(v, _) = file.change {
+                    let text = if let vfs::Change::Create(v, _) | vfs::Change::Modify(v, _) =
+                        file.change
+                    {
                         String::from_utf8(v).ok().map(|text| {
                             // FIXME: Consider doing normalization in the `vfs` instead? That allows
                             // getting rid of some locking
@@ -367,29 +391,28 @@ impl GlobalState {
                     } else {
                         None
                     };
-                // delay `line_endings_map` changes until we are done normalizing the text
-                // this allows delaying the re-acquisition of the write lock
-                bytes.push((file.file_id, text));
-            }
-            let (vfs, line_endings_map) = &mut *RwLockUpgradableReadGuard::upgrade(guard);
-            bytes.into_iter().for_each(|(file_id, text)| {
-                let text = match text {
-                    None => None,
-                    Some((text, line_endings)) => {
-                        line_endings_map.insert(file_id, line_endings);
-                        Some(text)
-                    }
-                };
-                change.change_file(file_id, text);
+                    // delay `line_endings_map` changes until we are done normalizing the text
+                    // this allows delaying the re-acquisition of the write lock
+                    bytes.push((file.file_id, text));
+                }
+                let (vfs, line_endings_map) = &mut *RwLockUpgradableReadGuard::upgrade(guard);
+                bytes.into_iter().for_each(|(file_id, text)| {
+                    let text = match text {
+                        None => None,
+                        Some((text, line_endings)) => {
+                            line_endings_map.insert(file_id, line_endings);
+                            Some(text)
+                        }
+                    };
+                    change.change_file(file_id, text);
+                });
+                if has_structure_changes {
+                    let roots = self.source_root_config.partition(vfs);
+                    change.set_roots(roots);
+                }
+                (change, modified_rust_files, workspace_structure_change)
             });
-            if has_structure_changes {
-                let roots = self.source_root_config.partition(vfs);
-                change.set_roots(roots);
-            }
-            (change, modified_rust_files, workspace_structure_change)
-        };
 
-        let _p = span!(Level::INFO, "GlobalState::process_changes/apply_change").entered();
         self.analysis_host.apply_change(change);
         if !modified_ratoml_files.is_empty()
             || !self.config.same_source_root_parent_map(&self.local_roots_parent_map)
@@ -508,11 +531,7 @@ impl GlobalState {
             if let Some((path, force_crate_graph_reload)) = workspace_structure_change {
                 let _p = span!(Level::INFO, "GlobalState::process_changes/ws_structure_change")
                     .entered();
-
-                self.fetch_workspaces_queue.request_op(
-                    format!("workspace vfs file change: {path}"),
-                    FetchWorkspaceRequest { path: Some(path), force_crate_graph_reload },
-                );
+                self.enqueue_workspace_fetch(path, force_crate_graph_reload);
             }
         }
 
@@ -660,6 +679,30 @@ impl GlobalState {
             None
         })
     }
+
+    fn enqueue_workspace_fetch(&mut self, path: AbsPathBuf, force_crate_graph_reload: bool) {
+        let already_requested = self.fetch_workspaces_queue.op_requested()
+            && !self.fetch_workspaces_queue.op_in_progress();
+        if self.fetch_ws_receiver.is_none() && already_requested {
+            // Don't queue up a new fetch request if we already have done so
+            // Otherwise we will re-fetch in quick succession which is unnecessary
+            // Note though, that if one is already in progress, we *want* to re-queue
+            // as the in-progress fetch might not have the latest changes in it anymore
+            // FIXME: We should cancel the in-progress fetch here
+            return;
+        }
+
+        self.fetch_ws_receiver = Some((
+            crossbeam_channel::after(Duration::from_millis(100)),
+            FetchWorkspaceRequest { path: Some(path), force_crate_graph_reload },
+        ));
+    }
+
+    pub(crate) fn debounce_workspace_fetch(&mut self) {
+        if let Some((fetch_receiver, _)) = &mut self.fetch_ws_receiver {
+            *fetch_receiver = crossbeam_channel::after(Duration::from_millis(100));
+        }
+    }
 }
 
 impl Drop for GlobalState {
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 bd213ffa57a..0c0438c4b8f 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
@@ -8,7 +8,7 @@ use std::{
     time::{Duration, Instant},
 };
 
-use crossbeam_channel::{Receiver, select};
+use crossbeam_channel::{Receiver, never, select};
 use ide_db::base_db::{SourceDatabase, VfsPath, salsa::Database as _};
 use lsp_server::{Connection, Notification, Request};
 use lsp_types::{TextDocumentIdentifier, notification::Notification as _};
@@ -71,6 +71,7 @@ enum Event {
     Flycheck(FlycheckMessage),
     TestResult(CargoTestMessage),
     DiscoverProject(DiscoverProjectMessage),
+    FetchWorkspaces(FetchWorkspaceRequest),
 }
 
 impl fmt::Display for Event {
@@ -83,6 +84,7 @@ impl fmt::Display for Event {
             Event::QueuedTask(_) => write!(f, "Event::QueuedTask"),
             Event::TestResult(_) => write!(f, "Event::TestResult"),
             Event::DiscoverProject(_) => write!(f, "Event::DiscoverProject"),
+            Event::FetchWorkspaces(_) => write!(f, "Event::SwitchWorkspaces"),
         }
     }
 }
@@ -150,6 +152,7 @@ impl fmt::Debug for Event {
             }
             _ => (),
         }
+
         match self {
             Event::Lsp(it) => fmt::Debug::fmt(it, f),
             Event::Task(it) => fmt::Debug::fmt(it, f),
@@ -158,6 +161,7 @@ impl fmt::Debug for Event {
             Event::Flycheck(it) => fmt::Debug::fmt(it, f),
             Event::TestResult(it) => fmt::Debug::fmt(it, f),
             Event::DiscoverProject(it) => fmt::Debug::fmt(it, f),
+            Event::FetchWorkspaces(it) => fmt::Debug::fmt(it, f),
         }
     }
 }
@@ -251,7 +255,7 @@ impl GlobalState {
     }
 
     fn next_event(
-        &self,
+        &mut self,
         inbox: &Receiver<lsp_server::Message>,
     ) -> Result<Option<Event>, crossbeam_channel::RecvError> {
         // Make sure we reply to formatting requests ASAP so the editor doesn't block
@@ -283,6 +287,10 @@ impl GlobalState {
 
             recv(self.discover_receiver) -> task =>
                 task.map(Event::DiscoverProject),
+
+            recv(self.fetch_ws_receiver.as_ref().map_or(&never(), |(chan, _)| chan)) -> _instant => {
+                Ok(Event::FetchWorkspaces(self.fetch_ws_receiver.take().unwrap().1))
+            },
         }
         .map(Some)
     }
@@ -412,6 +420,9 @@ impl GlobalState {
                     self.handle_discover_msg(message);
                 }
             }
+            Event::FetchWorkspaces(req) => {
+                self.fetch_workspaces_queue.request_op("project structure change".to_owned(), req)
+            }
         }
         let event_handling_duration = loop_start.elapsed();
         let (state_changed, memdocs_added_or_removed) = if self.vfs_done {
@@ -830,6 +841,7 @@ impl GlobalState {
         match message {
             vfs::loader::Message::Changed { files } | vfs::loader::Message::Loaded { files } => {
                 let _p = tracing::info_span!("GlobalState::handle_vfs_msg{changed/load}").entered();
+                self.debounce_workspace_fetch();
                 let vfs = &mut self.vfs.write().0;
                 for (path, contents) in files {
                     let path = VfsPath::from(path);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs
index 709d99bda75..7af5b48bb7a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs
@@ -36,7 +36,7 @@ impl<Args, Output> Default for OpQueue<Args, Output> {
     }
 }
 
-impl<Args, Output> OpQueue<Args, Output> {
+impl<Args: std::fmt::Debug, Output> OpQueue<Args, Output> {
     /// Request an operation to start.
     pub(crate) fn request_op(&mut self, reason: Cause, args: Args) {
         self.op_requested = Some((reason, args));
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 55ed1923653..ae9e3e99874 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -69,6 +69,7 @@ impl GlobalState {
     /// are ready to do semantic work.
     pub(crate) fn is_quiescent(&self) -> bool {
         self.vfs_done
+            && self.fetch_ws_receiver.is_none()
             && !self.fetch_workspaces_queue.op_in_progress()
             && !self.fetch_build_data_queue.op_in_progress()
             && !self.fetch_proc_macros_queue.op_in_progress()
@@ -659,6 +660,10 @@ impl GlobalState {
                         .chain(
                             ws.sysroot
                                 .root()
+                                .filter(|_| {
+                                    !self.config.extra_env(None).contains_key("RUSTUP_TOOLCHAIN")
+                                        && std::env::var_os("RUSTUP_TOOLCHAIN").is_none()
+                                })
                                 .map(|it| ("RUSTUP_TOOLCHAIN".to_owned(), Some(it.to_string()))),
                         )
                         .collect(),
diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
index 7bda106764b..b37aded6f68 100644
--- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
@@ -17,6 +17,7 @@ jod-thread = "1.0.0"
 crossbeam-channel.workspace = true
 itertools.workspace = true
 tracing.workspace = true
+crossbeam-utils = "0.8.21"
 # Think twice before adding anything here
 
 [target.'cfg(unix)'.dependencies]
diff --git a/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs b/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs
index a8de4db624f..8d76c5fd1fb 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/thread/pool.rs
@@ -8,6 +8,7 @@
 //! the threading utilities in [`crate::thread`].
 
 use std::{
+    marker::PhantomData,
     panic::{self, UnwindSafe},
     sync::{
         Arc,
@@ -16,8 +17,9 @@ use std::{
 };
 
 use crossbeam_channel::{Receiver, Sender};
+use crossbeam_utils::sync::WaitGroup;
 
-use super::{Builder, JoinHandle, ThreadIntent};
+use crate::thread::{Builder, JoinHandle, ThreadIntent};
 
 pub struct Pool {
     // `_handles` is never read: the field is present
@@ -79,9 +81,6 @@ impl Pool {
         Self { _handles: handles.into_boxed_slice(), extant_tasks, job_sender }
     }
 
-    /// # Panics
-    ///
-    /// Panics if job panics
     pub fn spawn<F>(&self, intent: ThreadIntent, f: F)
     where
         F: FnOnce() + Send + UnwindSafe + 'static,
@@ -97,6 +96,17 @@ impl Pool {
         self.job_sender.send(job).unwrap();
     }
 
+    pub fn scoped<'pool, 'scope, F, R>(&'pool self, f: F) -> R
+    where
+        F: FnOnce(&Scope<'pool, 'scope>) -> R,
+    {
+        let wg = WaitGroup::new();
+        let scope = Scope { pool: self, wg, _marker: PhantomData };
+        let r = f(&scope);
+        scope.wg.wait();
+        r
+    }
+
     #[must_use]
     pub fn len(&self) -> usize {
         self.extant_tasks.load(Ordering::SeqCst)
@@ -107,3 +117,36 @@ impl Pool {
         self.len() == 0
     }
 }
+
+pub struct Scope<'pool, 'scope> {
+    pool: &'pool Pool,
+    wg: WaitGroup,
+    _marker: PhantomData<fn(&'scope ()) -> &'scope ()>,
+}
+
+impl<'scope> Scope<'_, 'scope> {
+    pub fn spawn<F>(&self, intent: ThreadIntent, f: F)
+    where
+        F: 'scope + FnOnce() + Send + UnwindSafe,
+    {
+        let wg = self.wg.clone();
+        let f = Box::new(move || {
+            if cfg!(debug_assertions) {
+                intent.assert_is_used_on_current_thread();
+            }
+            f();
+            drop(wg);
+        });
+
+        let job = Job {
+            requested_intent: intent,
+            f: unsafe {
+                std::mem::transmute::<
+                    Box<dyn 'scope + FnOnce() + Send + UnwindSafe>,
+                    Box<dyn 'static + FnOnce() + Send + UnwindSafe>,
+                >(f)
+            },
+        };
+        self.pool.job_sender.send(job).unwrap();
+    }
+}
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 da0bfd4f37f..e60243f2c91 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
@@ -109,6 +109,67 @@ impl GenericParamsOwnerEdit for ast::Trait {
     }
 }
 
+impl GenericParamsOwnerEdit for ast::TraitAlias {
+    fn get_or_create_generic_param_list(&self) -> ast::GenericParamList {
+        match self.generic_param_list() {
+            Some(it) => it,
+            None => {
+                let position = if let Some(name) = self.name() {
+                    Position::after(name.syntax)
+                } else if let Some(trait_token) = self.trait_token() {
+                    Position::after(trait_token)
+                } else {
+                    Position::last_child_of(self.syntax())
+                };
+                create_generic_param_list(position)
+            }
+        }
+    }
+
+    fn get_or_create_where_clause(&self) -> ast::WhereClause {
+        if self.where_clause().is_none() {
+            let position = match self.semicolon_token() {
+                Some(tok) => Position::before(tok),
+                None => Position::last_child_of(self.syntax()),
+            };
+            create_where_clause(position);
+        }
+        self.where_clause().unwrap()
+    }
+}
+
+impl GenericParamsOwnerEdit for ast::TypeAlias {
+    fn get_or_create_generic_param_list(&self) -> ast::GenericParamList {
+        match self.generic_param_list() {
+            Some(it) => it,
+            None => {
+                let position = if let Some(name) = self.name() {
+                    Position::after(name.syntax)
+                } else if let Some(trait_token) = self.type_token() {
+                    Position::after(trait_token)
+                } else {
+                    Position::last_child_of(self.syntax())
+                };
+                create_generic_param_list(position)
+            }
+        }
+    }
+
+    fn get_or_create_where_clause(&self) -> ast::WhereClause {
+        if self.where_clause().is_none() {
+            let position = match self.eq_token() {
+                Some(tok) => Position::before(tok),
+                None => match self.semicolon_token() {
+                    Some(tok) => Position::before(tok),
+                    None => Position::last_child_of(self.syntax()),
+                },
+            };
+            create_where_clause(position);
+        }
+        self.where_clause().unwrap()
+    }
+}
+
 impl GenericParamsOwnerEdit for ast::Struct {
     fn get_or_create_generic_param_list(&self) -> ast::GenericParamList {
         match self.generic_param_list() {
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 596f73e0b10..fab4cb287c3 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -13,6 +13,7 @@
 
 mod quote;
 
+use either::Either;
 use itertools::Itertools;
 use parser::{Edition, T};
 use rowan::NodeOrToken;
@@ -881,7 +882,7 @@ pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::Mat
 }
 
 pub fn where_pred(
-    path: ast::Type,
+    path: Either<ast::Lifetime, ast::Type>,
     bounds: impl IntoIterator<Item = ast::TypeBound>,
 ) -> ast::WherePred {
     let bounds = bounds.into_iter().join(" + ");
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 f6ca5ab6c8c..96e1301f227 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -662,10 +662,6 @@ impl ProcMacroExpander for IdentityProcMacroExpander {
     ) -> Result<TopSubtree, ProcMacroExpansionError> {
         Ok(subtree.clone())
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
 
 // Expands to a macro_rules! macro, for issue #18089.
@@ -697,10 +693,6 @@ impl ProcMacroExpander for Issue18089ProcMacroExpander {
             #subtree
         })
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
 
 // Pastes the attribute input as its output
@@ -721,10 +713,6 @@ impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander {
             .cloned()
             .ok_or_else(|| ProcMacroExpansionError::Panic("Expected attribute input".into()))
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
 
 #[derive(Debug)]
@@ -756,10 +744,6 @@ impl ProcMacroExpander for Issue18840ProcMacroExpander {
         top_subtree_delimiter_mut.close = def_site;
         Ok(result)
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
 
 #[derive(Debug)]
@@ -791,10 +775,6 @@ impl ProcMacroExpander for MirrorProcMacroExpander {
         traverse(&mut builder, input.iter());
         Ok(builder.build())
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
 
 // Replaces every literal with an empty string literal and every identifier with its first letter,
@@ -835,10 +815,6 @@ impl ProcMacroExpander for ShortenProcMacroExpander {
             }
         }
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
 
 // Reads ident type within string quotes, for issue #17479.
@@ -864,10 +840,6 @@ impl ProcMacroExpander for Issue17479ProcMacroExpander {
             #symbol()
         })
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
 
 // Reads ident type within string quotes, for issue #17479.
@@ -919,10 +891,6 @@ impl ProcMacroExpander for Issue18898ProcMacroExpander {
             }
         })
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
 
 // Reads ident type within string quotes, for issue #17479.
@@ -950,8 +918,4 @@ impl ProcMacroExpander for DisallowCfgProcMacroExpander {
         }
         Ok(subtree.clone())
     }
-
-    fn eq_dyn(&self, other: &dyn ProcMacroExpander) -> bool {
-        other.as_any().type_id() == std::any::TypeId::of::<Self>()
-    }
 }
diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs
index 1dbc07c0929..14574a6456b 100644
--- a/src/tools/rust-analyzer/crates/tt/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs
@@ -817,6 +817,58 @@ impl<S> fmt::Display for Ident<S> {
     }
 }
 
+impl<S> Literal<S> {
+    pub fn display_no_minus(&self) -> impl fmt::Display {
+        struct NoMinus<'a, S>(&'a Literal<S>);
+        impl<S> fmt::Display for NoMinus<'_, S> {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                let symbol =
+                    self.0.symbol.as_str().strip_prefix('-').unwrap_or(self.0.symbol.as_str());
+                match self.0.kind {
+                    LitKind::Byte => write!(f, "b'{symbol}'"),
+                    LitKind::Char => write!(f, "'{symbol}'"),
+                    LitKind::Integer | LitKind::Float | LitKind::Err(_) => write!(f, "{symbol}"),
+                    LitKind::Str => write!(f, "\"{symbol}\""),
+                    LitKind::ByteStr => write!(f, "b\"{symbol}\""),
+                    LitKind::CStr => write!(f, "c\"{symbol}\""),
+                    LitKind::StrRaw(num_of_hashes) => {
+                        let num_of_hashes = num_of_hashes as usize;
+                        write!(
+                            f,
+                            r#"r{0:#<num_of_hashes$}"{text}"{0:#<num_of_hashes$}"#,
+                            "",
+                            text = symbol
+                        )
+                    }
+                    LitKind::ByteStrRaw(num_of_hashes) => {
+                        let num_of_hashes = num_of_hashes as usize;
+                        write!(
+                            f,
+                            r#"br{0:#<num_of_hashes$}"{text}"{0:#<num_of_hashes$}"#,
+                            "",
+                            text = symbol
+                        )
+                    }
+                    LitKind::CStrRaw(num_of_hashes) => {
+                        let num_of_hashes = num_of_hashes as usize;
+                        write!(
+                            f,
+                            r#"cr{0:#<num_of_hashes$}"{text}"{0:#<num_of_hashes$}"#,
+                            "",
+                            text = symbol
+                        )
+                    }
+                }?;
+                if let Some(suffix) = &self.0.suffix {
+                    write!(f, "{suffix}")?;
+                }
+                Ok(())
+            }
+        }
+        NoMinus(self)
+    }
+}
+
 impl<S> fmt::Display for Literal<S> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.kind {
diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json
index 11a37c218f7..18fb097aad7 100644
--- a/src/tools/rust-analyzer/editors/code/package-lock.json
+++ b/src/tools/rust-analyzer/editors/code/package-lock.json
@@ -5730,9 +5730,9 @@
             "license": "MIT"
         },
         "node_modules/undici": {
-            "version": "6.21.1",
-            "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
-            "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==",
+            "version": "6.21.3",
+            "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
+            "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
             "dev": true,
             "license": "MIT",
             "engines": {
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index 90e4d65bf96..5b47d1bbaed 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-6e23095adf9209614a45f7f75fea36dad7b92afb
+a8e4c68dcb4dc1e48a0db294c5323cab0227fcb9
diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml
index 6195de5d202..bb7d83c4b7d 100644
--- a/src/tools/rust-analyzer/xtask/Cargo.toml
+++ b/src/tools/rust-analyzer/xtask/Cargo.toml
@@ -14,7 +14,7 @@ write-json = "0.1.4"
 xshell.workspace = true
 xflags = "0.3.2"
 time = { version = "0.3", default-features = false }
-zip = { version = "2.4", default-features = false, features = ["deflate-flate2", "flate2", "time"] }
+zip = { version = "3.0", default-features = false, features = ["deflate-flate2", "time"] }
 stdx.workspace = true
 proc-macro2 = "1.0.94"
 quote = "1.0.40"
diff --git a/src/tools/rustfmt/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs
index 58c8d21bd7a..1a9614bacec 100644
--- a/src/tools/rustfmt/src/parse/macros/asm.rs
+++ b/src/tools/rustfmt/src/parse/macros/asm.rs
@@ -1,10 +1,10 @@
 use rustc_ast::ast;
-use rustc_builtin_macros::asm::{AsmArgs, parse_asm_args};
+use rustc_builtin_macros::asm::{AsmArg, parse_asm_args};
 
 use crate::rewrite::RewriteContext;
 
 #[allow(dead_code)]
-pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option<AsmArgs> {
+pub(crate) fn parse_asm(context: &RewriteContext<'_>, mac: &ast::MacCall) -> Option<Vec<AsmArg>> {
     let ts = mac.args.tokens.clone();
     let mut parser = super::build_parser(context, ts);
     parse_asm_args(&mut parser, mac.span(), ast::AsmMacro::Asm).ok()
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 4195258af88..9bb06c31c5c 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -429,10 +429,13 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "winapi-util",
     "winapi-x86_64-pc-windows-gnu",
     "windows",
+    "windows-collections",
     "windows-core",
+    "windows-future",
     "windows-implement",
     "windows-interface",
     "windows-link",
+    "windows-numerics",
     "windows-result",
     "windows-strings",
     "windows-sys",
diff --git a/tests/codegen/autodiff/generic.rs b/tests/codegen/autodiff/generic.rs
new file mode 100644
index 00000000000..15e7d8a4957
--- /dev/null
+++ b/tests/codegen/autodiff/generic.rs
@@ -0,0 +1,42 @@
+//@ compile-flags: -Zautodiff=Enable -Zautodiff=NoPostopt -C opt-level=3 -Clto=fat
+//@ no-prefer-dynamic
+//@ needs-enzyme
+#![feature(autodiff)]
+
+use std::autodiff::autodiff;
+
+#[autodiff(d_square, Reverse, Duplicated, Active)]
+fn square<T: std::ops::Mul<Output = T> + Copy>(x: &T) -> T {
+    *x * *x
+}
+
+// Ensure that `d_square::<f64>` code is generated even if `square::<f64>` was never called
+//
+// CHECK: ; generic::square
+// CHECK-NEXT: ; Function Attrs:
+// CHECK-NEXT: define internal {{.*}} double
+// CHECK-NEXT: start:
+// CHECK-NOT: ret
+// CHECK: fmul double
+
+// Ensure that `d_square::<f32>` code is generated
+//
+// CHECK: ; generic::square
+// CHECK-NEXT: ; Function Attrs: {{.*}}
+// CHECK-NEXT: define internal {{.*}} float
+// CHECK-NEXT: start:
+// CHECK-NOT: ret
+// CHECK: fmul float
+
+fn main() {
+    let xf32: f32 = std::hint::black_box(3.0);
+    let xf64: f64 = std::hint::black_box(3.0);
+
+    let outputf32 = square::<f32>(&xf32);
+    assert_eq!(9.0, outputf32);
+
+    let mut df_dxf64: f64 = std::hint::black_box(0.0);
+
+    let output_f64 = d_square::<f64>(&xf64, &mut df_dxf64, 1.0);
+    assert_eq!(6.0, df_dxf64);
+}
diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map
index 9f8dc8d6cbb..53128dd7a48 100644
--- a/tests/coverage/async_closure.cov-map
+++ b/tests/coverage/async_closure.cov-map
@@ -37,32 +37,29 @@ Number of file 0 mappings: 8
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
 Number of files: 1
 - file 0 => $DIR/async_closure.rs
 Number of expressions: 0
-Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
-- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
 Number of files: 1
 - file 0 => $DIR/async_closure.rs
 Number of expressions: 0
-Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
-- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
-Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
 Number of files: 1
 - file 0 => $DIR/async_closure.rs
 Number of expressions: 0
-Number of file 0 mappings: 2
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
-- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
 Highest counter ID seen: c0
 
diff --git a/tests/coverage/unused-local-file.coverage b/tests/coverage/unused-local-file.coverage
new file mode 100644
index 00000000000..8f5a32f6d70
--- /dev/null
+++ b/tests/coverage/unused-local-file.coverage
@@ -0,0 +1,7 @@
+   LL|       |//@ edition: 2021
+   LL|       |
+   LL|       |// Force this function to be generated in its home crate, so that it ends up
+   LL|       |// with normal coverage metadata.
+   LL|       |#[inline(never)]
+   LL|      1|pub fn external_function() {}
+
diff --git a/tests/coverage/unused-local-file.rs b/tests/coverage/unused-local-file.rs
new file mode 100644
index 00000000000..cf43c62d703
--- /dev/null
+++ b/tests/coverage/unused-local-file.rs
@@ -0,0 +1,22 @@
+//! If we give LLVM a local file table for a function, but some of the entries
+//! in that table have no associated mapping regions, then an assertion failure
+//! will occur in LLVM. We therefore need to detect and skip any function that
+//! would trigger that assertion.
+//!
+//! To test that this case is handled, even before adding code that could allow
+//! it to happen organically (for expansion region support), we use a special
+//! testing-only flag to force it to occur.
+
+//@ edition: 2024
+//@ compile-flags: -Zcoverage-options=inject-unused-local-file
+
+// The `llvm-cov` tool will complain if the test binary ends up having no
+// coverage metadata at all. To prevent that, we also link to instrumented
+// code in an auxiliary crate that doesn't have the special flag set.
+
+//@ aux-build: discard_all_helper.rs
+extern crate discard_all_helper;
+
+fn main() {
+    discard_all_helper::external_function();
+}
diff --git a/tests/crashes/139905.rs b/tests/crashes/139905.rs
new file mode 100644
index 00000000000..7da622aaaba
--- /dev/null
+++ b/tests/crashes/139905.rs
@@ -0,0 +1,6 @@
+//@ known-bug: #139905
+trait a<const b: bool> {}
+impl a<{}> for () {}
+trait c {}
+impl<const d: u8> c for () where (): a<d> {}
+impl c for () {}
diff --git a/tests/crashes/140011.rs b/tests/crashes/140011.rs
new file mode 100644
index 00000000000..b9d57a2822d
--- /dev/null
+++ b/tests/crashes/140011.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #140011
+//@compile-flags: -Wrust-2021-incompatible-closure-captures
+enum b {
+    c(d),
+    e(f),
+}
+struct f;
+fn g() {
+    let h;
+    || b::e(a) = h;
+}
diff --git a/tests/crashes/140099.rs b/tests/crashes/140099.rs
new file mode 100644
index 00000000000..fca12910055
--- /dev/null
+++ b/tests/crashes/140099.rs
@@ -0,0 +1,6 @@
+//@ known-bug: #140099
+struct a;
+impl From for a where for<'any> &'any mut (): Clone {}
+fn b() -> Result<(), std::convert::Infallible> {
+    || -> Result<_, a> { b()? }
+}
diff --git a/tests/crashes/140100.rs b/tests/crashes/140100.rs
new file mode 100644
index 00000000000..0836ffe2d92
--- /dev/null
+++ b/tests/crashes/140100.rs
@@ -0,0 +1,7 @@
+//@ known-bug: #140100
+fn a()
+where
+    b: Sized,
+{
+    println!()
+}
diff --git a/tests/crashes/140123-2.rs b/tests/crashes/140123-2.rs
new file mode 100644
index 00000000000..6ed10b9dcc3
--- /dev/null
+++ b/tests/crashes/140123-2.rs
@@ -0,0 +1,12 @@
+//@ known-bug: #140123
+//@ compile-flags: --crate-type lib
+
+trait Trait {}
+
+impl Trait for [(); 0] {}
+
+const ICE: [&mut dyn Trait; 2] = [const { empty_mut() }; 2];
+
+const fn empty_mut() -> &'static mut [(); 0] {
+    &mut []
+}
diff --git a/tests/crashes/140123-3.rs b/tests/crashes/140123-3.rs
new file mode 100644
index 00000000000..a1dcd7fc39f
--- /dev/null
+++ b/tests/crashes/140123-3.rs
@@ -0,0 +1,10 @@
+//@ known-bug: #140123
+//@ compile-flags: --crate-type lib
+
+const ICE: [&mut [()]; 2] = [const { empty_mut() }; 2];
+
+const fn empty_mut() -> &'static mut [()] {
+    unsafe {
+        std::slice::from_raw_parts_mut(std::ptr::dangling_mut(), 0)
+    }
+}
diff --git a/tests/crashes/140123-4.rs b/tests/crashes/140123-4.rs
new file mode 100644
index 00000000000..39042d897ee
--- /dev/null
+++ b/tests/crashes/140123-4.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #140123
+//@ compile-flags: --crate-type lib
+
+const ICE: [&mut [(); 0]; 2] = [const { empty_mut() }; 2];
+
+const fn empty_mut() -> &'static mut [(); 0] {
+    &mut []
+}
+// https://github.com/rust-lang/rust/issues/140123#issuecomment-2820664450
+const ICE2: [&mut [(); 0]; 2] = [const {
+    let x = &mut [];
+    x
+}; 2];
diff --git a/tests/crashes/140123.rs b/tests/crashes/140123.rs
new file mode 100644
index 00000000000..337b5f3cef0
--- /dev/null
+++ b/tests/crashes/140123.rs
@@ -0,0 +1,10 @@
+//@ known-bug: #140123
+//@ compile-flags: --crate-type lib
+
+const OK: [&mut [()]; 2] = [empty_mut(), empty_mut()];
+const ICE: [&mut [()]; 2] = [const { empty_mut() }; 2];
+
+// Any kind of fn call gets around E0764.
+const fn empty_mut() -> &'static mut [()] {
+    &mut []
+}
diff --git a/tests/crashes/140255.rs b/tests/crashes/140255.rs
new file mode 100644
index 00000000000..6b0ec1718b0
--- /dev/null
+++ b/tests/crashes/140255.rs
@@ -0,0 +1,3 @@
+//@ known-bug: #140255
+#[unsafe(macro_use::VAR2)]
+fn dead_code() {}
diff --git a/tests/crashes/140275.rs b/tests/crashes/140275.rs
new file mode 100644
index 00000000000..5ea04af0c8e
--- /dev/null
+++ b/tests/crashes/140275.rs
@@ -0,0 +1,5 @@
+//@ known-bug: #140275
+#![feature(generic_const_exprs)]
+trait T{}
+trait V{}
+impl<const N: i32> T for [i32; N::<&mut V>] {}
diff --git a/tests/crashes/140281.rs b/tests/crashes/140281.rs
new file mode 100644
index 00000000000..76858cfc74a
--- /dev/null
+++ b/tests/crashes/140281.rs
@@ -0,0 +1,18 @@
+//@ known-bug: #140281
+
+macro_rules! foo {
+    ($x:expr) => { $x }
+}
+
+fn main() {
+    let t = vec![
+        /// ‮test⁦ RTL in doc in vec!
+        //  ICE (Sadly)
+        1
+    ];
+
+        foo!(
+        /// ‮test⁦ RTL in doc in macro
+        1
+    );
+}
diff --git a/tests/crashes/140303.rs b/tests/crashes/140303.rs
new file mode 100644
index 00000000000..43a20b5e58e
--- /dev/null
+++ b/tests/crashes/140303.rs
@@ -0,0 +1,22 @@
+//@ known-bug: #140303
+//@compile-flags: -Zvalidate-mir
+use std::future::Future;
+async fn a() -> impl Sized {
+    b(c)
+}
+async fn c(); // kaboom
+fn b<d>(e: d) -> impl Sized
+where
+    d: f,
+{
+    || -> <d>::h { panic!() }
+}
+trait f {
+    type h;
+}
+impl<d, g> f for d
+where
+    d: Fn() -> g,
+    g: Future,
+{
+}
diff --git a/tests/crashes/140333.rs b/tests/crashes/140333.rs
new file mode 100644
index 00000000000..cec1100e6ad
--- /dev/null
+++ b/tests/crashes/140333.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #140333
+fn a() -> impl b<
+    [c; {
+        struct d {
+            #[a]
+            bar: e,
+        }
+    }],
+>;
diff --git a/tests/crashes/140365.rs b/tests/crashes/140365.rs
new file mode 100644
index 00000000000..809ceaf35a0
--- /dev/null
+++ b/tests/crashes/140365.rs
@@ -0,0 +1,8 @@
+//@ known-bug: #140365
+//@compile-flags: -C opt-level=1 -Zvalidate-mir
+fn f() -> &'static str
+where
+    Self: Sized,
+{
+    ""
+}
diff --git a/tests/crashes/140381.rs b/tests/crashes/140381.rs
new file mode 100644
index 00000000000..439ca694d56
--- /dev/null
+++ b/tests/crashes/140381.rs
@@ -0,0 +1,16 @@
+//@ known-bug: #140381
+pub trait Foo<T> {}
+pub trait Lend {
+    type From<'a>
+    where
+        Self: 'a;
+    fn lend(from: Self::From<'_>) -> impl Foo<Self::From<'_>>;
+}
+
+impl<T, F> Lend for (T, F) {
+    type From<'a> = ();
+
+    fn lend(from: Self::From<'_>) -> impl Foo<Self::From<'_>> {
+        from
+    }
+}
diff --git a/tests/crashes/140429.rs b/tests/crashes/140429.rs
new file mode 100644
index 00000000000..041eaf86c5c
--- /dev/null
+++ b/tests/crashes/140429.rs
@@ -0,0 +1,6 @@
+//@ known-bug: #140429
+//@ compile-flags: -Zlint-mir --crate-type lib
+//@ edition:2024
+
+#![feature(async_drop)]
+async fn a<T>(x: T) {}
diff --git a/tests/crashes/140479.rs b/tests/crashes/140479.rs
new file mode 100644
index 00000000000..ed3ca887546
--- /dev/null
+++ b/tests/crashes/140479.rs
@@ -0,0 +1,5 @@
+//@ known-bug: #140479
+macro_rules! a { ( $( { $ [ $b:c ] } )) => ( $(${ concat(d, $b)} ))}
+fn e() {
+    a!({})
+}
diff --git a/tests/crashes/140484.rs b/tests/crashes/140484.rs
new file mode 100644
index 00000000000..92ec1984398
--- /dev/null
+++ b/tests/crashes/140484.rs
@@ -0,0 +1,14 @@
+//@ known-bug: #140484
+//@edition:2024
+#![feature(async_drop)]
+use std::future::AsyncDrop;
+struct a;
+impl Drop for a {
+    fn b() {}
+}
+impl AsyncDrop for a {
+    type c;
+}
+async fn bar() {
+    a;
+}
diff --git a/tests/crashes/140500.rs b/tests/crashes/140500.rs
new file mode 100644
index 00000000000..ee5b93ab821
--- /dev/null
+++ b/tests/crashes/140500.rs
@@ -0,0 +1,14 @@
+//@ known-bug: #140500
+
+#![feature(async_drop)]
+use std::future::AsyncDrop;
+struct a;
+impl Drop for a {
+    fn b() {}
+}
+impl AsyncDrop for a {
+    fn c(d: impl Sized) {}
+}
+async fn bar() {
+    a;
+}
diff --git a/tests/crashes/140530.rs b/tests/crashes/140530.rs
new file mode 100644
index 00000000000..7e0372a4bd8
--- /dev/null
+++ b/tests/crashes/140530.rs
@@ -0,0 +1,8 @@
+//@ known-bug: #140530
+//@ edition: 2024
+
+#![feature(async_drop, gen_blocks)]
+async gen fn a() {
+  _ = async {}
+}
+fn main() {}
diff --git a/tests/crashes/140531.rs b/tests/crashes/140531.rs
new file mode 100644
index 00000000000..f664481d440
--- /dev/null
+++ b/tests/crashes/140531.rs
@@ -0,0 +1,7 @@
+//@ known-bug: #140531
+//@compile-flags: -Zlint-mir --crate-type lib
+//@ edition:2024
+#![feature(async_drop)]
+async fn call_once(f: impl AsyncFnOnce()) {
+    let fut = Box::pin(f());
+}
diff --git a/tests/crashes/140571.rs b/tests/crashes/140571.rs
new file mode 100644
index 00000000000..97fa1d8432d
--- /dev/null
+++ b/tests/crashes/140571.rs
@@ -0,0 +1,14 @@
+//@ known-bug: #140571
+pub trait IsVoid {
+    const IS_VOID: bool;
+}
+impl<T> IsVoid for T {
+    default const IS_VOID: bool = false;
+}
+impl<T> Maybe<T> for () where T: NotVoid + ?Sized {}
+
+pub trait NotVoid {}
+impl<T> NotVoid for T where T: IsVoid<IS_VOID = false> + ?Sized {}
+
+pub trait Maybe<T> {}
+impl<T> Maybe<T> for T {}
diff --git a/tests/crashes/140577.rs b/tests/crashes/140577.rs
new file mode 100644
index 00000000000..21e6b1e1522
--- /dev/null
+++ b/tests/crashes/140577.rs
@@ -0,0 +1,32 @@
+//@ known-bug: #140577
+//@ compile-flags: -Znext-solver=globally
+//@ edition:2021
+
+use std::future::Future;
+use std::pin::Pin;
+trait Acquire {
+    type Connection;
+}
+impl Acquire for &'static () {
+    type Connection = ();
+}
+fn b<T: Acquire>() -> impl Future + Send {
+    let x: Pin<Box<dyn Future<Output = T::Connection> + Send>> = todo!();
+    x
+}
+fn main() {
+    async {
+        b::<&()>().await;
+    }
+    .aa();
+}
+
+impl<F> Filter for F where F: Send {}
+
+trait Filter {
+    fn aa(self)
+    where
+        Self: Sized,
+    {
+    }
+}
diff --git a/tests/crashes/140609.rs b/tests/crashes/140609.rs
new file mode 100644
index 00000000000..ee8a4bb3048
--- /dev/null
+++ b/tests/crashes/140609.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #140609
+#![feature(with_negative_coherence)]
+#![feature(generic_const_exprs)]
+#![crate_type = "lib"]
+trait Trait {}
+struct A<const B: bool>;
+
+trait C {}
+
+impl<const D: u32> Trait for E<D> where A<{ D <= 2 }>: FnOnce(&isize) {}
+struct E<const D: u32>;
+
+impl<const D: u32> Trait for E<D> where A<{ D <= 2 }>: C {}
diff --git a/tests/crashes/140642.rs b/tests/crashes/140642.rs
new file mode 100644
index 00000000000..ff75a6ec2f2
--- /dev/null
+++ b/tests/crashes/140642.rs
@@ -0,0 +1,8 @@
+//@ known-bug: #140642
+#![feature(min_generic_const_args)]
+
+pub trait Tr<A> {
+    const SIZE: usize;
+}
+
+fn mk_array(_x: T) -> [(); <T as Tr<bool>>::SIZE] {}
diff --git a/tests/crashes/140683.rs b/tests/crashes/140683.rs
new file mode 100644
index 00000000000..74ea5c2533b
--- /dev/null
+++ b/tests/crashes/140683.rs
@@ -0,0 +1,5 @@
+//@ known-bug: #140683
+impl T {
+#[core::contracts::ensures]
+  fn b() { (loop) }
+}
diff --git a/tests/crashes/140729.rs b/tests/crashes/140729.rs
new file mode 100644
index 00000000000..a436ec58e8e
--- /dev/null
+++ b/tests/crashes/140729.rs
@@ -0,0 +1,11 @@
+//@ known-bug: #140729
+#![feature(min_generic_const_args)]
+
+const C: usize = 0;
+pub struct A<const M: usize> {}
+impl A<C> {
+    fn fun1() {}
+}
+impl A {
+    fn fun1() {}
+}
diff --git a/tests/crashes/140850.rs b/tests/crashes/140850.rs
new file mode 100644
index 00000000000..fd26097deda
--- /dev/null
+++ b/tests/crashes/140850.rs
@@ -0,0 +1,7 @@
+//@ known-bug: #140850
+//@ compile-flags: -Zvalidate-mir
+fn A() -> impl {
+    while A() {}
+    loop {}
+}
+fn main() {}
diff --git a/tests/crashes/140860.rs b/tests/crashes/140860.rs
new file mode 100644
index 00000000000..04da6bd832c
--- /dev/null
+++ b/tests/crashes/140860.rs
@@ -0,0 +1,10 @@
+//@ known-bug: #140860
+#![feature(min_generic_const_args)]
+#![feature(unsized_const_params)]
+#![feature(with_negative_coherence, negative_impls)]
+trait a < const b : &'static str> {} trait c {} struct d< e >(e);
+impl<e> c for e where e: a<""> {}
+impl<e> c for d<e> {}
+impl<e> !a<f> for e {}
+const f : &str = "";
+fn main() {}
diff --git a/tests/crashes/140884.rs b/tests/crashes/140884.rs
new file mode 100644
index 00000000000..6840760933a
--- /dev/null
+++ b/tests/crashes/140884.rs
@@ -0,0 +1,6 @@
+//@ known-bug: #140884
+//@ needs-rustc-debug-assertions
+
+fn a() {
+    extern "" {}
+}
diff --git a/tests/crashes/140891.rs b/tests/crashes/140891.rs
new file mode 100644
index 00000000000..421919403ef
--- /dev/null
+++ b/tests/crashes/140891.rs
@@ -0,0 +1,6 @@
+//@ known-bug: #140891
+struct A<const N: usize> {}
+impl<const N: usize> Iterator for A<N> {
+    fn next() -> [(); std::mem::size_of::<Option<Self::Item>>] {}
+}
+fn main() {}
diff --git a/tests/crashes/140974.rs b/tests/crashes/140974.rs
new file mode 100644
index 00000000000..ac1051a64fd
--- /dev/null
+++ b/tests/crashes/140974.rs
@@ -0,0 +1,14 @@
+//@ known-bug: #140974
+//@edition:2021
+#![feature(async_drop)]
+use core::future::AsyncDrop;
+
+async fn fun(_: HasIncompleteAsyncDrop) {}
+
+struct HasIncompleteAsyncDrop;
+impl Drop for HasIncompleteAsyncDrop {
+    fn drop(&mut self) {}
+}
+impl AsyncDrop for HasIncompleteAsyncDrop {
+    // not implemented yet..
+}
diff --git a/tests/crashes/140975.rs b/tests/crashes/140975.rs
new file mode 100644
index 00000000000..e11dd40612c
--- /dev/null
+++ b/tests/crashes/140975.rs
@@ -0,0 +1,22 @@
+//@ known-bug: #140975
+//@ compile-flags: --crate-type lib -Zvalidate-mir
+//@ edition: 2021
+#![feature(async_drop)]
+use std::{future::AsyncDrop, pin::Pin};
+
+struct HasAsyncDrop ;
+impl Drop for HasAsyncDrop {
+    fn drop(&mut self) {}
+}
+impl AsyncDrop for HasAsyncDrop {
+    async fn drop(self: Pin<&mut Self>) {}
+}
+
+struct Holder {
+    inner: HasAsyncDrop,
+}
+async fn bar() {
+    Holder {
+        inner: HasAsyncDrop
+   };
+}
diff --git a/tests/crashes/141124.rs b/tests/crashes/141124.rs
new file mode 100644
index 00000000000..38a2a55e1c4
--- /dev/null
+++ b/tests/crashes/141124.rs
@@ -0,0 +1,16 @@
+//@ known-bug: #141124
+struct S;
+trait SimpleTrait {}
+trait TraitAssoc {
+    type Assoc;
+}
+
+impl<T> TraitAssoc for T
+where
+    T: SimpleTrait,
+{
+    type Assoc = <(T,) as TraitAssoc>::Assoc;
+}
+impl SimpleTrait for <S as TraitAssoc>::Assoc {}
+
+pub fn main() {}
diff --git a/tests/crashes/141143.rs b/tests/crashes/141143.rs
new file mode 100644
index 00000000000..a4aa2f19a6c
--- /dev/null
+++ b/tests/crashes/141143.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #141143
+trait TypedClient {
+    fn publish_typed<F>(&self) -> impl Sized
+    where
+        F: Clone;
+}
+impl TypedClient for () {
+    fn publish_typed<F>(&self) -> impl Sized {}
+}
+
+fn main() {
+    ().publish_typed();
+}
diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
index d465b8bded2..fa88211383a 100644
--- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
@@ -40,7 +40,7 @@
 +     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:18 (#0);
 +     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:23: 19:30 (#0);
 +     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:31: 19:32 (#0);
-+     coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0);
++     coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:1: 21:2 (#0);
 + 
       bb0: {
 +         Coverage::VirtualCounter(bcb0);
diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff
index cf6d85abd80..9b6d2b22087 100644
--- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff
@@ -6,7 +6,7 @@
   
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:27:1: 27:17 (#0);
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:28:5: 28:9 (#0);
-+     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:2: 29:2 (#0);
++     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:1: 29:2 (#0);
 + 
       bb0: {
 +         Coverage::VirtualCounter(bcb0);
diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
index 980c5e202ff..b2bb2375aee 100644
--- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
@@ -10,8 +10,8 @@
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:10 (#0);
 +     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0);
 +     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0);
-+     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0);
-+     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0);
++     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:9: 17:10 (#0);
++     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:1: 19:2 (#0);
 + 
       bb0: {
 +         Coverage::VirtualCounter(bcb0);
diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
index b707cd41788..2eb78c08ee8 100644
--- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
+++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
@@ -10,8 +10,8 @@
       coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0);
       coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
       coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0);
-      coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0);
-      coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0);
+      coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0);
+      coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0);
       coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
   
       bb0: {
diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff
index 239b845c231..0c1bc24b6dc 100644
--- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff
@@ -10,8 +10,8 @@
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0);
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
 +     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0);
-+     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0);
-+     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0);
++     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0);
++     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0);
 +     coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
 + 
       bb0: {
diff --git a/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff b/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff
new file mode 100644
index 00000000000..fcabcdbcfef
--- /dev/null
+++ b/tests/mir-opt/gvn_overlapping.overlapping.GVN.diff
@@ -0,0 +1,18 @@
+- // MIR for `overlapping` before GVN
++ // MIR for `overlapping` after GVN
+  
+  fn overlapping(_1: Adt) -> () {
+      let mut _0: ();
+      let mut _2: *mut Adt;
+      let mut _3: u32;
+      let mut _4: &Adt;
+  
+      bb0: {
+          _2 = &raw mut _1;
+          _4 = &(*_2);
+          _3 = copy (((*_4) as variant#1).0: u32);
+          (*_2) = Adt::Some(copy _3);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn_overlapping.rs b/tests/mir-opt/gvn_overlapping.rs
new file mode 100644
index 00000000000..99113445e68
--- /dev/null
+++ b/tests/mir-opt/gvn_overlapping.rs
@@ -0,0 +1,36 @@
+//@ test-mir-pass: GVN
+
+#![feature(custom_mir, core_intrinsics)]
+
+// Check that we do not create overlapping assignments.
+
+use std::intrinsics::mir::*;
+
+// EMIT_MIR gvn_overlapping.overlapping.GVN.diff
+#[custom_mir(dialect = "runtime")]
+fn overlapping(_17: Adt) {
+    // CHECK-LABEL: fn overlapping(
+    // CHECK: let mut [[PTR:.*]]: *mut Adt;
+    // CHECK: (*[[PTR]]) = Adt::Some(copy {{.*}});
+    mir! {
+        let _33: *mut Adt;
+        let _48: u32;
+        let _73: &Adt;
+        {
+            _33 = core::ptr::addr_of_mut!(_17);
+            _73 = &(*_33);
+            _48 = Field(Variant((*_73), 1), 0);
+            (*_33) = Adt::Some(_48);
+            Return()
+        }
+    }
+}
+
+fn main() {
+    overlapping(Adt::Some(0));
+}
+
+enum Adt {
+    None,
+    Some(u32),
+}
diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff
index 7f325245bce..d73cc3d214e 100644
--- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff
+++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-abort.diff
@@ -45,7 +45,7 @@
           _9 = copy _10;
           _8 = move _9 as *mut i32 (PtrToPtr);
           StorageDead(_9);
--         _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable];
+-         _3 = std::intrinsics::copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable];
 +         copy_nonoverlapping(dst = move _8, src = move _4, count = const 0_usize);
 +         goto -> bb1;
       }
diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff
index 7f325245bce..d73cc3d214e 100644
--- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff
+++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.panic-unwind.diff
@@ -45,7 +45,7 @@
           _9 = copy _10;
           _8 = move _9 as *mut i32 (PtrToPtr);
           StorageDead(_9);
--         _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable];
+-         _3 = std::intrinsics::copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable];
 +         copy_nonoverlapping(dst = move _8, src = move _4, count = const 0_usize);
 +         goto -> bb1;
       }
diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs
index 5afddc5ff73..4e000b05a4b 100644
--- a/tests/mir-opt/lower_intrinsics.rs
+++ b/tests/mir-opt/lower_intrinsics.rs
@@ -1,9 +1,11 @@
 //@ test-mir-pass: LowerIntrinsics
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
-#![feature(core_intrinsics, intrinsics, rustc_attrs)]
+#![feature(core_intrinsics)]
 #![crate_type = "lib"]
 
+use std::intrinsics::copy_nonoverlapping;
+
 // EMIT_MIR lower_intrinsics.wrapping.LowerIntrinsics.diff
 pub fn wrapping(a: i32, b: i32) {
     // CHECK-LABEL: fn wrapping(
@@ -153,11 +155,6 @@ pub fn discriminant<T>(t: T) {
     core::intrinsics::discriminant_value(&E::B);
 }
 
-// Cannot use `std::intrinsics::copy_nonoverlapping` as that is a wrapper function
-#[rustc_nounwind]
-#[rustc_intrinsic]
-unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
-
 // EMIT_MIR lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
 pub fn f_copy_nonoverlapping() {
     // CHECK-LABEL: fn f_copy_nonoverlapping(
diff --git a/tests/pretty/autodiff/autodiff_forward.pp b/tests/pretty/autodiff/autodiff_forward.pp
index 713b8f541ae..8253603e807 100644
--- a/tests/pretty/autodiff/autodiff_forward.pp
+++ b/tests/pretty/autodiff/autodiff_forward.pp
@@ -31,6 +31,8 @@ pub fn f1(x: &[f64], y: f64) -> f64 {
 
     // We want to make sure that we can use the macro for functions defined inside of functions
 
+    // Make sure we can handle generics
+
     ::core::panicking::panic("not implemented")
 }
 #[rustc_autodiff(Forward, 1, Dual, Const, Dual)]
@@ -181,4 +183,16 @@ pub fn f9() {
         ::core::hint::black_box(<f32>::default())
     }
 }
+#[rustc_autodiff]
+#[inline(never)]
+pub fn f10<T: std::ops::Mul<Output = T> + Copy>(x: &T) -> T { *x * *x }
+#[rustc_autodiff(Reverse, 1, Duplicated, Active)]
+#[inline(never)]
+pub fn d_square<T: std::ops::Mul<Output = T> +
+    Copy>(x: &T, dx_0: &mut T, dret: T) -> T {
+    unsafe { asm!("NOP", options(pure, nomem)); };
+    ::core::hint::black_box(f10::<T>(x));
+    ::core::hint::black_box((dx_0, dret));
+    ::core::hint::black_box(f10::<T>(x))
+}
 fn main() {}
diff --git a/tests/pretty/autodiff/autodiff_forward.rs b/tests/pretty/autodiff/autodiff_forward.rs
index 5a0660a08e5..ae974f9b4db 100644
--- a/tests/pretty/autodiff/autodiff_forward.rs
+++ b/tests/pretty/autodiff/autodiff_forward.rs
@@ -63,4 +63,10 @@ pub fn f9() {
     }
 }
 
+// Make sure we can handle generics
+#[autodiff(d_square, Reverse, Duplicated, Active)]
+pub fn f10<T: std::ops::Mul<Output = T> + Copy>(x: &T) -> T {
+    *x * *x
+}
+
 fn main() {}
diff --git a/tests/run-make/core-no-oom-handling/rmake.rs b/tests/run-make/core-no-oom-handling/rmake.rs
index a9e2b33e210..5194d773114 100644
--- a/tests/run-make/core-no-oom-handling/rmake.rs
+++ b/tests/run-make/core-no-oom-handling/rmake.rs
@@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root};
 
 fn main() {
     rustc()
-        .edition("2021")
+        .edition("2024")
         .arg("-Dwarnings")
         .crate_type("rlib")
         .input(source_root().join("library/core/src/lib.rs"))
diff --git a/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs b/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs
index 2727effe818..d28c8463016 100644
--- a/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs
+++ b/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs
@@ -11,6 +11,13 @@
 //@ needs-dynamic-linking
 //@ only-nightly (requires unstable rustc flag)
 
+// This test trips a check in the MSVC linker for an outdated processor:
+// "LNK1322: cannot avoid potential ARM hazard (Cortex-A53 MPCore processor bug #843419)"
+// Until MSVC removes this check:
+// https://developercommunity.microsoft.com/t/Remove-checking-for-and-fixing-Cortex-A/10905134
+// we'll need to disable this test on Arm64 Windows.
+//@ ignore-aarch64-pc-windows-msvc
+
 #![deny(warnings)]
 
 use run_make_support::{dynamic_lib_name, rfs, rust_lib_name, rustc};
diff --git a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs
index 22b9b029a40..2c78b794a8d 100644
--- a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs
+++ b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs
@@ -7,8 +7,6 @@
 //@ run-pass
 //@ needs-subprocess
 
-#![feature(avx512_target_feature)]
-
 #![allow(overflowing_literals)]
 #![allow(unused_variables)]
 
diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs
index 772512702ec..7432381d15b 100644
--- a/tests/ui/abi/simd-abi-checks-avx.rs
+++ b/tests/ui/abi/simd-abi-checks-avx.rs
@@ -2,7 +2,6 @@
 //@ build-fail
 //@ compile-flags: -C target-feature=-avx
 
-#![feature(avx512_target_feature)]
 #![feature(portable_simd)]
 #![feature(simd_ffi)]
 #![allow(improper_ctypes_definitions)]
diff --git a/tests/ui/abi/simd-abi-checks-avx.stderr b/tests/ui/abi/simd-abi-checks-avx.stderr
index 48db30bf453..7489ca01946 100644
--- a/tests/ui/abi/simd-abi-checks-avx.stderr
+++ b/tests/ui/abi/simd-abi-checks-avx.stderr
@@ -1,5 +1,5 @@
 error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:60:11
+  --> $DIR/simd-abi-checks-avx.rs:59:11
    |
 LL |         f(g());
    |           ^^^ function called here
@@ -7,7 +7,7 @@ LL |         f(g());
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:60:9
+  --> $DIR/simd-abi-checks-avx.rs:59:9
    |
 LL |         f(g());
    |         ^^^^^^ function called here
@@ -15,7 +15,7 @@ LL |         f(g());
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:66:14
+  --> $DIR/simd-abi-checks-avx.rs:65:14
    |
 LL |         gavx(favx());
    |              ^^^^^^ function called here
@@ -23,7 +23,7 @@ LL |         gavx(favx());
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:66:9
+  --> $DIR/simd-abi-checks-avx.rs:65:9
    |
 LL |         gavx(favx());
    |         ^^^^^^^^^^^^ function called here
@@ -31,7 +31,7 @@ LL |         gavx(favx());
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:76:19
+  --> $DIR/simd-abi-checks-avx.rs:75:19
    |
 LL |         w(Wrapper(g()));
    |                   ^^^ function called here
@@ -39,7 +39,7 @@ LL |         w(Wrapper(g()));
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:76:9
+  --> $DIR/simd-abi-checks-avx.rs:75:9
    |
 LL |         w(Wrapper(g()));
    |         ^^^^^^^^^^^^^^^ function called here
@@ -47,7 +47,7 @@ LL |         w(Wrapper(g()));
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:90:9
+  --> $DIR/simd-abi-checks-avx.rs:89:9
    |
 LL |         some_extern();
    |         ^^^^^^^^^^^^^ function called here
@@ -55,7 +55,7 @@ LL |         some_extern();
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:25:1
+  --> $DIR/simd-abi-checks-avx.rs:24:1
    |
 LL | unsafe extern "C" fn g() -> __m256 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -63,7 +63,7 @@ LL | unsafe extern "C" fn g() -> __m256 {
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:20:1
+  --> $DIR/simd-abi-checks-avx.rs:19:1
    |
 LL | unsafe extern "C" fn f(_: __m256) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -71,7 +71,7 @@ LL | unsafe extern "C" fn f(_: __m256) {
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled
-  --> $DIR/simd-abi-checks-avx.rs:15:1
+  --> $DIR/simd-abi-checks-avx.rs:14:1
    |
 LL | unsafe extern "C" fn w(_: Wrapper) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
@@ -79,7 +79,7 @@ LL | unsafe extern "C" fn w(_: Wrapper) {
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 error: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller
-  --> $DIR/simd-abi-checks-avx.rs:54:8
+  --> $DIR/simd-abi-checks-avx.rs:53:8
    |
 LL |     || g()
    |        ^^^ function called here
@@ -87,7 +87,7 @@ LL |     || g()
    = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`)
 
 note: the above error was encountered while instantiating `fn in_closure::{closure#0}`
-  --> $DIR/simd-abi-checks-avx.rs:82:9
+  --> $DIR/simd-abi-checks-avx.rs:81:9
    |
 LL |         in_closure()();
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/aarch64/parse-error.rs b/tests/ui/asm/aarch64/parse-error.rs
index aa731c35dda..622f99aa1b1 100644
--- a/tests/ui/asm/aarch64/parse-error.rs
+++ b/tests/ui/asm/aarch64/parse-error.rs
@@ -1,57 +1,11 @@
 //@ only-aarch64
 
-use std::arch::{asm, global_asm};
+use std::arch::asm;
 
 fn main() {
     let mut foo = 0;
     let mut bar = 0;
     unsafe {
-        asm!();
-        //~^ ERROR requires at least a template string argument
-        asm!(foo);
-        //~^ ERROR asm template must be a string literal
-        asm!("{}" foo);
-        //~^ ERROR expected token: `,`
-        asm!("{}", foo);
-        //~^ ERROR expected operand, clobber_abi, options, or additional template string
-        asm!("{}", in foo);
-        //~^ ERROR expected `(`, found `foo`
-        asm!("{}", in(reg foo));
-        //~^ ERROR expected `)`, found `foo`
-        asm!("{}", in(reg));
-        //~^ ERROR expected expression, found end of macro arguments
-        asm!("{}", inout(=) foo => bar);
-        //~^ ERROR expected register class or explicit register
-        asm!("{}", inout(reg) foo =>);
-        //~^ ERROR expected expression, found end of macro arguments
-        asm!("{}", in(reg) foo => bar);
-        //~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
-        asm!("{}", sym foo + bar);
-        //~^ ERROR expected a path for argument to `sym`
-        asm!("", options(foo));
-        //~^ ERROR expected one of
-        asm!("", options(nomem foo));
-        //~^ ERROR expected one of
-        asm!("", options(nomem, foo));
-        //~^ ERROR expected one of
-        asm!("{}", options(), const foo);
-        //~^ ERROR attempt to use a non-constant value in a constant
-        asm!("", clobber_abi(foo));
-        //~^ ERROR expected string literal
-        asm!("", clobber_abi("C" foo));
-        //~^ ERROR expected one of `)` or `,`, found `foo`
-        asm!("", clobber_abi("C", foo));
-        //~^ ERROR expected string literal
-        asm!("{}", clobber_abi("C"), const foo);
-        //~^ ERROR attempt to use a non-constant value in a constant
-        asm!("", options(), clobber_abi("C"));
-        asm!("{}", options(), clobber_abi("C"), const foo);
-        //~^ ERROR attempt to use a non-constant value in a constant
-        asm!("{a}", a = const foo, a = const bar);
-        //~^ ERROR duplicate argument named `a`
-        //~^^ ERROR argument never used
-        //~^^^ ERROR attempt to use a non-constant value in a constant
-        //~^^^^ ERROR attempt to use a non-constant value in a constant
         asm!("", a = in("x0") foo);
         //~^ ERROR explicit register arguments cannot have names
         asm!("{a}", in("x0") foo, a = const bar);
@@ -61,66 +15,5 @@ fn main() {
         asm!("{1}", in("x0") foo, const bar);
         //~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
         //~^^ ERROR attempt to use a non-constant value in a constant
-        asm!("", options(), "");
-        //~^ ERROR expected one of
-        asm!("{}", in(reg) foo, "{}", out(reg) foo);
-        //~^ ERROR expected one of
-        asm!(format!("{{{}}}", 0), in(reg) foo);
-        //~^ ERROR asm template must be a string literal
-        asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
-        //~^ ERROR asm template must be a string literal
-        asm!("{}", in(reg) _);
-        //~^ ERROR _ cannot be used for input operands
-        asm!("{}", inout(reg) _);
-        //~^ ERROR _ cannot be used for input operands
-        asm!("{}", inlateout(reg) _);
-        //~^ ERROR _ cannot be used for input operands
     }
 }
-
-const FOO: i32 = 1;
-const BAR: i32 = 2;
-global_asm!();
-//~^ ERROR requires at least a template string argument
-global_asm!(FOO);
-//~^ ERROR asm template must be a string literal
-global_asm!("{}" FOO);
-//~^ ERROR expected token: `,`
-global_asm!("{}", FOO);
-//~^ ERROR expected operand, options, or additional template string
-global_asm!("{}", const);
-//~^ ERROR expected expression, found end of macro arguments
-global_asm!("{}", const(reg) FOO);
-//~^ ERROR expected one of
-global_asm!("", options(FOO));
-//~^ ERROR expected one of
-global_asm!("", options(nomem FOO));
-//~^ ERROR expected one of
-//~| ERROR the `nomem` option cannot be used with `global_asm!`
-global_asm!("", options(nomem, FOO));
-//~^ ERROR expected one of
-//~| ERROR the `nomem` option cannot be used with `global_asm!`
-global_asm!("{}", options(), const FOO);
-global_asm!("", clobber_abi(FOO));
-//~^ ERROR expected string literal
-global_asm!("", clobber_abi("C" FOO));
-//~^ ERROR expected one of `)` or `,`, found `FOO`
-global_asm!("", clobber_abi("C", FOO));
-//~^ ERROR expected string literal
-global_asm!("{}", clobber_abi("C"), const FOO);
-//~^ ERROR `clobber_abi` cannot be used with `global_asm!`
-global_asm!("", options(), clobber_abi("C"));
-//~^ ERROR `clobber_abi` cannot be used with `global_asm!`
-global_asm!("{}", options(), clobber_abi("C"), const FOO);
-//~^ ERROR `clobber_abi` cannot be used with `global_asm!`
-global_asm!("{a}", a = const FOO, a = const BAR);
-//~^ ERROR duplicate argument named `a`
-//~^^ ERROR argument never used
-global_asm!("", options(), "");
-//~^ ERROR expected one of
-global_asm!("{}", const FOO, "{}", const FOO);
-//~^ ERROR expected one of
-global_asm!(format!("{{{}}}", 0), const FOO);
-//~^ ERROR asm template must be a string literal
-global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
-//~^ ERROR asm template must be a string literal
diff --git a/tests/ui/asm/aarch64/parse-error.stderr b/tests/ui/asm/aarch64/parse-error.stderr
index b5e1169e5f6..ca21311f87f 100644
--- a/tests/ui/asm/aarch64/parse-error.stderr
+++ b/tests/ui/asm/aarch64/parse-error.stderr
@@ -1,389 +1,19 @@
-error: requires at least a template string argument
-  --> $DIR/parse-error.rs:9:9
-   |
-LL |         asm!();
-   |         ^^^^^^
-
-error: asm template must be a string literal
-  --> $DIR/parse-error.rs:11:14
-   |
-LL |         asm!(foo);
-   |              ^^^
-
-error: expected token: `,`
-  --> $DIR/parse-error.rs:13:19
-   |
-LL |         asm!("{}" foo);
-   |                   ^^^ expected `,`
-
-error: expected operand, clobber_abi, options, or additional template string
-  --> $DIR/parse-error.rs:15:20
-   |
-LL |         asm!("{}", foo);
-   |                    ^^^ expected operand, clobber_abi, options, or additional template string
-
-error: expected `(`, found `foo`
-  --> $DIR/parse-error.rs:17:23
-   |
-LL |         asm!("{}", in foo);
-   |                       ^^^ expected `(`
-
-error: expected `)`, found `foo`
-  --> $DIR/parse-error.rs:19:27
-   |
-LL |         asm!("{}", in(reg foo));
-   |                           ^^^ expected `)`
-
-error: expected expression, found end of macro arguments
-  --> $DIR/parse-error.rs:21:27
-   |
-LL |         asm!("{}", in(reg));
-   |                           ^ expected expression
-
-error: expected register class or explicit register
-  --> $DIR/parse-error.rs:23:26
-   |
-LL |         asm!("{}", inout(=) foo => bar);
-   |                          ^
-
-error: expected expression, found end of macro arguments
-  --> $DIR/parse-error.rs:25:37
-   |
-LL |         asm!("{}", inout(reg) foo =>);
-   |                                     ^ expected expression
-
-error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
-  --> $DIR/parse-error.rs:27:32
-   |
-LL |         asm!("{}", in(reg) foo => bar);
-   |                                ^^ expected one of 7 possible tokens
-
-error: expected a path for argument to `sym`
-  --> $DIR/parse-error.rs:29:24
-   |
-LL |         asm!("{}", sym foo + bar);
-   |                        ^^^^^^^^^
-
-error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
-  --> $DIR/parse-error.rs:31:26
-   |
-LL |         asm!("", options(foo));
-   |                          ^^^ expected one of 10 possible tokens
-
-error: expected one of `)` or `,`, found `foo`
-  --> $DIR/parse-error.rs:33:32
-   |
-LL |         asm!("", options(nomem foo));
-   |                                ^^^ expected one of `)` or `,`
-
-error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
-  --> $DIR/parse-error.rs:35:33
-   |
-LL |         asm!("", options(nomem, foo));
-   |                                 ^^^ expected one of 10 possible tokens
-
-error: expected string literal
-  --> $DIR/parse-error.rs:39:30
-   |
-LL |         asm!("", clobber_abi(foo));
-   |                              ^^^ not a string literal
-
-error: expected one of `)` or `,`, found `foo`
-  --> $DIR/parse-error.rs:41:34
-   |
-LL |         asm!("", clobber_abi("C" foo));
-   |                                  ^^^ expected one of `)` or `,`
-
-error: expected string literal
-  --> $DIR/parse-error.rs:43:35
-   |
-LL |         asm!("", clobber_abi("C", foo));
-   |                                   ^^^ not a string literal
-
-error: duplicate argument named `a`
-  --> $DIR/parse-error.rs:50:36
-   |
-LL |         asm!("{a}", a = const foo, a = const bar);
-   |                     -------------  ^^^^^^^^^^^^^ duplicate argument
-   |                     |
-   |                     previously here
-
-error: argument never used
-  --> $DIR/parse-error.rs:50:36
-   |
-LL |         asm!("{a}", a = const foo, a = const bar);
-   |                                    ^^^^^^^^^^^^^ argument never used
-   |
-   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
-
 error: explicit register arguments cannot have names
-  --> $DIR/parse-error.rs:55:18
+  --> $DIR/parse-error.rs:9:18
    |
 LL |         asm!("", a = in("x0") foo);
    |                  ^^^^^^^^^^^^^^^^
 
 error: positional arguments cannot follow named arguments or explicit register arguments
-  --> $DIR/parse-error.rs:61:35
+  --> $DIR/parse-error.rs:15:35
    |
 LL |         asm!("{1}", in("x0") foo, const bar);
    |                     ------------  ^^^^^^^^^ positional argument
    |                     |
    |                     explicit register argument
 
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `""`
-  --> $DIR/parse-error.rs:64:29
-   |
-LL |         asm!("", options(), "");
-   |                             ^^ expected one of 10 possible tokens
-
-error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `label`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
-  --> $DIR/parse-error.rs:66:33
-   |
-LL |         asm!("{}", in(reg) foo, "{}", out(reg) foo);
-   |                                 ^^^^ expected one of 10 possible tokens
-
-error: asm template must be a string literal
-  --> $DIR/parse-error.rs:68:14
-   |
-LL |         asm!(format!("{{{}}}", 0), in(reg) foo);
-   |              ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: asm template must be a string literal
-  --> $DIR/parse-error.rs:70:21
-   |
-LL |         asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
-   |                     ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: _ cannot be used for input operands
-  --> $DIR/parse-error.rs:72:28
-   |
-LL |         asm!("{}", in(reg) _);
-   |                            ^
-
-error: _ cannot be used for input operands
-  --> $DIR/parse-error.rs:74:31
-   |
-LL |         asm!("{}", inout(reg) _);
-   |                               ^
-
-error: _ cannot be used for input operands
-  --> $DIR/parse-error.rs:76:35
-   |
-LL |         asm!("{}", inlateout(reg) _);
-   |                                   ^
-
-error: requires at least a template string argument
-  --> $DIR/parse-error.rs:83:1
-   |
-LL | global_asm!();
-   | ^^^^^^^^^^^^^
-
-error: asm template must be a string literal
-  --> $DIR/parse-error.rs:85:13
-   |
-LL | global_asm!(FOO);
-   |             ^^^
-
-error: expected token: `,`
-  --> $DIR/parse-error.rs:87:18
-   |
-LL | global_asm!("{}" FOO);
-   |                  ^^^ expected `,`
-
-error: expected operand, options, or additional template string
-  --> $DIR/parse-error.rs:89:19
-   |
-LL | global_asm!("{}", FOO);
-   |                   ^^^ expected operand, options, or additional template string
-
-error: expected expression, found end of macro arguments
-  --> $DIR/parse-error.rs:91:24
-   |
-LL | global_asm!("{}", const);
-   |                        ^ expected expression
-
-error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
-  --> $DIR/parse-error.rs:93:30
-   |
-LL | global_asm!("{}", const(reg) FOO);
-   |                              ^^^ expected one of `,`, `.`, `?`, or an operator
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
-  --> $DIR/parse-error.rs:95:25
-   |
-LL | global_asm!("", options(FOO));
-   |                         ^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: the `nomem` option cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:97:25
-   |
-LL | global_asm!("", options(nomem FOO));
-   |                         ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly
-
-error: expected one of `)` or `,`, found `FOO`
-  --> $DIR/parse-error.rs:97:31
-   |
-LL | global_asm!("", options(nomem FOO));
-   |                               ^^^ expected one of `)` or `,`
-
-error: the `nomem` option cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:100:25
-   |
-LL | global_asm!("", options(nomem, FOO));
-   |                         ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly
-
-error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
-  --> $DIR/parse-error.rs:100:32
-   |
-LL | global_asm!("", options(nomem, FOO));
-   |                                ^^^ expected one of `)`, `att_syntax`, or `raw`
-
-error: expected string literal
-  --> $DIR/parse-error.rs:104:29
-   |
-LL | global_asm!("", clobber_abi(FOO));
-   |                             ^^^ not a string literal
-
-error: expected one of `)` or `,`, found `FOO`
-  --> $DIR/parse-error.rs:106:33
-   |
-LL | global_asm!("", clobber_abi("C" FOO));
-   |                                 ^^^ expected one of `)` or `,`
-
-error: expected string literal
-  --> $DIR/parse-error.rs:108:34
-   |
-LL | global_asm!("", clobber_abi("C", FOO));
-   |                                  ^^^ not a string literal
-
-error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:110:19
-   |
-LL | global_asm!("{}", clobber_abi("C"), const FOO);
-   |                   ^^^^^^^^^^^^^^^^
-
-error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:112:28
-   |
-LL | global_asm!("", options(), clobber_abi("C"));
-   |                            ^^^^^^^^^^^^^^^^
-
-error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:114:30
-   |
-LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
-   |                              ^^^^^^^^^^^^^^^^
-
-error: duplicate argument named `a`
-  --> $DIR/parse-error.rs:116:35
-   |
-LL | global_asm!("{a}", a = const FOO, a = const BAR);
-   |                    -------------  ^^^^^^^^^^^^^ duplicate argument
-   |                    |
-   |                    previously here
-
-error: argument never used
-  --> $DIR/parse-error.rs:116:35
-   |
-LL | global_asm!("{a}", a = const FOO, a = const BAR);
-   |                                   ^^^^^^^^^^^^^ argument never used
-   |
-   = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
-
-error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""`
-  --> $DIR/parse-error.rs:119:28
-   |
-LL | global_asm!("", options(), "");
-   |                            ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
-
-error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
-  --> $DIR/parse-error.rs:121:30
-   |
-LL | global_asm!("{}", const FOO, "{}", const FOO);
-   |                              ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
-
-error: asm template must be a string literal
-  --> $DIR/parse-error.rs:123:13
-   |
-LL | global_asm!(format!("{{{}}}", 0), const FOO);
-   |             ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: asm template must be a string literal
-  --> $DIR/parse-error.rs:125:20
-   |
-LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
-   |                    ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:37:37
-   |
-LL |         asm!("{}", options(), const foo);
-   |                                     ^^^ non-constant value
-   |
-help: consider using `const` instead of `let`
-   |
-LL -     let mut foo = 0;
-LL +     const foo: /* Type */ = 0;
-   |
-
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:45:44
-   |
-LL |         asm!("{}", clobber_abi("C"), const foo);
-   |                                            ^^^ non-constant value
-   |
-help: consider using `const` instead of `let`
-   |
-LL -     let mut foo = 0;
-LL +     const foo: /* Type */ = 0;
-   |
-
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:48:55
-   |
-LL |         asm!("{}", options(), clobber_abi("C"), const foo);
-   |                                                       ^^^ non-constant value
-   |
-help: consider using `const` instead of `let`
-   |
-LL -     let mut foo = 0;
-LL +     const foo: /* Type */ = 0;
-   |
-
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:50:31
-   |
-LL |         asm!("{a}", a = const foo, a = const bar);
-   |                               ^^^ non-constant value
-   |
-help: consider using `const` instead of `let`
-   |
-LL -     let mut foo = 0;
-LL +     const foo: /* Type */ = 0;
-   |
-
-error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:50:46
-   |
-LL |         asm!("{a}", a = const foo, a = const bar);
-   |                                              ^^^ non-constant value
-   |
-help: consider using `const` instead of `let`
-   |
-LL -     let mut bar = 0;
-LL +     const bar: /* Type */ = 0;
-   |
-
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:57:45
+  --> $DIR/parse-error.rs:11:45
    |
 LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                                             ^^^ non-constant value
@@ -395,7 +25,7 @@ LL +     const bar: /* Type */ = 0;
    |
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:59:45
+  --> $DIR/parse-error.rs:13:45
    |
 LL |         asm!("{a}", in("x0") foo, a = const bar);
    |                                             ^^^ non-constant value
@@ -407,7 +37,7 @@ LL +     const bar: /* Type */ = 0;
    |
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/parse-error.rs:61:41
+  --> $DIR/parse-error.rs:15:41
    |
 LL |         asm!("{1}", in("x0") foo, const bar);
    |                                         ^^^ non-constant value
@@ -418,6 +48,6 @@ LL -     let mut bar = 0;
 LL +     const bar: /* Type */ = 0;
    |
 
-error: aborting due to 59 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/asm/parse-error.rs b/tests/ui/asm/parse-error.rs
index 4d7b522f5fc..d135ccae128 100644
--- a/tests/ui/asm/parse-error.rs
+++ b/tests/ui/asm/parse-error.rs
@@ -113,11 +113,9 @@ global_asm!("", options(FOO));
 global_asm!("", options(FOO,));
 //~^ ERROR expected one of `)`, `att_syntax`, or `raw`, found `FOO`
 global_asm!("", options(nomem FOO));
-//~^ ERROR the `nomem` option cannot be used with `global_asm!`
-//~| ERROR expected one of `)` or `,`, found `FOO`
+//~^ ERROR expected one of `)` or `,`, found `FOO`
 global_asm!("", options(nomem, FOO));
-//~^ ERROR the `nomem` option cannot be used with `global_asm!`
-//~| ERROR expected one of `)`, `att_syntax`, or `raw`, found `FOO`
+//~^ ERROR expected one of `)`, `att_syntax`, or `raw`, found `FOO`
 global_asm!("{}", options(), const FOO);
 global_asm!("", clobber_abi(FOO));
 //~^ ERROR expected string literal
diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr
index 74647372a35..0bba1fd8d9b 100644
--- a/tests/ui/asm/parse-error.stderr
+++ b/tests/ui/asm/parse-error.stderr
@@ -270,74 +270,62 @@ error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
 LL | global_asm!("", options(FOO,));
    |                         ^^^ expected one of `)`, `att_syntax`, or `raw`
 
-error: the `nomem` option cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:115:25
-   |
-LL | global_asm!("", options(nomem FOO));
-   |                         ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly
-
 error: expected one of `)` or `,`, found `FOO`
   --> $DIR/parse-error.rs:115:31
    |
 LL | global_asm!("", options(nomem FOO));
    |                               ^^^ expected one of `)` or `,`
 
-error: the `nomem` option cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:118:25
-   |
-LL | global_asm!("", options(nomem, FOO));
-   |                         ^^^^^ the `nomem` option is not meaningful for global-scoped inline assembly
-
 error: expected one of `)`, `att_syntax`, or `raw`, found `FOO`
-  --> $DIR/parse-error.rs:118:32
+  --> $DIR/parse-error.rs:117:32
    |
 LL | global_asm!("", options(nomem, FOO));
    |                                ^^^ expected one of `)`, `att_syntax`, or `raw`
 
 error: expected string literal
-  --> $DIR/parse-error.rs:122:29
+  --> $DIR/parse-error.rs:120:29
    |
 LL | global_asm!("", clobber_abi(FOO));
    |                             ^^^ not a string literal
 
 error: expected one of `)` or `,`, found `FOO`
-  --> $DIR/parse-error.rs:124:33
+  --> $DIR/parse-error.rs:122:33
    |
 LL | global_asm!("", clobber_abi("C" FOO));
    |                                 ^^^ expected one of `)` or `,`
 
 error: expected string literal
-  --> $DIR/parse-error.rs:126:34
+  --> $DIR/parse-error.rs:124:34
    |
 LL | global_asm!("", clobber_abi("C", FOO));
    |                                  ^^^ not a string literal
 
 error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:128:19
+  --> $DIR/parse-error.rs:126:19
    |
 LL | global_asm!("{}", clobber_abi("C"), const FOO);
    |                   ^^^^^^^^^^^^^^^^
 
 error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:130:28
+  --> $DIR/parse-error.rs:128:28
    |
 LL | global_asm!("", options(), clobber_abi("C"));
    |                            ^^^^^^^^^^^^^^^^
 
 error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:132:30
+  --> $DIR/parse-error.rs:130:30
    |
 LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
    |                              ^^^^^^^^^^^^^^^^
 
 error: `clobber_abi` cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:134:17
+  --> $DIR/parse-error.rs:132:17
    |
 LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
    |                 ^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^
 
 error: duplicate argument named `a`
-  --> $DIR/parse-error.rs:136:35
+  --> $DIR/parse-error.rs:134:35
    |
 LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                    -------------  ^^^^^^^^^^^^^ duplicate argument
@@ -345,7 +333,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                    previously here
 
 error: argument never used
-  --> $DIR/parse-error.rs:136:35
+  --> $DIR/parse-error.rs:134:35
    |
 LL | global_asm!("{a}", a = const FOO, a = const BAR);
    |                                   ^^^^^^^^^^^^^ argument never used
@@ -353,19 +341,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
    = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
 
 error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `""`
-  --> $DIR/parse-error.rs:139:28
+  --> $DIR/parse-error.rs:137:28
    |
 LL | global_asm!("", options(), "");
    |                            ^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
 
 error: expected one of `clobber_abi`, `const`, `options`, or `sym`, found `"{}"`
-  --> $DIR/parse-error.rs:141:30
+  --> $DIR/parse-error.rs:139:30
    |
 LL | global_asm!("{}", const FOO, "{}", const FOO);
    |                              ^^^^ expected one of `clobber_abi`, `const`, `options`, or `sym`
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:143:13
+  --> $DIR/parse-error.rs:141:13
    |
 LL | global_asm!(format!("{{{}}}", 0), const FOO);
    |             ^^^^^^^^^^^^^^^^^^^^
@@ -373,7 +361,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO);
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: asm template must be a string literal
-  --> $DIR/parse-error.rs:145:20
+  --> $DIR/parse-error.rs:143:20
    |
 LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
    |                    ^^^^^^^^^^^^^^^^^^^^
@@ -381,37 +369,37 @@ LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `in` operand cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:148:19
+  --> $DIR/parse-error.rs:146:19
    |
 LL | global_asm!("{}", in(reg));
    |                   ^^ the `in` operand is not meaningful for global-scoped inline assembly, remove it
 
 error: the `out` operand cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:150:19
+  --> $DIR/parse-error.rs:148:19
    |
 LL | global_asm!("{}", out(reg));
    |                   ^^^ the `out` operand is not meaningful for global-scoped inline assembly, remove it
 
 error: the `lateout` operand cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:152:19
+  --> $DIR/parse-error.rs:150:19
    |
 LL | global_asm!("{}", lateout(reg));
    |                   ^^^^^^^ the `lateout` operand is not meaningful for global-scoped inline assembly, remove it
 
 error: the `inout` operand cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:154:19
+  --> $DIR/parse-error.rs:152:19
    |
 LL | global_asm!("{}", inout(reg));
    |                   ^^^^^ the `inout` operand is not meaningful for global-scoped inline assembly, remove it
 
 error: the `inlateout` operand cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:156:19
+  --> $DIR/parse-error.rs:154:19
    |
 LL | global_asm!("{}", inlateout(reg));
    |                   ^^^^^^^^^ the `inlateout` operand is not meaningful for global-scoped inline assembly, remove it
 
 error: the `label` operand cannot be used with `global_asm!`
-  --> $DIR/parse-error.rs:158:19
+  --> $DIR/parse-error.rs:156:19
    |
 LL | global_asm!("{}", label(reg));
    |                   ^^^^^ the `label` operand is not meaningful for global-scoped inline assembly, remove it
@@ -476,6 +464,6 @@ LL -     let mut bar = 0;
 LL +     const bar: /* Type */ = 0;
    |
 
-error: aborting due to 72 previous errors
+error: aborting due to 70 previous errors
 
 For more information about this error, try `rustc --explain E0435`.
diff --git a/tests/ui/asm/x86_64/evex512-implicit-feature.rs b/tests/ui/asm/x86_64/evex512-implicit-feature.rs
index ea2acd424e2..ec5da7c7fa4 100644
--- a/tests/ui/asm/x86_64/evex512-implicit-feature.rs
+++ b/tests/ui/asm/x86_64/evex512-implicit-feature.rs
@@ -2,7 +2,6 @@
 //@ only-x86_64
 //@ compile-flags: --crate-type=lib -C target-cpu=skylake
 
-#![feature(avx512_target_feature)]
 #![feature(stdarch_x86_avx512)]
 
 use std::arch::x86_64::*;
diff --git a/tests/ui/asm/x86_64/target-feature-attr.rs b/tests/ui/asm/x86_64/target-feature-attr.rs
index 6bb277ac165..2193117caeb 100644
--- a/tests/ui/asm/x86_64/target-feature-attr.rs
+++ b/tests/ui/asm/x86_64/target-feature-attr.rs
@@ -2,8 +2,6 @@
 // Set the base cpu explicitly, in case the default has been changed.
 //@ compile-flags: -C target-cpu=x86-64
 
-#![feature(avx512_target_feature)]
-
 use std::arch::asm;
 
 #[target_feature(enable = "avx")]
diff --git a/tests/ui/asm/x86_64/target-feature-attr.stderr b/tests/ui/asm/x86_64/target-feature-attr.stderr
index 0cd571ac8cc..c852726ee7f 100644
--- a/tests/ui/asm/x86_64/target-feature-attr.stderr
+++ b/tests/ui/asm/x86_64/target-feature-attr.stderr
@@ -1,23 +1,23 @@
 error: register class `ymm_reg` requires the `avx` target feature
-  --> $DIR/target-feature-attr.rs:20:40
+  --> $DIR/target-feature-attr.rs:18:40
    |
 LL |     asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
    |                                        ^^^^^^^^^^^^^
 
 error: register class `ymm_reg` requires the `avx` target feature
-  --> $DIR/target-feature-attr.rs:20:55
+  --> $DIR/target-feature-attr.rs:18:55
    |
 LL |     asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
    |                                                       ^^^^^^^^^^^^^
 
 error: register class `ymm_reg` requires the `avx` target feature
-  --> $DIR/target-feature-attr.rs:20:70
+  --> $DIR/target-feature-attr.rs:18:70
    |
 LL |     asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
    |                                                                      ^^^^^^^^^^^^^^^^^^
 
 error: register class `kreg` requires at least one of the following target features: avx512bw, avx512f
-  --> $DIR/target-feature-attr.rs:35:23
+  --> $DIR/target-feature-attr.rs:33:23
    |
 LL |     asm!("/* {0} */", in(kreg) x);
    |                       ^^^^^^^^^^
diff --git a/tests/ui/async-await/async-drop/dependency-dropped.rs b/tests/ui/async-await/async-drop/dependency-dropped.rs
index f763bb32b17..d7f415e19aa 100644
--- a/tests/ui/async-await/async-drop/dependency-dropped.rs
+++ b/tests/ui/async-await/async-drop/dependency-dropped.rs
@@ -1,9 +1,12 @@
 //@ run-pass
 //@ check-run-results
+//@ revisions: with_feature without_feature
 //@ aux-build:async-drop-dep.rs
 //@ edition:2021
 
-#![feature(async_drop)]
+#![cfg_attr(with_feature, feature(async_drop))]
+//[without_feature]~^ WARN found async drop types in dependency `async_drop_dep`, but async_drop feature is disabled for `dependency_dropped`
+
 #![allow(incomplete_features)]
 
 extern crate async_drop_dep;
diff --git a/tests/ui/async-await/async-drop/dependency-dropped.run.stdout b/tests/ui/async-await/async-drop/dependency-dropped.with_feature.run.stdout
index 7aaf70c12d6..7aaf70c12d6 100644
--- a/tests/ui/async-await/async-drop/dependency-dropped.run.stdout
+++ b/tests/ui/async-await/async-drop/dependency-dropped.with_feature.run.stdout
diff --git a/tests/ui/async-await/async-drop/dependency-dropped.without_feature.run.stdout b/tests/ui/async-await/async-drop/dependency-dropped.without_feature.run.stdout
new file mode 100644
index 00000000000..80eeeefc222
--- /dev/null
+++ b/tests/ui/async-await/async-drop/dependency-dropped.without_feature.run.stdout
@@ -0,0 +1 @@
+Sync drop
diff --git a/tests/ui/async-await/async-drop/dependency-dropped.without_feature.stderr b/tests/ui/async-await/async-drop/dependency-dropped.without_feature.stderr
new file mode 100644
index 00000000000..96a4572055c
--- /dev/null
+++ b/tests/ui/async-await/async-drop/dependency-dropped.without_feature.stderr
@@ -0,0 +1,10 @@
+warning: found async drop types in dependency `async_drop_dep`, but async_drop feature is disabled for `dependency_dropped`
+  --> $DIR/dependency-dropped.rs:7:1
+   |
+LL | #![cfg_attr(with_feature, feature(async_drop))]
+   | ^
+   |
+   = help: if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/format-await-send.rs b/tests/ui/async-await/format-await-send.rs
new file mode 100644
index 00000000000..13ae7233fd6
--- /dev/null
+++ b/tests/ui/async-await/format-await-send.rs
@@ -0,0 +1,24 @@
+// regression test for <https://github.com/rust-lang/rust/issues/101650>
+// assert that Future which has format!() with an async function is Send
+
+#![allow(unused)]
+
+//@ check-pass
+//@ edition: 2018
+
+use core::future::Future;
+use core::pin::Pin;
+
+fn build_string() -> Pin<Box<dyn Future<Output = String> + Send>> {
+    Box::pin(async move {
+        let mut string_builder = String::new();
+        string_builder += &format!("Hello {}", helper().await);
+        string_builder
+    })
+}
+
+async fn helper() -> String {
+    "World".to_string()
+}
+
+fn main() {}
diff --git a/tests/ui/attributes/auxiliary/use-doc-alias-name-extern.rs b/tests/ui/attributes/auxiliary/use-doc-alias-name-extern.rs
new file mode 100644
index 00000000000..4c06d0fdfe3
--- /dev/null
+++ b/tests/ui/attributes/auxiliary/use-doc-alias-name-extern.rs
@@ -0,0 +1,24 @@
+#[doc(alias="DocAliasS1")]
+pub struct S1;
+
+#[doc(alias="DocAliasS2")]
+#[doc(alias("DocAliasS3", "DocAliasS4"))]
+pub struct S2;
+
+#[doc(alias("doc_alias_f1", "doc_alias_f2"))]
+pub fn f() {}
+
+pub mod m {
+    #[doc(alias="DocAliasS5")]
+    pub struct S5;
+
+    pub mod n {
+        #[doc(alias("DocAliasX"))]
+        pub mod x {
+            pub mod y {
+                #[doc(alias="DocAliasS6")]
+                pub struct S6;
+            }
+        }
+    }
+}
diff --git a/tests/ui/attributes/use-doc-alias-name.rs b/tests/ui/attributes/use-doc-alias-name.rs
new file mode 100644
index 00000000000..1fc9199b6e3
--- /dev/null
+++ b/tests/ui/attributes/use-doc-alias-name.rs
@@ -0,0 +1,67 @@
+//@ aux-build: use-doc-alias-name-extern.rs
+
+// issue#124273
+
+extern crate use_doc_alias_name_extern;
+
+use use_doc_alias_name_extern::*;
+
+#[doc(alias="LocalDocAliasS")]
+struct S;
+
+fn main() {
+    LocalDocAliasS; // don't show help in local crate
+    //~^ ERROR: cannot find value `LocalDocAliasS` in this scope
+
+    DocAliasS1;
+    //~^ ERROR: cannot find value `DocAliasS1` in this scope
+    //~| HELP: `S1` has a name defined in the doc alias attribute as `DocAliasS1`
+
+    DocAliasS2;
+    //~^ ERROR: cannot find value `DocAliasS2` in this scope
+    //~| HELP: `S2` has a name defined in the doc alias attribute as `DocAliasS2`
+
+    DocAliasS3;
+    //~^ ERROR: cannot find value `DocAliasS3` in this scope
+    //~| HELP: `S2` has a name defined in the doc alias attribute as `DocAliasS3`
+
+    DocAliasS4;
+    //~^ ERROR: cannot find value `DocAliasS4` in this scope
+    //~| HELP: `S2` has a name defined in the doc alias attribute as `DocAliasS4`
+
+    doc_alias_f1();
+    //~^ ERROR: cannot find function `doc_alias_f1` in this scope
+    //~| HELP: `f` has a name defined in the doc alias attribute as `doc_alias_f1`
+
+    doc_alias_f2();
+    //~^ ERROR: cannot find function `doc_alias_f2` in this scope
+    //~| HELP: `f` has a name defined in the doc alias attribute as `doc_alias_f2`
+
+    m::DocAliasS5;
+    //~^ ERROR: cannot find value `DocAliasS5` in module `m`
+    //~| HELP: `S5` has a name defined in the doc alias attribute as `DocAliasS5`
+
+    not_exist_module::DocAliasS1;
+    //~^ ERROR: use of unresolved module or unlinked crate `not_exist_module`
+    //~| HELP: you might be missing a crate named `not_exist_module`
+
+    use_doc_alias_name_extern::DocAliasS1;
+    //~^ ERROR: cannot find value `DocAliasS1` in crate `use_doc_alias_name_extern
+    //~| HELP: `S1` has a name defined in the doc alias attribute as `DocAliasS1`
+
+    m::n::DocAliasX::y::S6;
+    //~^ ERROR: could not find `DocAliasX` in `n`
+    //~| HELP: `x` has a name defined in the doc alias attribute as `DocAliasX`
+
+    m::n::x::y::DocAliasS6;
+    //~^ ERROR: cannot find value `DocAliasS6` in module `m::n::x::y`
+    //~| HELP: `S6` has a name defined in the doc alias attribute as `DocAliasS6`
+}
+
+trait T {
+    fn f() {
+        DocAliasS1;
+        //~^ ERROR: cannot find value `DocAliasS1` in this scope
+        //~| HELP: `S1` has a name defined in the doc alias attribute as `DocAliasS1`
+    }
+}
diff --git a/tests/ui/attributes/use-doc-alias-name.stderr b/tests/ui/attributes/use-doc-alias-name.stderr
new file mode 100644
index 00000000000..07f4865e415
--- /dev/null
+++ b/tests/ui/attributes/use-doc-alias-name.stderr
@@ -0,0 +1,150 @@
+error[E0433]: failed to resolve: could not find `DocAliasX` in `n`
+  --> $DIR/use-doc-alias-name.rs:52:11
+   |
+LL |     m::n::DocAliasX::y::S6;
+   |           ^^^^^^^^^ could not find `DocAliasX` in `n`
+   |
+help: `x` has a name defined in the doc alias attribute as `DocAliasX`
+   |
+LL -     m::n::DocAliasX::y::S6;
+LL +     m::n::x::y::S6;
+   |
+
+error[E0425]: cannot find value `LocalDocAliasS` in this scope
+  --> $DIR/use-doc-alias-name.rs:13:5
+   |
+LL |     LocalDocAliasS; // don't show help in local crate
+   |     ^^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `DocAliasS1` in this scope
+  --> $DIR/use-doc-alias-name.rs:16:5
+   |
+LL |     DocAliasS1;
+   |     ^^^^^^^^^^
+   |
+help: `S1` has a name defined in the doc alias attribute as `DocAliasS1`
+   |
+LL -     DocAliasS1;
+LL +     S1;
+   |
+
+error[E0425]: cannot find value `DocAliasS2` in this scope
+  --> $DIR/use-doc-alias-name.rs:20:5
+   |
+LL |     DocAliasS2;
+   |     ^^^^^^^^^^
+   |
+help: `S2` has a name defined in the doc alias attribute as `DocAliasS2`
+   |
+LL -     DocAliasS2;
+LL +     S2;
+   |
+
+error[E0425]: cannot find value `DocAliasS3` in this scope
+  --> $DIR/use-doc-alias-name.rs:24:5
+   |
+LL |     DocAliasS3;
+   |     ^^^^^^^^^^
+   |
+help: `S2` has a name defined in the doc alias attribute as `DocAliasS3`
+   |
+LL -     DocAliasS3;
+LL +     S2;
+   |
+
+error[E0425]: cannot find value `DocAliasS4` in this scope
+  --> $DIR/use-doc-alias-name.rs:28:5
+   |
+LL |     DocAliasS4;
+   |     ^^^^^^^^^^
+   |
+help: `S2` has a name defined in the doc alias attribute as `DocAliasS4`
+   |
+LL -     DocAliasS4;
+LL +     S2;
+   |
+
+error[E0425]: cannot find value `DocAliasS5` in module `m`
+  --> $DIR/use-doc-alias-name.rs:40:8
+   |
+LL |     m::DocAliasS5;
+   |        ^^^^^^^^^^
+   |
+help: `S5` has a name defined in the doc alias attribute as `DocAliasS5`
+   |
+LL -     m::DocAliasS5;
+LL +     m::S5;
+   |
+
+error[E0425]: cannot find value `DocAliasS1` in crate `use_doc_alias_name_extern`
+  --> $DIR/use-doc-alias-name.rs:48:32
+   |
+LL |     use_doc_alias_name_extern::DocAliasS1;
+   |                                ^^^^^^^^^^
+   |
+help: `S1` has a name defined in the doc alias attribute as `DocAliasS1`
+   |
+LL -     use_doc_alias_name_extern::DocAliasS1;
+LL +     use_doc_alias_name_extern::S1;
+   |
+
+error[E0425]: cannot find value `DocAliasS6` in module `m::n::x::y`
+  --> $DIR/use-doc-alias-name.rs:56:17
+   |
+LL |     m::n::x::y::DocAliasS6;
+   |                 ^^^^^^^^^^
+   |
+help: `S6` has a name defined in the doc alias attribute as `DocAliasS6`
+   |
+LL -     m::n::x::y::DocAliasS6;
+LL +     m::n::x::y::S6;
+   |
+
+error[E0425]: cannot find value `DocAliasS1` in this scope
+  --> $DIR/use-doc-alias-name.rs:63:9
+   |
+LL |         DocAliasS1;
+   |         ^^^^^^^^^^
+   |
+help: `S1` has a name defined in the doc alias attribute as `DocAliasS1`
+   |
+LL -         DocAliasS1;
+LL +         S1;
+   |
+
+error[E0425]: cannot find function `doc_alias_f1` in this scope
+  --> $DIR/use-doc-alias-name.rs:32:5
+   |
+LL |     doc_alias_f1();
+   |     ^^^^^^^^^^^^
+   |
+help: `f` has a name defined in the doc alias attribute as `doc_alias_f1`
+   |
+LL -     doc_alias_f1();
+LL +     f();
+   |
+
+error[E0425]: cannot find function `doc_alias_f2` in this scope
+  --> $DIR/use-doc-alias-name.rs:36:5
+   |
+LL |     doc_alias_f2();
+   |     ^^^^^^^^^^^^
+   |
+help: `f` has a name defined in the doc alias attribute as `doc_alias_f2`
+   |
+LL -     doc_alias_f2();
+LL +     f();
+   |
+
+error[E0433]: failed to resolve: use of unresolved module or unlinked crate `not_exist_module`
+  --> $DIR/use-doc-alias-name.rs:44:5
+   |
+LL |     not_exist_module::DocAliasS1;
+   |     ^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `not_exist_module`
+   |
+   = help: you might be missing a crate named `not_exist_module`
+
+error: aborting due to 13 previous errors
+
+Some errors have detailed explanations: E0425, E0433.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.rs b/tests/ui/consts/const-eval/raw-pointer-ub.rs
index 13a95f9b78f..1383de63109 100644
--- a/tests/ui/consts/const-eval/raw-pointer-ub.rs
+++ b/tests/ui/consts/const-eval/raw-pointer-ub.rs
@@ -19,7 +19,7 @@ const MISALIGNED_COPY: () = unsafe {
     y.copy_to_nonoverlapping(&mut z, 1);
     //~^ ERROR evaluation of constant value failed
     //~| NOTE inside `std::ptr::const_ptr
-    //~| NOTE inside `copy_nonoverlapping::<u32>`
+    //~| NOTE inside `std::ptr::copy_nonoverlapping::<u32>`
     //~| NOTE accessing memory with alignment 1, but alignment 4 is required
     // The actual error points into the implementation of `copy_to_nonoverlapping`.
 };
diff --git a/tests/ui/consts/const-eval/raw-pointer-ub.stderr b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
index ed5793c84c5..0f3dc33f3a3 100644
--- a/tests/ui/consts/const-eval/raw-pointer-ub.stderr
+++ b/tests/ui/consts/const-eval/raw-pointer-ub.stderr
@@ -18,8 +18,8 @@ LL |     y.copy_to_nonoverlapping(&mut z, 1);
    |
 note: inside `std::ptr::const_ptr::<impl *const u32>::copy_to_nonoverlapping`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-note: inside `copy_nonoverlapping::<u32>`
-  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
+note: inside `std::ptr::copy_nonoverlapping::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/raw-pointer-ub.rs:34:16
diff --git a/tests/ui/consts/copy-intrinsic.rs b/tests/ui/consts/copy-intrinsic.rs
index da483d671f9..d0242f28544 100644
--- a/tests/ui/consts/copy-intrinsic.rs
+++ b/tests/ui/consts/copy-intrinsic.rs
@@ -1,22 +1,8 @@
-#![stable(feature = "dummy", since = "1.0.0")]
-
 // ignore-tidy-linelength
-#![feature(intrinsics, staged_api, rustc_attrs)]
-use std::mem;
-
-#[stable(feature = "dummy", since = "1.0.0")]
-#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
-#[rustc_intrinsic]
-const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
-    unimplemented!()
-}
+#![feature(core_intrinsics)]
 
-#[stable(feature = "dummy", since = "1.0.0")]
-#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
-#[rustc_intrinsic]
-const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
-    unimplemented!()
-}
+use std::mem;
+use std::intrinsics::{copy, copy_nonoverlapping};
 
 const COPY_ZERO: () = unsafe {
     // Since we are not copying anything, this should be allowed.
diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr
index 13321b5703a..8d586428e56 100644
--- a/tests/ui/consts/copy-intrinsic.stderr
+++ b/tests/ui/consts/copy-intrinsic.stderr
@@ -1,23 +1,23 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:34:5
+  --> $DIR/copy-intrinsic.rs:20:5
    |
 LL |     copy_nonoverlapping(0x100 as *const i32, dangle, 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: attempting to access 4 bytes, but got 0x100[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:43:5
+  --> $DIR/copy-intrinsic.rs:29:5
    |
 LL |     copy_nonoverlapping(dangle, 0x100 as *mut i32, 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: attempting to access 4 bytes, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:50:5
+  --> $DIR/copy-intrinsic.rs:36:5
    |
 LL |     copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy`
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:56:5
+  --> $DIR/copy-intrinsic.rs:42:5
    |
 LL |     copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping`
diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr
index 88b3e37bb84..7c07710332b 100644
--- a/tests/ui/consts/missing_span_in_backtrace.stderr
+++ b/tests/ui/consts/missing_span_in_backtrace.stderr
@@ -14,8 +14,8 @@ note: inside `swap_nonoverlapping::compiletime::<MaybeUninit<u8>>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 note: inside `std::ptr::swap_nonoverlapping_const::<MaybeUninit<u8>>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-note: inside `copy_nonoverlapping::<MaybeUninit<u8>>`
-  --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL
+note: inside `std::ptr::copy_nonoverlapping::<MaybeUninit<u8>>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    = help: this code performed an operation that depends on the underlying bytes representing a pointer
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: this error originates in the macro `$crate::intrinsics::const_eval_select` which comes from the expansion of the macro `const_eval_select` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/tests/ui/drop/drop-order-comparisons.e2021.fixed b/tests/ui/drop/drop-order-comparisons.e2021.fixed
index 71158cb8062..6c8d2d3fa9c 100644
--- a/tests/ui/drop/drop-order-comparisons.e2021.fixed
+++ b/tests/ui/drop/drop-order-comparisons.e2021.fixed
@@ -24,6 +24,7 @@
 //@ [e2024] edition: 2024
 //@ run-pass
 
+#![feature(if_let_guard)]
 #![cfg_attr(e2021, feature(let_chains))]
 #![cfg_attr(e2021, warn(rust_2024_compatibility))]
 
@@ -344,6 +345,25 @@ fn t_if_let_chains_then() {
     e.assert(9);
 }
 
+#[rustfmt::skip]
+fn t_guard_if_let_chains_then() {
+    let e = Events::new();
+    _ = match () {
+        () if e.ok(1).is_ok()
+            && let true = e.ok(9).is_ok()
+            && let Ok(_v) = e.ok(8)
+            && let Ok(_) = e.ok(7)
+            && let Ok(_) = e.ok(6).as_ref()
+            && e.ok(2).is_ok()
+            && let Ok(_v) = e.ok(5)
+            && let Ok(_) = e.ok(4).as_ref() => {
+                e.mark(3);
+            }
+        _ => {}
+    };
+    e.assert(9);
+}
+
 #[cfg(e2021)]
 #[rustfmt::skip]
 fn t_if_let_nested_else() {
@@ -484,6 +504,25 @@ fn t_if_let_chains_then_else() {
     e.assert(9);
 }
 
+#[rustfmt::skip]
+fn t_guard_if_let_chains_then_else() {
+    let e = Events::new();
+    _ = match () {
+       () if e.ok(1).is_ok()
+            && let true = e.ok(8).is_ok()
+            && let Ok(_v) = e.ok(7)
+            && let Ok(_) = e.ok(6)
+            && let Ok(_) = e.ok(5).as_ref()
+            && e.ok(2).is_ok()
+            && let Ok(_v) = e.ok(4)
+            && let Ok(_) = e.err(3) => {}
+        _ => {
+            e.mark(9);
+        }
+    };
+    e.assert(9);
+}
+
 fn main() {
     t_bindings();
     t_tuples();
@@ -502,10 +541,12 @@ fn main() {
     t_if_let_nested_then();
     t_let_else_chained_then();
     t_if_let_chains_then();
+    t_guard_if_let_chains_then();
     t_if_let_nested_else();
     t_if_let_nested_then_else();
     t_let_else_chained_then_else();
     t_if_let_chains_then_else();
+    t_guard_if_let_chains_then_else();
 }
 
 // # Test scaffolding
diff --git a/tests/ui/drop/drop-order-comparisons.e2021.stderr b/tests/ui/drop/drop-order-comparisons.e2021.stderr
index 0717a8c1b9b..8b93376cc0d 100644
--- a/tests/ui/drop/drop-order-comparisons.e2021.stderr
+++ b/tests/ui/drop/drop-order-comparisons.e2021.stderr
@@ -1,5 +1,5 @@
 warning: relative drop order changing in Rust 2024
-  --> $DIR/drop-order-comparisons.rs:76:9
+  --> $DIR/drop-order-comparisons.rs:77:9
    |
 LL |       _ = ({
    |  _________-
@@ -29,35 +29,35 @@ LL | |     }, e.mark(3), e.ok(4));
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
 note: `#3` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `#1` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `_v` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `#2` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 note: the lint level is defined here
-  --> $DIR/drop-order-comparisons.rs:28:25
+  --> $DIR/drop-order-comparisons.rs:29:25
    |
 LL | #![cfg_attr(e2021, warn(rust_2024_compatibility))]
    |                         ^^^^^^^^^^^^^^^^^^^^^^^
    = note: `#[warn(tail_expr_drop_order)]` implied by `#[warn(rust_2024_compatibility)]`
 
 warning: relative drop order changing in Rust 2024
-  --> $DIR/drop-order-comparisons.rs:100:45
+  --> $DIR/drop-order-comparisons.rs:101:45
    |
 LL |       _ = ({
    |  _________-
@@ -77,19 +77,19 @@ LL | |     }, e.mark(1), e.ok(4));
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
 note: `#2` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `#1` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 warning: relative drop order changing in Rust 2024
-  --> $DIR/drop-order-comparisons.rs:100:19
+  --> $DIR/drop-order-comparisons.rs:101:19
    |
 LL |       _ = ({
    |  _________-
@@ -109,19 +109,19 @@ LL | |     }, e.mark(1), e.ok(4));
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
 note: `#2` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `#1` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 warning: relative drop order changing in Rust 2024
-  --> $DIR/drop-order-comparisons.rs:221:24
+  --> $DIR/drop-order-comparisons.rs:222:24
    |
 LL |       _ = ({
    |  _________-
@@ -141,19 +141,19 @@ LL | |     }, e.mark(2), e.ok(3));
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
 note: `#2` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `#1` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 warning: relative drop order changing in Rust 2024
-  --> $DIR/drop-order-comparisons.rs:247:24
+  --> $DIR/drop-order-comparisons.rs:248:24
    |
 LL |       _ = ({
    |  _________-
@@ -173,19 +173,19 @@ LL | |     }, e.mark(2), e.ok(3));
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html>
 note: `#2` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: `#1` invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:123:13
+  --> $DIR/drop-order-comparisons.rs:124:13
    |
 LL |     _ = (if let Ok(_) = e.ok(4).as_ref() {
    |             ^^^^^^^^^^^^-------^^^^^^^^^
@@ -195,12 +195,12 @@ LL |     _ = (if let Ok(_) = e.ok(4).as_ref() {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:127:5
+  --> $DIR/drop-order-comparisons.rs:128:5
    |
 LL |     }, e.mark(2), e.ok(3));
    |     ^
@@ -215,7 +215,7 @@ LL ~     } _ => {}}, e.mark(2), e.ok(3));
    |
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:145:13
+  --> $DIR/drop-order-comparisons.rs:146:13
    |
 LL |     _ = (if let Ok(_) = e.err(4).as_ref() {} else {
    |             ^^^^^^^^^^^^--------^^^^^^^^^
@@ -225,12 +225,12 @@ LL |     _ = (if let Ok(_) = e.err(4).as_ref() {} else {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:145:44
+  --> $DIR/drop-order-comparisons.rs:146:44
    |
 LL |     _ = (if let Ok(_) = e.err(4).as_ref() {} else {
    |                                            ^
@@ -244,7 +244,7 @@ LL ~     }}, e.mark(2), e.ok(3));
    |
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:247:12
+  --> $DIR/drop-order-comparisons.rs:248:12
    |
 LL |         if let Ok(_) = e.err(4).as_ref() {} else {
    |            ^^^^^^^^^^^^--------^^^^^^^^^
@@ -254,12 +254,12 @@ LL |         if let Ok(_) = e.err(4).as_ref() {} else {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:247:43
+  --> $DIR/drop-order-comparisons.rs:248:43
    |
 LL |         if let Ok(_) = e.err(4).as_ref() {} else {
    |                                           ^
@@ -273,7 +273,7 @@ LL ~         }}
    |
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:352:12
+  --> $DIR/drop-order-comparisons.rs:372:12
    |
 LL |         if let true = e.err(9).is_ok() {} else {
    |            ^^^^^^^^^^^--------^^^^^^^^
@@ -283,12 +283,12 @@ LL |         if let true = e.err(9).is_ok() {} else {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:352:41
+  --> $DIR/drop-order-comparisons.rs:372:41
    |
 LL |         if let true = e.err(9).is_ok() {} else {
    |                                         ^
@@ -302,7 +302,7 @@ LL ~         }}}}}}}}};
    |
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:355:12
+  --> $DIR/drop-order-comparisons.rs:375:12
    |
 LL |         if let Ok(_v) = e.err(8) {} else {
    |            ^^^^^^^^^^^^^--------
@@ -312,12 +312,12 @@ LL |         if let Ok(_v) = e.err(8) {} else {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:355:35
+  --> $DIR/drop-order-comparisons.rs:375:35
    |
 LL |         if let Ok(_v) = e.err(8) {} else {
    |                                   ^
@@ -331,7 +331,7 @@ LL ~         }}}}}}}}};
    |
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:358:12
+  --> $DIR/drop-order-comparisons.rs:378:12
    |
 LL |         if let Ok(_) = e.err(7) {} else {
    |            ^^^^^^^^^^^^--------
@@ -341,12 +341,12 @@ LL |         if let Ok(_) = e.err(7) {} else {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:358:34
+  --> $DIR/drop-order-comparisons.rs:378:34
    |
 LL |         if let Ok(_) = e.err(7) {} else {
    |                                  ^
@@ -360,7 +360,7 @@ LL ~         }}}}}}}}};
    |
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:361:12
+  --> $DIR/drop-order-comparisons.rs:381:12
    |
 LL |         if let Ok(_) = e.err(6).as_ref() {} else {
    |            ^^^^^^^^^^^^--------^^^^^^^^^
@@ -370,12 +370,12 @@ LL |         if let Ok(_) = e.err(6).as_ref() {} else {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:361:43
+  --> $DIR/drop-order-comparisons.rs:381:43
    |
 LL |         if let Ok(_) = e.err(6).as_ref() {} else {
    |                                           ^
@@ -389,7 +389,7 @@ LL ~         }}}}}}}}};
    |
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:365:12
+  --> $DIR/drop-order-comparisons.rs:385:12
    |
 LL |         if let Ok(_v) = e.err(5) {} else {
    |            ^^^^^^^^^^^^^--------
@@ -399,12 +399,12 @@ LL |         if let Ok(_v) = e.err(5) {} else {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:365:35
+  --> $DIR/drop-order-comparisons.rs:385:35
    |
 LL |         if let Ok(_v) = e.err(5) {} else {
    |                                   ^
@@ -418,7 +418,7 @@ LL ~         }}}}}}}}};
    |
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:368:12
+  --> $DIR/drop-order-comparisons.rs:388:12
    |
 LL |         if let Ok(_) = e.err(4) {} else {
    |            ^^^^^^^^^^^^--------
@@ -428,12 +428,12 @@ LL |         if let Ok(_) = e.err(4) {} else {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:368:34
+  --> $DIR/drop-order-comparisons.rs:388:34
    |
 LL |         if let Ok(_) = e.err(4) {} else {
    |                                  ^
@@ -447,7 +447,7 @@ LL ~         }}}}}}}}};
    |
 
 warning: `if let` assigns a shorter lifetime since Edition 2024
-  --> $DIR/drop-order-comparisons.rs:404:12
+  --> $DIR/drop-order-comparisons.rs:424:12
    |
 LL |         if let Ok(_) = e.err(4).as_ref() {} else {
    |            ^^^^^^^^^^^^--------^^^^^^^^^
@@ -457,12 +457,12 @@ LL |         if let Ok(_) = e.err(4).as_ref() {} else {
    = warning: this changes meaning in Rust 2024
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html>
 note: value invokes this custom destructor
-  --> $DIR/drop-order-comparisons.rs:571:1
+  --> $DIR/drop-order-comparisons.rs:612:1
    |
 LL | impl<'b> Drop for LogDrop<'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: the value is now dropped here in Edition 2024
-  --> $DIR/drop-order-comparisons.rs:404:43
+  --> $DIR/drop-order-comparisons.rs:424:43
    |
 LL |         if let Ok(_) = e.err(4).as_ref() {} else {
    |                                           ^
diff --git a/tests/ui/drop/drop-order-comparisons.rs b/tests/ui/drop/drop-order-comparisons.rs
index 0492b3a4db7..9a10a08a3ff 100644
--- a/tests/ui/drop/drop-order-comparisons.rs
+++ b/tests/ui/drop/drop-order-comparisons.rs
@@ -24,6 +24,7 @@
 //@ [e2024] edition: 2024
 //@ run-pass
 
+#![feature(if_let_guard)]
 #![cfg_attr(e2021, feature(let_chains))]
 #![cfg_attr(e2021, warn(rust_2024_compatibility))]
 
@@ -344,6 +345,25 @@ fn t_if_let_chains_then() {
     e.assert(9);
 }
 
+#[rustfmt::skip]
+fn t_guard_if_let_chains_then() {
+    let e = Events::new();
+    _ = match () {
+        () if e.ok(1).is_ok()
+            && let true = e.ok(9).is_ok()
+            && let Ok(_v) = e.ok(8)
+            && let Ok(_) = e.ok(7)
+            && let Ok(_) = e.ok(6).as_ref()
+            && e.ok(2).is_ok()
+            && let Ok(_v) = e.ok(5)
+            && let Ok(_) = e.ok(4).as_ref() => {
+                e.mark(3);
+            }
+        _ => {}
+    };
+    e.assert(9);
+}
+
 #[cfg(e2021)]
 #[rustfmt::skip]
 fn t_if_let_nested_else() {
@@ -484,6 +504,25 @@ fn t_if_let_chains_then_else() {
     e.assert(9);
 }
 
+#[rustfmt::skip]
+fn t_guard_if_let_chains_then_else() {
+    let e = Events::new();
+    _ = match () {
+       () if e.ok(1).is_ok()
+            && let true = e.ok(8).is_ok()
+            && let Ok(_v) = e.ok(7)
+            && let Ok(_) = e.ok(6)
+            && let Ok(_) = e.ok(5).as_ref()
+            && e.ok(2).is_ok()
+            && let Ok(_v) = e.ok(4)
+            && let Ok(_) = e.err(3) => {}
+        _ => {
+            e.mark(9);
+        }
+    };
+    e.assert(9);
+}
+
 fn main() {
     t_bindings();
     t_tuples();
@@ -502,10 +541,12 @@ fn main() {
     t_if_let_nested_then();
     t_let_else_chained_then();
     t_if_let_chains_then();
+    t_guard_if_let_chains_then();
     t_if_let_nested_else();
     t_if_let_nested_then_else();
     t_let_else_chained_then_else();
     t_if_let_chains_then_else();
+    t_guard_if_let_chains_then_else();
 }
 
 // # Test scaffolding
diff --git a/tests/ui/feature-gates/feature-gate-guard-patterns.rs b/tests/ui/feature-gates/feature-gate-guard-patterns.rs
index 74fb5817081..095f66eeb90 100644
--- a/tests/ui/feature-gates/feature-gate-guard-patterns.rs
+++ b/tests/ui/feature-gates/feature-gate-guard-patterns.rs
@@ -22,7 +22,6 @@ fn other_guards_dont() {
 
     let ((x if guard(x)) | x) = 0;
     //~^ ERROR: guard patterns are experimental
-    //~| ERROR: cannot find value `x`
 
     if let (x if guard(x)) = 0 {}
     //~^ ERROR: guard patterns are experimental
@@ -37,7 +36,6 @@ fn other_guards_dont() {
 
 fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {}
 //~^ ERROR: guard patterns are experimental
-//~| ERROR: cannot find value `x`
 
 fn guard<T>(x: T) -> bool {
     unimplemented!()
diff --git a/tests/ui/feature-gates/feature-gate-guard-patterns.stderr b/tests/ui/feature-gates/feature-gate-guard-patterns.stderr
index 8b85b663889..b0bf302f3cb 100644
--- a/tests/ui/feature-gates/feature-gate-guard-patterns.stderr
+++ b/tests/ui/feature-gates/feature-gate-guard-patterns.stderr
@@ -10,24 +10,6 @@ LL -         (0 if guard(0)) => {},
 LL +         0 if guard(0) => {},
    |
 
-error[E0425]: cannot find value `x` in this scope
-  --> $DIR/feature-gate-guard-patterns.rs:23:22
-   |
-LL |     let ((x if guard(x)) | x) = 0;
-   |                      ^ not found in this scope
-
-error[E0425]: cannot find value `x` in this scope
-  --> $DIR/feature-gate-guard-patterns.rs:38:45
-   |
-LL | fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {}
-   |                                             ^
-   |
-help: the binding `x` is available in a different scope in the same function
-  --> $DIR/feature-gate-guard-patterns.rs:23:11
-   |
-LL |     let ((x if guard(x)) | x) = 0;
-   |           ^
-
 error[E0658]: guard patterns are experimental
   --> $DIR/feature-gate-guard-patterns.rs:18:15
    |
@@ -51,7 +33,7 @@ LL |     let ((x if guard(x)) | x) = 0;
    = help: consider using match arm guards
 
 error[E0658]: guard patterns are experimental
-  --> $DIR/feature-gate-guard-patterns.rs:27:18
+  --> $DIR/feature-gate-guard-patterns.rs:26:18
    |
 LL |     if let (x if guard(x)) = 0 {}
    |                  ^^^^^^^^
@@ -62,7 +44,7 @@ LL |     if let (x if guard(x)) = 0 {}
    = help: consider using match arm guards
 
 error[E0658]: guard patterns are experimental
-  --> $DIR/feature-gate-guard-patterns.rs:30:21
+  --> $DIR/feature-gate-guard-patterns.rs:29:21
    |
 LL |     while let (x if guard(x)) = 0 {}
    |                     ^^^^^^^^
@@ -73,7 +55,7 @@ LL |     while let (x if guard(x)) = 0 {}
    = help: consider using match arm guards
 
 error[E0658]: guard patterns are experimental
-  --> $DIR/feature-gate-guard-patterns.rs:34:21
+  --> $DIR/feature-gate-guard-patterns.rs:33:21
    |
 LL |     while let (x if guard(x)) = 0 {}
    |                     ^^^^^^^^
@@ -84,7 +66,7 @@ LL |     while let (x if guard(x)) = 0 {}
    = help: consider using match arm guards
 
 error[E0658]: guard patterns are experimental
-  --> $DIR/feature-gate-guard-patterns.rs:38:39
+  --> $DIR/feature-gate-guard-patterns.rs:37:39
    |
 LL | fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {}
    |                                       ^^^^^^^^
@@ -94,7 +76,6 @@ LL | fn even_as_function_parameters(((x if guard(x), _) | (_, x)): (i32, i32)) {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: consider using match arm guards
 
-error: aborting due to 9 previous errors
+error: aborting due to 7 previous errors
 
-Some errors have detailed explanations: E0425, E0658.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/fn/coerce-suggestion-infer-region.rs b/tests/ui/fn/coerce-suggestion-infer-region.rs
new file mode 100644
index 00000000000..7edb828c973
--- /dev/null
+++ b/tests/ui/fn/coerce-suggestion-infer-region.rs
@@ -0,0 +1,26 @@
+//! Functions with a mismatch between the expected and found type where the difference is a
+//! reference may trigger analysis for additional help. In this test the expected type will be
+//! &'a Container<&'a u8> and the found type will be Container<&'?0 u8>.
+//!
+//! This test exercises a scenario where the found type being analyzed contains an inference region
+//! variable ('?0). This cannot be used in comparisons because the variable no longer exists by the
+//! time the later analysis is performed.
+//!
+//! This is a regression test of #140823
+
+trait MyFn<P> {}
+
+struct Container<T> {
+    data: T,
+}
+
+struct Desugared {
+    callback: Box<dyn for<'a> MyFn<&'a Container<&'a u8>>>,
+}
+
+fn test(callback: Box<dyn for<'a> MyFn<Container<&'a u8>>>) -> Desugared {
+    Desugared { callback }
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/fn/coerce-suggestion-infer-region.stderr b/tests/ui/fn/coerce-suggestion-infer-region.stderr
new file mode 100644
index 00000000000..9dd0fcf76ce
--- /dev/null
+++ b/tests/ui/fn/coerce-suggestion-infer-region.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/coerce-suggestion-infer-region.rs:22:17
+   |
+LL |     Desugared { callback }
+   |                 ^^^^^^^^ expected `Box<dyn MyFn<&Container<&u8>>>`, found `Box<dyn MyFn<Container<&u8>>>`
+   |
+   = note: expected struct `Box<(dyn for<'a> MyFn<&'a Container<&'a u8>> + 'static)>`
+              found struct `Box<(dyn for<'a> MyFn<Container<&'a u8>> + 'static)>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/issues/issue-100075-2.stderr b/tests/ui/impl-trait/issues/issue-100075-2.stderr
index b3b69677507..554c3ea3433 100644
--- a/tests/ui/impl-trait/issues/issue-100075-2.stderr
+++ b/tests/ui/impl-trait/issues/issue-100075-2.stderr
@@ -1,3 +1,9 @@
+error[E0720]: cannot resolve opaque type
+  --> $DIR/issue-100075-2.rs:1:23
+   |
+LL | fn opaque<T>(t: T) -> impl Sized {
+   |                       ^^^^^^^^^^
+
 warning: function cannot return without recursing
   --> $DIR/issue-100075-2.rs:1:1
    |
@@ -10,15 +16,6 @@ LL |     opaque(Some(t))
    = help: a `loop` may express intention better if this is on purpose
    = note: `#[warn(unconditional_recursion)]` on by default
 
-error[E0720]: cannot resolve opaque type
-  --> $DIR/issue-100075-2.rs:1:23
-   |
-LL | fn opaque<T>(t: T) -> impl Sized {
-   |                       ^^^^^^^^^^ recursive opaque type
-...
-LL |     opaque(Some(t))
-   |     --------------- returning here with type `impl Sized`
-
 error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/impl-trait/issues/issue-100075.stderr b/tests/ui/impl-trait/issues/issue-100075.stderr
index 75963489236..bca2874b2b4 100644
--- a/tests/ui/impl-trait/issues/issue-100075.stderr
+++ b/tests/ui/impl-trait/issues/issue-100075.stderr
@@ -2,10 +2,7 @@ error[E0720]: cannot resolve opaque type
   --> $DIR/issue-100075.rs:13:37
    |
 LL | fn _g<T>(t: &'static T) -> &'static impl Marker {
-   |                                     ^^^^^^^^^^^ recursive opaque type
-...
-LL |         return _g(t);
-   |                ----- returning here with type `&impl Marker`
+   |                                     ^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issues/issue-103599.rs b/tests/ui/impl-trait/issues/issue-103599.rs
index 62741a7454c..e674ce3cbdf 100644
--- a/tests/ui/impl-trait/issues/issue-103599.rs
+++ b/tests/ui/impl-trait/issues/issue-103599.rs
@@ -1,9 +1,8 @@
-//@ check-pass
-
 trait T {}
 
 fn wrap(x: impl T) -> impl T {
-    //~^ WARN function cannot return without recursing
+    //~^ ERROR cannot resolve opaque type
+    //~| WARN function cannot return without recursing
     wrap(wrap(x))
 }
 
diff --git a/tests/ui/impl-trait/issues/issue-103599.stderr b/tests/ui/impl-trait/issues/issue-103599.stderr
index 82038c1dceb..9878b12044f 100644
--- a/tests/ui/impl-trait/issues/issue-103599.stderr
+++ b/tests/ui/impl-trait/issues/issue-103599.stderr
@@ -1,14 +1,21 @@
+error[E0720]: cannot resolve opaque type
+  --> $DIR/issue-103599.rs:3:23
+   |
+LL | fn wrap(x: impl T) -> impl T {
+   |                       ^^^^^^
+
 warning: function cannot return without recursing
-  --> $DIR/issue-103599.rs:5:1
+  --> $DIR/issue-103599.rs:3:1
    |
 LL | fn wrap(x: impl T) -> impl T {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
-LL |
+...
 LL |     wrap(wrap(x))
    |          ------- recursive call site
    |
    = help: a `loop` may express intention better if this is on purpose
    = note: `#[warn(unconditional_recursion)]` on by default
 
-warning: 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/impl-trait/issues/issue-87450.rs b/tests/ui/impl-trait/issues/issue-87450.rs
index 983ef7cfbe0..5a7759af111 100644
--- a/tests/ui/impl-trait/issues/issue-87450.rs
+++ b/tests/ui/impl-trait/issues/issue-87450.rs
@@ -3,8 +3,8 @@ fn bar() -> impl Fn() {
 }
 
 fn foo() -> impl Fn() {
-    //~^ WARNING 5:1: 5:22: function cannot return without recursing [unconditional_recursion]
-    //~| ERROR 5:13: 5:22: cannot resolve opaque type [E0720]
+    //~^ WARN function cannot return without recursing
+    //~| ERROR cannot resolve opaque type
     wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
 }
 
diff --git a/tests/ui/impl-trait/issues/issue-87450.stderr b/tests/ui/impl-trait/issues/issue-87450.stderr
index 9567e09651d..f0f8b5859c0 100644
--- a/tests/ui/impl-trait/issues/issue-87450.stderr
+++ b/tests/ui/impl-trait/issues/issue-87450.stderr
@@ -1,3 +1,9 @@
+error[E0720]: cannot resolve opaque type
+  --> $DIR/issue-87450.rs:5:13
+   |
+LL | fn foo() -> impl Fn() {
+   |             ^^^^^^^^^
+
 warning: function cannot return without recursing
   --> $DIR/issue-87450.rs:5:1
    |
@@ -10,18 +16,6 @@ LL |     wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
    = help: a `loop` may express intention better if this is on purpose
    = note: `#[warn(unconditional_recursion)]` on by default
 
-error[E0720]: cannot resolve opaque type
-  --> $DIR/issue-87450.rs:5:13
-   |
-LL | fn foo() -> impl Fn() {
-   |             ^^^^^^^^^ recursive opaque type
-...
-LL |     wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
-   |     ----------------------------------------------- returning here with type `impl Fn()`
-...
-LL | fn wrap(f: impl Fn()) -> impl Fn() {
-   |                          --------- returning this opaque type `impl Fn()`
-
 error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index 2d2731e4368..af84375c747 100644
--- a/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/tests/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -2,112 +2,67 @@ error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:6:22
    |
 LL | fn option(i: i32) -> impl Sized {
-   |                      ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     if i < 0 { None } else { Some((option(i - 1), i)) }
-   |                ----          ------------------------ returning here with type `Option<(impl Sized, i32)>`
-   |                |
-   |                returning here with type `Option<(impl Sized, i32)>`
+   |                      ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:11:15
    |
 LL | fn tuple() -> impl Sized {
-   |               ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     (tuple(),)
-   |     ---------- returning here with type `(impl Sized,)`
+   |               ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:16:15
    |
 LL | fn array() -> impl Sized {
-   |               ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     [array()]
-   |     --------- returning here with type `[impl Sized; 1]`
+   |               ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:21:13
    |
 LL | fn ptr() -> impl Sized {
-   |             ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     &ptr() as *const _
-   |     ------------------ returning here with type `*const impl Sized`
+   |             ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:26:16
    |
 LL | fn fn_ptr() -> impl Sized {
-   |                ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     fn_ptr as fn() -> _
-   |     ------------------- returning here with type `fn() -> impl Sized`
+   |                ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:31:25
    |
-LL |   fn closure_capture() -> impl Sized {
-   |                           ^^^^^^^^^^ recursive opaque type
-...
-LL | /     move || {
-LL | |         x;
-   | |         - closure captures itself here
-LL | |     }
-   | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:34:5: 34:12}`
+LL | fn closure_capture() -> impl Sized {
+   |                         ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:39:29
    |
-LL |   fn closure_ref_capture() -> impl Sized {
-   |                               ^^^^^^^^^^ recursive opaque type
-...
-LL | /     move || {
-LL | |         &x;
-   | |          - closure captures itself here
-LL | |     }
-   | |_____- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:42:5: 42:12}`
+LL | fn closure_ref_capture() -> impl Sized {
+   |                             ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:47:21
    |
 LL | fn closure_sig() -> impl Sized {
-   |                     ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     || closure_sig()
-   |     ---------------- returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:49:5: 49:7}`
+   |                     ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:52:23
    |
 LL | fn coroutine_sig() -> impl Sized {
-   |                       ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     || coroutine_sig()
-   |     ------------------ returning here with type `{closure@$DIR/recursive-impl-trait-type-indirect.rs:54:5: 54:7}`
+   |                       ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:57:27
    |
-LL |   fn coroutine_capture() -> impl Sized {
-   |                             ^^^^^^^^^^ recursive opaque type
-...
-LL | /     move || {
-LL | |         yield;
-LL | |         x;
-   | |         - coroutine captures itself here
-LL | |     }
-   | |_____- returning here with type `{coroutine@$DIR/recursive-impl-trait-type-indirect.rs:62:5: 62:12}`
+LL | fn coroutine_capture() -> impl Sized {
+   |                           ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:68:35
    |
 LL | fn substs_change<T: 'static>() -> impl Sized {
-   |                                   ^^^^^^^^^^ recursive opaque type
-LL |
-LL |     (substs_change::<&T>(),)
-   |     ------------------------ returning here with type `(impl Sized,)`
+   |                                   ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:78:26
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr
index 42dbc7c9160..080c3284641 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr
@@ -1,56 +1,21 @@
-warning: function cannot return without recursing
-  --> $DIR/recursive-in-exhaustiveness.rs:17:1
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-in-exhaustiveness.rs:17:22
    |
 LL | fn build<T>(x: T) -> impl Sized {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
-LL |
-LL |     let (x,) = (build(x),);
-   |                 -------- recursive call site
-   |
-   = help: a `loop` may express intention better if this is on purpose
-   = note: `#[warn(unconditional_recursion)]` on by default
-
-warning: function cannot return without recursing
-  --> $DIR/recursive-in-exhaustiveness.rs:27:1
-   |
-LL | fn build2<T>(x: T) -> impl Sized {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
-...
-LL |     let (x,) = (build2(x),);
-   |                 --------- recursive call site
-   |
-   = help: a `loop` may express intention better if this is on purpose
+   |                      ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-in-exhaustiveness.rs:27:23
    |
 LL | fn build2<T>(x: T) -> impl Sized {
-   |                       ^^^^^^^^^^ recursive opaque type
-...
-LL |     (build2(x),)
-   |     ------------ returning here with type `(impl Sized,)`
+   |                       ^^^^^^^^^^
 
-warning: function cannot return without recursing
-  --> $DIR/recursive-in-exhaustiveness.rs:40:1
-   |
-LL | fn build3<T>(x: T) -> impl Sized {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
-LL |
-LL |     let (x,) = (build3((x,)),);
-   |                 ------------ recursive call site
-   |
-   = help: a `loop` may express intention better if this is on purpose
-
-error[E0792]: expected generic type parameter, found `(T,)`
-  --> $DIR/recursive-in-exhaustiveness.rs:49:5
+error[E0720]: cannot resolve opaque type
+  --> $DIR/recursive-in-exhaustiveness.rs:39:23
    |
 LL | fn build3<T>(x: T) -> impl Sized {
-   |           - this generic parameter must be used with a generic type parameter
-...
-LL |     build3(x)
-   |     ^^^^^^^^^
+   |                       ^^^^^^^^^^
 
-error: aborting due to 2 previous errors; 3 warnings emitted
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0720, E0792.
-For more information about an error, try `rustc --explain E0720`.
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
index 4c3d5aa8fb8..a3609b93cb3 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
@@ -5,19 +5,19 @@ LL |     let (x,) = (build(x),);
    |                 ^^^^^^^^ cannot satisfy `impl Sized == _`
 
 error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:31:6
+  --> $DIR/recursive-in-exhaustiveness.rs:30:6
    |
 LL |     (build2(x),)
    |      ^^^^^^^^^ types differ
 
 error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:31:5
+  --> $DIR/recursive-in-exhaustiveness.rs:30:5
    |
 LL |     (build2(x),)
    |     ^^^^^^^^^^^^ types differ
 
 error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
-  --> $DIR/recursive-in-exhaustiveness.rs:31:5
+  --> $DIR/recursive-in-exhaustiveness.rs:30:5
    |
 LL |     (build2(x),)
    |     ^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -26,13 +26,13 @@ LL |     (build2(x),)
    = note: tuples must have a statically known size to be initialized
 
 error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:42:17
+  --> $DIR/recursive-in-exhaustiveness.rs:41:17
    |
 LL |     let (x,) = (build3((x,)),);
    |                 ^^^^^^^^^^^^ types differ
 
 error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
-  --> $DIR/recursive-in-exhaustiveness.rs:42:16
+  --> $DIR/recursive-in-exhaustiveness.rs:41:16
    |
 LL |     let (x,) = (build3((x,)),);
    |                ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -41,7 +41,7 @@ LL |     let (x,) = (build3((x,)),);
    = note: tuples must have a statically known size to be initialized
 
 error[E0308]: mismatched types
-  --> $DIR/recursive-in-exhaustiveness.rs:42:16
+  --> $DIR/recursive-in-exhaustiveness.rs:41:16
    |
 LL | fn build3<T>(x: T) -> impl Sized {
    |                       ---------- the found opaque type
@@ -53,7 +53,7 @@ LL |     let (x,) = (build3((x,)),);
              found tuple `(impl Sized,)`
 
 error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:42:17
+  --> $DIR/recursive-in-exhaustiveness.rs:41:17
    |
 LL |     let (x,) = (build3((x,)),);
    |                 ^^^^^^^^^^^^ types differ
@@ -61,13 +61,13 @@ LL |     let (x,) = (build3((x,)),);
    = note: the return type of a function must have a statically known size
 
 error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:42:16
+  --> $DIR/recursive-in-exhaustiveness.rs:41:16
    |
 LL |     let (x,) = (build3((x,)),);
    |                ^^^^^^^^^^^^^^^ types differ
 
 error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:42:17
+  --> $DIR/recursive-in-exhaustiveness.rs:41:17
    |
 LL |     let (x,) = (build3((x,)),);
    |                 ^^^^^^^^^^^^ types differ
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
index 58944533686..fa8fa0e8174 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
@@ -15,7 +15,7 @@
 // We unfortunately accept this today, and due to how opaque type relating is implemented
 // in the NLL type relation, this defines `Opaque<T> = T`.
 fn build<T>(x: T) -> impl Sized {
-    //[current]~^ WARN function cannot return without recursing
+    //[current]~^ ERROR cannot resolve opaque type
     let (x,) = (build(x),);
     //[next]~^ ERROR type annotations needed
     build(x)
@@ -26,7 +26,6 @@ fn build<T>(x: T) -> impl Sized {
 // Not allowed today. Detected as recursive.
 fn build2<T>(x: T) -> impl Sized {
     //[current]~^ ERROR cannot resolve opaque type
-    //[current]~| WARN function cannot return without recursing
     let (x,) = (build2(x),);
     (build2(x),)
     //[next]~^ ERROR type mismatch resolving
@@ -38,7 +37,7 @@ fn build2<T>(x: T) -> impl Sized {
 //
 // Not allowed today. Detected as not defining.
 fn build3<T>(x: T) -> impl Sized {
-    //[current]~^ WARN function cannot return without recursing
+    //[current]~^ ERROR cannot resolve opaque type
     let (x,) = (build3((x,)),);
     //[next]~^ ERROR type mismatch resolving
     //[next]~| ERROR type mismatch resolving
@@ -47,7 +46,6 @@ fn build3<T>(x: T) -> impl Sized {
     //[next]~| ERROR the size for values of type
     //[next]~| ERROR mismatched types
     build3(x)
-    //[current]~^ ERROR expected generic type parameter, found `(T,)`
 }
 
 fn main() {}
diff --git a/tests/ui/imports/issue-99695-b.fixed b/tests/ui/imports/issue-99695-b.fixed
index 0108f762400..ae63b0c4627 100644
--- a/tests/ui/imports/issue-99695-b.fixed
+++ b/tests/ui/imports/issue-99695-b.fixed
@@ -11,7 +11,7 @@ mod m {
         pub struct other_item;
     }
 
-    use ::nu;
+    use crate::nu;
 pub use self::p::{other_item as _};
     //~^ ERROR unresolved import `self::p::nu` [E0432]
     //~| HELP a macro with this name exists at the root of the crate
diff --git a/tests/ui/imports/issue-99695-b.stderr b/tests/ui/imports/issue-99695-b.stderr
index d58d2798746..ad752d5c45a 100644
--- a/tests/ui/imports/issue-99695-b.stderr
+++ b/tests/ui/imports/issue-99695-b.stderr
@@ -7,7 +7,7 @@ LL |     pub use self::p::{nu, other_item as _};
    = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
 help: a macro with this name exists at the root of the crate
    |
-LL ~     use ::nu;
+LL ~     use crate::nu;
 LL ~ pub use self::p::{other_item as _};
    |
 
diff --git a/tests/ui/imports/issue-99695.fixed b/tests/ui/imports/issue-99695.edition_2015.fixed
index 51ccd3f8c48..798acfd5874 100644
--- a/tests/ui/imports/issue-99695.fixed
+++ b/tests/ui/imports/issue-99695.edition_2015.fixed
@@ -1,4 +1,8 @@
 //@ run-rustfix
+//@ revisions: edition_2015 edition_2018
+//@ [edition_2015] edition: 2015
+//@ [edition_2018] edition: 2018
+
 #![allow(unused, nonstandard_style)]
 mod m {
     #[macro_export]
@@ -8,7 +12,7 @@ mod m {
 
     pub struct other_item;
 
-    use ::nu;
+    use crate::nu;
 pub use self::{other_item as _};
     //~^ ERROR unresolved import `self::nu` [E0432]
     //~| HELP a macro with this name exists at the root of the crate
diff --git a/tests/ui/imports/issue-99695.stderr b/tests/ui/imports/issue-99695.edition_2015.stderr
index 536f51dcb3b..4ef8e6426fb 100644
--- a/tests/ui/imports/issue-99695.stderr
+++ b/tests/ui/imports/issue-99695.edition_2015.stderr
@@ -1,5 +1,5 @@
 error[E0432]: unresolved import `self::nu`
-  --> $DIR/issue-99695.rs:11:20
+  --> $DIR/issue-99695.rs:15:20
    |
 LL |     pub use self::{nu, other_item as _};
    |                    ^^ no `nu` in `m`
@@ -7,7 +7,7 @@ LL |     pub use self::{nu, other_item as _};
    = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
 help: a macro with this name exists at the root of the crate
    |
-LL ~     use ::nu;
+LL ~     use crate::nu;
 LL ~ pub use self::{other_item as _};
    |
 
diff --git a/tests/ui/imports/issue-99695.edition_2018.fixed b/tests/ui/imports/issue-99695.edition_2018.fixed
new file mode 100644
index 00000000000..798acfd5874
--- /dev/null
+++ b/tests/ui/imports/issue-99695.edition_2018.fixed
@@ -0,0 +1,21 @@
+//@ run-rustfix
+//@ revisions: edition_2015 edition_2018
+//@ [edition_2015] edition: 2015
+//@ [edition_2018] edition: 2018
+
+#![allow(unused, nonstandard_style)]
+mod m {
+    #[macro_export]
+    macro_rules! nu {
+        {} => {};
+    }
+
+    pub struct other_item;
+
+    use crate::nu;
+pub use self::{other_item as _};
+    //~^ ERROR unresolved import `self::nu` [E0432]
+    //~| HELP a macro with this name exists at the root of the crate
+}
+
+fn main() {}
diff --git a/tests/ui/imports/issue-99695.edition_2018.stderr b/tests/ui/imports/issue-99695.edition_2018.stderr
new file mode 100644
index 00000000000..4ef8e6426fb
--- /dev/null
+++ b/tests/ui/imports/issue-99695.edition_2018.stderr
@@ -0,0 +1,16 @@
+error[E0432]: unresolved import `self::nu`
+  --> $DIR/issue-99695.rs:15:20
+   |
+LL |     pub use self::{nu, other_item as _};
+   |                    ^^ no `nu` in `m`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL ~     use crate::nu;
+LL ~ pub use self::{other_item as _};
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/imports/issue-99695.rs b/tests/ui/imports/issue-99695.rs
index a52370e0eb0..dc0a8f438e0 100644
--- a/tests/ui/imports/issue-99695.rs
+++ b/tests/ui/imports/issue-99695.rs
@@ -1,4 +1,8 @@
 //@ run-rustfix
+//@ revisions: edition_2015 edition_2018
+//@ [edition_2015] edition: 2015
+//@ [edition_2018] edition: 2018
+
 #![allow(unused, nonstandard_style)]
 mod m {
     #[macro_export]
diff --git a/tests/ui/mir/mir_match_guard_let_chains_drop_order.rs b/tests/ui/mir/mir_match_guard_let_chains_drop_order.rs
new file mode 100644
index 00000000000..e98d57d1154
--- /dev/null
+++ b/tests/ui/mir/mir_match_guard_let_chains_drop_order.rs
@@ -0,0 +1,110 @@
+//@ run-pass
+//@ needs-unwind
+//@ revisions: edition2021 edition2024
+//@ [edition2021] edition: 2021
+//@ [edition2024] edition: 2024
+
+// See `mir_drop_order.rs` for more information
+
+#![feature(if_let_guard)]
+#![allow(irrefutable_let_patterns)]
+
+use std::cell::RefCell;
+use std::panic;
+
+pub struct DropLogger<'a, T> {
+    extra: T,
+    id: usize,
+    log: &'a panic::AssertUnwindSafe<RefCell<Vec<usize>>>,
+}
+
+impl<'a, T> Drop for DropLogger<'a, T> {
+    fn drop(&mut self) {
+        self.log.0.borrow_mut().push(self.id);
+    }
+}
+
+struct InjectedFailure;
+
+#[allow(unreachable_code)]
+fn main() {
+    let log = panic::AssertUnwindSafe(RefCell::new(vec![]));
+    let d = |id, extra| DropLogger { extra, id: id, log: &log };
+    let get = || -> Vec<_> {
+        let mut m = log.0.borrow_mut();
+        let n = m.drain(..);
+        n.collect()
+    };
+
+    {
+        let _x = (
+            d(
+                0,
+                d(
+                    1,
+                    match () { () if let Some(_) = d(2, Some(true)).extra
+                        && let DropLogger { .. } = d(3, None) => {
+                            None
+                        }
+                        _ => {
+                            Some(true)
+                        }
+                    }
+                )
+                .extra,
+            ),
+            d(4, None),
+            &d(5, None),
+            d(6, None),
+            match () {
+                () if let DropLogger { .. } = d(7, None)
+                && let DropLogger { .. } = d(8, None) => {
+                    d(9, None)
+                }
+                _ => {
+                    // 10 is not constructed
+                    d(10, None)
+                }
+            },
+        );
+        assert_eq!(get(), vec![3, 2, 8, 7, 1]);
+    }
+    assert_eq!(get(), vec![0, 4, 6, 9, 5]);
+
+    let _ = std::panic::catch_unwind(|| {
+        (
+            d(
+                11,
+                d(
+                    12,
+                    match () {
+                        () if let Some(_) = d(13, Some(true)).extra
+                                && let DropLogger { .. } = d(14, None) => {
+                            None
+                        }
+                        _ => {
+                            Some(true)
+                        }
+                    }
+                )
+                .extra,
+            ),
+            d(15, None),
+            &d(16, None),
+            d(17, None),
+            match () {
+                () if let DropLogger { .. } = d(18, None)
+                    && let DropLogger { .. } = d(19, None)
+                => {
+                    d(20, None)
+                }
+                _ => {
+                    // 10 is not constructed
+                    d(21, None)
+                }
+            },
+            panic::panic_any(InjectedFailure),
+        );
+    });
+    assert_eq!(get(), vec![14, 13, 19, 18, 20, 17, 15, 11, 16, 12]);
+}
diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.rs b/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.rs
new file mode 100644
index 00000000000..83ad8c76bb1
--- /dev/null
+++ b/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.rs
@@ -0,0 +1,81 @@
+//! Test that guard patterns can see bindings already in scope and bindings introduced in their
+//! subpattern, but no other bindings from the containing pattern. Also make sure bindings
+//! introduced in guard patterns are visible in fn/arm/loop/etc bodies.
+
+#![feature(guard_patterns)]
+#![expect(incomplete_features)]
+
+fn good_fn_item(((x if x) | x): bool) -> bool { x }
+
+fn bad_fn_item_1(x: bool, ((y if x) | y): bool) {}
+//~^ ERROR cannot find value `x` in this scope
+fn bad_fn_item_2(((x if y) | x): bool, y: bool) {}
+//~^ ERROR cannot find value `y` in this scope
+
+fn main() {
+    let ((local if local) if local) = false;
+
+    match (true, true) {
+        (x if local, y if good_fn_item(y)) => x && y,
+        (x, y if x) => x && y,
+        //~^ ERROR cannot find value `x` in this scope
+        (x if y, y) => x && y,
+        //~^ ERROR cannot find value `y` in this scope
+    };
+
+    match (true,) {
+        (x @ y if x && y,) => x && y,
+        (x @ (y if y),) => x && y,
+        (x @ (y if x),) => x && y,
+        //~^ ERROR cannot find value `x` in this scope
+    };
+
+    match (Ok(true),) {
+        ((Ok(x) | Err(x)) if good_fn_item(x),) => x,
+        ((Ok(x) if local) | (Err(x) if good_fn_item(x)),) => x,
+        ((Ok(x if x) if x) | (Err(x if x) if x) if x,) if x => x,
+        ((Ok(x) if y) | (Err(y) if x),) => x && y,
+        //~^ ERROR variable `x` is not bound in all patterns
+        //~| ERROR variable `y` is not bound in all patterns
+        //~| ERROR cannot find value `x` in this scope
+        //~| ERROR cannot find value `y` in this scope
+    };
+
+    let (_ if nonexistent) = true;
+    //~^ ERROR cannot find value `nonexistent` in this scope
+    if let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
+    //~^ ERROR cannot find value `x` in this scope
+    //~| ERROR cannot find value `y` in this scope
+    while let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
+    //~^ ERROR cannot find value `x` in this scope
+    //~| ERROR cannot find value `y` in this scope
+    for ((x, y if x) | (x if y, y)) in [(true, true)] { x && y; }
+    //~^ ERROR cannot find value `x` in this scope
+    //~| ERROR cannot find value `y` in this scope
+
+    (|(x if x), (y if y)| x && y)(true, true);
+    (|(x if y), (y if x)| x && y)(true, true);
+    //~^ ERROR cannot find value `x` in this scope
+    //~| ERROR cannot find value `y` in this scope
+
+    // FIXME(guard_patterns): mismatched bindings are not yet allowed
+    match Some(0) {
+        Some(x if x > 0) | None => {}
+        //~^ ERROR variable `x` is not bound in all patterns
+    }
+}
+
+/// Make sure shadowing is handled properly. In particular, if a pattern shadows an identifier,
+/// a guard pattern's guard should still see the original binding if the shadowing binding isn't in
+/// its subpattern.
+fn test_shadowing(local: bool) -> u8 {
+    match (0, 0) {
+        // The `local` binding here shadows the `bool` definition, so we get a type error.
+        //~v ERROR mismatched types
+        local if local => 0,
+        // The guards here should see the `bool` definition of `local`, not the new `u8` binding.
+        // The body should see the new binding.
+        (local, _ if local) => local,
+        (_ if local, local) => local,
+    }
+}
diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.stderr b/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.stderr
new file mode 100644
index 00000000000..d76e60478a1
--- /dev/null
+++ b/tests/ui/pattern/rfc-3637-guard-patterns/name-resolution.stderr
@@ -0,0 +1,133 @@
+error[E0408]: variable `y` is not bound in all patterns
+  --> $DIR/name-resolution.rs:37:10
+   |
+LL |         ((Ok(x) if y) | (Err(y) if x),) => x && y,
+   |          ^^^^^^^^^^^^        - variable not in all patterns
+   |          |
+   |          pattern doesn't bind `y`
+
+error[E0408]: variable `x` is not bound in all patterns
+  --> $DIR/name-resolution.rs:37:25
+   |
+LL |         ((Ok(x) if y) | (Err(y) if x),) => x && y,
+   |              -          ^^^^^^^^^^^^^ pattern doesn't bind `x`
+   |              |
+   |              variable not in all patterns
+
+error[E0408]: variable `x` is not bound in all patterns
+  --> $DIR/name-resolution.rs:63:28
+   |
+LL |         Some(x if x > 0) | None => {}
+   |              -             ^^^^ pattern doesn't bind `x`
+   |              |
+   |              variable not in all patterns
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/name-resolution.rs:10:34
+   |
+LL | fn bad_fn_item_1(x: bool, ((y if x) | y): bool) {}
+   |                                  ^ help: a local variable with a similar name exists: `y`
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/name-resolution.rs:12:25
+   |
+LL | fn bad_fn_item_2(((x if y) | x): bool, y: bool) {}
+   |                         ^ help: a local variable with a similar name exists: `x`
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/name-resolution.rs:20:18
+   |
+LL |         (x, y if x) => x && y,
+   |                  ^ help: a local variable with a similar name exists: `y`
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/name-resolution.rs:22:15
+   |
+LL |         (x if y, y) => x && y,
+   |               ^ help: a local variable with a similar name exists: `x`
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/name-resolution.rs:29:20
+   |
+LL |         (x @ (y if x),) => x && y,
+   |                    ^ help: a local variable with a similar name exists: `y`
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/name-resolution.rs:37:20
+   |
+LL |         ((Ok(x) if y) | (Err(y) if x),) => x && y,
+   |                    ^ help: a local variable with a similar name exists: `x`
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/name-resolution.rs:37:36
+   |
+LL |         ((Ok(x) if y) | (Err(y) if x),) => x && y,
+   |                                    ^ help: a local variable with a similar name exists: `y`
+
+error[E0425]: cannot find value `nonexistent` in this scope
+  --> $DIR/name-resolution.rs:44:15
+   |
+LL |     let (_ if nonexistent) = true;
+   |               ^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/name-resolution.rs:46:22
+   |
+LL |     if let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
+   |                      ^ help: a local variable with a similar name exists: `y`
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/name-resolution.rs:46:33
+   |
+LL |     if let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
+   |                                 ^ help: a local variable with a similar name exists: `x`
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/name-resolution.rs:49:25
+   |
+LL |     while let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
+   |                         ^ help: a local variable with a similar name exists: `y`
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/name-resolution.rs:49:36
+   |
+LL |     while let ((x, y if x) | (x if y, y)) = (true, true) { x && y; }
+   |                                    ^ help: a local variable with a similar name exists: `x`
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/name-resolution.rs:52:19
+   |
+LL |     for ((x, y if x) | (x if y, y)) in [(true, true)] { x && y; }
+   |                   ^ help: a local variable with a similar name exists: `y`
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/name-resolution.rs:52:30
+   |
+LL |     for ((x, y if x) | (x if y, y)) in [(true, true)] { x && y; }
+   |                              ^ help: a local variable with a similar name exists: `x`
+
+error[E0425]: cannot find value `y` in this scope
+  --> $DIR/name-resolution.rs:57:13
+   |
+LL |     (|(x if y), (y if x)| x && y)(true, true);
+   |             ^ help: a local variable with a similar name exists: `x`
+
+error[E0425]: cannot find value `x` in this scope
+  --> $DIR/name-resolution.rs:57:23
+   |
+LL |     (|(x if y), (y if x)| x && y)(true, true);
+   |                       ^ help: a local variable with a similar name exists: `y`
+
+error[E0308]: mismatched types
+  --> $DIR/name-resolution.rs:75:18
+   |
+LL |         local if local => 0,
+   |                  ^^^^^ expected `bool`, found `({integer}, {integer})`
+   |
+   = note: expected type `bool`
+             found tuple `({integer}, {integer})`
+
+error: aborting due to 20 previous errors
+
+Some errors have detailed explanations: E0308, E0408, E0425.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs b/tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs
new file mode 100644
index 00000000000..7bb39ca7bb9
--- /dev/null
+++ b/tests/ui/pattern/rfc-3637-guard-patterns/only-gather-locals-once.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+//! Test that `GatherLocalsVisitor` only visits expressions in guard patterns when checking the
+//! expressions, and not a second time when visiting the pattern. If locals are declared inside the
+//! the guard expression, it would ICE if visited twice ("evaluated expression more than once").
+
+#![feature(guard_patterns)]
+#![expect(incomplete_features)]
+
+fn main() {
+    match (0,) {
+        // FIXME(guard_patterns): liveness lints don't work yet; this will ICE without the `_`.
+        (_ if { let _x = false; _x },) => {}
+        _ => {}
+    }
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/temporary-early-drop.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/temporary-early-drop.rs
new file mode 100644
index 00000000000..9edbc3243c7
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/temporary-early-drop.rs
@@ -0,0 +1,29 @@
+// issue-103476
+//@ revisions: edition2021 edition2024
+//@ [edition2021] edition: 2021
+//@ [edition2024] edition: 2024
+//@ check-pass
+
+#![feature(if_let_guard)]
+#![allow(irrefutable_let_patterns)]
+
+struct Pd;
+
+impl Pd {
+    fn it(&self) -> It {
+        todo!()
+    }
+}
+
+pub struct It<'a>(Box<dyn Tr<'a>>);
+
+trait Tr<'a> {}
+
+fn f(m: Option<Pd>) {
+    match () {
+        () if let Some(n) = m && let it = n.it() => {}
+        _ => {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/simd/target-feature-mixup.rs b/tests/ui/simd/target-feature-mixup.rs
index 2786251c795..77f18615248 100644
--- a/tests/ui/simd/target-feature-mixup.rs
+++ b/tests/ui/simd/target-feature-mixup.rs
@@ -7,7 +7,6 @@
 //@ ignore-fuchsia must translate zircon signal to SIGILL, FIXME (#58590)
 
 #![feature(repr_simd, target_feature, cfg_target_feature)]
-#![feature(avx512_target_feature)]
 
 use std::process::{Command, ExitStatus};
 use std::env;
diff --git a/tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs b/tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs
index 2682028936c..15bcfdd9076 100644
--- a/tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs
+++ b/tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs
@@ -1,5 +1,5 @@
-#![feature(avx512_target_feature)]
+#![feature(x87_target_feature)]
 
 #[inline]
-#[target_feature(enable = "avx512ifma")]
+#[target_feature(enable = "x87")]
 pub unsafe fn foo() {}
diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs
index 14fdad02f56..9244a98d82f 100644
--- a/tests/ui/target-feature/gate.rs
+++ b/tests/ui/target-feature/gate.rs
@@ -2,7 +2,6 @@
 //
 // gate-test-sse4a_target_feature
 // gate-test-powerpc_target_feature
-// gate-test-avx512_target_feature
 // gate-test-tbm_target_feature
 // gate-test-arm_target_feature
 // gate-test-hexagon_target_feature
@@ -27,7 +26,7 @@
 // gate-test-x87_target_feature
 // gate-test-m68k_target_feature
 
-#[target_feature(enable = "avx512bw")]
+#[target_feature(enable = "x87")]
 //~^ ERROR: currently unstable
 unsafe fn foo() {}
 
diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr
index fa876893848..32d60ce4382 100644
--- a/tests/ui/target-feature/gate.stderr
+++ b/tests/ui/target-feature/gate.stderr
@@ -1,11 +1,11 @@
-error[E0658]: the target feature `avx512bw` is currently unstable
-  --> $DIR/gate.rs:30:18
+error[E0658]: the target feature `x87` is currently unstable
+  --> $DIR/gate.rs:29:18
    |
-LL | #[target_feature(enable = "avx512bw")]
-   |                  ^^^^^^^^^^^^^^^^^^^
+LL | #[target_feature(enable = "x87")]
+   |                  ^^^^^^^^^^^^^^
    |
    = note: see issue #44839 <https://github.com/rust-lang/rust/issues/44839> for more information
-   = help: add `#![feature(avx512_target_feature)]` to the crate attributes to enable
+   = help: add `#![feature(x87_target_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/target-feature/unstable-feature.rs b/tests/ui/target-feature/unstable-feature.rs
index f62c4dd938a..a79ad469603 100644
--- a/tests/ui/target-feature/unstable-feature.rs
+++ b/tests/ui/target-feature/unstable-feature.rs
@@ -1,8 +1,8 @@
-//@ compile-flags: -Ctarget-feature=+vaes --crate-type=rlib --target=x86_64-unknown-linux-gnu
+//@ compile-flags: -Ctarget-feature=+x87 --crate-type=rlib --target=x86_64-unknown-linux-gnu
 //@ build-pass
 //@ needs-llvm-components: x86
 
 #![feature(no_core)]
 #![no_core]
 
-//~? WARN unstable feature specified for `-Ctarget-feature`: `vaes`
+//~? WARN unstable feature specified for `-Ctarget-feature`: `x87`
diff --git a/tests/ui/target-feature/unstable-feature.stderr b/tests/ui/target-feature/unstable-feature.stderr
index d34544c5c27..309b64afd92 100644
--- a/tests/ui/target-feature/unstable-feature.stderr
+++ b/tests/ui/target-feature/unstable-feature.stderr
@@ -1,4 +1,4 @@
-warning: unstable feature specified for `-Ctarget-feature`: `vaes`
+warning: unstable feature specified for `-Ctarget-feature`: `x87`
    |
    = note: this feature is not stably supported; its behavior can change in the future
 
diff --git a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs
index ef6871bec7c..0aaee5d1764 100644
--- a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs
+++ b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs
@@ -1,10 +1,10 @@
 #![feature(type_alias_impl_trait)]
 
 type T = impl Copy;
-//~^ ERROR cannot resolve opaque type
 
 #[define_opaque(T)]
 fn foo() -> T {
+    //~^ ERROR cannot resolve opaque type
     None::<&'static T>
 }
 
diff --git a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr
index d820df472f9..426a6c29fff 100644
--- a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr
+++ b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.stderr
@@ -1,8 +1,8 @@
 error[E0720]: cannot resolve opaque type
-  --> $DIR/infinite-cycle-involving-weak.rs:3:10
+  --> $DIR/infinite-cycle-involving-weak.rs:6:13
    |
-LL | type T = impl Copy;
-   |          ^^^^^^^^^ cannot resolve opaque type
+LL | fn foo() -> T {
+   |             ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/crashes/139817.rs b/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.rs
index d439ed4cacb..f4e2cb0c037 100644
--- a/tests/crashes/139817.rs
+++ b/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.rs
@@ -1,8 +1,12 @@
-//@ known-bug: #139817
+#![feature(type_alias_impl_trait)]
+
 fn enum_upvar() {
     type T = impl Copy;
     let foo: T = Some((42, std::marker::PhantomData::<T>));
     let x = move || match foo {
         None => (),
+        //~^ ERROR cannot resolve opaque type
     };
 }
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.stderr b/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.stderr
new file mode 100644
index 00000000000..2bfce2d63a8
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/match-upvar-discriminant-of-opaque.stderr
@@ -0,0 +1,9 @@
+error[E0720]: cannot resolve opaque type
+  --> $DIR/match-upvar-discriminant-of-opaque.rs:7:9
+   |
+LL |         None => (),
+   |         ^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs
index 94597adfed0..fe354cc6545 100644
--- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs
+++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs
@@ -13,7 +13,7 @@ pub fn add(
     n: Diff,
     m: Diff,
 ) -> Diff {
-    //~^ ERROR concrete type differs
+    //~^ ERROR cannot resolve opaque type
     move |x: usize| m(n(x))
 }
 
diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
index 59ff9917612..847f1cc6c2e 100644
--- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
+++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
@@ -1,14 +1,9 @@
-error: concrete type differs from previous defining opaque type use
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-fn-tait.rs:15:6
    |
 LL | ) -> Diff {
-   |      ^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:8:5: 8:16}`, got `{closure@$DIR/recursive-fn-tait.rs:17:5: 17:20}`
-   |
-note: previous use here
-  --> $DIR/recursive-fn-tait.rs:7:18
-   |
-LL | pub fn lift() -> Diff {
-   |                  ^^^^
+   |      ^^^^
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs
index 858f2a2feb6..7803b3b78db 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs
@@ -13,7 +13,7 @@ fn transform<S>() -> impl std::fmt::Display {
 }
 #[define_opaque(Op)]
 fn bad() -> Op {
-    //~^ ERROR concrete type differs from previous defining opaque type use
+    //~^ ERROR cannot resolve opaque type
     transform::<Op>()
 }
 
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr
index e527b5bc7f8..837df7f5d43 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr
@@ -1,14 +1,9 @@
-error: concrete type differs from previous defining opaque type use
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-tait-conflicting-defn-2.rs:15:13
    |
 LL | fn bad() -> Op {
-   |             ^^ expected `&&str`, got `impl std::fmt::Display`
-   |
-note: previous use here
-  --> $DIR/recursive-tait-conflicting-defn-2.rs:7:13
-   |
-LL | fn foo() -> Op {
    |             ^^
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
index 90581a98a34..d66ceda5234 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
@@ -23,7 +23,7 @@ pub fn test() -> TestImpl {
 
 #[define_opaque(TestImpl)]
 fn make_option2() -> Option<TestImpl> {
-    //~^ ERROR concrete type differs from previous defining opaque type use
+    //~^ ERROR cannot resolve opaque type
     let inner = make_option().unwrap();
     Some(B { inner })
 }
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
index 256f13b6221..c7a3381d615 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
@@ -1,14 +1,9 @@
-error: concrete type differs from previous defining opaque type use
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-tait-conflicting-defn.rs:25:22
    |
 LL | fn make_option2() -> Option<TestImpl> {
-   |                      ^^^^^^^^^^^^^^^^ expected `A`, got `B<TestImpl>`
-   |
-note: previous use here
-  --> $DIR/recursive-tait-conflicting-defn.rs:20:18
-   |
-LL | pub fn test() -> TestImpl {
-   |                  ^^^^^^^^
+   |                      ^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0720`.
diff --git a/triagebot.toml b/triagebot.toml
index 9dcdbcecbec..fd7a861bc92 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -133,7 +133,7 @@ In case it's useful, here are some [instructions] for tackling these sorts of is
 
 [instructions]: https://rustc-dev-guide.rust-lang.org/notification-groups/rust-for-linux.html
 """
-label = "O-rfl"
+label = "A-rust-for-linux"
 
 [ping.wasm]
 alias = ["webassembly"]
@@ -887,6 +887,7 @@ message = "Some changes occurred in HTML/CSS/JS."
 cc = [
     "@GuillaumeGomez",
     "@jsha",
+    "@lolbinarycat",
 ]
 
 [mentions."tests/rustdoc-gui/"]
@@ -1171,7 +1172,6 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
 users_on_vacation = [
     "fmease",
     "jyn514",
-    "Noratrieb",
     "spastorino",
 ]
 
@@ -1198,7 +1198,6 @@ compiler = [
     "@lcnr",
     "@Nadrieril",
     "@nnethercote",
-    "@Noratrieb",
     "@oli-obk",
     "@petrochenkov",
     "@SparrowLii",
@@ -1206,7 +1205,6 @@ compiler = [
 ]
 libs = [
     "@Mark-Simulacrum",
-    "@Noratrieb",
     "@workingjubilee",
     "@joboet",
     "@jhpratt",
@@ -1424,3 +1422,6 @@ compiletest = [
 # Enable `@rustbot note` functionality
 # Documentation at: https://forge.rust-lang.org/triagebot/note.html
 [note]
+
+[behind-upstream]
+days-threshold = 14