about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--bootstrap.example.toml18
-rw-r--r--compiler/rustc_ast/src/ast.rs331
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs11
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs5
-rw-r--r--compiler/rustc_ast/src/expand/autodiff_attrs.rs3
-rw-r--r--compiler/rustc_ast/src/format.rs3
-rw-r--r--compiler/rustc_ast/src/lib.rs1
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs19
-rw-r--r--compiler/rustc_ast/src/ptr.rs11
-rw-r--r--compiler/rustc_ast/src/visit.rs29
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs1
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs2
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs3
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs3
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs13
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs5
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs8
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs5
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/opaque_types.rs (renamed from compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs)19
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs3
-rw-r--r--compiler/rustc_borrowck/src/handle_placeholders.rs15
-rw-r--r--compiler/rustc_borrowck/src/lib.rs8
-rw-r--r--compiler/rustc_borrowck/src/nll.rs5
-rw-r--r--compiler/rustc_borrowck/src/polonius/constraints.rs4
-rw-r--r--compiler/rustc_borrowck/src/polonius/liveness_constraints.rs12
-rw-r--r--compiler/rustc_borrowck/src/polonius/loan_liveness.rs191
-rw-r--r--compiler/rustc_borrowck/src/polonius/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/polonius/typeck_constraints.rs19
-rw-r--r--compiler/rustc_borrowck/src/region_infer/graphviz.rs17
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs78
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs11
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs2
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/alloc_error_handler.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs13
-rw-r--r--compiler/rustc_builtin_macros/src/assert.rs15
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs32
-rw-r--r--compiler/rustc_builtin_macros/src/autodiff.rs55
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs15
-rw-r--r--compiler/rustc_builtin_macros/src/concat_bytes.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs78
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/ty.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs13
-rw-r--r--compiler/rustc_builtin_macros/src/edition_panic.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign.rs12
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs13
-rw-r--r--compiler/rustc_builtin_macros/src/iter.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/pattern_type.rs16
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs15
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/util.rs11
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs24
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs24
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/apple.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs82
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs3
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs5
-rw-r--r--compiler/rustc_errors/src/emitter.rs2
-rw-r--r--compiler/rustc_expand/messages.ftl3
-rw-r--r--compiler/rustc_expand/src/base.rs100
-rw-r--r--compiler/rustc_expand/src/build.rs218
-rw-r--r--compiler/rustc_expand/src/errors.rs18
-rw-r--r--compiler/rustc_expand/src/expand.rs122
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs55
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs264
-rw-r--r--compiler/rustc_expand/src/module.rs3
-rw-r--r--compiler/rustc_expand/src/placeholders.rs68
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs3
-rw-r--r--compiler/rustc_expand/src/stats.rs3
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/attrs/data_structures.rs3
-rw-r--r--compiler/rustc_hir/src/attrs/encode_cross_crate.rs1
-rw-r--r--compiler/rustc_hir/src/def.rs42
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs5
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl4
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs99
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs139
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs1
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_lint/src/builtin.rs13
-rw-r--r--compiler/rustc_lint/src/default_could_be_derived.rs3
-rw-r--r--compiler/rustc_lint/src/early.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs3
-rw-r--r--compiler/rustc_lint/src/map_unit_fn.rs103
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs2
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs18
-rw-r--r--compiler/rustc_metadata/src/rmeta/parameterized.rs7
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs63
-rw-r--r--compiler/rustc_middle/src/middle/region.rs6
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs17
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/rvalue_scopes.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/matches/mod.rs80
-rw-r--r--compiler/rustc_mir_build/src/builder/scope.rs37
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coverage/hir_info.rs128
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mappings.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs145
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs3
-rw-r--r--compiler/rustc_mir_transform/src/remove_unneeded_drops.rs31
-rw-r--r--compiler/rustc_parse/messages.ftl2
-rw-r--r--compiler/rustc_parse/src/errors.rs11
-rw-r--r--compiler/rustc_parse/src/parser/asm.rs3
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs89
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs208
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs6
-rw-r--r--compiler/rustc_parse/src/parser/item.rs41
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs31
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs16
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs39
-rw-r--r--compiler/rustc_parse/src/parser/path.rs9
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs27
-rw-r--r--compiler/rustc_parse/src/parser/tests.rs9
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs51
-rw-r--r--compiler/rustc_passes/messages.ftl2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs49
-rw-r--r--compiler/rustc_passes/src/errors.rs4
-rw-r--r--compiler/rustc_passes/src/input_stats.rs4
-rw-r--r--compiler/rustc_passes/src/stability.rs111
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs10
-rw-r--r--compiler/rustc_pattern_analysis/tests/exhaustiveness.rs3
-rw-r--r--compiler/rustc_public/src/mir/pretty.rs2
-rw-r--r--compiler/rustc_resolve/messages.ftl2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs3
-rw-r--r--compiler/rustc_resolve/src/ident.rs20
-rw-r--r--compiler/rustc_resolve/src/late.rs19
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs9
-rw-r--r--compiler/rustc_resolve/src/lib.rs3
-rw-r--r--compiler/rustc_resolve/src/macros.rs10
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs43
-rw-r--r--compiler/rustc_target/src/spec/base/apple/tests.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/i386_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs4
-rw-r--r--compiler/rustc_trait_selection/messages.ftl2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs15
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs32
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs3
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs57
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs119
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs69
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs11
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs36
-rw-r--r--compiler/rustc_type_ir/src/binder.rs60
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs1
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs7
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs2
-rw-r--r--library/core/src/char/methods.rs6
-rw-r--r--library/core/src/intrinsics/mod.rs30
-rw-r--r--library/core/src/sync/atomic.rs89
-rw-r--r--library/coretests/tests/floats/f128.rs290
-rw-r--r--library/coretests/tests/floats/f16.rs294
-rw-r--r--library/coretests/tests/floats/f32.rs298
-rw-r--r--library/coretests/tests/floats/f64.rs296
-rw-r--r--library/coretests/tests/floats/mod.rs459
-rw-r--r--library/std/src/sys/pal/wasm/atomics/thread.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs342
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs90
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs7
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs8
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs8
-rw-r--r--src/bootstrap/src/core/builder/mod.rs5
-rw-r--r--src/bootstrap/src/core/builder/tests.rs52
-rw-r--r--src/bootstrap/src/core/config/config.rs17
-rw-r--r--src/bootstrap/src/core/config/toml/rust.rs3
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios-macabi.md11
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios.md14
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/COLORTERM.md5
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/QNX_TARGET.md11
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md6
-rw-r--r--src/doc/unstable-book/src/compiler-environment-variables/TERM.md5
-rw-r--r--src/doc/unstable-book/src/compiler-flags/terminal-urls.md13
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md5
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/formats/cache.rs1
-rw-r--r--src/librustdoc/html/render/mod.rs1
-rw-r--r--src/librustdoc/html/render/search_index.rs6
-rw-r--r--src/librustdoc/html/static/js/rustdoc.d.ts3
-rw-r--r--src/librustdoc/html/static/js/search.js34
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs45
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/mod.rs9
-rw-r--r--src/tools/compiletest/src/directives/tests.rs7
-rw-r--r--src/tools/compiletest/src/runtest.rs2
m---------src/tools/enzyme0
-rw-r--r--src/tools/miri/src/intrinsics/atomic.rs19
-rw-r--r--src/tools/miri/src/operator.rs8
-rw-r--r--src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr2
-rw-r--r--src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs8
-rw-r--r--src/tools/rustfmt/src/chains.rs6
-rw-r--r--src/tools/rustfmt/src/closures.rs4
-rw-r--r--src/tools/rustfmt/src/expr.rs6
-rw-r--r--src/tools/rustfmt/src/items.rs10
-rw-r--r--src/tools/rustfmt/src/macros.rs10
-rw-r--r--src/tools/rustfmt/src/matches.rs6
-rw-r--r--src/tools/rustfmt/src/modules.rs8
-rw-r--r--src/tools/rustfmt/src/overflow.rs4
-rw-r--r--src/tools/rustfmt/src/parse/macros/lazy_static.rs3
-rw-r--r--src/tools/rustfmt/src/parse/macros/mod.rs14
-rw-r--r--src/tools/rustfmt/src/parse/parser.rs4
-rw-r--r--src/tools/rustfmt/src/patterns.rs13
-rw-r--r--src/tools/rustfmt/src/rewrite.rs3
-rw-r--r--src/tools/rustfmt/src/spanned.rs4
-rw-r--r--src/tools/rustfmt/src/types.rs5
-rw-r--r--src/tools/rustfmt/src/utils.rs6
-rw-r--r--src/tools/rustfmt/src/visitor.rs2
-rw-r--r--src/tools/tidy/src/features.rs35
-rw-r--r--src/tools/tidy/src/unstable_book.rs2
-rw-r--r--src/tools/unstable-book-gen/src/main.rs29
-rw-r--r--src/tools/unstable-book-gen/src/stub-env-var.md9
-rw-r--r--tests/assembly-llvm/asm/loongarch-type.rs51
-rw-r--r--tests/codegen-llvm/atomicptr.rs6
-rw-r--r--tests/crashes/135528.rs20
-rw-r--r--tests/crashes/135646.rs7
-rw-r--r--tests/mir-opt/remove_unneeded_drop_in_place.rs17
-rw-r--r--tests/mir-opt/remove_unneeded_drop_in_place.slice_in_place.RemoveUnneededDrops.diff20
-rw-r--r--tests/run-make/atomic-lock-free/atomic_lock_free.rs39
-rw-r--r--tests/rustdoc-js-std/core-transmute.js2
-rw-r--r--tests/rustdoc-js-std/transmute-fail.js2
-rw-r--r--tests/rustdoc-js-std/transmute.js2
-rw-r--r--tests/rustdoc-js/doc-alias-after-other-items.js38
-rw-r--r--tests/rustdoc-js/doc-alias-after-other-items.rs9
-rw-r--r--tests/rustdoc-js/sort-stability.js9
-rw-r--r--tests/rustdoc-js/sort-stability.rs16
-rw-r--r--tests/ui-fulldeps/auxiliary/parser.rs3
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs28
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr4
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr4
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr2
-rw-r--r--tests/ui/allocator/not-an-allocator.stderr8
-rw-r--r--tests/ui/allocator/two-allocators.stderr2
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr38
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr62
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr12
-rw-r--r--tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr20
-rw-r--r--tests/ui/asm/loongarch/bad-reg.rs15
-rw-r--r--tests/ui/asm/s390x/bad-reg.rs2
-rw-r--r--tests/ui/attributes/malformed-attrs.stderr15
-rw-r--r--tests/ui/attributes/rustc_confusables_std_cases.stderr6
-rw-r--r--tests/ui/borrowck/array-slice-coercion-mismatch-15783.rs (renamed from tests/ui/issues/issue-15783.rs)2
-rw-r--r--tests/ui/borrowck/array-slice-coercion-mismatch-15783.stderr (renamed from tests/ui/issues/issue-15783.stderr)4
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr2
-rw-r--r--tests/ui/closures/unused-closure-ice-16256.rs (renamed from tests/ui/issues/issue-16256.rs)2
-rw-r--r--tests/ui/closures/unused-closure-ice-16256.stderr (renamed from tests/ui/issues/issue-16256.stderr)2
-rw-r--r--tests/ui/codegen/nested-enum-match-optimization-15793.rs (renamed from tests/ui/issues/issue-15793.rs)2
-rw-r--r--tests/ui/codegen/overflow-during-mono.rs3
-rw-r--r--tests/ui/codegen/overflow-during-mono.stderr10
-rw-r--r--tests/ui/coherence/coherence-tuple-conflict.stderr2
-rw-r--r--tests/ui/confuse-field-and-method/issue-18343.stderr2
-rw-r--r--tests/ui/confuse-field-and-method/issue-2392.stderr12
-rw-r--r--tests/ui/consts/issue-19244-1.stderr2
-rw-r--r--tests/ui/custom_test_frameworks/mismatch.stderr2
-rw-r--r--tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr2
-rw-r--r--tests/ui/derives/derive-partial-ord-discriminant-64bit.rs (renamed from tests/ui/issues/issue-15523-big.rs)3
-rw-r--r--tests/ui/derives/derive-partial-ord-discriminant.rs (renamed from tests/ui/issues/issue-15523.rs)2
-rw-r--r--tests/ui/diagnostic-width/long-E0609.stderr1
-rw-r--r--tests/ui/drop/dropck-normalize-errors.nll.stderr (renamed from tests/ui/drop/dropck-normalize-errors.stderr)24
-rw-r--r--tests/ui/drop/dropck-normalize-errors.polonius.stderr64
-rw-r--r--tests/ui/drop/dropck-normalize-errors.rs6
-rw-r--r--tests/ui/drop/enum-drop-impl-15063.rs (renamed from tests/ui/issues/issue-15063.rs)2
-rw-r--r--tests/ui/drop/generic-drop-trait-bound-15858.rs (renamed from tests/ui/issues/issue-15858.rs)2
-rw-r--r--tests/ui/drop/generic-drop-trait-bound-15858.stderr (renamed from tests/ui/issues/issue-15858.stderr)2
-rw-r--r--tests/ui/drop/if-let-guards.rs88
-rw-r--r--tests/ui/drop/nested-return-drop-order.rs (renamed from tests/ui/issues/issue-15763.rs)2
-rw-r--r--tests/ui/drop/same-alloca-reassigned-match-binding-16151.rs34
-rw-r--r--tests/ui/drop/struct-field-drop-order.rs (renamed from tests/ui/issues/issue-16492.rs)2
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs1
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr6
-rw-r--r--tests/ui/editions/never-type-fallback-breaking.e2024.stderr8
-rw-r--r--tests/ui/error-codes/E0275.rs1
-rw-r--r--tests/ui/error-codes/E0275.stderr8
-rw-r--r--tests/ui/error-codes/ex-E0612.stderr6
-rw-r--r--tests/ui/extern/empty-struct-extern-fn-16441.rs (renamed from tests/ui/issues/issue-16441.rs)2
-rw-r--r--tests/ui/feature-gates/feature-gate-macro-attr.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-macro-attr.stderr13
-rw-r--r--tests/ui/fn/fn-traits-call-once-signature-15094.rs (renamed from tests/ui/issues/issue-15094.rs)2
-rw-r--r--tests/ui/fn/fn-traits-call-once-signature-15094.stderr (renamed from tests/ui/issues/issue-15094.stderr)2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr16
-rw-r--r--tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs1
-rw-r--r--tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr16
-rw-r--r--tests/ui/impl-trait/issues/type-error-post-normalization-test.rs24
-rw-r--r--tests/ui/impl-trait/issues/type-error-post-normalization-test.stderr14
-rw-r--r--tests/ui/impl-trait/member-constraints/apply_member_constraint-no-req-eq.rs24
-rw-r--r--tests/ui/impl-trait/member-constraints/incomplete-constraint.rs21
-rw-r--r--tests/ui/impl-trait/member-constraints/min-choice-reject-ambiguous.rs (renamed from tests/ui/nll/member-constraints/min-choice-reject-ambiguous.rs)0
-rw-r--r--tests/ui/impl-trait/member-constraints/min-choice-reject-ambiguous.stderr (renamed from tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr)0
-rw-r--r--tests/ui/impl-trait/member-constraints/min-choice.rs (renamed from tests/ui/nll/member-constraints/min-choice.rs)0
-rw-r--r--tests/ui/impl-trait/member-constraints/nested-impl-trait-fail.rs (renamed from tests/ui/nll/member-constraints/nested-impl-trait-fail.rs)0
-rw-r--r--tests/ui/impl-trait/member-constraints/nested-impl-trait-fail.stderr (renamed from tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr)0
-rw-r--r--tests/ui/impl-trait/member-constraints/nested-impl-trait-pass.rs (renamed from tests/ui/nll/member-constraints/nested-impl-trait-pass.rs)5
-rw-r--r--tests/ui/impl-trait/member-constraints/reject-choice-due-to-prev-constraint.rs34
-rw-r--r--tests/ui/impl-trait/no-anonymize-regions.rs18
-rw-r--r--tests/ui/imports/enum-variant-import-path-15774.rs (renamed from tests/ui/issues/issue-15774.rs)2
-rw-r--r--tests/ui/inference/iterator-sum-array-15673.rs11
-rw-r--r--tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs1
-rw-r--r--tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr6
-rw-r--r--tests/ui/inference/return-block-type-inference-15965.rs (renamed from tests/ui/issues/issue-15965.rs)2
-rw-r--r--tests/ui/inference/return-block-type-inference-15965.stderr (renamed from tests/ui/issues/issue-15965.stderr)2
-rw-r--r--tests/ui/interior-mutability/interior-mutability.rs1
-rw-r--r--tests/ui/interior-mutability/interior-mutability.stderr4
-rw-r--r--tests/ui/intrinsics/intrinsic-atomics.rs12
-rw-r--r--tests/ui/intrinsics/non-integer-atomic.rs32
-rw-r--r--tests/ui/intrinsics/non-integer-atomic.stderr32
-rw-r--r--tests/ui/issues/issue-41880.stderr2
-rw-r--r--tests/ui/iterators/explicit-deref-non-deref-type-15756.rs (renamed from tests/ui/issues/issue-15756.rs)2
-rw-r--r--tests/ui/iterators/explicit-deref-non-deref-type-15756.stderr (renamed from tests/ui/issues/issue-15756.stderr)2
-rw-r--r--tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.rs (renamed from tests/ui/issues/issue-15034.rs)2
-rw-r--r--tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.stderr (renamed from tests/ui/issues/issue-15034.stderr)2
-rw-r--r--tests/ui/lifetimes/struct-lifetime-inference-15735.rs19
-rw-r--r--tests/ui/macros/for-loop-macro-rules-hygiene.rs (renamed from tests/ui/issues/issue-15189.rs)2
-rw-r--r--tests/ui/macros/macro-hygiene-scope-15167.rs (renamed from tests/ui/issues/issue-15167.rs)2
-rw-r--r--tests/ui/macros/macro-hygiene-scope-15167.stderr (renamed from tests/ui/issues/issue-15167.stderr)8
-rw-r--r--tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr2
-rw-r--r--tests/ui/macros/macro-rules-attr-error.rs15
-rw-r--r--tests/ui/macros/macro-rules-attr-error.stderr22
-rw-r--r--tests/ui/macros/macro-rules-attr-infinite-recursion.rs12
-rw-r--r--tests/ui/macros/macro-rules-attr-infinite-recursion.stderr14
-rw-r--r--tests/ui/macros/macro-rules-attr-nested.rs24
-rw-r--r--tests/ui/macros/macro-rules-attr-nested.run.stdout3
-rw-r--r--tests/ui/macros/macro-rules-attr.rs90
-rw-r--r--tests/ui/macros/macro-rules-attr.run.stdout15
-rw-r--r--tests/ui/macros/macro-rules-attr.stderr21
-rw-r--r--tests/ui/methods/call_method_unknown_referent.rs2
-rw-r--r--tests/ui/methods/call_method_unknown_referent.stderr2
-rw-r--r--tests/ui/methods/inherent-bound-in-probe.rs1
-rw-r--r--tests/ui/methods/inherent-bound-in-probe.stderr12
-rw-r--r--tests/ui/methods/method-not-found-generic-arg-elision.stderr8
-rw-r--r--tests/ui/methods/probe-error-on-infinite-deref.rs1
-rw-r--r--tests/ui/methods/probe-error-on-infinite-deref.stderr8
-rw-r--r--tests/ui/methods/untrimmed-path-type.stderr2
-rw-r--r--tests/ui/moves/match-move-same-binding-15571.rs (renamed from tests/ui/issues/issue-15571.rs)2
-rw-r--r--tests/ui/never/never-type-method-call-15207.rs (renamed from tests/ui/issues/issue-15207.rs)2
-rw-r--r--tests/ui/never/never-type-method-call-15207.stderr (renamed from tests/ui/issues/issue-15207.stderr)2
-rw-r--r--tests/ui/never_type/defaulted-never-note.fallback.stderr2
-rw-r--r--tests/ui/never_type/defaulted-never-note.rs2
-rw-r--r--tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr2
-rw-r--r--tests/ui/nll/issue-46589.nll.stderr2
-rw-r--r--tests/ui/nll/issue-46589.polonius.stderr15
-rw-r--r--tests/ui/nll/issue-46589.rs12
-rw-r--r--tests/ui/nll/polonius/array-literal-index-oob-2024.rs12
-rw-r--r--tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr36
-rw-r--r--tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr36
-rw-r--r--tests/ui/nll/polonius/flow-sensitive-invariance.rs34
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr2
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.polonius.stderr12
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs7
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr4
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.polonius.stderr22
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs7
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr2
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.polonius.stderr18
-rw-r--r--tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs7
-rw-r--r--tests/ui/nll/polonius/iterating-updating-mutref.nll.stderr15
-rw-r--r--tests/ui/nll/polonius/iterating-updating-mutref.rs87
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr28
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr28
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr26
-rw-r--r--tests/ui/nll/polonius/lending-iterator-sanity-checks.rs71
-rw-r--r--tests/ui/offset-of/offset-of-tuple-field.stderr36
-rw-r--r--tests/ui/parser/float-field.stderr6
-rw-r--r--tests/ui/parser/generics-rangle-eq-15043.rs (renamed from tests/ui/issues/issue-15043.rs)2
-rw-r--r--tests/ui/parser/macro/macro-attr-bad.rs32
-rw-r--r--tests/ui/parser/macro/macro-attr-bad.stderr80
-rw-r--r--tests/ui/parser/macro/macro-attr-recovery.rs19
-rw-r--r--tests/ui/parser/macro/macro-attr-recovery.stderr31
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs2
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr6
-rw-r--r--tests/ui/pattern/enum-struct-pattern-mismatch-15896.rs (renamed from tests/ui/issues/issue-15896.rs)2
-rw-r--r--tests/ui/pattern/enum-struct-pattern-mismatch-15896.stderr (renamed from tests/ui/issues/issue-15896.stderr)2
-rw-r--r--tests/ui/pattern/refutable-pattern-for-loop-15381.rs (renamed from tests/ui/issues/issue-15381.rs)2
-rw-r--r--tests/ui/pattern/refutable-pattern-for-loop-15381.stderr (renamed from tests/ui/issues/issue-15381.stderr)2
-rw-r--r--tests/ui/pattern/slice-pattern-recursion-15104.rs (renamed from tests/ui/issues/issue-15104.rs)2
-rw-r--r--tests/ui/pattern/static-binding-shadow-16149.rs (renamed from tests/ui/issues/issue-16149.rs)2
-rw-r--r--tests/ui/pattern/static-binding-shadow-16149.stderr (renamed from tests/ui/issues/issue-16149.stderr)2
-rw-r--r--tests/ui/pattern/struct-field-duplicate-binding-15260.rs (renamed from tests/ui/issues/issue-15260.rs)2
-rw-r--r--tests/ui/pattern/struct-field-duplicate-binding-15260.stderr (renamed from tests/ui/issues/issue-15260.stderr)8
-rw-r--r--tests/ui/pattern/tuple-enum-match-15129.rs (renamed from tests/ui/issues/issue-15129-rpass.rs)13
-rw-r--r--tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.rs (renamed from tests/ui/issues/issue-16401.rs)2
-rw-r--r--tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.stderr (renamed from tests/ui/issues/issue-16401.stderr)2
-rw-r--r--tests/ui/pattern/usefulness/unions.rs2
-rw-r--r--tests/ui/pattern/usefulness/unions.stderr4
-rw-r--r--tests/ui/proc-macro/span-from-proc-macro.stderr2
-rw-r--r--tests/ui/recursion/issue-23122-2.rs1
-rw-r--r--tests/ui/recursion/issue-23122-2.stderr8
-rw-r--r--tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs1
-rw-r--r--tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr6
-rw-r--r--tests/ui/recursion/issue-83150.rs2
-rw-r--r--tests/ui/recursion/issue-83150.stderr6
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr2
-rw-r--r--tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs2
-rw-r--r--tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr28
-rw-r--r--tests/ui/rustc_public-ir-print/async-closure.stdout4
-rw-r--r--tests/ui/self/arbitrary_self_type_infinite_recursion.stderr2
-rw-r--r--tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr4
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs2
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr2
-rw-r--r--tests/ui/simd/libm_no_std_cant_float.stderr12
-rw-r--r--tests/ui/statics/conditional-static-declaration-16010.rs (renamed from tests/ui/issues/issue-16452.rs)2
-rw-r--r--tests/ui/stats/macro-stats.rs30
-rw-r--r--tests/ui/stats/macro-stats.stderr7
-rw-r--r--tests/ui/structs/tuple-struct-field-naming-47073.stderr6
-rw-r--r--tests/ui/suggestions/enum-method-probe.fixed12
-rw-r--r--tests/ui/suggestions/enum-method-probe.rs12
-rw-r--r--tests/ui/suggestions/enum-method-probe.stderr12
-rw-r--r--tests/ui/suggestions/field-has-method.rs2
-rw-r--r--tests/ui/suggestions/field-has-method.stderr2
-rw-r--r--tests/ui/suggestions/for-loop-missing-in.fixed7
-rw-r--r--tests/ui/suggestions/for-loop-missing-in.rs7
-rw-r--r--tests/ui/suggestions/for-loop-missing-in.stderr26
-rw-r--r--tests/ui/suggestions/inner_type.fixed10
-rw-r--r--tests/ui/suggestions/inner_type.rs10
-rw-r--r--tests/ui/suggestions/inner_type.stderr10
-rw-r--r--tests/ui/suggestions/inner_type2.rs4
-rw-r--r--tests/ui/suggestions/inner_type2.stderr4
-rw-r--r--tests/ui/test-attrs/issue-12997-2.stderr2
-rw-r--r--tests/ui/test-attrs/test-function-signature.stderr2
-rw-r--r--tests/ui/traits/fn-type-trait-impl-15444.rs (renamed from tests/ui/issues/issue-15444.rs)2
-rw-r--r--tests/ui/traits/index-trait-multiple-impls-15734.rs (renamed from tests/ui/issues/issue-15734.rs)2
-rw-r--r--tests/ui/traits/issue-91949-hangs-on-recursion.rs2
-rw-r--r--tests/ui/traits/issue-91949-hangs-on-recursion.stderr4
-rw-r--r--tests/ui/traits/lifetime-mismatch-trait-impl-16048.rs (renamed from tests/ui/issues/issue-16048.rs)2
-rw-r--r--tests/ui/traits/lifetime-mismatch-trait-impl-16048.stderr (renamed from tests/ui/issues/issue-16048.stderr)4
-rw-r--r--tests/ui/traits/well-formed-recursion-limit.stderr4
-rw-r--r--tests/ui/tuple/index-invalid.stderr6
-rw-r--r--tests/ui/tuple/missing-field-access.rs16
-rw-r--r--tests/ui/tuple/missing-field-access.stderr28
-rw-r--r--tests/ui/tuple/tuple-index-out-of-bounds.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden.rs8
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden.stderr30
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch2.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch2.stderr13
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch3.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch3.stderr13
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.nll.stderr (renamed from tests/ui/wf/hir-wf-check-erase-regions.stderr)8
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.polonius.stderr39
-rw-r--r--tests/ui/wf/hir-wf-check-erase-regions.rs6
488 files changed, 5664 insertions, 4301 deletions
diff --git a/bootstrap.example.toml b/bootstrap.example.toml
index 31966af3301..89da6eeb531 100644
--- a/bootstrap.example.toml
+++ b/bootstrap.example.toml
@@ -740,11 +740,19 @@
 # result (broken, compiling, testing) into this JSON file.
 #rust.save-toolstates = <none> (path)
 
-# This is an array of the codegen backends that will be compiled for the rustc
-# that's being compiled. The default is to only build the LLVM codegen backend,
-# and currently the only standard options supported are `"llvm"`, `"cranelift"`
-# and `"gcc"`. The first backend in this list will be used as default by rustc
-# when no explicit backend is specified.
+# This array serves three distinct purposes:
+# - Backends in this list will be automatically compiled and included in the sysroot of each
+# rustc compiled by bootstrap.
+# - The first backend in this list will be configured as the **default codegen backend** by each
+# rustc compiled by bootstrap. In other words, if the first backend is e.g. cranelift, then when
+# we build a stage 1 rustc, it will by default compile Rust programs using the Cranelift backend.
+# This also means that stage 2 rustc would get built by the Cranelift backend.
+# - Running `x dist` (without additional arguments, or with `--include-default-paths`) will produce
+# a dist component/tarball for the Cranelift backend if it is included in this array.
+#
+# Note that the LLVM codegen backend is special and will always be built and distributed.
+#
+# Currently, the only standard options supported here are `"llvm"`, `"cranelift"` and `"gcc"`.
 #rust.codegen-backends = ["llvm"]
 
 # Indicates whether LLD will be compiled and made available in the sysroot for rustc to execute, and
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index fdff18ffd47..8160ed3cc46 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -35,7 +35,6 @@ use rustc_span::{ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw,
 use thin_vec::{ThinVec, thin_vec};
 
 pub use crate::format::*;
-use crate::ptr::P;
 use crate::token::{self, CommentKind, Delimiter};
 use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
 use crate::util::parser::{ExprPrecedence, Fixity};
@@ -225,7 +224,7 @@ pub struct PathSegment {
     /// `Some` means that parameter list is supplied (`Path<X, Y>`)
     /// but it can be empty (`Path<>`).
     /// `P` is used as a size optimization for the common case with no parameters.
-    pub args: Option<P<GenericArgs>>,
+    pub args: Option<Box<GenericArgs>>,
 }
 
 // Succeeds if the path segment is arg-free and matches the given symbol.
@@ -286,7 +285,7 @@ pub enum GenericArg {
     /// `'a` in `Foo<'a>`.
     Lifetime(#[visitable(extra = LifetimeCtxt::GenericArg)] Lifetime),
     /// `Bar` in `Foo<Bar>`.
-    Type(P<Ty>),
+    Type(Box<Ty>),
     /// `1` in `Foo<1>`.
     Const(AnonConst),
 }
@@ -328,15 +327,15 @@ impl AngleBracketedArg {
     }
 }
 
-impl From<AngleBracketedArgs> for P<GenericArgs> {
+impl From<AngleBracketedArgs> for Box<GenericArgs> {
     fn from(val: AngleBracketedArgs) -> Self {
-        P(GenericArgs::AngleBracketed(val))
+        Box::new(GenericArgs::AngleBracketed(val))
     }
 }
 
-impl From<ParenthesizedArgs> for P<GenericArgs> {
+impl From<ParenthesizedArgs> for Box<GenericArgs> {
     fn from(val: ParenthesizedArgs) -> Self {
-        P(GenericArgs::Parenthesized(val))
+        Box::new(GenericArgs::Parenthesized(val))
     }
 }
 
@@ -350,7 +349,7 @@ pub struct ParenthesizedArgs {
     pub span: Span,
 
     /// `(A, B)`
-    pub inputs: ThinVec<P<Ty>>,
+    pub inputs: ThinVec<Box<Ty>>,
 
     /// ```text
     /// Foo(A, B) -> C
@@ -435,10 +434,10 @@ pub enum GenericParamKind {
     /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
     Lifetime,
     Type {
-        default: Option<P<Ty>>,
+        default: Option<Box<Ty>>,
     },
     Const {
-        ty: P<Ty>,
+        ty: Box<Ty>,
         /// Span of the whole parameter definition, including default.
         span: Span,
         /// Optional default value for the const generic param.
@@ -526,7 +525,7 @@ pub struct WhereBoundPredicate {
     /// Any generics from a `for` binding.
     pub bound_generic_params: ThinVec<GenericParam>,
     /// The type being bounded.
-    pub bounded_ty: P<Ty>,
+    pub bounded_ty: Box<Ty>,
     /// Trait and lifetime bounds (`Clone + Send + 'static`).
     #[visitable(extra = BoundKind::Bound)]
     pub bounds: GenericBounds,
@@ -548,8 +547,8 @@ pub struct WhereRegionPredicate {
 /// E.g., `T = int`.
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct WhereEqPredicate {
-    pub lhs_ty: P<Ty>,
-    pub rhs_ty: P<Ty>,
+    pub lhs_ty: Box<Ty>,
+    pub rhs_ty: Box<Ty>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
@@ -558,7 +557,7 @@ pub struct Crate {
     /// expansion placeholders or an unassigned value (`DUMMY_NODE_ID`) before that.
     pub id: NodeId,
     pub attrs: AttrVec,
-    pub items: ThinVec<P<Item>>,
+    pub items: ThinVec<Box<Item>>,
     pub spans: ModSpans,
     pub is_placeholder: bool,
 }
@@ -638,7 +637,7 @@ pub struct Pat {
 impl Pat {
     /// Attempt reparsing the pattern as a type.
     /// This is intended for use by diagnostics.
-    pub fn to_ty(&self) -> Option<P<Ty>> {
+    pub fn to_ty(&self) -> Option<Box<Ty>> {
         let kind = match &self.kind {
             PatKind::Missing => unreachable!(),
             // In a type expression `_` is an inference variable.
@@ -671,7 +670,7 @@ impl Pat {
             _ => return None,
         };
 
-        Some(P(Ty { kind, id: self.id, span: self.span, tokens: None }))
+        Some(Box::new(Ty { kind, id: self.id, span: self.span, tokens: None }))
     }
 
     /// Walk top-down and call `it` in each place where a pattern occurs
@@ -764,8 +763,8 @@ impl Pat {
     }
 }
 
-impl From<P<Pat>> for Pat {
-    fn from(value: P<Pat>) -> Self {
+impl From<Box<Pat>> for Pat {
+    fn from(value: Box<Pat>) -> Self {
         *value
     }
 }
@@ -780,7 +779,7 @@ pub struct PatField {
     /// The identifier for the field.
     pub ident: Ident,
     /// The pattern the field is destructured to.
-    pub pat: P<Pat>,
+    pub pat: Box<Pat>,
     pub is_shorthand: bool,
     pub attrs: AttrVec,
     pub id: NodeId,
@@ -865,44 +864,44 @@ pub enum PatKind {
     /// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
     /// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
     /// during name resolution.
-    Ident(BindingMode, Ident, Option<P<Pat>>),
+    Ident(BindingMode, Ident, Option<Box<Pat>>),
 
     /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
-    Struct(Option<P<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),
+    Struct(Option<Box<QSelf>>, Path, ThinVec<PatField>, PatFieldsRest),
 
     /// A tuple struct/variant pattern (`Variant(x, y, .., z)`).
-    TupleStruct(Option<P<QSelf>>, Path, ThinVec<P<Pat>>),
+    TupleStruct(Option<Box<QSelf>>, Path, ThinVec<Box<Pat>>),
 
     /// An or-pattern `A | B | C`.
     /// Invariant: `pats.len() >= 2`.
-    Or(ThinVec<P<Pat>>),
+    Or(ThinVec<Box<Pat>>),
 
     /// A possibly qualified path pattern.
     /// Unqualified path patterns `A::B::C` can legally refer to variants, structs, constants
     /// or associated constants. Qualified path patterns `<A>::B::C`/`<A as Trait>::B::C` can
     /// only legally refer to associated constants.
-    Path(Option<P<QSelf>>, Path),
+    Path(Option<Box<QSelf>>, Path),
 
     /// A tuple pattern (`(a, b)`).
-    Tuple(ThinVec<P<Pat>>),
+    Tuple(ThinVec<Box<Pat>>),
 
     /// A `box` pattern.
-    Box(P<Pat>),
+    Box(Box<Pat>),
 
     /// A `deref` pattern (currently `deref!()` macro-based syntax).
-    Deref(P<Pat>),
+    Deref(Box<Pat>),
 
     /// A reference pattern (e.g., `&mut (a, b)`).
-    Ref(P<Pat>, Mutability),
+    Ref(Box<Pat>, Mutability),
 
     /// A literal, const block or path.
-    Expr(P<Expr>),
+    Expr(Box<Expr>),
 
     /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
-    Range(Option<P<Expr>>, Option<P<Expr>>, Spanned<RangeEnd>),
+    Range(Option<Box<Expr>>, Option<Box<Expr>>, Spanned<RangeEnd>),
 
     /// A slice pattern `[a, b, c]`.
-    Slice(ThinVec<P<Pat>>),
+    Slice(ThinVec<Box<Pat>>),
 
     /// A rest pattern `..`.
     ///
@@ -922,13 +921,13 @@ pub enum PatKind {
     Never,
 
     /// A guard pattern (e.g., `x if guard(x)`).
-    Guard(P<Pat>, P<Expr>),
+    Guard(Box<Pat>, Box<Expr>),
 
     /// Parentheses in patterns used for grouping (i.e., `(PAT)`).
-    Paren(P<Pat>),
+    Paren(Box<Pat>),
 
     /// A macro pattern; pre-expansion.
-    MacCall(P<MacCall>),
+    MacCall(Box<MacCall>),
 
     /// Placeholder for a pattern that wasn't syntactically well formed in some way.
     Err(ErrorGuaranteed),
@@ -1223,22 +1222,22 @@ impl Stmt {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub enum StmtKind {
     /// A local (let) binding.
-    Let(P<Local>),
+    Let(Box<Local>),
     /// An item definition.
-    Item(P<Item>),
+    Item(Box<Item>),
     /// Expr without trailing semi-colon.
-    Expr(P<Expr>),
+    Expr(Box<Expr>),
     /// Expr with a trailing semi-colon.
-    Semi(P<Expr>),
+    Semi(Box<Expr>),
     /// Just a trailing semi-colon.
     Empty,
     /// Macro.
-    MacCall(P<MacCallStmt>),
+    MacCall(Box<MacCallStmt>),
 }
 
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct MacCallStmt {
-    pub mac: P<MacCall>,
+    pub mac: Box<MacCall>,
     pub style: MacStmtStyle,
     pub attrs: AttrVec,
     pub tokens: Option<LazyAttrTokenStream>,
@@ -1262,8 +1261,8 @@ pub enum MacStmtStyle {
 pub struct Local {
     pub id: NodeId,
     pub super_: Option<Span>,
-    pub pat: P<Pat>,
-    pub ty: Option<P<Ty>>,
+    pub pat: Box<Pat>,
+    pub ty: Option<Box<Ty>>,
     pub kind: LocalKind,
     pub span: Span,
     pub colon_sp: Option<Span>,
@@ -1278,10 +1277,10 @@ pub enum LocalKind {
     Decl,
     /// Local declaration with an initializer.
     /// Example: `let x = y;`
-    Init(P<Expr>),
+    Init(Box<Expr>),
     /// Local declaration with an initializer and an `else` clause.
     /// Example: `let Some(x) = y else { return };`
-    InitElse(P<Expr>, P<Block>),
+    InitElse(Box<Expr>, Box<Block>),
 }
 
 impl LocalKind {
@@ -1315,11 +1314,11 @@ impl LocalKind {
 pub struct Arm {
     pub attrs: AttrVec,
     /// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`.
-    pub pat: P<Pat>,
+    pub pat: Box<Pat>,
     /// Match arm guard, e.g. `n > 10` in `match foo { n if n > 10 => {}, _ => {} }`.
-    pub guard: Option<P<Expr>>,
+    pub guard: Option<Box<Expr>>,
     /// Match arm body. Omitted if the pattern is a never pattern.
-    pub body: Option<P<Expr>>,
+    pub body: Option<Box<Expr>>,
     pub span: Span,
     pub id: NodeId,
     pub is_placeholder: bool,
@@ -1332,7 +1331,7 @@ pub struct ExprField {
     pub id: NodeId,
     pub span: Span,
     pub ident: Ident,
-    pub expr: P<Expr>,
+    pub expr: Box<Expr>,
     pub is_shorthand: bool,
     pub is_placeholder: bool,
 }
@@ -1357,7 +1356,7 @@ pub enum UnsafeSource {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct AnonConst {
     pub id: NodeId,
-    pub value: P<Expr>,
+    pub value: Box<Expr>,
 }
 
 /// An expression.
@@ -1469,7 +1468,7 @@ impl Expr {
     }
 
     /// Attempts to reparse as `Ty` (for diagnostic purposes).
-    pub fn to_ty(&self) -> Option<P<Ty>> {
+    pub fn to_ty(&self) -> Option<Box<Ty>> {
         let kind = match &self.kind {
             // Trivial conversions.
             ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
@@ -1511,7 +1510,7 @@ impl Expr {
             _ => return None,
         };
 
-        Some(P(Ty { kind, id: self.id, span: self.span, tokens: None }))
+        Some(Box::new(Ty { kind, id: self.id, span: self.span, tokens: None }))
     }
 
     pub fn precedence(&self) -> ExprPrecedence {
@@ -1632,8 +1631,8 @@ impl Expr {
     }
 }
 
-impl From<P<Expr>> for Expr {
-    fn from(value: P<Expr>) -> Self {
+impl From<Box<Expr>> for Expr {
+    fn from(value: Box<Expr>) -> Self {
         *value
     }
 }
@@ -1645,8 +1644,8 @@ pub struct Closure {
     pub constness: Const,
     pub coroutine_kind: Option<CoroutineKind>,
     pub movability: Movability,
-    pub fn_decl: P<FnDecl>,
-    pub body: P<Expr>,
+    pub fn_decl: Box<FnDecl>,
+    pub body: Box<Expr>,
     /// The span of the declaration block: 'move |...| -> ...'
     pub fn_decl_span: Span,
     /// The span of the argument block `|...|`
@@ -1677,9 +1676,9 @@ pub struct MethodCall {
     /// The method name and its generic arguments, e.g. `foo::<Bar, Baz>`.
     pub seg: PathSegment,
     /// The receiver, e.g. `x`.
-    pub receiver: P<Expr>,
+    pub receiver: Box<Expr>,
     /// The arguments, e.g. `a, b, c`.
-    pub args: ThinVec<P<Expr>>,
+    pub args: ThinVec<Box<Expr>>,
     /// The span of the function, without the dot and receiver e.g. `foo::<Bar,
     /// Baz>(a, b, c)`.
     pub span: Span,
@@ -1688,7 +1687,7 @@ pub struct MethodCall {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub enum StructRest {
     /// `..x`.
-    Base(P<Expr>),
+    Base(Box<Expr>),
     /// `..`.
     Rest(Span),
     /// No trailing `..` or expression.
@@ -1697,7 +1696,7 @@ pub enum StructRest {
 
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct StructExpr {
-    pub qself: Option<P<QSelf>>,
+    pub qself: Option<Box<QSelf>>,
     pub path: Path,
     pub fields: ThinVec<ExprField>,
     pub rest: StructRest,
@@ -1707,7 +1706,7 @@ pub struct StructExpr {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum ExprKind {
     /// An array (e.g, `[a, b, c, d]`).
-    Array(ThinVec<P<Expr>>),
+    Array(ThinVec<Box<Expr>>),
     /// Allow anonymous constants from an inline `const` block.
     ConstBlock(AnonConst),
     /// A function call.
@@ -1716,90 +1715,90 @@ pub enum ExprKind {
     /// and the second field is the list of arguments.
     /// This also represents calling the constructor of
     /// tuple-like ADTs such as tuple structs and enum variants.
-    Call(P<Expr>, ThinVec<P<Expr>>),
+    Call(Box<Expr>, ThinVec<Box<Expr>>),
     /// A method call (e.g., `x.foo::<Bar, Baz>(a, b, c)`).
     MethodCall(Box<MethodCall>),
     /// A tuple (e.g., `(a, b, c, d)`).
-    Tup(ThinVec<P<Expr>>),
+    Tup(ThinVec<Box<Expr>>),
     /// A binary operation (e.g., `a + b`, `a * b`).
-    Binary(BinOp, P<Expr>, P<Expr>),
+    Binary(BinOp, Box<Expr>, Box<Expr>),
     /// A unary operation (e.g., `!x`, `*x`).
-    Unary(UnOp, P<Expr>),
+    Unary(UnOp, Box<Expr>),
     /// A literal (e.g., `1`, `"foo"`).
     Lit(token::Lit),
     /// A cast (e.g., `foo as f64`).
-    Cast(P<Expr>, P<Ty>),
+    Cast(Box<Expr>, Box<Ty>),
     /// A type ascription (e.g., `builtin # type_ascribe(42, usize)`).
     ///
     /// Usually not written directly in user code but
     /// indirectly via the macro `type_ascribe!(...)`.
-    Type(P<Expr>, P<Ty>),
+    Type(Box<Expr>, Box<Ty>),
     /// A `let pat = expr` expression that is only semantically allowed in the condition
     /// of `if` / `while` expressions. (e.g., `if let 0 = x { .. }`).
     ///
     /// `Span` represents the whole `let pat = expr` statement.
-    Let(P<Pat>, P<Expr>, Span, Recovered),
+    Let(Box<Pat>, Box<Expr>, Span, Recovered),
     /// An `if` block, with an optional `else` block.
     ///
     /// `if expr { block } else { expr }`
     ///
     /// If present, the "else" expr is always `ExprKind::Block` (for `else`) or
     /// `ExprKind::If` (for `else if`).
-    If(P<Expr>, P<Block>, Option<P<Expr>>),
+    If(Box<Expr>, Box<Block>, Option<Box<Expr>>),
     /// A while loop, with an optional label.
     ///
     /// `'label: while expr { block }`
-    While(P<Expr>, P<Block>, Option<Label>),
+    While(Box<Expr>, Box<Block>, Option<Label>),
     /// A `for` loop, with an optional label.
     ///
     /// `'label: for await? pat in iter { block }`
     ///
     /// This is desugared to a combination of `loop` and `match` expressions.
     ForLoop {
-        pat: P<Pat>,
-        iter: P<Expr>,
-        body: P<Block>,
+        pat: Box<Pat>,
+        iter: Box<Expr>,
+        body: Box<Block>,
         label: Option<Label>,
         kind: ForLoopKind,
     },
     /// Conditionless loop (can be exited with `break`, `continue`, or `return`).
     ///
     /// `'label: loop { block }`
-    Loop(P<Block>, Option<Label>, Span),
+    Loop(Box<Block>, Option<Label>, Span),
     /// A `match` block.
-    Match(P<Expr>, ThinVec<Arm>, MatchKind),
+    Match(Box<Expr>, ThinVec<Arm>, MatchKind),
     /// A closure (e.g., `move |a, b, c| a + b + c`).
     Closure(Box<Closure>),
     /// A block (`'label: { ... }`).
-    Block(P<Block>, Option<Label>),
+    Block(Box<Block>, Option<Label>),
     /// An `async` block (`async move { ... }`),
     /// or a `gen` block (`gen move { ... }`).
     ///
     /// The span is the "decl", which is the header before the body `{ }`
     /// including the `asyng`/`gen` keywords and possibly `move`.
-    Gen(CaptureBy, P<Block>, GenBlockKind, Span),
+    Gen(CaptureBy, Box<Block>, GenBlockKind, Span),
     /// An await expression (`my_future.await`). Span is of await keyword.
-    Await(P<Expr>, Span),
+    Await(Box<Expr>, Span),
     /// A use expression (`x.use`). Span is of use keyword.
-    Use(P<Expr>, Span),
+    Use(Box<Expr>, Span),
 
     /// A try block (`try { ... }`).
-    TryBlock(P<Block>),
+    TryBlock(Box<Block>),
 
     /// An assignment (`a = foo()`).
     /// The `Span` argument is the span of the `=` token.
-    Assign(P<Expr>, P<Expr>, Span),
+    Assign(Box<Expr>, Box<Expr>, Span),
     /// An assignment with an operator.
     ///
     /// E.g., `a += 1`.
-    AssignOp(AssignOp, P<Expr>, P<Expr>),
+    AssignOp(AssignOp, Box<Expr>, Box<Expr>),
     /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
-    Field(P<Expr>, Ident),
+    Field(Box<Expr>, Ident),
     /// An indexing operation (e.g., `foo[2]`).
     /// The span represents the span of the `[2]`, including brackets.
-    Index(P<Expr>, P<Expr>, Span),
+    Index(Box<Expr>, Box<Expr>, Span),
     /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assignment).
-    Range(Option<P<Expr>>, Option<P<Expr>>, RangeLimits),
+    Range(Option<Box<Expr>>, Option<Box<Expr>>, RangeLimits),
     /// An underscore, used in destructuring assignment to ignore a value.
     Underscore,
 
@@ -1807,57 +1806,57 @@ pub enum ExprKind {
     /// parameters (e.g., `foo::bar::<baz>`).
     ///
     /// Optionally "qualified" (e.g., `<Vec<T> as SomeTrait>::SomeType`).
-    Path(Option<P<QSelf>>, Path),
+    Path(Option<Box<QSelf>>, Path),
 
     /// A referencing operation (`&a`, `&mut a`, `&raw const a` or `&raw mut a`).
-    AddrOf(BorrowKind, Mutability, P<Expr>),
+    AddrOf(BorrowKind, Mutability, Box<Expr>),
     /// A `break`, with an optional label to break, and an optional expression.
-    Break(Option<Label>, Option<P<Expr>>),
+    Break(Option<Label>, Option<Box<Expr>>),
     /// A `continue`, with an optional label.
     Continue(Option<Label>),
     /// A `return`, with an optional value to be returned.
-    Ret(Option<P<Expr>>),
+    Ret(Option<Box<Expr>>),
 
     /// Output of the `asm!()` macro.
-    InlineAsm(P<InlineAsm>),
+    InlineAsm(Box<InlineAsm>),
 
     /// An `offset_of` expression (e.g., `builtin # offset_of(Struct, field)`).
     ///
     /// Usually not written directly in user code but
     /// indirectly via the macro `core::mem::offset_of!(...)`.
-    OffsetOf(P<Ty>, Vec<Ident>),
+    OffsetOf(Box<Ty>, Vec<Ident>),
 
     /// A macro invocation; pre-expansion.
-    MacCall(P<MacCall>),
+    MacCall(Box<MacCall>),
 
     /// A struct literal expression.
     ///
     /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. rest}`.
-    Struct(P<StructExpr>),
+    Struct(Box<StructExpr>),
 
     /// An array literal constructed from one repeated element.
     ///
     /// E.g., `[1; 5]`. The expression is the element to be
     /// repeated; the constant is the number of times to repeat it.
-    Repeat(P<Expr>, AnonConst),
+    Repeat(Box<Expr>, AnonConst),
 
     /// No-op: used solely so we can pretty-print faithfully.
-    Paren(P<Expr>),
+    Paren(Box<Expr>),
 
     /// A try expression (`expr?`).
-    Try(P<Expr>),
+    Try(Box<Expr>),
 
     /// A `yield`, with an optional value to be yielded.
     Yield(YieldKind),
 
     /// A `do yeet` (aka `throw`/`fail`/`bail`/`raise`/whatever),
     /// with an optional value to be returned.
-    Yeet(Option<P<Expr>>),
+    Yeet(Option<Box<Expr>>),
 
     /// A tail call return, with the value to be returned.
     ///
     /// While `.0` must be a function call, we check this later, after parsing.
-    Become(P<Expr>),
+    Become(Box<Expr>),
 
     /// Bytes included via `include_bytes!`
     ///
@@ -1873,9 +1872,9 @@ pub enum ExprKind {
     IncludedBytes(ByteSymbol),
 
     /// A `format_args!()` expression.
-    FormatArgs(P<FormatArgs>),
+    FormatArgs(Box<FormatArgs>),
 
-    UnsafeBinderCast(UnsafeBinderCastKind, P<Expr>, Option<P<Ty>>),
+    UnsafeBinderCast(UnsafeBinderCastKind, Box<Expr>, Option<Box<Ty>>),
 
     /// Placeholder for an expression that wasn't syntactically well formed in some way.
     Err(ErrorGuaranteed),
@@ -1941,7 +1940,7 @@ pub enum UnsafeBinderCastKind {
 /// ```
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct QSelf {
-    pub ty: P<Ty>,
+    pub ty: Box<Ty>,
 
     /// The span of `a::b::Trait` in a path like `<Vec<T> as
     /// a::b::Trait>::AssociatedItem`; in the case where `position ==
@@ -2001,7 +2000,7 @@ pub enum ClosureBinder {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct MacCall {
     pub path: Path,
-    pub args: P<DelimArgs>,
+    pub args: Box<DelimArgs>,
 }
 
 impl MacCall {
@@ -2021,7 +2020,7 @@ pub enum AttrArgs {
     Eq {
         /// Span of the `=` token.
         eq_span: Span,
-        expr: P<Expr>,
+        expr: Box<Expr>,
     },
 }
 
@@ -2064,7 +2063,7 @@ impl DelimArgs {
 /// Represents a macro definition.
 #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic, Walkable)]
 pub struct MacroDef {
-    pub body: P<DelimArgs>,
+    pub body: Box<DelimArgs>,
     /// `true` if macro was defined with `macro_rules`.
     pub macro_rules: bool,
 }
@@ -2093,16 +2092,16 @@ pub enum MatchKind {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub enum YieldKind {
     /// yield expr { ... }
-    Prefix(Option<P<Expr>>),
+    Prefix(Option<Box<Expr>>),
     /// expr.yield { ... }
-    Postfix(P<Expr>),
+    Postfix(Box<Expr>),
 }
 
 impl YieldKind {
     /// Returns the expression inside the yield expression, if any.
     ///
     /// For postfix yields, this is guaranteed to be `Some`.
-    pub const fn expr(&self) -> Option<&P<Expr>> {
+    pub const fn expr(&self) -> Option<&Box<Expr>> {
         match self {
             YieldKind::Prefix(expr) => expr.as_ref(),
             YieldKind::Postfix(expr) => Some(expr),
@@ -2110,7 +2109,7 @@ impl YieldKind {
     }
 
     /// Returns a mutable reference to the expression being yielded, if any.
-    pub const fn expr_mut(&mut self) -> Option<&mut P<Expr>> {
+    pub const fn expr_mut(&mut self) -> Option<&mut Box<Expr>> {
         match self {
             YieldKind::Prefix(expr) => expr.as_mut(),
             YieldKind::Postfix(expr) => Some(expr),
@@ -2272,7 +2271,7 @@ impl LitKind {
 // type structure in `middle/ty.rs` as well.
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct MutTy {
-    pub ty: P<Ty>,
+    pub ty: Box<Ty>,
     pub mutbl: Mutability,
 }
 
@@ -2281,7 +2280,7 @@ pub struct MutTy {
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct FnSig {
     pub header: FnHeader,
-    pub decl: P<FnDecl>,
+    pub decl: Box<FnDecl>,
     pub span: Span,
 }
 
@@ -2306,12 +2305,12 @@ pub struct AssocItemConstraint {
 
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub enum Term {
-    Ty(P<Ty>),
+    Ty(Box<Ty>),
     Const(AnonConst),
 }
 
-impl From<P<Ty>> for Term {
-    fn from(v: P<Ty>) -> Self {
+impl From<Box<Ty>> for Term {
+    fn from(v: Box<Ty>) -> Self {
         Term::Ty(v)
     }
 }
@@ -2358,8 +2357,8 @@ impl Clone for Ty {
     }
 }
 
-impl From<P<Ty>> for Ty {
-    fn from(value: P<Ty>) -> Self {
+impl From<Box<Ty>> for Ty {
+    fn from(value: Box<Ty>) -> Self {
         *value
     }
 }
@@ -2388,7 +2387,7 @@ pub struct FnPtrTy {
     pub safety: Safety,
     pub ext: Extern,
     pub generic_params: ThinVec<GenericParam>,
-    pub decl: P<FnDecl>,
+    pub decl: Box<FnDecl>,
     /// Span of the `[unsafe] [extern] fn(...) -> ...` part, i.e. everything
     /// after the generic params (if there are any, e.g. `for<'a>`).
     pub decl_span: Span,
@@ -2397,7 +2396,7 @@ pub struct FnPtrTy {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct UnsafeBinderTy {
     pub generic_params: ThinVec<GenericParam>,
-    pub inner_ty: P<Ty>,
+    pub inner_ty: Box<Ty>,
 }
 
 /// The various kinds of type recognized by the compiler.
@@ -2406,9 +2405,9 @@ pub struct UnsafeBinderTy {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub enum TyKind {
     /// A variable-length slice (`[T]`).
-    Slice(P<Ty>),
+    Slice(Box<Ty>),
     /// A fixed length array (`[T; n]`).
-    Array(P<Ty>, AnonConst),
+    Array(Box<Ty>, AnonConst),
     /// A raw pointer (`*const T` or `*mut T`).
     Ptr(MutTy),
     /// A reference (`&'a T` or `&'a mut T`).
@@ -2418,18 +2417,18 @@ pub enum TyKind {
     /// Desugars into `Pin<&'a T>` or `Pin<&'a mut T>`.
     PinnedRef(#[visitable(extra = LifetimeCtxt::Ref)] Option<Lifetime>, MutTy),
     /// A function pointer type (e.g., `fn(usize) -> bool`).
-    FnPtr(P<FnPtrTy>),
+    FnPtr(Box<FnPtrTy>),
     /// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`).
-    UnsafeBinder(P<UnsafeBinderTy>),
+    UnsafeBinder(Box<UnsafeBinderTy>),
     /// The never type (`!`).
     Never,
     /// A tuple (`(A, B, C, D,...)`).
-    Tup(ThinVec<P<Ty>>),
+    Tup(ThinVec<Box<Ty>>),
     /// A path (`module::module::...::Type`), optionally
     /// "qualified", e.g., `<Vec<T> as SomeTrait>::SomeType`.
     ///
     /// Type parameters are stored in the `Path` itself.
-    Path(Option<P<QSelf>>, Path),
+    Path(Option<Box<QSelf>>, Path),
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
     TraitObject(#[visitable(extra = BoundKind::TraitObject)] GenericBounds, TraitObjectSyntax),
@@ -2441,7 +2440,7 @@ pub enum TyKind {
     /// the generation of opaque `type Foo = impl Trait` items significantly.
     ImplTrait(NodeId, #[visitable(extra = BoundKind::Impl)] GenericBounds),
     /// No-op; kept solely so that we can pretty-print faithfully.
-    Paren(P<Ty>),
+    Paren(Box<Ty>),
     /// Unused for now.
     Typeof(AnonConst),
     /// This means the type should be inferred instead of it having been
@@ -2450,12 +2449,12 @@ pub enum TyKind {
     /// Inferred type of a `self` or `&self` argument in a method.
     ImplicitSelf,
     /// A macro in the type position.
-    MacCall(P<MacCall>),
+    MacCall(Box<MacCall>),
     /// Placeholder for a `va_list`.
     CVarArgs,
     /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`,
     /// just as part of the type system.
-    Pat(P<Ty>, P<TyPat>),
+    Pat(Box<Ty>, Box<TyPat>),
     /// Sometimes we need a dummy value when no error has occurred.
     Dummy,
     /// Placeholder for a kind that has failed to be defined.
@@ -2531,9 +2530,9 @@ pub struct TyPat {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub enum TyPatKind {
     /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
-    Range(Option<P<AnonConst>>, Option<P<AnonConst>>, Spanned<RangeEnd>),
+    Range(Option<Box<AnonConst>>, Option<Box<AnonConst>>, Spanned<RangeEnd>),
 
-    Or(ThinVec<P<TyPat>>),
+    Or(ThinVec<Box<TyPat>>),
 
     /// Placeholder for a pattern that wasn't syntactically well formed in some way.
     Err(ErrorGuaranteed),
@@ -2698,7 +2697,7 @@ impl InlineAsmTemplatePiece {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct InlineAsmSym {
     pub id: NodeId,
-    pub qself: Option<P<QSelf>>,
+    pub qself: Option<Box<QSelf>>,
     pub path: Path,
 }
 
@@ -2709,23 +2708,23 @@ pub struct InlineAsmSym {
 pub enum InlineAsmOperand {
     In {
         reg: InlineAsmRegOrRegClass,
-        expr: P<Expr>,
+        expr: Box<Expr>,
     },
     Out {
         reg: InlineAsmRegOrRegClass,
         late: bool,
-        expr: Option<P<Expr>>,
+        expr: Option<Box<Expr>>,
     },
     InOut {
         reg: InlineAsmRegOrRegClass,
         late: bool,
-        expr: P<Expr>,
+        expr: Box<Expr>,
     },
     SplitInOut {
         reg: InlineAsmRegOrRegClass,
         late: bool,
-        in_expr: P<Expr>,
-        out_expr: Option<P<Expr>>,
+        in_expr: Box<Expr>,
+        out_expr: Option<Box<Expr>>,
     },
     Const {
         anon_const: AnonConst,
@@ -2734,7 +2733,7 @@ pub enum InlineAsmOperand {
         sym: InlineAsmSym,
     },
     Label {
-        block: P<Block>,
+        block: Box<Block>,
     },
 }
 
@@ -2807,8 +2806,8 @@ pub struct InlineAsm {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct Param {
     pub attrs: AttrVec,
-    pub ty: P<Ty>,
-    pub pat: P<Pat>,
+    pub ty: Box<Ty>,
+    pub pat: Box<Pat>,
     pub id: NodeId,
     pub span: Span,
     pub is_placeholder: bool,
@@ -2826,7 +2825,7 @@ pub enum SelfKind {
     /// `&'lt pin const self`, `&'lt pin mut self`
     Pinned(Option<Lifetime>, Mutability),
     /// `self: TYPE`, `mut self: TYPE`
-    Explicit(P<Ty>, Mutability),
+    Explicit(Box<Ty>, Mutability),
 }
 
 impl SelfKind {
@@ -2882,7 +2881,7 @@ impl Param {
     /// Builds a `Param` object from `ExplicitSelf`.
     pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param {
         let span = eself.span.to(eself_ident.span);
-        let infer_ty = P(Ty {
+        let infer_ty = Box::new(Ty {
             id: DUMMY_NODE_ID,
             kind: TyKind::ImplicitSelf,
             span: eself_ident.span,
@@ -2893,7 +2892,7 @@ impl Param {
             SelfKind::Value(mutbl) => (mutbl, infer_ty),
             SelfKind::Region(lt, mutbl) => (
                 Mutability::Not,
-                P(Ty {
+                Box::new(Ty {
                     id: DUMMY_NODE_ID,
                     kind: TyKind::Ref(lt, MutTy { ty: infer_ty, mutbl }),
                     span,
@@ -2902,7 +2901,7 @@ impl Param {
             ),
             SelfKind::Pinned(lt, mutbl) => (
                 mutbl,
-                P(Ty {
+                Box::new(Ty {
                     id: DUMMY_NODE_ID,
                     kind: TyKind::PinnedRef(lt, MutTy { ty: infer_ty, mutbl }),
                     span,
@@ -2912,7 +2911,7 @@ impl Param {
         };
         Param {
             attrs,
-            pat: P(Pat {
+            pat: Box::new(Pat {
                 id: DUMMY_NODE_ID,
                 kind: PatKind::Ident(BindingMode(ByRef::No, mutbl), eself_ident, None),
                 span,
@@ -3123,7 +3122,7 @@ pub enum FnRetTy {
     /// Span points to where return type would be inserted.
     Default(Span),
     /// Everything else.
-    Ty(P<Ty>),
+    Ty(Box<Ty>),
 }
 
 impl FnRetTy {
@@ -3148,7 +3147,7 @@ pub enum ModKind {
     /// or with definition outlined to a separate file `mod foo;` and already loaded from it.
     /// The inner span is from the first token past `{` to the last token until `}`,
     /// or from the first to the last token in the loaded file.
-    Loaded(ThinVec<P<Item>>, Inline, ModSpans, Result<(), ErrorGuaranteed>),
+    Loaded(ThinVec<Box<Item>>, Inline, ModSpans, Result<(), ErrorGuaranteed>),
     /// Module with definition outlined to a separate file `mod foo;` but not yet loaded from it.
     Unloaded,
 }
@@ -3172,7 +3171,7 @@ pub struct ForeignMod {
     /// semantically by Rust.
     pub safety: Safety,
     pub abi: Option<StrLit>,
-    pub items: ThinVec<P<ForeignItem>>,
+    pub items: ThinVec<Box<ForeignItem>>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
@@ -3267,7 +3266,7 @@ pub struct Attribute {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub enum AttrKind {
     /// A normal attribute.
-    Normal(P<NormalAttr>),
+    Normal(Box<NormalAttr>),
 
     /// A doc comment (e.g. `/// ...`, `//! ...`, `/** ... */`, `/*! ... */`).
     /// Doc attributes (e.g. `#[doc="..."]`) are represented with the `Normal`
@@ -3381,7 +3380,7 @@ pub struct Visibility {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub enum VisibilityKind {
     Public,
-    Restricted { path: P<Path>, id: NodeId, shorthand: bool },
+    Restricted { path: Box<Path>, id: NodeId, shorthand: bool },
     Inherited,
 }
 
@@ -3403,7 +3402,7 @@ pub struct FieldDef {
     pub safety: Safety,
     pub ident: Option<Ident>,
 
-    pub ty: P<Ty>,
+    pub ty: Box<Ty>,
     pub default: Option<AnonConst>,
     pub is_placeholder: bool,
 }
@@ -3609,7 +3608,7 @@ pub struct Trait {
     #[visitable(extra = BoundKind::SuperTraits)]
     pub bounds: GenericBounds,
     #[visitable(extra = AssocCtxt::Trait)]
-    pub items: ThinVec<P<AssocItem>>,
+    pub items: ThinVec<Box<AssocItem>>,
 }
 
 /// The location of a where clause on a `TyAlias` (`Span`) and whether there was
@@ -3657,7 +3656,7 @@ pub struct TyAlias {
     pub where_clauses: TyAliasWhereClauses,
     #[visitable(extra = BoundKind::Bound)]
     pub bounds: GenericBounds,
-    pub ty: Option<P<Ty>>,
+    pub ty: Option<Box<Ty>>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
@@ -3669,14 +3668,14 @@ pub struct Impl {
     pub polarity: ImplPolarity,
     /// The trait being implemented, if any.
     pub of_trait: Option<TraitRef>,
-    pub self_ty: P<Ty>,
-    pub items: ThinVec<P<AssocItem>>,
+    pub self_ty: Box<Ty>,
+    pub items: ThinVec<Box<AssocItem>>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug, Default, Walkable)]
 pub struct FnContract {
-    pub requires: Option<P<Expr>>,
-    pub ensures: Option<P<Expr>>,
+    pub requires: Option<Box<Expr>>,
+    pub ensures: Option<Box<Expr>>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug)]
@@ -3685,40 +3684,40 @@ pub struct Fn {
     pub ident: Ident,
     pub generics: Generics,
     pub sig: FnSig,
-    pub contract: Option<P<FnContract>>,
+    pub contract: Option<Box<FnContract>>,
     pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
-    pub body: Option<P<Block>>,
+    pub body: Option<Box<Block>>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct Delegation {
     /// Path resolution id.
     pub id: NodeId,
-    pub qself: Option<P<QSelf>>,
+    pub qself: Option<Box<QSelf>>,
     pub path: Path,
     pub ident: Ident,
     pub rename: Option<Ident>,
-    pub body: Option<P<Block>>,
+    pub body: Option<Box<Block>>,
     /// The item was expanded from a glob delegation item.
     pub from_glob: bool,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct DelegationMac {
-    pub qself: Option<P<QSelf>>,
+    pub qself: Option<Box<QSelf>>,
     pub prefix: Path,
     // Some for list delegation, and None for glob delegation.
     pub suffixes: Option<ThinVec<(Ident, Option<Ident>)>>,
-    pub body: Option<P<Block>>,
+    pub body: Option<Box<Block>>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct StaticItem {
     pub ident: Ident,
-    pub ty: P<Ty>,
+    pub ty: Box<Ty>,
     pub safety: Safety,
     pub mutability: Mutability,
-    pub expr: Option<P<Expr>>,
+    pub expr: Option<Box<Expr>>,
     pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
 }
 
@@ -3727,8 +3726,8 @@ pub struct ConstItem {
     pub defaultness: Defaultness,
     pub ident: Ident,
     pub generics: Generics,
-    pub ty: P<Ty>,
-    pub expr: Option<P<Expr>>,
+    pub ty: Box<Ty>,
+    pub expr: Option<Box<Expr>>,
     pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
 }
 
@@ -3798,7 +3797,7 @@ pub enum ItemKind {
     /// A macro invocation.
     ///
     /// E.g., `foo!(..)`.
-    MacCall(P<MacCall>),
+    MacCall(Box<MacCall>),
     /// A macro definition.
     MacroDef(Ident, MacroDef),
     /// A single delegation item (`reuse`).
@@ -3908,7 +3907,7 @@ pub enum AssocItemKind {
     /// An associated type.
     Type(Box<TyAlias>),
     /// A macro expanding to associated items.
-    MacCall(P<MacCall>),
+    MacCall(Box<MacCall>),
     /// An associated delegation item.
     Delegation(Box<Delegation>),
     /// An associated list or glob delegation item.
@@ -3978,7 +3977,7 @@ pub enum ForeignItemKind {
     /// A foreign type.
     TyAlias(Box<TyAlias>),
     /// A macro expanding to foreign items.
-    MacCall(P<MacCall>),
+    MacCall(Box<MacCall>),
 }
 
 impl ForeignItemKind {
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 9d91f41d6c7..3d2477e5f03 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -5,7 +5,6 @@
 use std::fmt;
 use std::marker::PhantomData;
 
-use crate::ptr::P;
 use crate::tokenstream::LazyAttrTokenStream;
 use crate::{
     Arm, AssocItem, AttrItem, AttrKind, AttrVec, Attribute, Block, Crate, Expr, ExprField,
@@ -53,7 +52,7 @@ impl_has_node_id!(
     WherePredicate,
 );
 
-impl<T: HasNodeId> HasNodeId for P<T> {
+impl<T: HasNodeId> HasNodeId for Box<T> {
     fn node_id(&self) -> NodeId {
         (**self).node_id()
     }
@@ -119,7 +118,7 @@ impl<T: HasTokens> HasTokens for Option<T> {
     }
 }
 
-impl<T: HasTokens> HasTokens for P<T> {
+impl<T: HasTokens> HasTokens for Box<T> {
     fn tokens(&self) -> Option<&LazyAttrTokenStream> {
         (**self).tokens()
     }
@@ -245,7 +244,7 @@ impl_has_attrs!(
 );
 impl_has_attrs_none!(Attribute, AttrItem, Block, Pat, Path, Ty, Visibility);
 
-impl<T: HasAttrs> HasAttrs for P<T> {
+impl<T: HasAttrs> HasAttrs for Box<T> {
     const SUPPORTS_CUSTOM_INNER_ATTRS: bool = T::SUPPORTS_CUSTOM_INNER_ATTRS;
     fn attrs(&self) -> &[Attribute] {
         (**self).attrs()
@@ -322,8 +321,8 @@ impl<Wrapped, Tag> AstNodeWrapper<Wrapped, Tag> {
 }
 
 // FIXME: remove after `stmt_expr_attributes` is stabilized.
-impl<T, Tag> From<AstNodeWrapper<P<T>, Tag>> for AstNodeWrapper<T, Tag> {
-    fn from(value: AstNodeWrapper<P<T>, Tag>) -> Self {
+impl<T, Tag> From<AstNodeWrapper<Box<T>, Tag>> for AstNodeWrapper<T, Tag> {
+    fn from(value: AstNodeWrapper<Box<T>, Tag>) -> Self {
         AstNodeWrapper { wrapped: *value.wrapped, tag: value.tag }
     }
 }
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 4348a4bb120..6ada93b4c89 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -13,7 +13,6 @@ use crate::ast::{
     Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NormalAttr, Path,
     PathSegment, Safety,
 };
-use crate::ptr::P;
 use crate::token::{self, CommentKind, Delimiter, InvisibleOrigin, MetaVarKind, Token};
 use crate::tokenstream::{
     DelimSpan, LazyAttrTokenStream, Spacing, TokenStream, TokenStreamIter, TokenTree,
@@ -660,7 +659,7 @@ pub fn mk_attr_from_item(
     span: Span,
 ) -> Attribute {
     Attribute {
-        kind: AttrKind::Normal(P(NormalAttr { item, tokens })),
+        kind: AttrKind::Normal(Box::new(NormalAttr { item, tokens })),
         id: g.mk_attr_id(),
         style,
         span,
@@ -710,7 +709,7 @@ pub fn mk_attr_name_value_str(
     span: Span,
 ) -> Attribute {
     let lit = token::Lit::new(token::Str, escape_string_symbol(val), None);
-    let expr = P(Expr {
+    let expr = Box::new(Expr {
         id: DUMMY_NODE_ID,
         kind: ExprKind::Lit(lit),
         span,
diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
index 2f918faaf75..33451f99748 100644
--- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs
+++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs
@@ -7,7 +7,6 @@ use std::fmt::{self, Display, Formatter};
 use std::str::FromStr;
 
 use crate::expand::{Decodable, Encodable, HashStable_Generic};
-use crate::ptr::P;
 use crate::{Ty, TyKind};
 
 /// Forward and Reverse Mode are well known names for automatic differentiation implementations.
@@ -162,7 +161,7 @@ pub fn valid_ret_activity(mode: DiffMode, activity: DiffActivity) -> bool {
 /// since Duplicated expects a mutable ref/ptr and we would thus end up with a shadow value
 /// who is an indirect type, which doesn't match the primal scalar type. We can't prevent
 /// users here from marking scalars as Duplicated, due to type aliases.
-pub fn valid_ty_for_activity(ty: &P<Ty>, activity: DiffActivity) -> bool {
+pub fn valid_ty_for_activity(ty: &Box<Ty>, activity: DiffActivity) -> bool {
     use DiffActivity::*;
     // It's always allowed to mark something as Const, since we won't compute derivatives wrt. it.
     // Dual variants also support all types.
diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs
index c2a1de60a98..cadebb2254d 100644
--- a/compiler/rustc_ast/src/format.rs
+++ b/compiler/rustc_ast/src/format.rs
@@ -3,7 +3,6 @@ use rustc_macros::{Decodable, Encodable, Walkable};
 use rustc_span::{Ident, Span, Symbol};
 
 use crate::Expr;
-use crate::ptr::P;
 use crate::token::LitKind;
 
 // Definitions:
@@ -147,7 +146,7 @@ impl FormatArguments {
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
 pub struct FormatArgument {
     pub kind: FormatArgumentKind,
-    pub expr: P<Expr>,
+    pub expr: Box<Expr>,
 }
 
 #[derive(Clone, Encodable, Decodable, Debug, Walkable)]
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 896d1e1148a..f1951049b47 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -37,7 +37,6 @@ pub mod expand;
 pub mod format;
 pub mod mut_visit;
 pub mod node_id;
-pub mod ptr;
 pub mod token;
 pub mod tokenstream;
 pub mod visit;
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 06708e2e703..be8e1d22c9d 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -17,7 +17,6 @@ use smallvec::{SmallVec, smallvec};
 use thin_vec::ThinVec;
 
 use crate::ast::*;
-use crate::ptr::P;
 use crate::tokenstream::*;
 use crate::visit::{AssocCtxt, BoundKind, FnCtxt, LifetimeCtxt, VisitorResult, try_visit};
 
@@ -41,7 +40,7 @@ pub(crate) trait MutVisitable<V: MutVisitor> {
     fn visit_mut(&mut self, visitor: &mut V, extra: Self::Extra);
 }
 
-impl<V: MutVisitor, T: ?Sized> MutVisitable<V> for P<T>
+impl<V: MutVisitor, T: ?Sized> MutVisitable<V> for Box<T>
 where
     T: MutVisitable<V>,
 {
@@ -293,15 +292,15 @@ macro_rules! generate_flat_map_visitor_fns {
 }
 
 generate_flat_map_visitor_fns! {
-    visit_items, P<Item>, flat_map_item;
-    visit_foreign_items, P<ForeignItem>, flat_map_foreign_item;
+    visit_items, Box<Item>, flat_map_item;
+    visit_foreign_items, Box<ForeignItem>, flat_map_foreign_item;
     visit_generic_params, GenericParam, flat_map_generic_param;
     visit_stmts, Stmt, flat_map_stmt;
-    visit_exprs, P<Expr>, filter_map_expr;
+    visit_exprs, Box<Expr>, filter_map_expr;
     visit_expr_fields, ExprField, flat_map_expr_field;
     visit_pat_fields, PatField, flat_map_pat_field;
     visit_variants, Variant, flat_map_variant;
-    visit_assoc_items, P<AssocItem>, flat_map_assoc_item, ctxt: AssocCtxt;
+    visit_assoc_items, Box<AssocItem>, flat_map_assoc_item, ctxt: AssocCtxt;
     visit_where_predicates, WherePredicate, flat_map_where_predicate;
     visit_params, Param, flat_map_param;
     visit_field_defs, FieldDef, flat_map_field_def;
@@ -333,12 +332,12 @@ generate_walk_flat_map_fns! {
     walk_flat_map_where_predicate(WherePredicate) => visit_where_predicate;
     walk_flat_map_field_def(FieldDef) => visit_field_def;
     walk_flat_map_expr_field(ExprField) => visit_expr_field;
-    walk_flat_map_item(P<Item>) => visit_item;
-    walk_flat_map_foreign_item(P<ForeignItem>) => visit_foreign_item;
-    walk_flat_map_assoc_item(P<AssocItem>, ctxt: AssocCtxt) => visit_assoc_item;
+    walk_flat_map_item(Box<Item>) => visit_item;
+    walk_flat_map_foreign_item(Box<ForeignItem>) => visit_foreign_item;
+    walk_flat_map_assoc_item(Box<AssocItem>, ctxt: AssocCtxt) => visit_assoc_item;
 }
 
-pub fn walk_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: P<Expr>) -> Option<P<Expr>> {
+pub fn walk_filter_map_expr<T: MutVisitor>(vis: &mut T, mut e: Box<Expr>) -> Option<Box<Expr>> {
     vis.visit_expr(&mut e);
     Some(e)
 }
diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs
deleted file mode 100644
index fffeab8bbca..00000000000
--- a/compiler/rustc_ast/src/ptr.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-/// A pointer type that uniquely owns a heap allocation of type T.
-///
-/// This used to be its own type, but now it's just a typedef for `Box` and we are planning to
-/// remove it soon.
-pub type P<T> = Box<T>;
-
-/// Construct a `P<T>` from a `T` value.
-#[allow(non_snake_case)]
-pub fn P<T>(value: T) -> P<T> {
-    Box::new(value)
-}
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index ab15cb28fa1..5fdce27db53 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -20,7 +20,6 @@ use rustc_span::{Ident, Span, Symbol};
 use thin_vec::ThinVec;
 
 use crate::ast::*;
-use crate::ptr::P;
 use crate::tokenstream::DelimSpan;
 
 #[derive(Copy, Clone, Debug, PartialEq)]
@@ -82,7 +81,7 @@ pub(crate) trait Visitable<'a, V: Visitor<'a>> {
     fn visit(&'a self, visitor: &mut V, extra: Self::Extra) -> V::Result;
 }
 
-impl<'a, V: Visitor<'a>, T: ?Sized> Visitable<'a, V> for P<T>
+impl<'a, V: Visitor<'a>, T: ?Sized> Visitable<'a, V> for Box<T>
 where
     T: Visitable<'a, V>,
 {
@@ -322,7 +321,7 @@ macro_rules! common_visitor_and_walkers {
             Fn(FnCtxt, &'a $($mut)? Visibility, &'a $($mut)? Fn),
 
             /// E.g., `|x, y| body`.
-            Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option<CoroutineKind>, &'a $($mut)? P<FnDecl>, &'a $($mut)? P<Expr>),
+            Closure(&'a $($mut)? ClosureBinder, &'a $($mut)? Option<CoroutineKind>, &'a $($mut)? Box<FnDecl>, &'a $($mut)? Box<Expr>),
         }
 
         impl<'a> FnKind<'a> {
@@ -390,9 +389,9 @@ macro_rules! common_visitor_and_walkers {
             ThinVec<(NodeId, Path)>,
             ThinVec<PathSegment>,
             ThinVec<PreciseCapturingArg>,
-            ThinVec<P<Pat>>,
-            ThinVec<P<Ty>>,
-            ThinVec<P<TyPat>>,
+            ThinVec<Box<Pat>>,
+            ThinVec<Box<Ty>>,
+            ThinVec<Box<TyPat>>,
         );
 
         // This macro generates `impl Visitable` and `impl MutVisitable` that forward to `Walkable`
@@ -676,11 +675,11 @@ macro_rules! common_visitor_and_walkers {
                     // Do nothing.
                 }
 
-                fn flat_map_foreign_item(&mut self, ni: P<ForeignItem>) -> SmallVec<[P<ForeignItem>; 1]> {
+                fn flat_map_foreign_item(&mut self, ni: Box<ForeignItem>) -> SmallVec<[Box<ForeignItem>; 1]> {
                     walk_flat_map_foreign_item(self, ni)
                 }
 
-                fn flat_map_item(&mut self, i: P<Item>) -> SmallVec<[P<Item>; 1]> {
+                fn flat_map_item(&mut self, i: Box<Item>) -> SmallVec<[Box<Item>; 1]> {
                     walk_flat_map_item(self, i)
                 }
 
@@ -690,9 +689,9 @@ macro_rules! common_visitor_and_walkers {
 
                 fn flat_map_assoc_item(
                     &mut self,
-                    i: P<AssocItem>,
+                    i: Box<AssocItem>,
                     ctxt: AssocCtxt,
-                ) -> SmallVec<[P<AssocItem>; 1]> {
+                ) -> SmallVec<[Box<AssocItem>; 1]> {
                     walk_flat_map_assoc_item(self, i, ctxt)
                 }
 
@@ -704,7 +703,7 @@ macro_rules! common_visitor_and_walkers {
                     walk_flat_map_arm(self, arm)
                 }
 
-                fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
+                fn filter_map_expr(&mut self, e: Box<Expr>) -> Option<Box<Expr>> {
                     walk_filter_map_expr(self, e)
                 }
 
@@ -1144,15 +1143,15 @@ macro_rules! generate_list_visit_fns {
 }
 
 generate_list_visit_fns! {
-    visit_items, P<Item>, visit_item;
-    visit_foreign_items, P<ForeignItem>, visit_foreign_item;
+    visit_items, Box<Item>, visit_item;
+    visit_foreign_items, Box<ForeignItem>, visit_foreign_item;
     visit_generic_params, GenericParam, visit_generic_param;
     visit_stmts, Stmt, visit_stmt;
-    visit_exprs, P<Expr>, visit_expr;
+    visit_exprs, Box<Expr>, visit_expr;
     visit_expr_fields, ExprField, visit_expr_field;
     visit_pat_fields, PatField, visit_pat_field;
     visit_variants, Variant, visit_variant;
-    visit_assoc_items, P<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
+    visit_assoc_items, Box<AssocItem>, visit_assoc_item, ctxt: AssocCtxt;
     visit_where_predicates, WherePredicate, visit_where_predicate;
     visit_params, Param, visit_param;
     visit_field_defs, FieldDef, visit_field_def;
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index af279e07acc..d44faad017e 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -48,6 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     | asm::InlineAsmArch::Arm64EC
                     | asm::InlineAsmArch::RiscV32
                     | asm::InlineAsmArch::RiscV64
+                    | asm::InlineAsmArch::LoongArch32
                     | asm::InlineAsmArch::LoongArch64
                     | asm::InlineAsmArch::S390x
             );
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index fb42cfea30b..2ddbf083a09 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1,7 +1,6 @@
 use std::ops::ControlFlow;
 use std::sync::Arc;
 
-use rustc_ast::ptr::P as AstP;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust::expr_to_string;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -53,7 +52,7 @@ impl<'v> rustc_ast::visit::Visitor<'v> for WillCreateDefIdsVisitor {
 }
 
 impl<'hir> LoweringContext<'_, 'hir> {
-    fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
+    fn lower_exprs(&mut self, exprs: &[Box<Expr>]) -> &'hir [hir::Expr<'hir>] {
         self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))
     }
 
@@ -455,7 +454,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_legacy_const_generics(
         &mut self,
         mut f: Expr,
-        args: ThinVec<AstP<Expr>>,
+        args: ThinVec<Box<Expr>>,
         legacy_args_idx: &[usize],
     ) -> hir::ExprKind<'hir> {
         let ExprKind::Path(None, path) = &mut f.kind else {
@@ -495,7 +494,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self.create_def(node_id, None, DefKind::AnonConst, f.span);
                 let mut visitor = WillCreateDefIdsVisitor {};
                 let const_value = if let ControlFlow::Break(span) = visitor.visit_expr(&arg) {
-                    AstP(Expr {
+                    Box::new(Expr {
                         id: self.next_node_id(),
                         kind: ExprKind::Err(invalid_expr_error(self.tcx, span)),
                         span: f.span,
@@ -516,7 +515,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // Add generic args to the last element of the path.
         let last_segment = path.segments.last_mut().unwrap();
         assert!(last_segment.args.is_none());
-        last_segment.args = Some(AstP(GenericArgs::AngleBracketed(AngleBracketedArgs {
+        last_segment.args = Some(Box::new(GenericArgs::AngleBracketed(AngleBracketedArgs {
             span: DUMMY_SP,
             args: generic_args,
         })));
@@ -812,7 +811,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             self.lower_attrs(
                 inner_hir_id,
                 &[Attribute {
-                    kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(
+                    kind: AttrKind::Normal(Box::new(NormalAttr::from_ident(Ident::new(
                         sym::track_caller,
                         span,
                     )))),
@@ -1285,7 +1284,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn extract_tuple_struct_path<'a>(
         &mut self,
         expr: &'a Expr,
-    ) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> {
+    ) -> Option<(&'a Option<Box<QSelf>>, &'a Path)> {
         if let ExprKind::Path(qself, path) = &expr.kind {
             // Does the path resolve to something disallowed in a tuple struct/variant pattern?
             if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
@@ -1307,7 +1306,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     fn extract_unit_struct_path<'a>(
         &mut self,
         expr: &'a Expr,
-    ) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> {
+    ) -> Option<(&'a Option<Box<QSelf>>, &'a Path)> {
         if let ExprKind::Path(qself, path) = &expr.kind {
             // Does the path resolve to something disallowed in a unit struct/variant pattern?
             if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
@@ -1478,7 +1477,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
     /// Each sub-assignment is recorded in `assignments`.
     fn destructure_sequence(
         &mut self,
-        elements: &[AstP<Expr>],
+        elements: &[Box<Expr>],
         ctx: &str,
         eq_sign_span: Span,
         assignments: &mut Vec<hir::Stmt<'hir>>,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 9f54af57528..ac6fac4c08e 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1,5 +1,4 @@
 use rustc_abi::ExternAbi;
-use rustc_ast::ptr::P;
 use rustc_ast::visit::AssocCtxt;
 use rustc_ast::*;
 use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
@@ -102,7 +101,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
 impl<'hir> LoweringContext<'_, 'hir> {
     pub(super) fn lower_mod(
         &mut self,
-        items: &[P<Item>],
+        items: &[Box<Item>],
         spans: &ModSpans,
     ) -> &'hir hir::Mod<'hir> {
         self.arena.alloc(hir::Mod {
@@ -462,7 +461,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             }
             ItemKind::MacroDef(ident, MacroDef { body, macro_rules }) => {
                 let ident = self.lower_ident(*ident);
-                let body = P(self.lower_delim_args(body));
+                let body = Box::new(self.lower_delim_args(body));
                 let def_id = self.local_def_id(id);
                 let def_kind = self.tcx.def_kind(def_id);
                 let DefKind::Macro(macro_kind) = def_kind else {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index d097e3cbaa8..64c1b53f633 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1217,7 +1217,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_path_ty(
         &mut self,
         t: &Ty,
-        qself: &Option<ptr::P<QSelf>>,
+        qself: &Option<Box<QSelf>>,
         path: &Path,
         param_mode: ParamMode,
         itctx: ImplTraitContext,
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index e4440621048..b6533060a76 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -1,6 +1,5 @@
 use std::sync::Arc;
 
-use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def::{DefKind, Res};
@@ -154,7 +153,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
     fn lower_pat_tuple(
         &mut self,
-        pats: &[P<Pat>],
+        pats: &[Box<Pat>],
         ctx: &str,
     ) -> (&'hir [hir::Pat<'hir>], hir::DotDotPos) {
         let mut elems = Vec::with_capacity(pats.len());
@@ -209,7 +208,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// When encountering `($binding_mode $ident @)? ..` (`slice`),
     /// this is interpreted as a sub-slice pattern semantically.
     /// Patterns that follow, which are not like `slice` -- or an error occurs, are in `after`.
-    fn lower_pat_slice(&mut self, pats: &[P<Pat>]) -> hir::PatKind<'hir> {
+    fn lower_pat_slice(&mut self, pats: &[Box<Pat>]) -> hir::PatKind<'hir> {
         let mut before = Vec::new();
         let mut after = Vec::new();
         let mut slice = None;
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index c80ef275c80..3322e0fb66b 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -24,7 +24,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     pub(crate) fn lower_qpath(
         &mut self,
         id: NodeId,
-        qself: &Option<ptr::P<QSelf>>,
+        qself: &Option<Box<QSelf>>,
         p: &Path,
         param_mode: ParamMode,
         allow_return_type_notation: AllowReturnTypeNotation,
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 1c1c5f82f3e..9d3b0969ef3 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -22,7 +22,6 @@ use std::str::FromStr;
 
 use itertools::{Either, Itertools};
 use rustc_abi::{CanonAbi, ExternAbi, InterruptKind};
-use rustc_ast::ptr::P;
 use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list};
 use rustc_ast::*;
 use rustc_ast_pretty::pprust::{self, State};
@@ -719,7 +718,7 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
+    fn deny_items(&self, trait_items: &[Box<AssocItem>], ident_span: Span) {
         if !trait_items.is_empty() {
             let spans: Vec<_> = trait_items.iter().map(|i| i.kind.ident().unwrap().span).collect();
             let total = trait_items.first().unwrap().span.to(trait_items.last().unwrap().span);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index f0cf0c1487f..85f76036df7 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -10,7 +10,6 @@ use std::borrow::Cow;
 use std::sync::Arc;
 
 use rustc_ast::attr::AttrIdGenerator;
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind};
 use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
 use rustc_ast::util::classify;
@@ -1178,7 +1177,7 @@ impl<'a> State<'a> {
         self.end(rb);
     }
 
-    fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
+    fn commasep_exprs(&mut self, b: Breaks, exprs: &[Box<ast::Expr>]) {
         self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e, FixupContext::default()), |e| e.span)
     }
 
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 8a2cb64b2a0..bdf73ac32f0 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -2,7 +2,6 @@ use std::fmt::Write;
 
 use ast::{ForLoopKind, MatchKind};
 use itertools::{Itertools, Position};
-use rustc_ast::ptr::P;
 use rustc_ast::util::classify;
 use rustc_ast::util::literal::escape_byte_str_symbol;
 use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
@@ -54,7 +53,7 @@ impl<'a> State<'a> {
         self.print_else(elseopt)
     }
 
-    fn print_call_post(&mut self, args: &[P<ast::Expr>]) {
+    fn print_call_post(&mut self, args: &[Box<ast::Expr>]) {
         self.popen();
         self.commasep_exprs(Inconsistent, args);
         self.pclose()
@@ -111,7 +110,7 @@ impl<'a> State<'a> {
         }
     }
 
-    fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) {
+    fn print_expr_vec(&mut self, exprs: &[Box<ast::Expr>]) {
         let ib = self.ibox(INDENT_UNIT);
         self.word("[");
         self.commasep_exprs(Inconsistent, exprs);
@@ -149,7 +148,7 @@ impl<'a> State<'a> {
 
     fn print_expr_struct(
         &mut self,
-        qself: &Option<P<ast::QSelf>>,
+        qself: &Option<Box<ast::QSelf>>,
         path: &ast::Path,
         fields: &[ast::ExprField],
         rest: &ast::StructRest,
@@ -204,7 +203,7 @@ impl<'a> State<'a> {
         self.word("}");
     }
 
-    fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>]) {
+    fn print_expr_tup(&mut self, exprs: &[Box<ast::Expr>]) {
         self.popen();
         self.commasep_exprs(Inconsistent, exprs);
         if exprs.len() == 1 {
@@ -213,7 +212,7 @@ impl<'a> State<'a> {
         self.pclose()
     }
 
-    fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
+    fn print_expr_call(&mut self, func: &ast::Expr, args: &[Box<ast::Expr>], fixup: FixupContext) {
         // Independent of parenthesization related to precedence, we must
         // parenthesize `func` if this is a statement context in which without
         // parentheses, a statement boundary would occur inside `func` or
@@ -247,7 +246,7 @@ impl<'a> State<'a> {
         &mut self,
         segment: &ast::PathSegment,
         receiver: &ast::Expr,
-        base_args: &[P<ast::Expr>],
+        base_args: &[Box<ast::Expr>],
         fixup: FixupContext,
     ) {
         // The fixup here is different than in `print_expr_call` because
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 11c97a552c6..6e34d1b61db 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -2,7 +2,6 @@ use ast::StaticItem;
 use itertools::{Itertools, Position};
 use rustc_ast as ast;
 use rustc_ast::ModKind;
-use rustc_ast::ptr::P;
 use rustc_span::Ident;
 
 use crate::pp::BoxMarker;
@@ -628,10 +627,10 @@ impl<'a> State<'a> {
         &mut self,
         attrs: &[ast::Attribute],
         vis: &ast::Visibility,
-        qself: &Option<P<ast::QSelf>>,
+        qself: &Option<Box<ast::QSelf>>,
         path: &ast::Path,
         kind: DelegationKind<'_>,
-        body: &Option<P<ast::Block>>,
+        body: &Option<Box<ast::Block>>,
     ) {
         let body_cb_ib = body.as_ref().map(|body| (body, self.head("")));
         self.print_visibility(vis);
diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
index 0779248e1a9..886f7a889d3 100644
--- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs
@@ -113,11 +113,3 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser {
         Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state })
     }
 }
-
-pub(crate) struct AllowInternalUnsafeParser;
-
-impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
-    const PATH: &[Symbol] = &[sym::allow_internal_unsafe];
-    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
-    const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
-}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 1420753a44e..80dfdffdb55 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -33,9 +33,7 @@ use crate::attributes::lint_helpers::{
     AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
 };
 use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
-use crate::attributes::macro_attrs::{
-    AllowInternalUnsafeParser, MacroEscapeParser, MacroUseParser,
-};
+use crate::attributes::macro_attrs::{MacroEscapeParser, MacroUseParser};
 use crate::attributes::must_use::MustUseParser;
 use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
 use crate::attributes::non_exhaustive::NonExhaustiveParser;
@@ -180,7 +178,6 @@ attribute_parsers!(
         Single<SkipDuringMethodDispatchParser>,
         Single<TransparencyParser>,
         Single<WithoutArgs<AllowIncoherentImplParser>>,
-        Single<WithoutArgs<AllowInternalUnsafeParser>>,
         Single<WithoutArgs<AsPtrParser>>,
         Single<WithoutArgs<AutomaticallyDerivedParser>>,
         Single<WithoutArgs<CoherenceIsCoreParser>>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 34bed375cb9..b67dba3af96 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -51,7 +51,7 @@ mod conflict_errors;
 mod explain_borrow;
 mod move_errors;
 mod mutability_errors;
-mod opaque_suggestions;
+mod opaque_types;
 mod region_errors;
 
 pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo};
diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
index 7192a889adc..83fe4a9f98f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/opaque_suggestions.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
@@ -18,9 +18,28 @@ use rustc_trait_selection::errors::impl_trait_overcapture_suggestion;
 use crate::MirBorrowckCtxt;
 use crate::borrow_set::BorrowData;
 use crate::consumers::RegionInferenceContext;
+use crate::region_infer::opaque_types::DeferredOpaqueTypeError;
 use crate::type_check::Locations;
 
 impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
+    pub(crate) fn report_opaque_type_errors(&mut self, errors: Vec<DeferredOpaqueTypeError<'tcx>>) {
+        if errors.is_empty() {
+            return;
+        }
+        let mut guar = None;
+        for error in errors {
+            guar = Some(match error {
+                DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err) => err.report(self.infcx),
+                DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(err) => {
+                    self.infcx.dcx().emit_err(err)
+                }
+            });
+        }
+        let guar = guar.unwrap();
+        self.root_cx.set_tainted_by_errors(guar);
+        self.infcx.set_tainted_by_errors(guar);
+    }
+
     /// Try to note when an opaque is involved in a borrowck error and that
     /// opaque captures lifetimes due to edition 2024.
     // FIXME: This code is otherwise somewhat general, and could easily be adapted
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index b130cf8ed27..2b74f1a48f7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -92,9 +92,6 @@ impl<'tcx> RegionErrors<'tcx> {
     ) -> impl Iterator<Item = (RegionErrorKind<'tcx>, ErrorGuaranteed)> {
         self.0.into_iter()
     }
-    pub(crate) fn has_errors(&self) -> Option<ErrorGuaranteed> {
-        self.0.get(0).map(|x| x.1)
-    }
 }
 
 impl std::fmt::Debug for RegionErrors<'_> {
diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs
index aaaf2f45c86..e168b819a8d 100644
--- a/compiler/rustc_borrowck/src/handle_placeholders.rs
+++ b/compiler/rustc_borrowck/src/handle_placeholders.rs
@@ -157,7 +157,7 @@ fn region_definitions<'tcx>(
     for info in var_infos.iter() {
         let origin = match info.origin {
             RegionVariableOrigin::Nll(origin) => origin,
-            _ => NllRegionVariableOrigin::Existential { from_forall: false },
+            _ => NllRegionVariableOrigin::Existential { from_forall: false, name: None },
         };
 
         let definition = RegionDefinition { origin, universe: info.universe, external_name: None };
@@ -216,22 +216,11 @@ pub(crate) fn compute_sccs_applying_placeholder_outlives_constraints<'tcx>(
         placeholder_index_to_region: _,
         liveness_constraints,
         mut outlives_constraints,
-        mut member_constraints,
+        member_constraints,
         universe_causes,
         type_tests,
     } = constraints;
 
-    if let Some(guar) = universal_regions.tainted_by_errors() {
-        debug!("Universal regions tainted by errors; removing constraints!");
-        // Suppress unhelpful extra errors in `infer_opaque_types` by clearing out all
-        // outlives bounds that we may end up checking.
-        outlives_constraints = Default::default();
-        member_constraints = Default::default();
-
-        // Also taint the entire scope.
-        infcx.set_tainted_by_errors(guar);
-    }
-
     let fr_static = universal_regions.fr_static;
     let compute_sccs =
         |constraints: &OutlivesConstraintSet<'tcx>,
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 752ff8e6f58..d76d6a04e6e 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -375,7 +375,7 @@ fn do_mir_borrowck<'tcx>(
         polonius_context,
     );
 
-    regioncx.infer_opaque_types(root_cx, &infcx, opaque_type_values);
+    let opaque_type_errors = regioncx.infer_opaque_types(root_cx, &infcx, opaque_type_values);
 
     // Dump MIR results into a file, if that is enabled. This lets us
     // write unit-tests, as well as helping with debugging.
@@ -471,7 +471,11 @@ fn do_mir_borrowck<'tcx>(
     };
 
     // Compute and report region errors, if any.
-    mbcx.report_region_errors(nll_errors);
+    if nll_errors.is_empty() {
+        mbcx.report_opaque_type_errors(opaque_type_errors);
+    } else {
+        mbcx.report_region_errors(nll_errors);
+    }
 
     let (mut flow_analysis, flow_entry_states) =
         get_flow_results(tcx, body, &move_data, &borrow_set, &regioncx);
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index ca6092e70d2..8608a8a3a66 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -148,11 +148,6 @@ pub(crate) fn compute_regions<'tcx>(
     let (closure_region_requirements, nll_errors) =
         regioncx.solve(infcx, body, polonius_output.clone());
 
-    if let Some(guar) = nll_errors.has_errors() {
-        // Suppress unhelpful extra errors in `infer_opaque_types`.
-        infcx.set_tainted_by_errors(guar);
-    }
-
     NllOutput {
         regioncx,
         polonius_input: polonius_facts.map(Box::new),
diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs
index 50f59dd0dee..52595757859 100644
--- a/compiler/rustc_borrowck/src/polonius/constraints.rs
+++ b/compiler/rustc_borrowck/src/polonius/constraints.rs
@@ -7,9 +7,7 @@ use rustc_mir_dataflow::points::PointIndex;
 ///
 /// This models two sources of constraints:
 /// - constraints that traverse the subsets between regions at a given point, `a@p: b@p`. These
-///   depend on typeck constraints generated via assignments, calls, etc. (In practice there are
-///   subtleties where a statement's effect only starts being visible at the successor point, via
-///   the "result" of that statement).
+///   depend on typeck constraints generated via assignments, calls, etc.
 /// - constraints that traverse the CFG via the same region, `a@p: a@q`, where `p` is a predecessor
 ///   of `q`. These depend on the liveness of the regions at these points, as well as their
 ///   variance.
diff --git a/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs b/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs
index 6ab09f731c0..2ba72180d66 100644
--- a/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs
+++ b/compiler/rustc_borrowck/src/polonius/liveness_constraints.rs
@@ -105,22 +105,14 @@ fn propagate_loans_between_points(
         });
     }
 
-    let Some(current_live_regions) = live_regions.row(current_point) else {
-        // There are no constraints to add: there are no live regions at the current point.
-        return;
-    };
     let Some(next_live_regions) = live_regions.row(next_point) else {
         // There are no constraints to add: there are no live regions at the next point.
         return;
     };
 
     for region in next_live_regions.iter() {
-        if !current_live_regions.contains(region) {
-            continue;
-        }
-
-        // `region` is indeed live at both points, add a constraint between them, according to
-        // variance.
+        // `region` could be live at the current point, and is live at the next point: add a
+        // constraint between them, according to variance.
         if let Some(&direction) = live_region_variances.get(&region) {
             add_liveness_constraint(
                 region,
diff --git a/compiler/rustc_borrowck/src/polonius/loan_liveness.rs b/compiler/rustc_borrowck/src/polonius/loan_liveness.rs
index 5cd265e0db9..bdc3047e5ba 100644
--- a/compiler/rustc_borrowck/src/polonius/loan_liveness.rs
+++ b/compiler/rustc_borrowck/src/polonius/loan_liveness.rs
@@ -1,27 +1,18 @@
-use std::collections::{BTreeMap, BTreeSet};
-
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{
-    Body, Local, Location, Place, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
-};
-use rustc_middle::ty::{RegionVid, TyCtxt};
+use rustc_middle::ty::RegionVid;
 use rustc_mir_dataflow::points::PointIndex;
 
 use super::{LiveLoans, LocalizedOutlivesConstraintSet};
+use crate::BorrowSet;
 use crate::constraints::OutlivesConstraint;
-use crate::dataflow::BorrowIndex;
 use crate::region_infer::values::LivenessValues;
 use crate::type_check::Locations;
-use crate::{BorrowSet, PlaceConflictBias, places_conflict};
 
-/// Compute loan reachability, stop at kills, and trace loan liveness throughout the CFG, by
+/// Compute loan reachability to approximately trace loan liveness throughout the CFG, by
 /// traversing the full graph of constraints that combines:
 /// - the localized constraints (the physical edges),
 /// - with the constraints that hold at all points (the logical edges).
 pub(super) fn compute_loan_liveness<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
     liveness: &LivenessValues,
     outlives_constraints: impl Iterator<Item = OutlivesConstraint<'tcx>>,
     borrow_set: &BorrowSet<'tcx>,
@@ -29,11 +20,6 @@ pub(super) fn compute_loan_liveness<'tcx>(
 ) -> LiveLoans {
     let mut live_loans = LiveLoans::new(borrow_set.len());
 
-    // FIXME: it may be preferable for kills to be encoded in the edges themselves, to simplify and
-    // likely make traversal (and constraint generation) more efficient. We also display kills on
-    // edges when visualizing the constraint graph anyways.
-    let kills = collect_kills(body, tcx, borrow_set);
-
     // Create the full graph with the physical edges we've localized earlier, and the logical edges
     // of constraints that hold at all points.
     let logical_constraints =
@@ -59,15 +45,15 @@ pub(super) fn compute_loan_liveness<'tcx>(
                 continue;
             }
 
-            // Record the loan as being live on entry to this point.
-            live_loans.insert(node.point, loan_idx);
-
-            // Here, we have a conundrum. There's currently a weakness in our theory, in that
-            // we're using a single notion of reachability to represent what used to be _two_
-            // different transitive closures. It didn't seem impactful when coming up with the
-            // single-graph and reachability through space (regions) + time (CFG) concepts, but in
-            // practice the combination of time-traveling with kills is more impactful than
-            // initially anticipated.
+            // Record the loan as being live on entry to this point if it reaches a live region
+            // there.
+            //
+            // This is an approximation of liveness (which is the thing we want), in that we're
+            // using a single notion of reachability to represent what used to be _two_ different
+            // transitive closures. It didn't seem impactful when coming up with the single-graph
+            // and reachability through space (regions) + time (CFG) concepts, but in practice the
+            // combination of time-traveling with kills is more impactful than initially
+            // anticipated.
             //
             // Kills should prevent a loan from reaching its successor points in the CFG, but not
             // while time-traveling: we're not actually at that CFG point, but looking for
@@ -92,40 +78,20 @@ pub(super) fn compute_loan_liveness<'tcx>(
             //   two-step traversal described above: only kills encountered on exit via a backward
             //   edge are ignored.
             //
-            // In our test suite, there are a couple of cases where kills are encountered while
-            // time-traveling, however as far as we can tell, always in cases where they would be
-            // unreachable. We have reason to believe that this is a property of the single-graph
-            // approach (but haven't proved it yet):
-            // - reachable kills while time-traveling would also be encountered via regular
-            //   traversal
-            // - it makes _some_ sense to ignore unreachable kills, but subtleties around dead code
-            //   in general need to be better thought through (like they were for NLLs).
-            // - ignoring kills is a conservative approximation: the loan is still live and could
-            //   cause false positive errors at another place access. Soundness issues in this
-            //   domain should look more like the absence of reachability instead.
-            //
-            // This is enough in practice to pass tests, and therefore is what we have implemented
-            // for now.
+            // This version of the analysis, however, is enough in practice to pass the tests that
+            // we care about and NLLs reject, without regressions on crater, and is an actionable
+            // subset of the full analysis. It also naturally points to areas of improvement that we
+            // wish to explore later, namely handling kills appropriately during traversal, instead
+            // of continuing traversal to all the reachable nodes.
             //
-            // FIXME: all of the above. Analyze potential unsoundness, possibly in concert with a
-            // borrowck implementation in a-mir-formality, fuzzing, or manually crafting
-            // counter-examples.
+            // FIXME: analyze potential unsoundness, possibly in concert with a borrowck
+            // implementation in a-mir-formality, fuzzing, or manually crafting counter-examples.
 
-            // Continuing traversal will depend on whether the loan is killed at this point, and
-            // whether we're time-traveling.
-            let current_location = liveness.location_from_point(node.point);
-            let is_loan_killed =
-                kills.get(&current_location).is_some_and(|kills| kills.contains(&loan_idx));
+            if liveness.is_live_at(node.region, liveness.location_from_point(node.point)) {
+                live_loans.insert(node.point, loan_idx);
+            }
 
             for succ in graph.outgoing_edges(node) {
-                // If the loan is killed at this point, it is killed _on exit_. But only during
-                // forward traversal.
-                if is_loan_killed {
-                    let destination = liveness.location_from_point(succ.point);
-                    if current_location.is_predecessor_of(destination, body) {
-                        continue;
-                    }
-                }
                 stack.push(succ);
             }
         }
@@ -192,116 +158,3 @@ impl LocalizedConstraintGraph {
         physical_edges.chain(materialized_edges)
     }
 }
-
-/// Traverses the MIR and collects kills.
-fn collect_kills<'tcx>(
-    body: &Body<'tcx>,
-    tcx: TyCtxt<'tcx>,
-    borrow_set: &BorrowSet<'tcx>,
-) -> BTreeMap<Location, BTreeSet<BorrowIndex>> {
-    let mut collector = KillsCollector { borrow_set, tcx, body, kills: BTreeMap::default() };
-    for (block, data) in body.basic_blocks.iter_enumerated() {
-        collector.visit_basic_block_data(block, data);
-    }
-    collector.kills
-}
-
-struct KillsCollector<'a, 'tcx> {
-    body: &'a Body<'tcx>,
-    tcx: TyCtxt<'tcx>,
-    borrow_set: &'a BorrowSet<'tcx>,
-
-    /// The set of loans killed at each location.
-    kills: BTreeMap<Location, BTreeSet<BorrowIndex>>,
-}
-
-// This visitor has a similar structure to the `Borrows` dataflow computation with respect to kills,
-// and the datalog polonius fact generation for the `loan_killed_at` relation.
-impl<'tcx> KillsCollector<'_, 'tcx> {
-    /// Records the borrows on the specified place as `killed`. For example, when assigning to a
-    /// local, or on a call's return destination.
-    fn record_killed_borrows_for_place(&mut self, place: Place<'tcx>, location: Location) {
-        // For the reasons described in graph traversal, we also filter out kills
-        // unreachable from the loan's introduction point, as they would stop traversal when
-        // e.g. checking for reachability in the subset graph through invariance constraints
-        // higher up.
-        let filter_unreachable_kills = |loan| {
-            let introduction = self.borrow_set[loan].reserve_location;
-            let reachable = introduction.is_predecessor_of(location, self.body);
-            reachable
-        };
-
-        let other_borrows_of_local = self
-            .borrow_set
-            .local_map
-            .get(&place.local)
-            .into_iter()
-            .flat_map(|bs| bs.iter())
-            .copied();
-
-        // If the borrowed place is a local with no projections, all other borrows of this
-        // local must conflict. This is purely an optimization so we don't have to call
-        // `places_conflict` for every borrow.
-        if place.projection.is_empty() {
-            if !self.body.local_decls[place.local].is_ref_to_static() {
-                self.kills
-                    .entry(location)
-                    .or_default()
-                    .extend(other_borrows_of_local.filter(|&loan| filter_unreachable_kills(loan)));
-            }
-            return;
-        }
-
-        // By passing `PlaceConflictBias::NoOverlap`, we conservatively assume that any given
-        // pair of array indices are not equal, so that when `places_conflict` returns true, we
-        // will be assured that two places being compared definitely denotes the same sets of
-        // locations.
-        let definitely_conflicting_borrows = other_borrows_of_local
-            .filter(|&i| {
-                places_conflict(
-                    self.tcx,
-                    self.body,
-                    self.borrow_set[i].borrowed_place,
-                    place,
-                    PlaceConflictBias::NoOverlap,
-                )
-            })
-            .filter(|&loan| filter_unreachable_kills(loan));
-
-        self.kills.entry(location).or_default().extend(definitely_conflicting_borrows);
-    }
-
-    /// Records the borrows on the specified local as `killed`.
-    fn record_killed_borrows_for_local(&mut self, local: Local, location: Location) {
-        if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) {
-            self.kills.entry(location).or_default().extend(borrow_indices.iter());
-        }
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for KillsCollector<'_, 'tcx> {
-    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
-        // Make sure there are no remaining borrows for locals that have gone out of scope.
-        if let StatementKind::StorageDead(local) = statement.kind {
-            self.record_killed_borrows_for_local(local, location);
-        }
-
-        self.super_statement(statement, location);
-    }
-
-    fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
-        // When we see `X = ...`, then kill borrows of `(*X).foo` and so forth.
-        self.record_killed_borrows_for_place(*place, location);
-        self.super_assign(place, rvalue, location);
-    }
-
-    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
-        // A `Call` terminator's return value can be a local which has borrows, so we need to record
-        // those as killed as well.
-        if let TerminatorKind::Call { destination, .. } = terminator.kind {
-            self.record_killed_borrows_for_place(destination, location);
-        }
-
-        self.super_terminator(terminator, location);
-    }
-}
diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs
index 142ef8ba28e..a9092b1981e 100644
--- a/compiler/rustc_borrowck/src/polonius/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/mod.rs
@@ -146,8 +146,8 @@ impl PoloniusContext {
     /// - converting NLL typeck constraints to be localized
     /// - encoding liveness constraints
     ///
-    /// Then, this graph is traversed, and combined with kills, reachability is recorded as loan
-    /// liveness, to be used by the loan scope and active loans computations.
+    /// Then, this graph is traversed, reachability is recorded as loan liveness, to be used by the
+    /// loan scope and active loans computations.
     ///
     /// The constraint data will be used to compute errors and diagnostics.
     pub(crate) fn compute_loan_liveness<'tcx>(
@@ -182,8 +182,6 @@ impl PoloniusContext {
         // Now that we have a complete graph, we can compute reachability to trace the liveness of
         // loans for the next step in the chain, the NLL loan scope and active loans computations.
         let live_loans = compute_loan_liveness(
-            tcx,
-            body,
             regioncx.liveness_constraints(),
             regioncx.outlives_constraints(),
             borrow_set,
diff --git a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs
index 1289b1899eb..e4e52962bf7 100644
--- a/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs
+++ b/compiler/rustc_borrowck/src/polonius/typeck_constraints.rs
@@ -47,9 +47,7 @@ pub(super) fn convert_typeck_constraints<'tcx>(
                         tcx,
                         body,
                         stmt,
-                        liveness,
                         &outlives_constraint,
-                        location,
                         point,
                         universal_regions,
                     )
@@ -78,9 +76,7 @@ fn localize_statement_constraint<'tcx>(
     tcx: TyCtxt<'tcx>,
     body: &Body<'tcx>,
     stmt: &Statement<'tcx>,
-    liveness: &LivenessValues,
     outlives_constraint: &OutlivesConstraint<'tcx>,
-    current_location: Location,
     current_point: PointIndex,
     universal_regions: &UniversalRegions<'tcx>,
 ) -> LocalizedOutlivesConstraint {
@@ -98,8 +94,8 @@ fn localize_statement_constraint<'tcx>(
             // - and that should be impossible in MIR
             //
             // When we have a more complete implementation in the future, tested with crater, etc,
-            // we can relax this to a debug assert instead, or remove it.
-            assert!(
+            // we can remove this assertion. It's a debug assert because it can be expensive.
+            debug_assert!(
                 {
                     let mut lhs_regions = FxHashSet::default();
                     tcx.for_each_free_region(lhs, |region| {
@@ -119,16 +115,8 @@ fn localize_statement_constraint<'tcx>(
                 "there should be no common regions between the LHS and RHS of an assignment"
             );
 
-            // As mentioned earlier, we should be tracking these better upstream but: we want to
-            // relate the types on entry to the type of the place on exit. That is, outlives
-            // constraints on the RHS are on entry, and outlives constraints to/from the LHS are on
-            // exit (i.e. on entry to the successor location).
             let lhs_ty = body.local_decls[lhs.local].ty;
-            let successor_location = Location {
-                block: current_location.block,
-                statement_index: current_location.statement_index + 1,
-            };
-            let successor_point = liveness.point_from_location(successor_location);
+            let successor_point = current_point;
             compute_constraint_direction(
                 tcx,
                 outlives_constraint,
@@ -195,6 +183,7 @@ fn localize_terminator_constraint<'tcx>(
         }
     }
 }
+
 /// For a given outlives constraint and CFG edge, returns the localized constraint with the
 /// appropriate `from`-`to` direction. This is computed according to whether the constraint flows to
 /// or from a free region in the given `value`, some kind of result for an effectful operation, like
diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
index a3e29982e90..b2f67c43125 100644
--- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs
+++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
@@ -41,7 +41,22 @@ fn render_region_vid<'tcx>(
         "".to_string()
     };
 
-    format!("{:?}{universe_str}{external_name_str}", rvid)
+    let extra_info = match regioncx.region_definition(rvid).origin {
+        NllRegionVariableOrigin::FreeRegion => "".to_string(),
+        NllRegionVariableOrigin::Placeholder(p) => match p.bound.kind {
+            ty::BoundRegionKind::Named(def_id) => {
+                format!(" (for<{}>)", tcx.item_name(def_id))
+            }
+            ty::BoundRegionKind::ClosureEnv | ty::BoundRegionKind::Anon => " (for<'_>)".to_string(),
+            ty::BoundRegionKind::NamedAnon(_) => {
+                bug!("only used for pretty printing")
+            }
+        },
+        NllRegionVariableOrigin::Existential { name: Some(name), .. } => format!(" (ex<{name}>)"),
+        NllRegionVariableOrigin::Existential { .. } => format!(" (ex<'_>)"),
+    };
+
+    format!("{:?}{universe_str}{external_name_str}{extra_info}", rvid)
 }
 
 impl<'tcx> RegionInferenceContext<'tcx> {
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index f1320048533..dbd245214a2 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -44,7 +44,7 @@ use crate::{
 
 mod dump_mir;
 mod graphviz;
-mod opaque_types;
+pub(crate) mod opaque_types;
 mod reverse_sccs;
 
 pub(crate) mod values;
@@ -1940,9 +1940,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // and here we prefer to blame the source (the y = x statement).
         let blame_source = match from_region_origin {
             NllRegionVariableOrigin::FreeRegion
-            | NllRegionVariableOrigin::Existential { from_forall: false } => true,
+            | NllRegionVariableOrigin::Existential { from_forall: false, name: _ } => true,
             NllRegionVariableOrigin::Placeholder(_)
-            | NllRegionVariableOrigin::Existential { from_forall: true } => false,
+            | NllRegionVariableOrigin::Existential { from_forall: true, name: _ } => false,
         };
 
         // To pick a constraint to blame, we organize constraints by how interesting we expect them
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 6270e6d9a60..23c4554aa15 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -6,7 +6,9 @@ use rustc_middle::ty::{
     TypeVisitableExt, fold_regions,
 };
 use rustc_span::Span;
-use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
+use rustc_trait_selection::opaque_types::{
+    InvalidOpaqueTypeArgs, check_opaque_type_parameter_valid,
+};
 use tracing::{debug, instrument};
 
 use super::RegionInferenceContext;
@@ -14,6 +16,11 @@ use crate::BorrowCheckRootCtxt;
 use crate::session_diagnostics::LifetimeMismatchOpaqueParam;
 use crate::universal_regions::RegionClassification;
 
+pub(crate) enum DeferredOpaqueTypeError<'tcx> {
+    InvalidOpaqueTypeArgs(InvalidOpaqueTypeArgs<'tcx>),
+    LifetimeMismatchOpaqueParam(LifetimeMismatchOpaqueParam<'tcx>),
+}
+
 impl<'tcx> RegionInferenceContext<'tcx> {
     /// Resolve any opaque types that were encountered while borrow checking
     /// this item. This is then used to get the type in the `type_of` query.
@@ -58,13 +65,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// [rustc-dev-guide chapter]:
     /// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
-    #[instrument(level = "debug", skip(self, root_cx, infcx), ret)]
+    #[instrument(level = "debug", skip(self, root_cx, infcx))]
     pub(crate) fn infer_opaque_types(
         &self,
         root_cx: &mut BorrowCheckRootCtxt<'tcx>,
         infcx: &InferCtxt<'tcx>,
         opaque_ty_decls: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
-    ) {
+    ) -> Vec<DeferredOpaqueTypeError<'tcx>> {
+        let mut errors = Vec::new();
         let mut decls_modulo_regions: FxIndexMap<OpaqueTypeKey<'tcx>, (OpaqueTypeKey<'tcx>, Span)> =
             FxIndexMap::default();
 
@@ -124,8 +132,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             });
             debug!(?concrete_type);
 
-            let ty =
-                infcx.infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type);
+            let ty = match infcx
+                .infer_opaque_definition_from_instantiation(opaque_type_key, concrete_type)
+            {
+                Ok(ty) => ty,
+                Err(err) => {
+                    errors.push(DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err));
+                    continue;
+                }
+            };
 
             // Sometimes, when the hidden type is an inference variable, it can happen that
             // the hidden type becomes the opaque type itself. In this case, this was an opaque
@@ -149,25 +164,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             // non-region parameters. This is necessary because within the new solver we perform
             // various query operations modulo regions, and thus could unsoundly select some impls
             // that don't hold.
-            if !ty.references_error()
-                && let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
-                    infcx.tcx.erase_regions(opaque_type_key),
-                    (opaque_type_key, concrete_type.span),
-                )
-                && let Some((arg1, arg2)) = std::iter::zip(
-                    prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
-                    opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
-                )
-                .find(|(arg1, arg2)| arg1 != arg2)
+            if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert(
+                infcx.tcx.erase_regions(opaque_type_key),
+                (opaque_type_key, concrete_type.span),
+            ) && let Some((arg1, arg2)) = std::iter::zip(
+                prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
+                opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg),
+            )
+            .find(|(arg1, arg2)| arg1 != arg2)
             {
-                infcx.dcx().emit_err(LifetimeMismatchOpaqueParam {
-                    arg: arg1,
-                    prev: arg2,
-                    span: prev_span,
-                    prev_span: concrete_type.span,
-                });
+                errors.push(DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(
+                    LifetimeMismatchOpaqueParam {
+                        arg: arg1,
+                        prev: arg2,
+                        span: prev_span,
+                        prev_span: concrete_type.span,
+                    },
+                ));
             }
         }
+
+        errors
     }
 
     /// Map the regions in the type to named regions. This is similar to what
@@ -260,19 +277,13 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
         instantiated_ty: OpaqueHiddenType<'tcx>,
-    ) -> Ty<'tcx> {
-        if let Some(e) = self.tainted_by_errors() {
-            return Ty::new_error(self.tcx, e);
-        }
-
-        if let Err(err) = check_opaque_type_parameter_valid(
+    ) -> Result<Ty<'tcx>, InvalidOpaqueTypeArgs<'tcx>> {
+        check_opaque_type_parameter_valid(
             self,
             opaque_type_key,
             instantiated_ty.span,
             DefiningScopeKind::MirBorrowck,
-        ) {
-            return Ty::new_error(self.tcx, err.report(self));
-        }
+        )?;
 
         let definition_ty = instantiated_ty
             .remap_generic_params_to_declaration_params(
@@ -282,10 +293,7 @@ impl<'tcx> InferCtxt<'tcx> {
             )
             .ty;
 
-        if let Err(e) = definition_ty.error_reported() {
-            return Ty::new_error(self.tcx, e);
-        }
-
-        definition_ty
+        definition_ty.error_reported()?;
+        Ok(definition_ty)
     }
 }
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index ff92b4168a8..100d30704b9 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -66,7 +66,7 @@ impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> {
         T: TypeFoldable<TyCtxt<'tcx>>,
         F: Fn() -> RegionCtxt,
     {
-        let origin = NllRegionVariableOrigin::Existential { from_forall: false };
+        let origin = NllRegionVariableOrigin::Existential { from_forall: false, name: None };
         fold_regions(self.infcx.tcx, value, |_region, _depth| {
             self.infcx.next_nll_region_var(origin, || region_ctxt_fn())
         })
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 148d0de3bab..c3aa205d5aa 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -182,6 +182,17 @@ pub(crate) fn type_check<'tcx>(
         )
     });
 
+    // In case type check encountered an error region, we suppress unhelpful extra
+    // errors in by clearing out all outlives bounds that we may end up checking.
+    if let Some(guar) = universal_region_relations.universal_regions.encountered_re_error() {
+        debug!("encountered an error region; removing constraints!");
+        constraints.outlives_constraints = Default::default();
+        constraints.member_constraints = Default::default();
+        constraints.type_tests = Default::default();
+        root_cx.set_tainted_by_errors(guar);
+        infcx.set_tainted_by_errors(guar);
+    }
+
     MirTypeckResults {
         constraints,
         universal_region_relations,
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index bb72d1d52f3..393adafea0b 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -249,7 +249,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
         from_forall: bool,
         name: Option<Symbol>,
     ) -> ty::Region<'tcx> {
-        let origin = NllRegionVariableOrigin::Existential { from_forall };
+        let origin = NllRegionVariableOrigin::Existential { name, from_forall };
 
         let reg_var =
             self.type_checker.infcx.next_nll_region_var(origin, || RegionCtxt::Existential(name));
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 240c9a5223b..296a2735533 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -217,7 +217,7 @@ struct UniversalRegionIndices<'tcx> {
 
     /// Whether we've encountered an error region. If we have, cancel all
     /// outlives errors, as they are likely bogus.
-    pub tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
+    pub encountered_re_error: Cell<Option<ErrorGuaranteed>>,
 }
 
 #[derive(Debug, PartialEq)]
@@ -442,8 +442,8 @@ impl<'tcx> UniversalRegions<'tcx> {
         self.fr_fn_body
     }
 
-    pub(crate) fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
-        self.indices.tainted_by_errors.get()
+    pub(crate) fn encountered_re_error(&self) -> Option<ErrorGuaranteed> {
+        self.indices.encountered_re_error.get()
     }
 }
 
@@ -706,7 +706,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
         UniversalRegionIndices {
             indices: global_mapping.chain(arg_mapping).collect(),
             fr_static,
-            tainted_by_errors: Cell::new(None),
+            encountered_re_error: Cell::new(None),
         }
     }
 
@@ -916,7 +916,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
         match r.kind() {
             ty::ReVar(..) => r.as_var(),
             ty::ReError(guar) => {
-                self.tainted_by_errors.set(Some(guar));
+                self.encountered_re_error.set(Some(guar));
                 // We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
                 // `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
                 // errors are being emitted and 2) it leaves the happy path unaffected.
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index e75bc944d7e..35ef6be095e 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::{
     self as ast, Fn, FnHeader, FnSig, Generics, ItemKind, Safety, Stmt, StmtKind, TyKind,
 };
@@ -46,7 +45,7 @@ pub(crate) fn expand(
     let const_body = ecx.expr_block(ecx.block(span, stmts));
     let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
     let const_item = if is_stmt {
-        Annotatable::Stmt(P(ecx.stmt_item(span, const_item)))
+        Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
     } else {
         Annotatable::Item(const_item)
     };
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 1fb99817222..86b8e1ff8db 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -1,5 +1,4 @@
 use lint::BuiltinLintDiag;
-use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{AsmMacro, token};
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
@@ -19,7 +18,7 @@ use crate::{errors, fluent_generated as fluent};
 
 /// Validated assembly arguments, ready for macro expansion.
 struct ValidatedAsmArgs {
-    pub templates: Vec<P<ast::Expr>>,
+    pub templates: Vec<Box<ast::Expr>>,
     pub operands: Vec<(ast::InlineAsmOperand, Span)>,
     named_args: FxIndexMap<Symbol, usize>,
     reg_args: GrowableBitSet<usize>,
@@ -600,9 +599,9 @@ pub(super) fn expand_asm<'cx>(
                 return ExpandResult::Retry(());
             };
             let expr = match mac {
-                Ok(inline_asm) => P(ast::Expr {
+                Ok(inline_asm) => Box::new(ast::Expr {
                     id: ast::DUMMY_NODE_ID,
-                    kind: ast::ExprKind::InlineAsm(P(inline_asm)),
+                    kind: ast::ExprKind::InlineAsm(Box::new(inline_asm)),
                     span: sp,
                     attrs: ast::AttrVec::new(),
                     tokens: None,
@@ -630,9 +629,9 @@ pub(super) fn expand_naked_asm<'cx>(
                 return ExpandResult::Retry(());
             };
             let expr = match mac {
-                Ok(inline_asm) => P(ast::Expr {
+                Ok(inline_asm) => Box::new(ast::Expr {
                     id: ast::DUMMY_NODE_ID,
-                    kind: ast::ExprKind::InlineAsm(P(inline_asm)),
+                    kind: ast::ExprKind::InlineAsm(Box::new(inline_asm)),
                     span: sp,
                     attrs: ast::AttrVec::new(),
                     tokens: None,
@@ -660,7 +659,7 @@ pub(super) fn expand_global_asm<'cx>(
                 return ExpandResult::Retry(());
             };
             match mac {
-                Ok(inline_asm) => MacEager::items(smallvec![P(ast::Item {
+                Ok(inline_asm) => MacEager::items(smallvec![Box::new(ast::Item {
                     attrs: ast::AttrVec::new(),
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index c659b1cff59..855da5caa31 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -1,6 +1,5 @@
 mod context;
 
-use rustc_ast::ptr::P;
 use rustc_ast::token::Delimiter;
 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
 use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp, token};
@@ -55,9 +54,9 @@ pub(crate) fn expand_assert<'cx>(
     let expr = if let Some(tokens) = custom_message {
         let then = cx.expr(
             call_site_span,
-            ExprKind::MacCall(P(MacCall {
+            ExprKind::MacCall(Box::new(MacCall {
                 path: panic_path(),
-                args: P(DelimArgs {
+                args: Box::new(DelimArgs {
                     dspan: DelimSpan::from_single(call_site_span),
                     delim: Delimiter::Parenthesis,
                     tokens,
@@ -96,7 +95,7 @@ pub(crate) fn expand_assert<'cx>(
 }
 
 struct Assert {
-    cond_expr: P<Expr>,
+    cond_expr: Box<Expr>,
     custom_message: Option<TokenStream>,
 }
 
@@ -104,10 +103,10 @@ struct Assert {
 fn expr_if_not(
     cx: &ExtCtxt<'_>,
     span: Span,
-    cond: P<Expr>,
-    then: P<Expr>,
-    els: Option<P<Expr>>,
-) -> P<Expr> {
+    cond: Box<Expr>,
+    then: Box<Expr>,
+    els: Option<Box<Expr>>,
+) -> Box<Expr> {
     cx.expr_if(span, cx.expr(span, ExprKind::Unary(UnOp::Not, cond)), then, els)
 }
 
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index ea7248ca539..31855cbd4e6 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, IdentIsRaw};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast::{
@@ -70,7 +69,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
     ///   }
     /// }
     /// ```
-    pub(super) fn build(mut self, mut cond_expr: P<Expr>, panic_path: Path) -> P<Expr> {
+    pub(super) fn build(mut self, mut cond_expr: Box<Expr>, panic_path: Path) -> Box<Expr> {
         let expr_str = pprust::expr_to_string(&cond_expr);
         self.manage_cond_expr(&mut cond_expr);
         let initial_imports = self.build_initial_imports();
@@ -129,7 +128,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
     }
 
     /// Takes the conditional expression of `assert!` and then wraps it inside `unlikely`
-    fn build_unlikely(&self, cond_expr: P<Expr>) -> P<Expr> {
+    fn build_unlikely(&self, cond_expr: Box<Expr>) -> Box<Expr> {
         let unlikely_path = self.cx.std_path(&[sym::intrinsics, sym::unlikely]);
         self.cx.expr_call(
             self.span,
@@ -145,7 +144,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
     ///     __capture0,
     ///     ...
     /// );
-    fn build_panic(&self, expr_str: &str, panic_path: Path) -> P<Expr> {
+    fn build_panic(&self, expr_str: &str, panic_path: Path) -> Box<Expr> {
         let escaped_expr_str = escape_to_fmt(expr_str);
         let initial = [
             TokenTree::token_joint(
@@ -176,9 +175,9 @@ impl<'cx, 'a> Context<'cx, 'a> {
         });
         self.cx.expr(
             self.span,
-            ExprKind::MacCall(P(MacCall {
+            ExprKind::MacCall(Box::new(MacCall {
                 path: panic_path,
-                args: P(DelimArgs {
+                args: Box::new(DelimArgs {
                     dspan: DelimSpan::from_single(self.span),
                     delim: Delimiter::Parenthesis,
                     tokens: initial.into_iter().chain(captures).collect::<TokenStream>(),
@@ -190,7 +189,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
     /// Recursive function called until `cond_expr` and `fmt_str` are fully modified.
     ///
     /// See [Self::manage_initial_capture] and [Self::manage_try_capture]
-    fn manage_cond_expr(&mut self, expr: &mut P<Expr>) {
+    fn manage_cond_expr(&mut self, expr: &mut Box<Expr>) {
         match &mut expr.kind {
             ExprKind::AddrOf(_, mutability, local_expr) => {
                 self.with_is_consumed_management(matches!(mutability, Mutability::Mut), |this| {
@@ -331,7 +330,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
     ///
     /// `fmt_str`, the formatting string used for debugging, is constructed to show possible
     /// captured variables.
-    fn manage_initial_capture(&mut self, expr: &mut P<Expr>, path_ident: Ident) {
+    fn manage_initial_capture(&mut self, expr: &mut Box<Expr>, path_ident: Ident) {
         if self.paths.contains(&path_ident) {
             return;
         } else {
@@ -360,7 +359,12 @@ impl<'cx, 'a> Context<'cx, 'a> {
     ///    (&Wrapper(__local_bindN)).try_capture(&mut __captureN);
     ///    __local_bindN
     /// }
-    fn manage_try_capture(&mut self, capture: Ident, curr_capture_idx: usize, expr: &mut P<Expr>) {
+    fn manage_try_capture(
+        &mut self,
+        capture: Ident,
+        curr_capture_idx: usize,
+        expr: &mut Box<Expr>,
+    ) {
         let local_bind_string = format!("__local_bind{curr_capture_idx}");
         let local_bind = Ident::new(Symbol::intern(&local_bind_string), self.span);
         self.local_bind_decls.push(self.cx.stmt_let(
@@ -441,20 +445,20 @@ fn escape_to_fmt(s: &str) -> String {
     rslt
 }
 
-fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
+fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: Box<Expr>) -> Box<Expr> {
     cx.expr(sp, ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, e))
 }
 
 fn expr_method_call(
     cx: &ExtCtxt<'_>,
     seg: PathSegment,
-    receiver: P<Expr>,
-    args: ThinVec<P<Expr>>,
+    receiver: Box<Expr>,
+    args: ThinVec<Box<Expr>>,
     span: Span,
-) -> P<Expr> {
+) -> Box<Expr> {
     cx.expr(span, ExprKind::MethodCall(Box::new(MethodCall { seg, receiver, args, span })))
 }
 
-fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
+fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: Box<Expr>) -> Box<Expr> {
     cx.expr(sp, ExprKind::Paren(e))
 }
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index c7844778332..a662840eda5 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -11,7 +11,6 @@ mod llvm_enzyme {
         AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
         valid_ty_for_activity,
     };
-    use rustc_ast::ptr::P;
     use rustc_ast::token::{Lit, LitKind, Token, TokenKind};
     use rustc_ast::tokenstream::*;
     use rustc_ast::visit::AssocCtxt::*;
@@ -27,7 +26,7 @@ mod llvm_enzyme {
     use crate::errors;
 
     pub(crate) fn outer_normal_attr(
-        kind: &P<rustc_ast::NormalAttr>,
+        kind: &Box<rustc_ast::NormalAttr>,
         id: rustc_ast::AttrId,
         span: Span,
     ) -> rustc_ast::Attribute {
@@ -73,7 +72,7 @@ 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, Generics)> {
+    fn extract_item_info(iitem: &Box<ast::Item>) -> Option<(Visibility, FnSig, Ident, Generics)> {
         match &iitem.kind {
             ItemKind::Fn(box ast::Fn { sig, ident, generics, .. }) => {
                 Some((iitem.vis.clone(), sig.clone(), ident.clone(), generics.clone()))
@@ -346,7 +345,7 @@ mod llvm_enzyme {
             define_opaque: None,
         });
         let mut rustc_ad_attr =
-            P(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff)));
+            Box::new(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff)));
 
         let ts2: Vec<TokenTree> = vec![TokenTree::Token(
             Token::new(TokenKind::Ident(sym::never, false.into()), span),
@@ -363,7 +362,7 @@ mod llvm_enzyme {
             args: ast::AttrArgs::Delimited(never_arg),
             tokens: None,
         };
-        let inline_never_attr = P(ast::NormalAttr { item: inline_item, tokens: None });
+        let inline_never_attr = Box::new(ast::NormalAttr { item: inline_item, tokens: None });
         let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
         let attr = outer_normal_attr(&rustc_ad_attr, new_id, span);
         let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id();
@@ -433,7 +432,7 @@ mod llvm_enzyme {
         let d_annotatable = match &item {
             Annotatable::AssocItem(_, _) => {
                 let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf);
-                let d_fn = P(ast::AssocItem {
+                let d_fn = Box::new(ast::AssocItem {
                     attrs: thin_vec![d_attr, inline_never],
                     id: ast::DUMMY_NODE_ID,
                     span,
@@ -453,7 +452,7 @@ mod llvm_enzyme {
                 let mut d_fn = ecx.item(span, thin_vec![d_attr, inline_never], ItemKind::Fn(asdf));
                 d_fn.vis = vis;
 
-                Annotatable::Stmt(P(ast::Stmt {
+                Annotatable::Stmt(Box::new(ast::Stmt {
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::StmtKind::Item(d_fn),
                     span,
@@ -506,7 +505,7 @@ mod llvm_enzyme {
         idents: &[Ident],
         errored: bool,
         generics: &Generics,
-    ) -> (P<ast::Block>, P<ast::Expr>, P<ast::Expr>, P<ast::Expr>) {
+    ) -> (Box<ast::Block>, Box<ast::Expr>, Box<ast::Expr>, Box<ast::Expr>) {
         let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]);
         let noop = ast::InlineAsm {
             asm_macro: ast::AsmMacro::Asm,
@@ -517,7 +516,7 @@ mod llvm_enzyme {
             options: ast::InlineAsmOptions::PURE | ast::InlineAsmOptions::NOMEM,
             line_spans: vec![],
         };
-        let noop_expr = ecx.expr_asm(span, P(noop));
+        let noop_expr = ecx.expr_asm(span, Box::new(noop));
         let unsf = ast::BlockCheckMode::Unsafe(ast::UnsafeSource::CompilerGenerated);
         let unsf_block = ast::Block {
             stmts: thin_vec![ecx.stmt_semi(noop_expr)],
@@ -526,7 +525,7 @@ mod llvm_enzyme {
             rules: unsf,
             span,
         };
-        let unsf_expr = ecx.expr_block(P(unsf_block));
+        let unsf_expr = ecx.expr_block(Box::new(unsf_block));
         let blackbox_call_expr = ecx.expr_path(ecx.path(span, blackbox_path));
         let primal_call = gen_primal_call(ecx, span, primal, idents, generics);
         let black_box_primal_call = ecx.expr_call(
@@ -578,7 +577,7 @@ mod llvm_enzyme {
         idents: Vec<Ident>,
         errored: bool,
         generics: &Generics,
-    ) -> P<ast::Block> {
+    ) -> Box<ast::Block> {
         let new_decl_span = d_sig.span;
 
         // Just adding some default inline-asm and black_box usages to prevent early inlining
@@ -634,7 +633,7 @@ mod llvm_enzyme {
             return body;
         }
 
-        let mut exprs: P<ast::Expr> = primal_call;
+        let mut exprs: Box<ast::Expr> = primal_call;
         let d_ret_ty = match d_sig.decl.output {
             FnRetTy::Ty(ref ty) => ty.clone(),
             FnRetTy::Default(span) => {
@@ -653,7 +652,7 @@ mod llvm_enzyme {
             } else {
                 let q = QSelf { ty: d_ret_ty, path_span: span, position: 0 };
                 let y = ExprKind::Path(
-                    Some(P(q)),
+                    Some(Box::new(q)),
                     ecx.path_ident(span, Ident::with_dummy_span(kw::Default)),
                 );
                 let default_call_expr = ecx.expr(span, y);
@@ -703,7 +702,7 @@ mod llvm_enzyme {
         primal: Ident,
         idents: &[Ident],
         generics: &Generics,
-    ) -> P<ast::Expr> {
+    ) -> Box<ast::Expr> {
         let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower;
 
         if has_self {
@@ -740,7 +739,7 @@ mod llvm_enzyme {
                                 },
                             );
 
-                            ast::AngleBracketedArg::Arg(ast::GenericArg::Type(P(ast::Ty {
+                            ast::AngleBracketedArg::Arg(ast::GenericArg::Type(Box::new(ast::Ty {
                                 id: type_param.id,
                                 span,
                                 kind: generic_param,
@@ -750,7 +749,7 @@ mod llvm_enzyme {
                         .collect();
 
                     function_path.args =
-                        Some(P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
+                        Some(Box::new(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
                             span,
                             args: generated_generic_types,
                         })));
@@ -856,7 +855,7 @@ mod llvm_enzyme {
                     for i in 0..x.width {
                         let mut shadow_arg = arg.clone();
                         // We += into the shadow in reverse mode.
-                        shadow_arg.ty = P(assure_mut_ref(&arg.ty));
+                        shadow_arg.ty = Box::new(assure_mut_ref(&arg.ty));
                         let old_name = if let PatKind::Ident(_, ident, _) = arg.pat.kind {
                             ident.name
                         } else {
@@ -866,7 +865,7 @@ mod llvm_enzyme {
                         let name: String = format!("d{}_{}", old_name, i);
                         new_inputs.push(name.clone());
                         let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span);
-                        shadow_arg.pat = P(ast::Pat {
+                        shadow_arg.pat = Box::new(ast::Pat {
                             id: ast::DUMMY_NODE_ID,
                             kind: PatKind::Ident(BindingMode::NONE, ident, None),
                             span: shadow_arg.pat.span,
@@ -898,7 +897,7 @@ mod llvm_enzyme {
                         let name: String = format!("b{}_{}", old_name, i);
                         new_inputs.push(name.clone());
                         let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span);
-                        shadow_arg.pat = P(ast::Pat {
+                        shadow_arg.pat = Box::new(ast::Pat {
                             id: ast::DUMMY_NODE_ID,
                             kind: PatKind::Ident(BindingMode::NONE, ident, None),
                             span: shadow_arg.pat.span,
@@ -942,7 +941,7 @@ mod llvm_enzyme {
                     let shadow_arg = ast::Param {
                         attrs: ThinVec::new(),
                         ty: ty.clone(),
-                        pat: P(ast::Pat {
+                        pat: Box::new(ast::Pat {
                             id: ast::DUMMY_NODE_ID,
                             kind: PatKind::Ident(BindingMode::NONE, ident, None),
                             span: ty.span,
@@ -966,7 +965,12 @@ mod llvm_enzyme {
                 FnRetTy::Default(span) => {
                     // We want to return std::hint::black_box(()).
                     let kind = TyKind::Tup(ThinVec::new());
-                    let ty = P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None });
+                    let ty = Box::new(rustc_ast::Ty {
+                        kind,
+                        id: ast::DUMMY_NODE_ID,
+                        span,
+                        tokens: None,
+                    });
                     d_decl.output = FnRetTy::Ty(ty.clone());
                     assert!(matches!(x.ret_activity, DiffActivity::None));
                     // this won't be used below, so any type would be fine.
@@ -987,7 +991,7 @@ mod llvm_enzyme {
                     };
                     TyKind::Array(ty.clone(), anon_const)
                 };
-                let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
+                let ty = Box::new(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
                 d_decl.output = FnRetTy::Ty(ty);
             }
             if matches!(x.ret_activity, DiffActivity::DualOnly | DiffActivity::DualvOnly) {
@@ -1000,7 +1004,8 @@ mod llvm_enzyme {
                         value: ecx.expr_usize(span, x.width as usize),
                     };
                     let kind = TyKind::Array(ty.clone(), anon_const);
-                    let ty = P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
+                    let ty =
+                        Box::new(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None });
                     d_decl.output = FnRetTy::Ty(ty);
                 }
             }
@@ -1022,14 +1027,14 @@ mod llvm_enzyme {
                         act_ret.insert(0, ty.clone());
                     }
                     let kind = TyKind::Tup(act_ret);
-                    P(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None })
+                    Box::new(rustc_ast::Ty { kind, id: ty.id, span: ty.span, tokens: None })
                 }
                 FnRetTy::Default(span) => {
                     if act_ret.len() == 1 {
                         act_ret[0].clone()
                     } else {
                         let kind = TyKind::Tup(act_ret.iter().map(|arg| arg.clone()).collect());
-                        P(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None })
+                        Box::new(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span, tokens: None })
                     }
                 }
             };
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index ec3b87467a9..dd770fe5f1a 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -2,7 +2,6 @@ use core::ops::ControlFlow;
 
 use rustc_ast as ast;
 use rustc_ast::mut_visit::MutVisitor;
-use rustc_ast::ptr::P;
 use rustc_ast::visit::{AssocCtxt, Visitor};
 use rustc_ast::{Attribute, HasAttrs, HasTokens, NodeId, mut_visit, visit};
 use rustc_errors::PResult;
@@ -132,7 +131,7 @@ impl CfgEval<'_> {
                     let stmt = parser
                         .parse_stmt_without_recovery(false, ForceCollect::Yes, false)?
                         .unwrap();
-                    Annotatable::Stmt(P(self.flat_map_stmt(stmt).pop().unwrap()))
+                    Annotatable::Stmt(Box::new(self.flat_map_stmt(stmt).pop().unwrap()))
                 }
                 Annotatable::Expr(_) => {
                     let mut expr = parser.parse_expr_force_collect()?;
@@ -166,7 +165,7 @@ impl MutVisitor for CfgEval<'_> {
         mut_visit::walk_expr(self, expr);
     }
 
-    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
+    fn filter_map_expr(&mut self, expr: Box<ast::Expr>) -> Option<Box<ast::Expr>> {
         let mut expr = configure!(self, expr);
         mut_visit::walk_expr(self, &mut expr);
         Some(expr)
@@ -185,24 +184,24 @@ impl MutVisitor for CfgEval<'_> {
         mut_visit::walk_flat_map_stmt(self, stmt)
     }
 
-    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
+    fn flat_map_item(&mut self, item: Box<ast::Item>) -> SmallVec<[Box<ast::Item>; 1]> {
         let item = configure!(self, item);
         mut_visit::walk_flat_map_item(self, item)
     }
 
     fn flat_map_assoc_item(
         &mut self,
-        item: P<ast::AssocItem>,
+        item: Box<ast::AssocItem>,
         ctxt: AssocCtxt,
-    ) -> SmallVec<[P<ast::AssocItem>; 1]> {
+    ) -> SmallVec<[Box<ast::AssocItem>; 1]> {
         let item = configure!(self, item);
         mut_visit::walk_flat_map_assoc_item(self, item, ctxt)
     }
 
     fn flat_map_foreign_item(
         &mut self,
-        foreign_item: P<ast::ForeignItem>,
-    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
+        foreign_item: Box<ast::ForeignItem>,
+    ) -> SmallVec<[Box<ast::ForeignItem>; 1]> {
         let foreign_item = configure!(self, foreign_item);
         mut_visit::walk_flat_map_foreign_item(self, foreign_item)
     }
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index fd2d740c020..8885017b930 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{ExprKind, LitIntType, LitKind, StrStyle, UintTy, token};
 use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
@@ -90,7 +89,7 @@ fn handle_array_element(
     cx: &ExtCtxt<'_>,
     guar: &mut Option<ErrorGuaranteed>,
     missing_literals: &mut Vec<rustc_span::Span>,
-    expr: &P<rustc_ast::Expr>,
+    expr: &Box<rustc_ast::Expr>,
 ) -> Option<u8> {
     let dcx = cx.dcx();
 
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index 990835fa277..a0f71a1868b 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, MetaItem, Mutability};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::{Span, sym};
@@ -119,7 +118,7 @@ fn get_substructure_equality_expr(
     cx: &ExtCtxt<'_>,
     span: Span,
     substructure: &Substructure<'_>,
-) -> P<Expr> {
+) -> Box<Expr> {
     use SubstructureFields::*;
 
     match substructure.fields {
@@ -180,7 +179,7 @@ fn get_substructure_equality_expr(
 ///
 /// Panics if there are not exactly two arguments to compare (should be `self`
 /// and `other`).
-fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> P<Expr> {
+fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> Box<Expr> {
     let [rhs] = &field.other_selflike_exprs[..] else {
         cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`");
     };
@@ -198,7 +197,7 @@ fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> P<Expr> {
 /// This is used to strip away any number of leading `&` from an expression
 /// (e.g., `&&&T` becomes `T`). Only removes immutable references; mutable
 /// references are preserved.
-fn peel_refs(mut expr: &P<Expr>) -> P<Expr> {
+fn peel_refs(mut expr: &Box<Expr>) -> Box<Expr> {
     while let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = &expr.kind {
         expr = &inner;
     }
@@ -210,7 +209,7 @@ fn peel_refs(mut expr: &P<Expr>) -> P<Expr> {
 ///
 /// If the given expression is a block, it is wrapped in parentheses; otherwise,
 /// it is returned unchanged.
-fn wrap_block_expr(cx: &ExtCtxt<'_>, expr: P<Expr>) -> P<Expr> {
+fn wrap_block_expr(cx: &ExtCtxt<'_>, expr: Box<Expr>) -> Box<Expr> {
     if matches!(&expr.kind, ExprKind::Block(..)) {
         return cx.expr_paren(expr.span, expr);
     }
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 1d63ce7d5fd..597af0e09c0 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -94,7 +94,7 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) ->
         field: &FieldInfo,
         index: usize,
         len: usize,
-    ) -> ast::ptr::P<ast::Expr> {
+    ) -> Box<ast::Expr> {
         if index < len - 1 {
             field.self_expr.clone()
         } else {
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index b4e2d27fed3..2462114ec24 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -56,7 +56,7 @@ pub(crate) fn expand_deriving_default(
     trait_def.expand(cx, mitem, item, push)
 }
 
-fn default_call(cx: &ExtCtxt<'_>, span: Span) -> ast::ptr::P<ast::Expr> {
+fn default_call(cx: &ExtCtxt<'_>, span: Span) -> Box<ast::Expr> {
     // Note that `kw::Default` is "default" and `sym::Default` is "Default"!
     let default_ident = cx.std_path(&[kw::Default, sym::Default, kw::Default]);
     cx.expr_call_global(span, default_ident, ThinVec::new())
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index fc9eed24ee0..3f4b47152c4 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -180,7 +180,6 @@ use std::{iter, vec};
 
 pub(crate) use StaticFields::*;
 pub(crate) use SubstructureFields::*;
-use rustc_ast::ptr::P;
 use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree};
 use rustc_ast::{
@@ -272,7 +271,7 @@ pub(crate) struct Substructure<'a> {
     pub type_ident: Ident,
     /// Verbatim access to any non-selflike arguments, i.e. arguments that
     /// don't have type `&Self`.
-    pub nonselflike_args: &'a [P<Expr>],
+    pub nonselflike_args: &'a [Box<Expr>],
     pub fields: &'a SubstructureFields<'a>,
 }
 
@@ -284,10 +283,10 @@ pub(crate) struct FieldInfo {
     pub name: Option<Ident>,
     /// The expression corresponding to this field of `self`
     /// (specifically, a reference to it).
-    pub self_expr: P<Expr>,
+    pub self_expr: Box<Expr>,
     /// The expressions corresponding to references to this field in
     /// the other selflike arguments.
-    pub other_selflike_exprs: Vec<P<Expr>>,
+    pub other_selflike_exprs: Vec<Box<Expr>>,
     pub maybe_scalar: bool,
 }
 
@@ -323,7 +322,7 @@ pub(crate) enum SubstructureFields<'a> {
     /// The discriminant of an enum. The first field is a `FieldInfo` for the discriminants, as
     /// if they were fields. The second field is the expression to combine the
     /// discriminant expression with; it will be `None` if no match is necessary.
-    EnumDiscr(FieldInfo, Option<P<Expr>>),
+    EnumDiscr(FieldInfo, Option<Box<Expr>>),
 
     /// A static method where `Self` is a struct.
     StaticStruct(&'a ast::VariantData, StaticFields),
@@ -345,7 +344,7 @@ pub(crate) fn combine_substructure(
 
 struct TypeParameter {
     bound_generic_params: ThinVec<ast::GenericParam>,
-    ty: P<ast::Ty>,
+    ty: Box<ast::Ty>,
 }
 
 /// The code snippets built up for derived code are sometimes used as blocks
@@ -354,23 +353,23 @@ struct TypeParameter {
 /// avoiding the insertion of any unnecessary blocks.
 ///
 /// The statements come before the expression.
-pub(crate) struct BlockOrExpr(ThinVec<ast::Stmt>, Option<P<Expr>>);
+pub(crate) struct BlockOrExpr(ThinVec<ast::Stmt>, Option<Box<Expr>>);
 
 impl BlockOrExpr {
     pub(crate) fn new_stmts(stmts: ThinVec<ast::Stmt>) -> BlockOrExpr {
         BlockOrExpr(stmts, None)
     }
 
-    pub(crate) fn new_expr(expr: P<Expr>) -> BlockOrExpr {
+    pub(crate) fn new_expr(expr: Box<Expr>) -> BlockOrExpr {
         BlockOrExpr(ThinVec::new(), Some(expr))
     }
 
-    pub(crate) fn new_mixed(stmts: ThinVec<ast::Stmt>, expr: Option<P<Expr>>) -> BlockOrExpr {
+    pub(crate) fn new_mixed(stmts: ThinVec<ast::Stmt>, expr: Option<Box<Expr>>) -> BlockOrExpr {
         BlockOrExpr(stmts, expr)
     }
 
     // Converts it into a block.
-    fn into_block(mut self, cx: &ExtCtxt<'_>, span: Span) -> P<ast::Block> {
+    fn into_block(mut self, cx: &ExtCtxt<'_>, span: Span) -> Box<ast::Block> {
         if let Some(expr) = self.1 {
             self.0.push(cx.stmt_expr(expr));
         }
@@ -378,7 +377,7 @@ impl BlockOrExpr {
     }
 
     // Converts it into an expression.
-    fn into_expr(self, cx: &ExtCtxt<'_>, span: Span) -> P<Expr> {
+    fn into_expr(self, cx: &ExtCtxt<'_>, span: Span) -> Box<Expr> {
         if self.0.is_empty() {
             match self.1 {
                 None => cx.expr_block(cx.block(span, ThinVec::new())),
@@ -432,7 +431,7 @@ fn find_type_parameters(
             {
                 self.type_params.push(TypeParameter {
                     bound_generic_params: self.bound_generic_params_stack.clone(),
-                    ty: P(ty.clone()),
+                    ty: Box::new(ty.clone()),
                 });
             }
 
@@ -544,7 +543,7 @@ impl<'a> TraitDef<'a> {
                         })
                         .cloned(),
                 );
-                push(Annotatable::Item(P(ast::Item { attrs, ..(*newitem).clone() })))
+                push(Annotatable::Item(Box::new(ast::Item { attrs, ..(*newitem).clone() })))
             }
             _ => unreachable!(),
         }
@@ -590,15 +589,15 @@ impl<'a> TraitDef<'a> {
         cx: &ExtCtxt<'_>,
         type_ident: Ident,
         generics: &Generics,
-        field_tys: Vec<P<ast::Ty>>,
-        methods: Vec<P<ast::AssocItem>>,
+        field_tys: Vec<Box<ast::Ty>>,
+        methods: Vec<Box<ast::AssocItem>>,
         is_packed: bool,
-    ) -> P<ast::Item> {
+    ) -> Box<ast::Item> {
         let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
 
         // Transform associated types from `deriving::ty::Ty` into `ast::AssocItem`
         let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| {
-            P(ast::AssocItem {
+            Box::new(ast::AssocItem {
                 id: ast::DUMMY_NODE_ID,
                 span: self.span,
                 vis: ast::Visibility {
@@ -853,8 +852,8 @@ impl<'a> TraitDef<'a> {
         generics: &Generics,
         from_scratch: bool,
         is_packed: bool,
-    ) -> P<ast::Item> {
-        let field_tys: Vec<P<ast::Ty>> =
+    ) -> Box<ast::Item> {
+        let field_tys: Vec<Box<ast::Ty>> =
             struct_def.fields().iter().map(|field| field.ty.clone()).collect();
 
         let methods = self
@@ -906,7 +905,7 @@ impl<'a> TraitDef<'a> {
         type_ident: Ident,
         generics: &Generics,
         from_scratch: bool,
-    ) -> P<ast::Item> {
+    ) -> Box<ast::Item> {
         let mut field_tys = Vec::new();
 
         for variant in &enum_def.variants {
@@ -962,7 +961,7 @@ impl<'a> MethodDef<'a> {
         cx: &ExtCtxt<'_>,
         trait_: &TraitDef<'_>,
         type_ident: Ident,
-        nonselflike_args: &[P<Expr>],
+        nonselflike_args: &[Box<Expr>],
         fields: &SubstructureFields<'_>,
     ) -> BlockOrExpr {
         let span = trait_.span;
@@ -978,7 +977,7 @@ impl<'a> MethodDef<'a> {
         trait_: &TraitDef<'_>,
         generics: &Generics,
         type_ident: Ident,
-    ) -> P<ast::Ty> {
+    ) -> Box<ast::Ty> {
         self.ret_ty.to_ty(cx, trait_.span, type_ident, generics)
     }
 
@@ -999,7 +998,8 @@ impl<'a> MethodDef<'a> {
         trait_: &TraitDef<'_>,
         type_ident: Ident,
         generics: &Generics,
-    ) -> (Option<ast::ExplicitSelf>, ThinVec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
+    ) -> (Option<ast::ExplicitSelf>, ThinVec<Box<Expr>>, Vec<Box<Expr>>, Vec<(Ident, Box<ast::Ty>)>)
+    {
         let mut selflike_args = ThinVec::new();
         let mut nonselflike_args = Vec::new();
         let mut nonself_arg_tys = Vec::new();
@@ -1036,9 +1036,9 @@ impl<'a> MethodDef<'a> {
         type_ident: Ident,
         generics: &Generics,
         explicit_self: Option<ast::ExplicitSelf>,
-        nonself_arg_tys: Vec<(Ident, P<ast::Ty>)>,
+        nonself_arg_tys: Vec<(Ident, Box<ast::Ty>)>,
         body: BlockOrExpr,
-    ) -> P<ast::AssocItem> {
+    ) -> Box<ast::AssocItem> {
         let span = trait_.span;
         // Create the generics that aren't for `Self`.
         let fn_generics = self.generics.to_generics(cx, span, type_ident, generics);
@@ -1065,7 +1065,7 @@ impl<'a> MethodDef<'a> {
         let defaultness = ast::Defaultness::Final;
 
         // Create the method.
-        P(ast::AssocItem {
+        Box::new(ast::AssocItem {
             id: ast::DUMMY_NODE_ID,
             attrs: self.attributes.clone(),
             span,
@@ -1128,8 +1128,8 @@ impl<'a> MethodDef<'a> {
         trait_: &TraitDef<'b>,
         struct_def: &'b VariantData,
         type_ident: Ident,
-        selflike_args: &[P<Expr>],
-        nonselflike_args: &[P<Expr>],
+        selflike_args: &[Box<Expr>],
+        nonselflike_args: &[Box<Expr>],
         is_packed: bool,
     ) -> BlockOrExpr {
         assert!(selflike_args.len() == 1 || selflike_args.len() == 2);
@@ -1151,7 +1151,7 @@ impl<'a> MethodDef<'a> {
         trait_: &TraitDef<'_>,
         struct_def: &VariantData,
         type_ident: Ident,
-        nonselflike_args: &[P<Expr>],
+        nonselflike_args: &[Box<Expr>],
     ) -> BlockOrExpr {
         let summary = trait_.summarise_struct(cx, struct_def);
 
@@ -1205,8 +1205,8 @@ impl<'a> MethodDef<'a> {
         trait_: &TraitDef<'b>,
         enum_def: &'b EnumDef,
         type_ident: Ident,
-        mut selflike_args: ThinVec<P<Expr>>,
-        nonselflike_args: &[P<Expr>],
+        mut selflike_args: ThinVec<Box<Expr>>,
+        nonselflike_args: &[Box<Expr>],
     ) -> BlockOrExpr {
         assert!(
             !selflike_args.is_empty(),
@@ -1418,7 +1418,7 @@ impl<'a> MethodDef<'a> {
         //          ...
         //          _ => ::core::intrinsics::unreachable(),
         //      }
-        let get_match_expr = |mut selflike_args: ThinVec<P<Expr>>| {
+        let get_match_expr = |mut selflike_args: ThinVec<Box<Expr>>| {
             let match_arg = if selflike_args.len() == 1 {
                 selflike_args.pop().unwrap()
             } else {
@@ -1454,7 +1454,7 @@ impl<'a> MethodDef<'a> {
         trait_: &TraitDef<'_>,
         enum_def: &EnumDef,
         type_ident: Ident,
-        nonselflike_args: &[P<Expr>],
+        nonselflike_args: &[Box<Expr>],
     ) -> BlockOrExpr {
         self.call_substructure_method(
             cx,
@@ -1503,7 +1503,7 @@ impl<'a> TraitDef<'a> {
         struct_def: &'a VariantData,
         prefixes: &[String],
         by_ref: ByRef,
-    ) -> ThinVec<P<ast::Pat>> {
+    ) -> ThinVec<Box<ast::Pat>> {
         prefixes
             .iter()
             .map(|prefix| {
@@ -1558,7 +1558,7 @@ impl<'a> TraitDef<'a> {
 
     fn create_fields<F>(&self, struct_def: &'a VariantData, mk_exprs: F) -> Vec<FieldInfo>
     where
-        F: Fn(usize, &ast::FieldDef, Span) -> Vec<P<ast::Expr>>,
+        F: Fn(usize, &ast::FieldDef, Span) -> Vec<Box<ast::Expr>>,
     {
         struct_def
             .fields()
@@ -1606,7 +1606,7 @@ impl<'a> TraitDef<'a> {
     fn create_struct_field_access_fields(
         &self,
         cx: &ExtCtxt<'_>,
-        selflike_args: &[P<Expr>],
+        selflike_args: &[Box<Expr>],
         struct_def: &'a VariantData,
         is_packed: bool,
     ) -> Vec<FieldInfo> {
@@ -1651,7 +1651,7 @@ pub(crate) enum CsFold<'a> {
 
     /// The combination of two field expressions. E.g. for `PartialEq::eq` this
     /// is something like `<field1 equality> && <field2 equality>`.
-    Combine(Span, P<Expr>, P<Expr>),
+    Combine(Span, Box<Expr>, Box<Expr>),
 
     // The fallback case for a struct or enum variant with no fields.
     Fieldless,
@@ -1665,9 +1665,9 @@ pub(crate) fn cs_fold<F>(
     trait_span: Span,
     substructure: &Substructure<'_>,
     mut f: F,
-) -> P<Expr>
+) -> Box<Expr>
 where
-    F: FnMut(&ExtCtxt<'_>, CsFold<'_>) -> P<Expr>,
+    F: FnMut(&ExtCtxt<'_>, CsFold<'_>) -> Box<Expr>,
 {
     match substructure.fields {
         EnumMatching(.., all_fields) | Struct(_, all_fields) => {
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
index f34a6ae1d98..00e70b21cf4 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
@@ -2,7 +2,6 @@
 //! when specifying impls to be derived.
 
 pub(crate) use Ty::*;
-use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
 use rustc_expand::base::ExtCtxt;
 use rustc_span::source_map::respan;
@@ -41,7 +40,7 @@ impl Path {
         span: Span,
         self_ty: Ident,
         self_generics: &Generics,
-    ) -> P<ast::Ty> {
+    ) -> Box<ast::Ty> {
         cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
     }
     pub(crate) fn to_path(
@@ -90,7 +89,7 @@ impl Ty {
         span: Span,
         self_ty: Ident,
         self_generics: &Generics,
-    ) -> P<ast::Ty> {
+    ) -> Box<ast::Ty> {
         match self {
             Ref(ty, mutbl) => {
                 let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
@@ -192,7 +191,7 @@ impl Bounds {
     }
 }
 
-pub(crate) fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (P<Expr>, ast::ExplicitSelf) {
+pub(crate) fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (Box<Expr>, ast::ExplicitSelf) {
     // This constructs a fresh `self` path.
     let self_path = cx.expr_self(span);
     let self_ty = respan(span, SelfKind::Region(None, ast::Mutability::Not));
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index e45d09b5796..1edc2965def 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -1,7 +1,6 @@
 //! The compiler code necessary to implement the `#[derive]` extensions.
 
 use rustc_ast as ast;
-use rustc_ast::ptr::P;
 use rustc_ast::{GenericArg, MetaItem};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
 use rustc_span::{Span, Symbol, sym};
@@ -66,7 +65,7 @@ impl MultiItemModifier for BuiltinDerive {
                         &mut |a| {
                             // Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
                             // to the function
-                            items.push(Annotatable::Stmt(P(ast::Stmt {
+                            items.push(Annotatable::Stmt(Box::new(ast::Stmt {
                                 id: ast::DUMMY_NODE_ID,
                                 kind: ast::StmtKind::Item(a.expect_item()),
                                 span,
@@ -91,20 +90,20 @@ fn call_intrinsic(
     cx: &ExtCtxt<'_>,
     span: Span,
     intrinsic: Symbol,
-    args: ThinVec<P<ast::Expr>>,
-) -> P<ast::Expr> {
+    args: ThinVec<Box<ast::Expr>>,
+) -> Box<ast::Expr> {
     let span = cx.with_def_site_ctxt(span);
     let path = cx.std_path(&[sym::intrinsics, intrinsic]);
     cx.expr_call_global(span, path, args)
 }
 
 /// Constructs an expression that calls the `unreachable` intrinsic.
-fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
+fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> Box<ast::Expr> {
     let span = cx.with_def_site_ctxt(span);
     let path = cx.std_path(&[sym::intrinsics, sym::unreachable]);
     let call = cx.expr_call_global(span, path, ThinVec::new());
 
-    cx.expr_block(P(ast::Block {
+    cx.expr_block(Box::new(ast::Block {
         stmts: thin_vec![cx.stmt_expr(call)],
         id: ast::DUMMY_NODE_ID,
         rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
@@ -116,7 +115,7 @@ fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> P<ast::Expr> {
 fn assert_ty_bounds(
     cx: &ExtCtxt<'_>,
     stmts: &mut ThinVec<ast::Stmt>,
-    ty: P<ast::Ty>,
+    ty: Box<ast::Ty>,
     span: Span,
     assert_path: &[Symbol],
 ) {
diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs
index ccfcc3079eb..08f555b9e52 100644
--- a/compiler/rustc_builtin_macros/src/edition_panic.rs
+++ b/compiler/rustc_builtin_macros/src/edition_panic.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::token::Delimiter;
 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
 use rustc_ast::*;
@@ -48,7 +47,7 @@ fn expand<'cx>(
     ExpandResult::Ready(MacEager::expr(
         cx.expr(
             sp,
-            ExprKind::MacCall(P(MacCall {
+            ExprKind::MacCall(Box::new(MacCall {
                 path: Path {
                     span: sp,
                     segments: cx
@@ -58,7 +57,7 @@ fn expand<'cx>(
                         .collect(),
                     tokens: None,
                 },
-                args: P(DelimArgs {
+                args: Box::new(DelimArgs {
                     dspan: DelimSpan::from_single(sp),
                     delim: Delimiter::Parenthesis,
                     tokens: tts,
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 6785cb6aef5..ec613b7b710 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,7 +1,6 @@
 use std::ops::Range;
 
 use parse::Position::ArgumentNamed;
-use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{
     Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
@@ -45,7 +44,7 @@ use PositionUsedAs::*;
 
 #[derive(Debug)]
 struct MacroInput {
-    fmtstr: P<Expr>,
+    fmtstr: Box<Expr>,
     args: FormatArguments,
     /// Whether the first argument was a string literal or a result from eager macro expansion.
     /// If it's not a string literal, we disallow implicit argument capturing.
@@ -1018,7 +1017,7 @@ fn expand_format_args_impl<'cx>(
             };
             match mac {
                 Ok(format_args) => {
-                    MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(P(format_args))))
+                    MacEager::expr(ecx.expr(sp, ExprKind::FormatArgs(Box::new(format_args))))
                 }
                 Err(guar) => MacEager::expr(DummyResult::raw_expr(sp, Some(guar))),
             }
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index 13d5b42942a..3e5a26c0556 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -346,18 +346,18 @@ pub(crate) mod printf {
         // ```regex
         // (?x)
         // ^ %
-        // (?: (?P<parameter> \d+) \$ )?
-        // (?P<flags> [-+ 0\#']* )
-        // (?P<width> \d+ | \* (?: (?P<widtha> \d+) \$ )? )?
-        // (?: \. (?P<precision> \d+ | \* (?: (?P<precisiona> \d+) \$ )? ) )?
-        // (?P<length>
+        // (?: (?Box<parameter> \d+) \$ )?
+        // (?Box<flags> [-+ 0\#']* )
+        // (?Box<width> \d+ | \* (?: (?Box<widtha> \d+) \$ )? )?
+        // (?: \. (?Box<precision> \d+ | \* (?: (?Box<precisiona> \d+) \$ )? ) )?
+        // (?Box<length>
         //     # Standard
         //     hh | h | ll | l | L | z | j | t
         //
         //     # Other
         //     | I32 | I64 | I | q
         // )?
-        // (?P<type> . )
+        // (?Box<type> . )
         // ```
 
         // Used to establish the full span at the end.
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 4b1958bce32..f14b1920722 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -1,7 +1,6 @@
 use rustc_ast::expand::allocator::{
     ALLOCATOR_METHODS, AllocatorMethod, AllocatorMethodInput, AllocatorTy, global_fn_name,
 };
-use rustc_ast::ptr::P;
 use rustc_ast::{
     self as ast, AttrVec, Expr, Fn, FnHeader, FnSig, Generics, ItemKind, Mutability, Param, Safety,
     Stmt, StmtKind, Ty, TyKind,
@@ -51,7 +50,7 @@ pub(crate) fn expand(
     let const_body = ecx.expr_block(ecx.block(span, stmts));
     let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
     let const_item = if is_stmt {
-        Annotatable::Stmt(P(ecx.stmt_item(span, const_item)))
+        Annotatable::Stmt(Box::new(ecx.stmt_item(span, const_item)))
     } else {
         Annotatable::Item(const_item)
     };
@@ -90,7 +89,7 @@ impl AllocFnFactory<'_, '_> {
         self.cx.stmt_item(self.ty_span, item)
     }
 
-    fn call_allocator(&self, method: Symbol, mut args: ThinVec<P<Expr>>) -> P<Expr> {
+    fn call_allocator(&self, method: Symbol, mut args: ThinVec<Box<Expr>>) -> Box<Expr> {
         let method = self.cx.std_path(&[sym::alloc, sym::GlobalAlloc, method]);
         let method = self.cx.expr_path(self.cx.path(self.ty_span, method));
         let allocator = self.cx.path_ident(self.ty_span, self.global);
@@ -105,7 +104,7 @@ impl AllocFnFactory<'_, '_> {
         thin_vec![self.cx.attr_word(sym::rustc_std_internal_symbol, self.span)]
     }
 
-    fn arg_ty(&self, input: &AllocatorMethodInput, args: &mut ThinVec<Param>) -> P<Expr> {
+    fn arg_ty(&self, input: &AllocatorMethodInput, args: &mut ThinVec<Param>) -> Box<Expr> {
         match input.ty {
             AllocatorTy::Layout => {
                 // If an allocator method is ever introduced having multiple
@@ -148,7 +147,7 @@ impl AllocFnFactory<'_, '_> {
         }
     }
 
-    fn ret_ty(&self, ty: &AllocatorTy) -> P<Ty> {
+    fn ret_ty(&self, ty: &AllocatorTy) -> Box<Ty> {
         match *ty {
             AllocatorTy::ResultPtr => self.ptr_u8(),
 
@@ -160,12 +159,12 @@ impl AllocFnFactory<'_, '_> {
         }
     }
 
-    fn usize(&self) -> P<Ty> {
+    fn usize(&self) -> Box<Ty> {
         let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
         self.cx.ty_path(usize)
     }
 
-    fn ptr_u8(&self) -> P<Ty> {
+    fn ptr_u8(&self) -> Box<Ty> {
         let u8 = self.cx.path_ident(self.span, Ident::new(sym::u8, self.span));
         let ty_u8 = self.cx.ty_path(u8);
         self.cx.ty_ptr(self.span, ty_u8, Mutability::Mut)
diff --git a/compiler/rustc_builtin_macros/src/iter.rs b/compiler/rustc_builtin_macros/src/iter.rs
index 7ad83903a1b..e9f340ef119 100644
--- a/compiler/rustc_builtin_macros/src/iter.rs
+++ b/compiler/rustc_builtin_macros/src/iter.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{CoroutineKind, DUMMY_NODE_ID, Expr, ast, token};
 use rustc_errors::PResult;
@@ -24,7 +23,7 @@ fn parse_closure<'a>(
     cx: &mut ExtCtxt<'a>,
     span: Span,
     stream: TokenStream,
-) -> PResult<'a, P<Expr>> {
+) -> PResult<'a, Box<Expr>> {
     let mut closure_parser = cx.new_parser_from_tts(stream);
 
     let coroutine_kind = Some(CoroutineKind::Gen {
diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs
index b61af0b0aaa..34faafdc07c 100644
--- a/compiler/rustc_builtin_macros/src/pattern_type.rs
+++ b/compiler/rustc_builtin_macros/src/pattern_type.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast, token};
 use rustc_errors::PResult;
@@ -22,7 +21,10 @@ pub(crate) fn expand<'cx>(
     ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat))))
 }
 
-fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<TyPat>)> {
+fn parse_pat_ty<'a>(
+    cx: &mut ExtCtxt<'a>,
+    stream: TokenStream,
+) -> PResult<'a, (Box<Ty>, Box<TyPat>)> {
     let mut parser = cx.new_parser_from_tts(stream);
 
     let ty = parser.parse_ty()?;
@@ -45,15 +47,15 @@ fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P
     Ok((ty, pat))
 }
 
-fn ty_pat(kind: TyPatKind, span: Span) -> P<TyPat> {
-    P(TyPat { id: DUMMY_NODE_ID, kind, span, tokens: None })
+fn ty_pat(kind: TyPatKind, span: Span) -> Box<TyPat> {
+    Box::new(TyPat { id: DUMMY_NODE_ID, kind, span, tokens: None })
 }
 
-fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> P<TyPat> {
+fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> Box<TyPat> {
     let kind = match pat.kind {
         ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
-            start.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
-            end.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
+            start.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })),
+            end.map(|value| Box::new(AnonConst { id: DUMMY_NODE_ID, value })),
             include_end,
         ),
         ast::PatKind::Or(variants) => {
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index df70c93c1c2..f440adf6cf0 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -1,6 +1,5 @@
 use std::{mem, slice};
 
-use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast::{self as ast, HasNodeId, NodeId, attr};
 use rustc_ast_pretty::pprust;
@@ -286,7 +285,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
 //              // ...
 //          ];
 //      }
-fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
+fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> Box<ast::Item> {
     let expn_id = cx.resolver.expansion_for_ast_pass(
         DUMMY_SP,
         AstPass::ProcMacroHarness,
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index ecfd46a84ec..37bab5be542 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -3,7 +3,6 @@ use std::rc::Rc;
 use std::sync::Arc;
 
 use rustc_ast as ast;
-use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{join_path_idents, token};
 use rustc_ast_pretty::pprust;
@@ -144,7 +143,7 @@ pub(crate) fn expand_include<'cx>(
         node_id: ast::NodeId,
     }
     impl<'a> MacResult for ExpandInclude<'a> {
-        fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<P<ast::Expr>> {
+        fn make_expr(mut self: Box<ExpandInclude<'a>>) -> Option<Box<ast::Expr>> {
             let expr = parse_expr(&mut self.p).ok()?;
             if self.p.token != token::Eof {
                 self.p.psess.buffer_lint(
@@ -157,7 +156,7 @@ pub(crate) fn expand_include<'cx>(
             Some(expr)
         }
 
-        fn make_items(mut self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
+        fn make_items(mut self: Box<ExpandInclude<'a>>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
             let mut ret = SmallVec::new();
             loop {
                 match self.p.parse_item(ForceCollect::No) {
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 7b57c02b197..7a189ee1f4d 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -4,7 +4,6 @@
 use std::assert_matches::assert_matches;
 use std::iter;
 
-use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, GenericParamKind, HasNodeId, attr, join_path_idents};
 use rustc_ast_pretty::pprust;
 use rustc_attr_parsing::AttributeParser;
@@ -78,7 +77,7 @@ pub(crate) fn expand_test_case(
     }
 
     let ret = if is_stmt {
-        Annotatable::Stmt(P(ecx.stmt_item(item.span, item)))
+        Annotatable::Stmt(Box::new(ecx.stmt_item(item.span, item)))
     } else {
         Annotatable::Item(item)
     };
@@ -131,7 +130,7 @@ pub(crate) fn expand_test_or_bench(
     let ast::ItemKind::Fn(fn_) = &item.kind else {
         not_testable_error(cx, attr_sp, Some(&item));
         return if is_stmt {
-            vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
+            vec![Annotatable::Stmt(Box::new(cx.stmt_item(item.span, item)))]
         } else {
             vec![Annotatable::Item(item)]
         };
@@ -155,7 +154,7 @@ pub(crate) fn expand_test_or_bench(
     };
     if check_result.is_err() {
         return if is_stmt {
-            vec![Annotatable::Stmt(P(cx.stmt_item(item.span, item)))]
+            vec![Annotatable::Stmt(Box::new(cx.stmt_item(item.span, item)))]
         } else {
             vec![Annotatable::Item(item)]
         };
@@ -201,7 +200,7 @@ pub(crate) fn expand_test_or_bench(
     // `-Cinstrument-coverage` builds.
     // This requires `#[allow_internal_unstable(coverage_attribute)]` on the
     // corresponding macro declaration in `core::macros`.
-    let coverage_off = |mut expr: P<ast::Expr>| {
+    let coverage_off = |mut expr: Box<ast::Expr>| {
         assert_matches!(expr.kind, ast::ExprKind::Closure(_));
         expr.attrs.push(cx.attr_nested_word(sym::coverage, sym::off, sp));
         expr
@@ -388,11 +387,11 @@ pub(crate) fn expand_test_or_bench(
     if is_stmt {
         vec![
             // Access to libtest under a hygienic name
-            Annotatable::Stmt(P(cx.stmt_item(sp, test_extern))),
+            Annotatable::Stmt(Box::new(cx.stmt_item(sp, test_extern))),
             // The generated test case
-            Annotatable::Stmt(P(cx.stmt_item(sp, test_const))),
+            Annotatable::Stmt(Box::new(cx.stmt_item(sp, test_const))),
             // The original item
-            Annotatable::Stmt(P(cx.stmt_item(sp, item))),
+            Annotatable::Stmt(Box::new(cx.stmt_item(sp, item))),
         ]
     } else {
         vec![
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 111c85d49eb..e803f3be82b 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -5,7 +5,6 @@ use std::mem;
 use rustc_ast as ast;
 use rustc_ast::entry::EntryPointType;
 use rustc_ast::mut_visit::*;
-use rustc_ast::ptr::P;
 use rustc_ast::visit::Visitor;
 use rustc_ast::{ModKind, attr};
 use rustc_errors::DiagCtxtHandle;
@@ -284,7 +283,7 @@ fn generate_test_harness(
 /// [`TestCtxt::reexport_test_harness_main`] provides a different name for the `main`
 /// function and [`TestCtxt::test_runner`] provides a path that replaces
 /// `test::test_main_static`.
-fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
+fn mk_main(cx: &mut TestCtxt<'_>) -> Box<ast::Item> {
     let sp = cx.def_site;
     let ecx = &cx.ext_cx;
     let test_ident = Ident::new(sym::test, sp);
@@ -348,7 +347,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
         define_opaque: None,
     }));
 
-    let main = P(ast::Item {
+    let main = Box::new(ast::Item {
         attrs: thin_vec![main_attr, coverage_attr, doc_hidden_attr],
         id: ast::DUMMY_NODE_ID,
         kind: main,
@@ -364,7 +363,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
 
 /// Creates a slice containing every test like so:
 /// &[&test1, &test2]
-fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
+fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> Box<ast::Expr> {
     debug!("building test vector from {} tests", cx.test_cases.len());
     let ecx = &cx.ext_cx;
 
diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs
index 38fec2bff14..f00c170e485 100644
--- a/compiler/rustc_builtin_macros/src/util.rs
+++ b/compiler/rustc_builtin_macros/src/util.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{self as ast, AttrStyle, Attribute, MetaItem, attr, token};
 use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
@@ -83,7 +82,7 @@ type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), Err
 #[allow(rustc::untranslatable_diagnostic)]
 pub(crate) fn expr_to_spanned_string<'a>(
     cx: &'a mut ExtCtxt<'_>,
-    expr: P<ast::Expr>,
+    expr: Box<ast::Expr>,
     err_msg: &'static str,
 ) -> ExpandResult<ExprToSpannedStringResult<'a>, ()> {
     if !cx.force_mode
@@ -135,7 +134,7 @@ pub(crate) fn expr_to_spanned_string<'a>(
 /// compilation on error, merely emits a non-fatal error and returns `Err`.
 pub(crate) fn expr_to_string(
     cx: &mut ExtCtxt<'_>,
-    expr: P<ast::Expr>,
+    expr: Box<ast::Expr>,
     err_msg: &'static str,
 ) -> ExpandResult<Result<(Symbol, ast::StrStyle), ErrorGuaranteed>, ()> {
     expr_to_spanned_string(cx, expr, err_msg).map(|res| {
@@ -158,7 +157,7 @@ pub(crate) fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, nam
 }
 
 /// Parse an expression. On error, emit it, advancing to `Eof`, and return `Err`.
-pub(crate) fn parse_expr(p: &mut parser::Parser<'_>) -> Result<P<ast::Expr>, ErrorGuaranteed> {
+pub(crate) fn parse_expr(p: &mut parser::Parser<'_>) -> Result<Box<ast::Expr>, ErrorGuaranteed> {
     let guar = match p.parse_expr() {
         Ok(expr) => return Ok(expr),
         Err(err) => err.emit(),
@@ -209,7 +208,7 @@ pub(crate) fn get_single_expr_from_tts(
     span: Span,
     tts: TokenStream,
     name: &str,
-) -> ExpandResult<Result<P<ast::Expr>, ErrorGuaranteed>, ()> {
+) -> ExpandResult<Result<Box<ast::Expr>, ErrorGuaranteed>, ()> {
     let mut p = cx.new_parser_from_tts(tts);
     if p.token == token::Eof {
         let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name });
@@ -232,7 +231,7 @@ pub(crate) fn get_single_expr_from_tts(
 pub(crate) fn get_exprs_from_tts(
     cx: &mut ExtCtxt<'_>,
     tts: TokenStream,
-) -> ExpandResult<Result<Vec<P<ast::Expr>>, ErrorGuaranteed>, ()> {
+) -> ExpandResult<Result<Vec<Box<ast::Expr>>, ErrorGuaranteed>, ()> {
     let mut p = cx.new_parser_from_tts(tts);
     let mut es = Vec::new();
     while p.token != token::Eof {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 4ff5773a06c..ed40901ac9b 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -969,7 +969,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = amount.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -982,7 +982,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let old =
                 fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Add, ptr, amount);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_xsub => {
@@ -991,7 +991,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = amount.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1004,7 +1004,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let old =
                 fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Sub, ptr, amount);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_and => {
@@ -1013,7 +1013,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1025,7 +1025,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::And, ptr, src);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_or => {
@@ -1034,7 +1034,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1046,7 +1046,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Or, ptr, src);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_xor => {
@@ -1055,7 +1055,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1067,7 +1067,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Xor, ptr, src);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_nand => {
@@ -1076,7 +1076,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1088,7 +1088,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Nand, ptr, src);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_max => {
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 34ade3d025f..f7a7a3f8c7e 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1671,6 +1671,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         dst: RValue<'gcc>,
         src: RValue<'gcc>,
         order: AtomicOrdering,
+        ret_ptr: bool,
     ) -> RValue<'gcc> {
         let size = get_maybe_pointer_size(src);
         let name = match op {
@@ -1698,6 +1699,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let atomic_function = self.context.get_builtin_function(name);
         let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
 
+        // FIXME: If `ret_ptr` is true and `src` is an integer, we should really tell GCC
+        // that this is a pointer operation that needs to preserve provenance -- but like LLVM,
+        // GCC does not currently seems to support that.
         let void_ptr_type = self.context.new_type::<*mut ()>();
         let volatile_void_ptr_type = void_ptr_type.make_volatile();
         let dst = self.context.new_cast(self.location, dst, volatile_void_ptr_type);
@@ -1705,7 +1709,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let new_src_type = atomic_function.get_param(1).to_rvalue().get_type();
         let src = self.context.new_bitcast(self.location, src, new_src_type);
         let res = self.context.new_call(self.location, atomic_function, &[dst, src, order]);
-        self.context.new_cast(self.location, res, src.get_type())
+        let res_type = if ret_ptr { void_ptr_type } else { src.get_type() };
+        self.context.new_cast(self.location, res, res_type)
     }
 
     fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope) {
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index bd175e560c7..32cdef075e7 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1327,15 +1327,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         &mut self,
         op: rustc_codegen_ssa::common::AtomicRmwBinOp,
         dst: &'ll Value,
-        mut src: &'ll Value,
+        src: &'ll Value,
         order: rustc_middle::ty::AtomicOrdering,
+        ret_ptr: bool,
     ) -> &'ll Value {
-        // The only RMW operation that LLVM supports on pointers is compare-exchange.
-        let requires_cast_to_int = self.val_ty(src) == self.type_ptr()
-            && op != rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicXchg;
-        if requires_cast_to_int {
-            src = self.ptrtoint(src, self.type_isize());
-        }
+        // FIXME: If `ret_ptr` is true and `src` is not a pointer, we *should* tell LLVM that the
+        // LHS is a pointer and the operation should be provenance-preserving, but LLVM does not
+        // currently support that (https://github.com/llvm/llvm-project/issues/120837).
         let mut res = unsafe {
             llvm::LLVMBuildAtomicRMW(
                 self.llbuilder,
@@ -1346,7 +1344,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 llvm::False, // SingleThreaded
             )
         };
-        if requires_cast_to_int {
+        if ret_ptr && self.val_ty(res) != self.type_ptr() {
             res = self.inttoptr(res, self.type_ptr());
         }
         res
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 3b290e5a129..28d2100f478 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -377,24 +377,25 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
     let target_abi = sess.target.options.abi.as_ref();
     let target_pointer_width = sess.target.pointer_width;
     let version = get_version();
+    let lt_20_1_1 = version < (20, 1, 1);
+    let lt_21_0_0 = version < (21, 0, 0);
 
     cfg.has_reliable_f16 = match (target_arch, target_os) {
-        // Selection failure <https://github.com/llvm/llvm-project/issues/50374>
-        ("s390x", _) => false,
-        // LLVM crash without neon <https://github.com/llvm/llvm-project/issues/129394> (now fixed)
+        // LLVM crash without neon <https://github.com/llvm/llvm-project/issues/129394> (fixed in llvm20)
         ("aarch64", _)
-            if !cfg.target_features.iter().any(|f| f.as_str() == "neon")
-                && version < (20, 1, 1) =>
+            if !cfg.target_features.iter().any(|f| f.as_str() == "neon") && lt_20_1_1 =>
         {
             false
         }
         // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
         ("arm64ec", _) => false,
+        // Selection failure <https://github.com/llvm/llvm-project/issues/50374> (fixed in llvm21)
+        ("s390x", _) if lt_21_0_0 => false,
         // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
         ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
         // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
         ("csky", _) => false,
-        ("hexagon", _) => false,
+        ("hexagon", _) if lt_21_0_0 => false, // (fixed in llvm21)
         ("powerpc" | "powerpc64", _) => false,
         ("sparc" | "sparc64", _) => false,
         ("wasm32" | "wasm64", _) => false,
@@ -407,9 +408,10 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
     cfg.has_reliable_f128 = match (target_arch, target_os) {
         // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
         ("arm64ec", _) => false,
-        // Selection bug <https://github.com/llvm/llvm-project/issues/96432>
-        ("mips64" | "mips64r6", _) => false,
-        // Selection bug <https://github.com/llvm/llvm-project/issues/95471>
+        // Selection bug <https://github.com/llvm/llvm-project/issues/96432> (fixed in llvm20)
+        ("mips64" | "mips64r6", _) if lt_20_1_1 => false,
+        // Selection bug <https://github.com/llvm/llvm-project/issues/95471>. This issue is closed
+        // but basic math still does not work.
         ("nvptx64", _) => false,
         // Unsupported https://github.com/llvm/llvm-project/issues/121122
         ("amdgpu", _) => false,
@@ -419,8 +421,8 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
         // ABI unsupported  <https://github.com/llvm/llvm-project/issues/41838>
         ("sparc", _) => false,
         // Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
-        // not fail if our compiler-builtins is linked.
-        ("x86", _) => false,
+        // not fail if our compiler-builtins is linked. (fixed in llvm21)
+        ("x86", _) if lt_21_0_0 => false,
         // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
         ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
         // There are no known problems on other platforms, so the only requirement is that symbols
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index a70d0011d16..3ca070acc9d 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -101,6 +101,8 @@ codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization
 
 codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
 
+codegen_ssa_invalid_monomorphization_basic_integer_or_ptr_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer or pointer type, found `{$ty}`
+
 codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
 
 codegen_ssa_invalid_monomorphization_cast_wide_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast wide pointer `{$ty}`
@@ -178,6 +180,10 @@ codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented y
 
 codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error}
 
+codegen_ssa_link_exe_status_stack_buffer_overrun = 0xc0000409 is `STATUS_STACK_BUFFER_OVERRUN`
+    .abort_note = this may have been caused by a program abort and not a stack buffer overrun
+    .event_log_note = consider checking the Application Event Log for Windows Error Reporting events to see the fail fast error code
+
 codegen_ssa_link_exe_unexpected_error = `link.exe` returned an unexpected error
 
 codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker
diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs
index d242efaf4fd..2f68bad1695 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple.rs
@@ -17,7 +17,7 @@ mod tests;
 
 /// The canonical name of the desired SDK for a given target.
 pub(super) fn sdk_name(target: &Target) -> &'static str {
-    match (&*target.os, &*target.abi) {
+    match (&*target.os, &*target.env) {
         ("macos", "") => "MacOSX",
         ("ios", "") => "iPhoneOS",
         ("ios", "sim") => "iPhoneSimulator",
@@ -34,7 +34,7 @@ pub(super) fn sdk_name(target: &Target) -> &'static str {
 }
 
 pub(super) fn macho_platform(target: &Target) -> u32 {
-    match (&*target.os, &*target.abi) {
+    match (&*target.os, &*target.env) {
         ("macos", _) => object::macho::PLATFORM_MACOS,
         ("ios", "macabi") => object::macho::PLATFORM_MACCATALYST,
         ("ios", "sim") => object::macho::PLATFORM_IOSSIMULATOR,
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index b69fbf61185..3ec0d900994 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -880,6 +880,14 @@ fn link_natively(
                             windows_registry::find_tool(&sess.target.arch, "link.exe").is_some();
 
                         sess.dcx().emit_note(errors::LinkExeUnexpectedError);
+
+                        // STATUS_STACK_BUFFER_OVERRUN is also used for fast abnormal program termination, e.g. abort().
+                        // Emit a special diagnostic to let people know that this most likely doesn't indicate a stack buffer overrun.
+                        const STATUS_STACK_BUFFER_OVERRUN: i32 = 0xc0000409u32 as _;
+                        if code == STATUS_STACK_BUFFER_OVERRUN {
+                            sess.dcx().emit_note(errors::LinkExeStatusStackBufferOverrun);
+                        }
+
                         if is_vs_installed && has_linker {
                             // the linker is broken
                             sess.dcx().emit_note(errors::RepairVSBuildTools);
@@ -3026,7 +3034,7 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool
 /// We need to communicate five things to the linker on Apple/Darwin targets:
 /// - The architecture.
 /// - The operating system (and that it's an Apple platform).
-/// - The environment / ABI.
+/// - The environment.
 /// - The deployment target.
 /// - The SDK version.
 fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
@@ -3040,7 +3048,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
     // `sess.target.arch` (`target_arch`) is not detailed enough.
     let llvm_arch = sess.target.llvm_target.split_once('-').expect("LLVM target must have arch").0;
     let target_os = &*sess.target.os;
-    let target_abi = &*sess.target.abi;
+    let target_env = &*sess.target.env;
 
     // The architecture name to forward to the linker.
     //
@@ -3091,14 +3099,14 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
         // > - visionos-simulator
         // > - xros-simulator
         // > - driverkit
-        let platform_name = match (target_os, target_abi) {
+        let platform_name = match (target_os, target_env) {
             (os, "") => os,
             ("ios", "macabi") => "mac-catalyst",
             ("ios", "sim") => "ios-simulator",
             ("tvos", "sim") => "tvos-simulator",
             ("watchos", "sim") => "watchos-simulator",
             ("visionos", "sim") => "visionos-simulator",
-            _ => bug!("invalid OS/ABI combination for Apple target: {target_os}, {target_abi}"),
+            _ => bug!("invalid OS/env combination for Apple target: {target_os}, {target_env}"),
         };
 
         let min_version = sess.apple_deployment_target().fmt_full().to_string();
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 3d787d8bdbd..7ac830bcda9 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -550,6 +550,18 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
 #[diag(codegen_ssa_link_exe_unexpected_error)]
 pub(crate) struct LinkExeUnexpectedError;
 
+pub(crate) struct LinkExeStatusStackBufferOverrun;
+
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for LinkExeStatusStackBufferOverrun {
+    fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
+        let mut diag =
+            Diag::new(dcx, level, fluent::codegen_ssa_link_exe_status_stack_buffer_overrun);
+        diag.note(fluent::codegen_ssa_abort_note);
+        diag.note(fluent::codegen_ssa_event_log_note);
+        diag
+    }
+}
+
 #[derive(Diagnostic)]
 #[diag(codegen_ssa_repair_vs_build_tools)]
 pub(crate) struct RepairVSBuildTools;
@@ -764,6 +776,14 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
+    #[diag(codegen_ssa_invalid_monomorphization_basic_integer_or_ptr_type, code = E0511)]
+    BasicIntegerOrPtrType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
     #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = E0511)]
     BasicFloatType {
         #[primary_span]
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index fc95f62b4a4..3c667b8e882 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -92,6 +92,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let invalid_monomorphization_int_type = |ty| {
             bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
         };
+        let invalid_monomorphization_int_or_ptr_type = |ty| {
+            bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerOrPtrType {
+                span,
+                name,
+                ty,
+            });
+        };
 
         let parse_atomic_ordering = |ord: ty::Value<'tcx>| {
             let discr = ord.valtree.unwrap_branch()[0].unwrap_leaf();
@@ -351,7 +358,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             sym::atomic_load => {
                 let ty = fn_args.type_at(0);
                 if !(int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr()) {
-                    invalid_monomorphization_int_type(ty);
+                    invalid_monomorphization_int_or_ptr_type(ty);
                     return Ok(());
                 }
                 let ordering = fn_args.const_at(1).to_value();
@@ -367,7 +374,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             sym::atomic_store => {
                 let ty = fn_args.type_at(0);
                 if !(int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr()) {
-                    invalid_monomorphization_int_type(ty);
+                    invalid_monomorphization_int_or_ptr_type(ty);
                     return Ok(());
                 }
                 let ordering = fn_args.const_at(1).to_value();
@@ -377,10 +384,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 bx.atomic_store(val, ptr, parse_atomic_ordering(ordering), size);
                 return Ok(());
             }
+            // These are all AtomicRMW ops
             sym::atomic_cxchg | sym::atomic_cxchgweak => {
                 let ty = fn_args.type_at(0);
                 if !(int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr()) {
-                    invalid_monomorphization_int_type(ty);
+                    invalid_monomorphization_int_or_ptr_type(ty);
                     return Ok(());
                 }
                 let succ_ordering = fn_args.const_at(1).to_value();
@@ -407,7 +415,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
                 return Ok(());
             }
-            // These are all AtomicRMW ops
             sym::atomic_max | sym::atomic_min => {
                 let atom_op = if name == sym::atomic_max {
                     AtomicRmwBinOp::AtomicMax
@@ -420,7 +427,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     let ordering = fn_args.const_at(1).to_value();
                     let ptr = args[0].immediate();
                     let val = args[1].immediate();
-                    bx.atomic_rmw(atom_op, ptr, val, parse_atomic_ordering(ordering))
+                    bx.atomic_rmw(
+                        atom_op,
+                        ptr,
+                        val,
+                        parse_atomic_ordering(ordering),
+                        /* ret_ptr */ false,
+                    )
                 } else {
                     invalid_monomorphization_int_type(ty);
                     return Ok(());
@@ -438,21 +451,44 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     let ordering = fn_args.const_at(1).to_value();
                     let ptr = args[0].immediate();
                     let val = args[1].immediate();
-                    bx.atomic_rmw(atom_op, ptr, val, parse_atomic_ordering(ordering))
+                    bx.atomic_rmw(
+                        atom_op,
+                        ptr,
+                        val,
+                        parse_atomic_ordering(ordering),
+                        /* ret_ptr */ false,
+                    )
                 } else {
                     invalid_monomorphization_int_type(ty);
                     return Ok(());
                 }
             }
-            sym::atomic_xchg
-            | sym::atomic_xadd
+            sym::atomic_xchg => {
+                let ty = fn_args.type_at(0);
+                let ordering = fn_args.const_at(1).to_value();
+                if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
+                    let ptr = args[0].immediate();
+                    let val = args[1].immediate();
+                    let atomic_op = AtomicRmwBinOp::AtomicXchg;
+                    bx.atomic_rmw(
+                        atomic_op,
+                        ptr,
+                        val,
+                        parse_atomic_ordering(ordering),
+                        /* ret_ptr */ ty.is_raw_ptr(),
+                    )
+                } else {
+                    invalid_monomorphization_int_or_ptr_type(ty);
+                    return Ok(());
+                }
+            }
+            sym::atomic_xadd
             | sym::atomic_xsub
             | sym::atomic_and
             | sym::atomic_nand
             | sym::atomic_or
             | sym::atomic_xor => {
                 let atom_op = match name {
-                    sym::atomic_xchg => AtomicRmwBinOp::AtomicXchg,
                     sym::atomic_xadd => AtomicRmwBinOp::AtomicAdd,
                     sym::atomic_xsub => AtomicRmwBinOp::AtomicSub,
                     sym::atomic_and => AtomicRmwBinOp::AtomicAnd,
@@ -462,14 +498,28 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     _ => unreachable!(),
                 };
 
-                let ty = fn_args.type_at(0);
-                if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
-                    let ordering = fn_args.const_at(1).to_value();
-                    let ptr = args[0].immediate();
-                    let val = args[1].immediate();
-                    bx.atomic_rmw(atom_op, ptr, val, parse_atomic_ordering(ordering))
+                // The type of the in-memory data.
+                let ty_mem = fn_args.type_at(0);
+                // The type of the 2nd operand, given by-value.
+                let ty_op = fn_args.type_at(1);
+
+                let ordering = fn_args.const_at(2).to_value();
+                // We require either both arguments to have the same integer type, or the first to
+                // be a pointer and the second to be `usize`.
+                if (int_type_width_signed(ty_mem, bx.tcx()).is_some() && ty_op == ty_mem)
+                    || (ty_mem.is_raw_ptr() && ty_op == bx.tcx().types.usize)
+                {
+                    let ptr = args[0].immediate(); // of type "pointer to `ty_mem`"
+                    let val = args[1].immediate(); // of type `ty_op`
+                    bx.atomic_rmw(
+                        atom_op,
+                        ptr,
+                        val,
+                        parse_atomic_ordering(ordering),
+                        /* ret_ptr */ ty_mem.is_raw_ptr(),
+                    )
                 } else {
-                    invalid_monomorphization_int_type(ty);
+                    invalid_monomorphization_int_or_ptr_type(ty_mem);
                     return Ok(());
                 }
             }
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 4b18146863b..f417d1a7bf7 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -548,12 +548,15 @@ pub trait BuilderMethods<'a, 'tcx>:
         failure_order: AtomicOrdering,
         weak: bool,
     ) -> (Self::Value, Self::Value);
+    /// `ret_ptr` indicates whether the return type (which is also the type `dst` points to)
+    /// is a pointer or the same type as `src`.
     fn atomic_rmw(
         &mut self,
         op: AtomicRmwBinOp,
         dst: Self::Value,
         src: Self::Value,
         order: AtomicOrdering,
+        ret_ptr: bool,
     ) -> Self::Value;
     fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope);
     fn set_invariant_load(&mut self, load: Self::Value);
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 96c7ba6ed27..5a5563c7bb2 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1382,6 +1382,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         &mut self.long_ty_path
     }
 
+    pub fn with_long_ty_path(mut self, long_ty_path: Option<PathBuf>) -> Self {
+        self.long_ty_path = long_ty_path;
+        self
+    }
+
     /// Most `emit_producing_guarantee` functions use this as a starting point.
     fn emit_producing_nothing(mut self) {
         let diag = self.take_diag();
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 84970e7c162..0c839f94f7f 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -409,7 +409,7 @@ pub trait Emitter {
                 if !redundant_span || always_backtrace {
                     let msg: Cow<'static, _> = match trace.kind {
                         ExpnKind::Macro(MacroKind::Attr, _) => {
-                            "this procedural macro expansion".into()
+                            "this attribute macro expansion".into()
                         }
                         ExpnKind::Macro(MacroKind::Derive, _) => {
                             "this derive macro expansion".into()
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 5a53670c865..1f8f3be6809 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -70,6 +70,9 @@ expand_invalid_fragment_specifier =
     invalid fragment specifier `{$fragment}`
     .help = {$help}
 
+expand_macro_args_bad_delim = macro attribute argument matchers require parentheses
+expand_macro_args_bad_delim_sugg = the delimiters should be `(` and `)`
+
 expand_macro_body_stability =
     macros cannot have body stability attributes
     .label = invalid body stability attribute
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 163fe34c194..c234aa43c09 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -7,7 +7,6 @@ use std::rc::Rc;
 use std::sync::Arc;
 
 use rustc_ast::attr::{AttributeExt, MarkedAttrs};
-use rustc_ast::ptr::P;
 use rustc_ast::token::MetaVarKind;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{AssocCtxt, Visitor};
@@ -45,11 +44,11 @@ use crate::stats::MacroStat;
 // to use `assign_id!`
 #[derive(Debug, Clone)]
 pub enum Annotatable {
-    Item(P<ast::Item>),
-    AssocItem(P<ast::AssocItem>, AssocCtxt),
-    ForeignItem(P<ast::ForeignItem>),
-    Stmt(P<ast::Stmt>),
-    Expr(P<ast::Expr>),
+    Item(Box<ast::Item>),
+    AssocItem(Box<ast::AssocItem>, AssocCtxt),
+    ForeignItem(Box<ast::ForeignItem>),
+    Stmt(Box<ast::Stmt>),
+    Expr(Box<ast::Expr>),
     Arm(ast::Arm),
     ExprField(ast::ExprField),
     PatField(ast::PatField),
@@ -141,28 +140,28 @@ impl Annotatable {
         }
     }
 
-    pub fn expect_item(self) -> P<ast::Item> {
+    pub fn expect_item(self) -> Box<ast::Item> {
         match self {
             Annotatable::Item(i) => i,
             _ => panic!("expected Item"),
         }
     }
 
-    pub fn expect_trait_item(self) -> P<ast::AssocItem> {
+    pub fn expect_trait_item(self) -> Box<ast::AssocItem> {
         match self {
             Annotatable::AssocItem(i, AssocCtxt::Trait) => i,
             _ => panic!("expected Item"),
         }
     }
 
-    pub fn expect_impl_item(self) -> P<ast::AssocItem> {
+    pub fn expect_impl_item(self) -> Box<ast::AssocItem> {
         match self {
             Annotatable::AssocItem(i, AssocCtxt::Impl { .. }) => i,
             _ => panic!("expected Item"),
         }
     }
 
-    pub fn expect_foreign_item(self) -> P<ast::ForeignItem> {
+    pub fn expect_foreign_item(self) -> Box<ast::ForeignItem> {
         match self {
             Annotatable::ForeignItem(i) => i,
             _ => panic!("expected foreign item"),
@@ -176,7 +175,7 @@ impl Annotatable {
         }
     }
 
-    pub fn expect_expr(self) -> P<ast::Expr> {
+    pub fn expect_expr(self) -> Box<ast::Expr> {
         match self {
             Annotatable::Expr(expr) => expr,
             _ => panic!("expected expression"),
@@ -412,37 +411,37 @@ macro_rules! make_stmts_default {
 /// methods are spliced into the AST at the callsite of the macro.
 pub trait MacResult {
     /// Creates an expression.
-    fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
+    fn make_expr(self: Box<Self>) -> Option<Box<ast::Expr>> {
         None
     }
 
     /// Creates zero or more items.
-    fn make_items(self: Box<Self>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
+    fn make_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
         None
     }
 
     /// Creates zero or more impl items.
-    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
         None
     }
 
     /// Creates zero or more impl items.
-    fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+    fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
         None
     }
 
     /// Creates zero or more trait items.
-    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
         None
     }
 
     /// Creates zero or more items in an `extern {}` block
-    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
+    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::ForeignItem>; 1]>> {
         None
     }
 
     /// Creates a pattern.
-    fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
+    fn make_pat(self: Box<Self>) -> Option<Box<ast::Pat>> {
         None
     }
 
@@ -454,7 +453,7 @@ pub trait MacResult {
         make_stmts_default!(self)
     }
 
-    fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
+    fn make_ty(self: Box<Self>) -> Option<Box<ast::Ty>> {
         None
     }
 
@@ -521,38 +520,38 @@ macro_rules! make_MacEager {
 }
 
 make_MacEager! {
-    expr: P<ast::Expr>,
-    pat: P<ast::Pat>,
-    items: SmallVec<[P<ast::Item>; 1]>,
-    impl_items: SmallVec<[P<ast::AssocItem>; 1]>,
-    trait_items: SmallVec<[P<ast::AssocItem>; 1]>,
-    foreign_items: SmallVec<[P<ast::ForeignItem>; 1]>,
+    expr: Box<ast::Expr>,
+    pat: Box<ast::Pat>,
+    items: SmallVec<[Box<ast::Item>; 1]>,
+    impl_items: SmallVec<[Box<ast::AssocItem>; 1]>,
+    trait_items: SmallVec<[Box<ast::AssocItem>; 1]>,
+    foreign_items: SmallVec<[Box<ast::ForeignItem>; 1]>,
     stmts: SmallVec<[ast::Stmt; 1]>,
-    ty: P<ast::Ty>,
+    ty: Box<ast::Ty>,
 }
 
 impl MacResult for MacEager {
-    fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
+    fn make_expr(self: Box<Self>) -> Option<Box<ast::Expr>> {
         self.expr
     }
 
-    fn make_items(self: Box<Self>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
+    fn make_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
         self.items
     }
 
-    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+    fn make_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
         self.impl_items
     }
 
-    fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+    fn make_trait_impl_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
         self.impl_items
     }
 
-    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+    fn make_trait_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
         self.trait_items
     }
 
-    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
+    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::ForeignItem>; 1]>> {
         self.foreign_items
     }
 
@@ -563,13 +562,13 @@ impl MacResult for MacEager {
         }
     }
 
-    fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
+    fn make_pat(self: Box<Self>) -> Option<Box<ast::Pat>> {
         if let Some(p) = self.pat {
             return Some(p);
         }
         if let Some(e) = self.expr {
             if matches!(e.kind, ast::ExprKind::Lit(_) | ast::ExprKind::IncludedBytes(_)) {
-                return Some(P(ast::Pat {
+                return Some(Box::new(ast::Pat {
                     id: ast::DUMMY_NODE_ID,
                     span: e.span,
                     kind: PatKind::Expr(e),
@@ -580,7 +579,7 @@ impl MacResult for MacEager {
         None
     }
 
-    fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
+    fn make_ty(self: Box<Self>) -> Option<Box<ast::Ty>> {
         self.ty
     }
 }
@@ -608,8 +607,8 @@ impl DummyResult {
     }
 
     /// A plain dummy expression.
-    pub fn raw_expr(sp: Span, guar: Option<ErrorGuaranteed>) -> P<ast::Expr> {
-        P(ast::Expr {
+    pub fn raw_expr(sp: Span, guar: Option<ErrorGuaranteed>) -> Box<ast::Expr> {
+        Box::new(ast::Expr {
             id: ast::DUMMY_NODE_ID,
             kind: if let Some(guar) = guar {
                 ast::ExprKind::Err(guar)
@@ -624,12 +623,12 @@ impl DummyResult {
 }
 
 impl MacResult for DummyResult {
-    fn make_expr(self: Box<DummyResult>) -> Option<P<ast::Expr>> {
+    fn make_expr(self: Box<DummyResult>) -> Option<Box<ast::Expr>> {
         Some(DummyResult::raw_expr(self.span, self.guar))
     }
 
-    fn make_pat(self: Box<DummyResult>) -> Option<P<ast::Pat>> {
-        Some(P(ast::Pat {
+    fn make_pat(self: Box<DummyResult>) -> Option<Box<ast::Pat>> {
+        Some(Box::new(ast::Pat {
             id: ast::DUMMY_NODE_ID,
             kind: PatKind::Wild,
             span: self.span,
@@ -637,23 +636,23 @@ impl MacResult for DummyResult {
         }))
     }
 
-    fn make_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::Item>; 1]>> {
+    fn make_items(self: Box<DummyResult>) -> Option<SmallVec<[Box<ast::Item>; 1]>> {
         Some(SmallVec::new())
     }
 
-    fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+    fn make_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
         Some(SmallVec::new())
     }
 
-    fn make_trait_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+    fn make_trait_impl_items(self: Box<DummyResult>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
         Some(SmallVec::new())
     }
 
-    fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[P<ast::AssocItem>; 1]>> {
+    fn make_trait_items(self: Box<DummyResult>) -> Option<SmallVec<[Box<ast::AssocItem>; 1]>> {
         Some(SmallVec::new())
     }
 
-    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[P<ast::ForeignItem>; 1]>> {
+    fn make_foreign_items(self: Box<Self>) -> Option<SmallVec<[Box<ast::ForeignItem>; 1]>> {
         Some(SmallVec::new())
     }
 
@@ -665,11 +664,11 @@ impl MacResult for DummyResult {
         }])
     }
 
-    fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
+    fn make_ty(self: Box<DummyResult>) -> Option<Box<ast::Ty>> {
         // FIXME(nnethercote): you might expect `ast::TyKind::Dummy` to be used here, but some
         // values produced here end up being lowered to HIR, which `ast::TyKind::Dummy` does not
         // support, so we use an empty tuple instead.
-        Some(P(ast::Ty {
+        Some(Box::new(ast::Ty {
             id: ast::DUMMY_NODE_ID,
             kind: ast::TyKind::Tup(ThinVec::new()),
             span: self.span,
@@ -905,7 +904,10 @@ impl SyntaxExtension {
             find_attr!(attrs, AttributeKind::AllowInternalUnstable(i, _) => i)
                 .map(|i| i.as_slice())
                 .unwrap_or_default();
-        let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe(_));
+        // FIXME(jdonszelman): allow_internal_unsafe isn't yet new-style
+        // let allow_internal_unsafe = find_attr!(attrs, AttributeKind::AllowInternalUnsafe);
+        let allow_internal_unsafe =
+            ast::attr::find_by_name(attrs, sym::allow_internal_unsafe).is_some();
 
         let local_inner_macros = ast::attr::find_by_name(attrs, sym::macro_export)
             .and_then(|macro_export| macro_export.meta_item_list())
@@ -1159,7 +1161,7 @@ pub trait LintStoreExpand {
         registered_tools: &RegisteredTools,
         node_id: NodeId,
         attrs: &[Attribute],
-        items: &[P<Item>],
+        items: &[Box<Item>],
         name: Symbol,
     );
 }
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 51d6e43ab67..c3e86ec0614 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::token::Delimiter;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::literal;
@@ -59,10 +58,10 @@ impl<'a> ExtCtxt<'a> {
         path: ast::Path,
         delim: Delimiter,
         tokens: TokenStream,
-    ) -> P<ast::MacCall> {
-        P(ast::MacCall {
+    ) -> Box<ast::MacCall> {
+        Box::new(ast::MacCall {
             path,
-            args: P(ast::DelimArgs {
+            args: Box::new(ast::DelimArgs {
                 dspan: tokenstream::DelimSpan { open: span, close: span },
                 delim,
                 tokens,
@@ -70,32 +69,32 @@ impl<'a> ExtCtxt<'a> {
         })
     }
 
-    pub fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
+    pub fn ty_mt(&self, ty: Box<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
         ast::MutTy { ty, mutbl }
     }
 
-    pub fn ty(&self, span: Span, kind: ast::TyKind) -> P<ast::Ty> {
-        P(ast::Ty { id: ast::DUMMY_NODE_ID, span, kind, tokens: None })
+    pub fn ty(&self, span: Span, kind: ast::TyKind) -> Box<ast::Ty> {
+        Box::new(ast::Ty { id: ast::DUMMY_NODE_ID, span, kind, tokens: None })
     }
 
-    pub fn ty_infer(&self, span: Span) -> P<ast::Ty> {
+    pub fn ty_infer(&self, span: Span) -> Box<ast::Ty> {
         self.ty(span, ast::TyKind::Infer)
     }
 
-    pub fn ty_path(&self, path: ast::Path) -> P<ast::Ty> {
+    pub fn ty_path(&self, path: ast::Path) -> Box<ast::Ty> {
         self.ty(path.span, ast::TyKind::Path(None, path))
     }
 
     // Might need to take bounds as an argument in the future, if you ever want
     // to generate a bounded existential trait type.
-    pub fn ty_ident(&self, span: Span, ident: Ident) -> P<ast::Ty> {
+    pub fn ty_ident(&self, span: Span, ident: Ident) -> Box<ast::Ty> {
         self.ty_path(self.path_ident(span, ident))
     }
 
     pub fn anon_const(&self, span: Span, kind: ast::ExprKind) -> ast::AnonConst {
         ast::AnonConst {
             id: ast::DUMMY_NODE_ID,
-            value: P(ast::Expr {
+            value: Box::new(ast::Expr {
                 id: ast::DUMMY_NODE_ID,
                 kind,
                 span,
@@ -112,14 +111,14 @@ impl<'a> ExtCtxt<'a> {
     pub fn ty_ref(
         &self,
         span: Span,
-        ty: P<ast::Ty>,
+        ty: Box<ast::Ty>,
         lifetime: Option<ast::Lifetime>,
         mutbl: ast::Mutability,
-    ) -> P<ast::Ty> {
+    ) -> Box<ast::Ty> {
         self.ty(span, ast::TyKind::Ref(lifetime, self.ty_mt(ty, mutbl)))
     }
 
-    pub fn ty_ptr(&self, span: Span, ty: P<ast::Ty>, mutbl: ast::Mutability) -> P<ast::Ty> {
+    pub fn ty_ptr(&self, span: Span, ty: Box<ast::Ty>, mutbl: ast::Mutability) -> Box<ast::Ty> {
         self.ty(span, ast::TyKind::Ptr(self.ty_mt(ty, mutbl)))
     }
 
@@ -128,7 +127,7 @@ impl<'a> ExtCtxt<'a> {
         span: Span,
         ident: Ident,
         bounds: ast::GenericBounds,
-        default: Option<P<ast::Ty>>,
+        default: Option<Box<ast::Ty>>,
     ) -> ast::GenericParam {
         ast::GenericParam {
             ident: ident.with_span_pos(span),
@@ -163,7 +162,7 @@ impl<'a> ExtCtxt<'a> {
         span: Span,
         ident: Ident,
         bounds: ast::GenericBounds,
-        ty: P<ast::Ty>,
+        ty: Box<ast::Ty>,
         default: Option<AnonConst>,
     ) -> ast::GenericParam {
         ast::GenericParam {
@@ -211,11 +210,11 @@ impl<'a> ExtCtxt<'a> {
         self.lifetime(span, Ident::new(kw::StaticLifetime, span))
     }
 
-    pub fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt {
+    pub fn stmt_expr(&self, expr: Box<ast::Expr>) -> ast::Stmt {
         ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) }
     }
 
-    pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt {
+    pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: Box<ast::Expr>) -> ast::Stmt {
         self.stmt_let_ty(sp, mutbl, ident, None, ex)
     }
 
@@ -224,15 +223,15 @@ impl<'a> ExtCtxt<'a> {
         sp: Span,
         mutbl: bool,
         ident: Ident,
-        ty: Option<P<ast::Ty>>,
-        ex: P<ast::Expr>,
+        ty: Option<Box<ast::Ty>>,
+        ex: Box<ast::Expr>,
     ) -> ast::Stmt {
         let pat = if mutbl {
             self.pat_ident_binding_mode(sp, ident, ast::BindingMode::MUT)
         } else {
             self.pat_ident(sp, ident)
         };
-        let local = P(ast::Local {
+        let local = Box::new(ast::Local {
             super_: None,
             pat,
             ty,
@@ -247,8 +246,8 @@ impl<'a> ExtCtxt<'a> {
     }
 
     /// Generates `let _: Type;`, which is usually used for type assertions.
-    pub fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
-        let local = P(ast::Local {
+    pub fn stmt_let_type_only(&self, span: Span, ty: Box<ast::Ty>) -> ast::Stmt {
+        let local = Box::new(ast::Local {
             super_: None,
             pat: self.pat_wild(span),
             ty: Some(ty),
@@ -262,19 +261,19 @@ impl<'a> ExtCtxt<'a> {
         self.stmt_local(local, span)
     }
 
-    pub fn stmt_semi(&self, expr: P<ast::Expr>) -> ast::Stmt {
+    pub fn stmt_semi(&self, expr: Box<ast::Expr>) -> ast::Stmt {
         ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Semi(expr) }
     }
 
-    pub fn stmt_local(&self, local: P<ast::Local>, span: Span) -> ast::Stmt {
+    pub fn stmt_local(&self, local: Box<ast::Local>, span: Span) -> ast::Stmt {
         ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Let(local), span }
     }
 
-    pub fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt {
+    pub fn stmt_item(&self, sp: Span, item: Box<ast::Item>) -> ast::Stmt {
         ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp }
     }
 
-    pub fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {
+    pub fn block_expr(&self, expr: Box<ast::Expr>) -> Box<ast::Block> {
         self.block(
             expr.span,
             thin_vec![ast::Stmt {
@@ -284,8 +283,8 @@ impl<'a> ExtCtxt<'a> {
             }],
         )
     }
-    pub fn block(&self, span: Span, stmts: ThinVec<ast::Stmt>) -> P<ast::Block> {
-        P(ast::Block {
+    pub fn block(&self, span: Span, stmts: ThinVec<ast::Stmt>) -> Box<ast::Block> {
+        Box::new(ast::Block {
             stmts,
             id: ast::DUMMY_NODE_ID,
             rules: BlockCheckMode::Default,
@@ -294,22 +293,28 @@ impl<'a> ExtCtxt<'a> {
         })
     }
 
-    pub fn expr(&self, span: Span, kind: ast::ExprKind) -> P<ast::Expr> {
-        P(ast::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new(), tokens: None })
+    pub fn expr(&self, span: Span, kind: ast::ExprKind) -> Box<ast::Expr> {
+        Box::new(ast::Expr {
+            id: ast::DUMMY_NODE_ID,
+            kind,
+            span,
+            attrs: AttrVec::new(),
+            tokens: None,
+        })
     }
 
-    pub fn expr_path(&self, path: ast::Path) -> P<ast::Expr> {
+    pub fn expr_path(&self, path: ast::Path) -> Box<ast::Expr> {
         self.expr(path.span, ast::ExprKind::Path(None, path))
     }
 
-    pub fn expr_ident(&self, span: Span, id: Ident) -> P<ast::Expr> {
+    pub fn expr_ident(&self, span: Span, id: Ident) -> Box<ast::Expr> {
         self.expr_path(self.path_ident(span, id))
     }
-    pub fn expr_self(&self, span: Span) -> P<ast::Expr> {
+    pub fn expr_self(&self, span: Span) -> Box<ast::Expr> {
         self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower))
     }
 
-    pub fn expr_macro_call(&self, span: Span, call: P<ast::MacCall>) -> P<ast::Expr> {
+    pub fn expr_macro_call(&self, span: Span, call: Box<ast::MacCall>) -> Box<ast::Expr> {
         self.expr(span, ast::ExprKind::MacCall(call))
     }
 
@@ -317,31 +322,31 @@ impl<'a> ExtCtxt<'a> {
         &self,
         sp: Span,
         op: ast::BinOpKind,
-        lhs: P<ast::Expr>,
-        rhs: P<ast::Expr>,
-    ) -> P<ast::Expr> {
+        lhs: Box<ast::Expr>,
+        rhs: Box<ast::Expr>,
+    ) -> Box<ast::Expr> {
         self.expr(sp, ast::ExprKind::Binary(Spanned { node: op, span: sp }, lhs, rhs))
     }
 
-    pub fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
+    pub fn expr_deref(&self, sp: Span, e: Box<ast::Expr>) -> Box<ast::Expr> {
         self.expr(sp, ast::ExprKind::Unary(UnOp::Deref, e))
     }
 
-    pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
+    pub fn expr_addr_of(&self, sp: Span, e: Box<ast::Expr>) -> Box<ast::Expr> {
         self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
     }
 
-    pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
+    pub fn expr_paren(&self, sp: Span, e: Box<ast::Expr>) -> Box<ast::Expr> {
         self.expr(sp, ast::ExprKind::Paren(e))
     }
 
     pub fn expr_method_call(
         &self,
         span: Span,
-        expr: P<ast::Expr>,
+        expr: Box<ast::Expr>,
         ident: Ident,
-        args: ThinVec<P<ast::Expr>>,
-    ) -> P<ast::Expr> {
+        args: ThinVec<Box<ast::Expr>>,
+    ) -> Box<ast::Expr> {
         let seg = ast::PathSegment::from_ident(ident);
         self.expr(
             span,
@@ -357,38 +362,38 @@ impl<'a> ExtCtxt<'a> {
     pub fn expr_call(
         &self,
         span: Span,
-        expr: P<ast::Expr>,
-        args: ThinVec<P<ast::Expr>>,
-    ) -> P<ast::Expr> {
+        expr: Box<ast::Expr>,
+        args: ThinVec<Box<ast::Expr>>,
+    ) -> Box<ast::Expr> {
         self.expr(span, ast::ExprKind::Call(expr, args))
     }
-    pub fn expr_loop(&self, sp: Span, block: P<ast::Block>) -> P<ast::Expr> {
+    pub fn expr_loop(&self, sp: Span, block: Box<ast::Block>) -> Box<ast::Expr> {
         self.expr(sp, ast::ExprKind::Loop(block, None, sp))
     }
-    pub fn expr_asm(&self, sp: Span, expr: P<ast::InlineAsm>) -> P<ast::Expr> {
+    pub fn expr_asm(&self, sp: Span, expr: Box<ast::InlineAsm>) -> Box<ast::Expr> {
         self.expr(sp, ast::ExprKind::InlineAsm(expr))
     }
     pub fn expr_call_ident(
         &self,
         span: Span,
         id: Ident,
-        args: ThinVec<P<ast::Expr>>,
-    ) -> P<ast::Expr> {
+        args: ThinVec<Box<ast::Expr>>,
+    ) -> Box<ast::Expr> {
         self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args))
     }
     pub fn expr_call_global(
         &self,
         sp: Span,
         fn_path: Vec<Ident>,
-        args: ThinVec<P<ast::Expr>>,
-    ) -> P<ast::Expr> {
+        args: ThinVec<Box<ast::Expr>>,
+    ) -> Box<ast::Expr> {
         let pathexpr = self.expr_path(self.path_global(sp, fn_path));
         self.expr_call(sp, pathexpr, args)
     }
-    pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
+    pub fn expr_block(&self, b: Box<ast::Block>) -> Box<ast::Expr> {
         self.expr(b.span, ast::ExprKind::Block(b, None))
     }
-    pub fn field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::ExprField {
+    pub fn field_imm(&self, span: Span, ident: Ident, e: Box<ast::Expr>) -> ast::ExprField {
         ast::ExprField {
             ident: ident.with_span_pos(span),
             expr: e,
@@ -404,10 +409,10 @@ impl<'a> ExtCtxt<'a> {
         span: Span,
         path: ast::Path,
         fields: ThinVec<ast::ExprField>,
-    ) -> P<ast::Expr> {
+    ) -> Box<ast::Expr> {
         self.expr(
             span,
-            ast::ExprKind::Struct(P(ast::StructExpr {
+            ast::ExprKind::Struct(Box::new(ast::StructExpr {
                 qself: None,
                 path,
                 fields,
@@ -420,61 +425,61 @@ impl<'a> ExtCtxt<'a> {
         span: Span,
         id: Ident,
         fields: ThinVec<ast::ExprField>,
-    ) -> P<ast::Expr> {
+    ) -> Box<ast::Expr> {
         self.expr_struct(span, self.path_ident(span, id), fields)
     }
 
-    pub fn expr_usize(&self, span: Span, n: usize) -> P<ast::Expr> {
+    pub fn expr_usize(&self, span: Span, n: usize) -> Box<ast::Expr> {
         let suffix = Some(ast::UintTy::Usize.name());
         let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
         self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_u32(&self, span: Span, n: u32) -> P<ast::Expr> {
+    pub fn expr_u32(&self, span: Span, n: u32) -> Box<ast::Expr> {
         let suffix = Some(ast::UintTy::U32.name());
         let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
         self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_bool(&self, span: Span, value: bool) -> P<ast::Expr> {
+    pub fn expr_bool(&self, span: Span, value: bool) -> Box<ast::Expr> {
         let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None);
         self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr> {
+    pub fn expr_str(&self, span: Span, s: Symbol) -> Box<ast::Expr> {
         let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None);
         self.expr(span, ast::ExprKind::Lit(lit))
     }
 
-    pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> {
+    pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> Box<ast::Expr> {
         let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None);
         self.expr(span, ast::ExprKind::Lit(lit))
     }
 
     /// `[expr1, expr2, ...]`
-    pub fn expr_array(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
+    pub fn expr_array(&self, sp: Span, exprs: ThinVec<Box<ast::Expr>>) -> Box<ast::Expr> {
         self.expr(sp, ast::ExprKind::Array(exprs))
     }
 
     /// `&[expr1, expr2, ...]`
-    pub fn expr_array_ref(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
+    pub fn expr_array_ref(&self, sp: Span, exprs: ThinVec<Box<ast::Expr>>) -> Box<ast::Expr> {
         self.expr_addr_of(sp, self.expr_array(sp, exprs))
     }
 
-    pub fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
+    pub fn expr_some(&self, sp: Span, expr: Box<ast::Expr>) -> Box<ast::Expr> {
         let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
         self.expr_call_global(sp, some, thin_vec![expr])
     }
 
-    pub fn expr_none(&self, sp: Span) -> P<ast::Expr> {
+    pub fn expr_none(&self, sp: Span) -> Box<ast::Expr> {
         let none = self.std_path(&[sym::option, sym::Option, sym::None]);
         self.expr_path(self.path_global(sp, none))
     }
-    pub fn expr_tuple(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
+    pub fn expr_tuple(&self, sp: Span, exprs: ThinVec<Box<ast::Expr>>) -> Box<ast::Expr> {
         self.expr(sp, ast::ExprKind::Tup(exprs))
     }
 
-    pub fn expr_unreachable(&self, span: Span) -> P<ast::Expr> {
+    pub fn expr_unreachable(&self, span: Span) -> Box<ast::Expr> {
         self.expr_macro_call(
             span,
             self.macro_call(
@@ -489,12 +494,12 @@ impl<'a> ExtCtxt<'a> {
         )
     }
 
-    pub fn expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
+    pub fn expr_ok(&self, sp: Span, expr: Box<ast::Expr>) -> Box<ast::Expr> {
         let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
         self.expr_call_global(sp, ok, thin_vec![expr])
     }
 
-    pub fn expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr> {
+    pub fn expr_try(&self, sp: Span, head: Box<ast::Expr>) -> Box<ast::Expr> {
         let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
         let ok_path = self.path_global(sp, ok);
         let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
@@ -523,16 +528,16 @@ impl<'a> ExtCtxt<'a> {
         self.expr_match(sp, head, thin_vec![ok_arm, err_arm])
     }
 
-    pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
-        P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None })
+    pub fn pat(&self, span: Span, kind: PatKind) -> Box<ast::Pat> {
+        Box::new(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None })
     }
-    pub fn pat_wild(&self, span: Span) -> P<ast::Pat> {
+    pub fn pat_wild(&self, span: Span) -> Box<ast::Pat> {
         self.pat(span, PatKind::Wild)
     }
-    pub fn pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat> {
+    pub fn pat_lit(&self, span: Span, expr: Box<ast::Expr>) -> Box<ast::Pat> {
         self.pat(span, PatKind::Expr(expr))
     }
-    pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> {
+    pub fn pat_ident(&self, span: Span, ident: Ident) -> Box<ast::Pat> {
         self.pat_ident_binding_mode(span, ident, ast::BindingMode::NONE)
     }
 
@@ -541,19 +546,19 @@ impl<'a> ExtCtxt<'a> {
         span: Span,
         ident: Ident,
         ann: ast::BindingMode,
-    ) -> P<ast::Pat> {
+    ) -> Box<ast::Pat> {
         let pat = PatKind::Ident(ann, ident.with_span_pos(span), None);
         self.pat(span, pat)
     }
-    pub fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
+    pub fn pat_path(&self, span: Span, path: ast::Path) -> Box<ast::Pat> {
         self.pat(span, PatKind::Path(None, path))
     }
     pub fn pat_tuple_struct(
         &self,
         span: Span,
         path: ast::Path,
-        subpats: ThinVec<P<ast::Pat>>,
-    ) -> P<ast::Pat> {
+        subpats: ThinVec<Box<ast::Pat>>,
+    ) -> Box<ast::Pat> {
         self.pat(span, PatKind::TupleStruct(None, path, subpats))
     }
     pub fn pat_struct(
@@ -561,20 +566,20 @@ impl<'a> ExtCtxt<'a> {
         span: Span,
         path: ast::Path,
         field_pats: ThinVec<ast::PatField>,
-    ) -> P<ast::Pat> {
+    ) -> Box<ast::Pat> {
         self.pat(span, PatKind::Struct(None, path, field_pats, ast::PatFieldsRest::None))
     }
-    pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> {
+    pub fn pat_tuple(&self, span: Span, pats: ThinVec<Box<ast::Pat>>) -> Box<ast::Pat> {
         self.pat(span, PatKind::Tuple(pats))
     }
 
-    pub fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
+    pub fn pat_some(&self, span: Span, pat: Box<ast::Pat>) -> Box<ast::Pat> {
         let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
         let path = self.path_global(span, some);
         self.pat_tuple_struct(span, path, thin_vec![pat])
     }
 
-    pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
+    pub fn arm(&self, span: Span, pat: Box<ast::Pat>, expr: Box<ast::Expr>) -> ast::Arm {
         ast::Arm {
             attrs: AttrVec::new(),
             pat,
@@ -590,22 +595,27 @@ impl<'a> ExtCtxt<'a> {
         self.arm(span, self.pat_wild(span), self.expr_unreachable(span))
     }
 
-    pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> {
+    pub fn expr_match(
+        &self,
+        span: Span,
+        arg: Box<ast::Expr>,
+        arms: ThinVec<ast::Arm>,
+    ) -> Box<Expr> {
         self.expr(span, ast::ExprKind::Match(arg, arms, MatchKind::Prefix))
     }
 
     pub fn expr_if(
         &self,
         span: Span,
-        cond: P<ast::Expr>,
-        then: P<ast::Expr>,
-        els: Option<P<ast::Expr>>,
-    ) -> P<ast::Expr> {
+        cond: Box<ast::Expr>,
+        then: Box<ast::Expr>,
+        els: Option<Box<ast::Expr>>,
+    ) -> Box<ast::Expr> {
         let els = els.map(|x| self.expr_block(self.block_expr(x)));
         self.expr(span, ast::ExprKind::If(cond, self.block_expr(then), els))
     }
 
-    pub fn lambda(&self, span: Span, ids: Vec<Ident>, body: P<ast::Expr>) -> P<ast::Expr> {
+    pub fn lambda(&self, span: Span, ids: Vec<Ident>, body: Box<ast::Expr>) -> Box<ast::Expr> {
         let fn_decl = self.fn_decl(
             ids.iter().map(|id| self.param(span, *id, self.ty(span, ast::TyKind::Infer))).collect(),
             ast::FnRetTy::Default(span),
@@ -633,11 +643,11 @@ impl<'a> ExtCtxt<'a> {
         )
     }
 
-    pub fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> {
+    pub fn lambda0(&self, span: Span, body: Box<ast::Expr>) -> Box<ast::Expr> {
         self.lambda(span, Vec::new(), body)
     }
 
-    pub fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: Ident) -> P<ast::Expr> {
+    pub fn lambda1(&self, span: Span, body: Box<ast::Expr>, ident: Ident) -> Box<ast::Expr> {
         self.lambda(span, vec![ident], body)
     }
 
@@ -646,11 +656,11 @@ impl<'a> ExtCtxt<'a> {
         span: Span,
         stmts: ThinVec<ast::Stmt>,
         ident: Ident,
-    ) -> P<ast::Expr> {
+    ) -> Box<ast::Expr> {
         self.lambda1(span, self.expr_block(self.block(span, stmts)), ident)
     }
 
-    pub fn param(&self, span: Span, ident: Ident, ty: P<ast::Ty>) -> ast::Param {
+    pub fn param(&self, span: Span, ident: Ident, ty: Box<ast::Ty>) -> ast::Param {
         let arg_pat = self.pat_ident(span, ident);
         ast::Param {
             attrs: AttrVec::default(),
@@ -663,12 +673,12 @@ impl<'a> ExtCtxt<'a> {
     }
 
     // `self` is unused but keep it as method for the convenience use.
-    pub fn fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> {
-        P(ast::FnDecl { inputs, output })
+    pub fn fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> Box<ast::FnDecl> {
+        Box::new(ast::FnDecl { inputs, output })
     }
 
-    pub fn item(&self, span: Span, attrs: ast::AttrVec, kind: ast::ItemKind) -> P<ast::Item> {
-        P(ast::Item {
+    pub fn item(&self, span: Span, attrs: ast::AttrVec, kind: ast::ItemKind) -> Box<ast::Item> {
+        Box::new(ast::Item {
             attrs,
             id: ast::DUMMY_NODE_ID,
             kind,
@@ -686,10 +696,10 @@ impl<'a> ExtCtxt<'a> {
         &self,
         span: Span,
         ident: Ident,
-        ty: P<ast::Ty>,
+        ty: Box<ast::Ty>,
         mutability: ast::Mutability,
-        expr: P<ast::Expr>,
-    ) -> P<ast::Item> {
+        expr: Box<ast::Expr>,
+    ) -> Box<ast::Item> {
         self.item(
             span,
             AttrVec::new(),
@@ -711,9 +721,9 @@ impl<'a> ExtCtxt<'a> {
         &self,
         span: Span,
         ident: Ident,
-        ty: P<ast::Ty>,
-        expr: P<ast::Expr>,
-    ) -> P<ast::Item> {
+        ty: Box<ast::Ty>,
+        expr: Box<ast::Expr>,
+    ) -> Box<ast::Item> {
         let defaultness = ast::Defaultness::Final;
         self.item(
             span,
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index fd1391a554a..e58269991fc 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -482,3 +482,21 @@ mod metavar_exprs {
         pub key: MacroRulesNormalizedIdent,
     }
 }
+
+#[derive(Diagnostic)]
+#[diag(expand_macro_args_bad_delim)]
+pub(crate) struct MacroArgsBadDelim {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: MacroArgsBadDelimSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(expand_macro_args_bad_delim_sugg, applicability = "machine-applicable")]
+pub(crate) struct MacroArgsBadDelimSugg {
+    #[suggestion_part(code = "(")]
+    pub open: Span,
+    #[suggestion_part(code = ")")]
+    pub close: Span,
+}
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index f02aa6c120f..e7ae4416968 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -4,7 +4,6 @@ use std::sync::Arc;
 use std::{iter, mem};
 
 use rustc_ast::mut_visit::*;
-use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
 use rustc_ast::{
@@ -65,8 +64,8 @@ macro_rules! ast_fragments {
         /// A fragment of AST that can be produced by a single macro expansion.
         /// Can also serve as an input and intermediate result for macro expansion operations.
         pub enum AstFragment {
-            OptExpr(Option<P<ast::Expr>>),
-            MethodReceiverExpr(P<ast::Expr>),
+            OptExpr(Option<Box<ast::Expr>>),
+            MethodReceiverExpr(Box<ast::Expr>),
             $($Kind($AstTy),)*
         }
 
@@ -112,14 +111,14 @@ macro_rules! ast_fragments {
                 }
             }
 
-            pub(crate) fn make_opt_expr(self) -> Option<P<ast::Expr>> {
+            pub(crate) fn make_opt_expr(self) -> Option<Box<ast::Expr>> {
                 match self {
                     AstFragment::OptExpr(expr) => expr,
                     _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
                 }
             }
 
-            pub(crate) fn make_method_receiver_expr(self) -> P<ast::Expr> {
+            pub(crate) fn make_method_receiver_expr(self) -> Box<ast::Expr> {
                 match self {
                     AstFragment::MethodReceiverExpr(expr) => expr,
                     _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
@@ -188,17 +187,17 @@ macro_rules! ast_fragments {
 }
 
 ast_fragments! {
-    Expr(P<ast::Expr>) {
+    Expr(Box<ast::Expr>) {
         "expression";
         one fn visit_expr; fn visit_expr; fn pprust::expr_to_string;
         fn make_expr;
     }
-    Pat(P<ast::Pat>) {
+    Pat(Box<ast::Pat>) {
         "pattern";
         one fn visit_pat; fn visit_pat; fn pprust::pat_to_string;
         fn make_pat;
     }
-    Ty(P<ast::Ty>) {
+    Ty(Box<ast::Ty>) {
         "type";
         one fn visit_ty; fn visit_ty; fn pprust::ty_to_string;
         fn make_ty;
@@ -208,30 +207,30 @@ ast_fragments! {
         many fn flat_map_stmt; fn visit_stmt(); fn pprust::stmt_to_string;
         fn make_stmts;
     }
-    Items(SmallVec<[P<ast::Item>; 1]>) {
+    Items(SmallVec<[Box<ast::Item>; 1]>) {
         "item";
         many fn flat_map_item; fn visit_item(); fn pprust::item_to_string;
         fn make_items;
     }
-    TraitItems(SmallVec<[P<ast::AssocItem>; 1]>) {
+    TraitItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
         "trait item";
         many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Trait);
             fn pprust::assoc_item_to_string;
         fn make_trait_items;
     }
-    ImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
+    ImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
         "impl item";
         many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: false });
             fn pprust::assoc_item_to_string;
         fn make_impl_items;
     }
-    TraitImplItems(SmallVec<[P<ast::AssocItem>; 1]>) {
+    TraitImplItems(SmallVec<[Box<ast::AssocItem>; 1]>) {
         "impl item";
         many fn flat_map_assoc_item; fn visit_assoc_item(AssocCtxt::Impl { of_trait: true });
             fn pprust::assoc_item_to_string;
         fn make_trait_impl_items;
     }
-    ForeignItems(SmallVec<[P<ast::ForeignItem>; 1]>) {
+    ForeignItems(SmallVec<[Box<ast::ForeignItem>; 1]>) {
         "foreign item";
         many fn flat_map_foreign_item; fn visit_foreign_item(); fn pprust::foreign_item_to_string;
         fn make_foreign_items;
@@ -392,7 +391,7 @@ pub struct Invocation {
 
 pub enum InvocationKind {
     Bang {
-        mac: P<ast::MacCall>,
+        mac: Box<ast::MacCall>,
         span: Span,
     },
     Attr {
@@ -409,7 +408,7 @@ pub enum InvocationKind {
         item: Annotatable,
     },
     GlobDelegation {
-        item: P<ast::AssocItem>,
+        item: Box<ast::AssocItem>,
         /// Whether this is a trait impl or an inherent impl
         of_trait: bool,
     },
@@ -948,15 +947,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     _ => unreachable!(),
                 };
 
-                type Node = AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>;
+                type Node = AstNodeWrapper<Box<ast::AssocItem>, ImplItemTag>;
                 let single_delegations = build_single_delegations::<Node>(
                     self.cx, deleg, &item, &suffixes, item.span, true,
                 );
                 // `-Zmacro-stats` ignores these because they don't seem important.
-                fragment_kind.expect_from_annotatables(
-                    single_delegations
-                        .map(|item| Annotatable::AssocItem(P(item), AssocCtxt::Impl { of_trait })),
-                )
+                fragment_kind.expect_from_annotatables(single_delegations.map(|item| {
+                    Annotatable::AssocItem(Box::new(item), AssocCtxt::Impl { of_trait })
+                }))
             }
         })
     }
@@ -1228,7 +1226,7 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
     fn is_mac_call(&self) -> bool {
         false
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         unreachable!()
     }
     fn delegation(&self) -> Option<(&ast::DelegationMac, &ast::Item<Self::ItemKind>)> {
@@ -1269,7 +1267,7 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
     }
 }
 
-impl InvocationCollectorNode for P<ast::Item> {
+impl InvocationCollectorNode for Box<ast::Item> {
     const KIND: AstFragmentKind = AstFragmentKind::Items;
     fn to_annotatable(self) -> Annotatable {
         Annotatable::Item(self)
@@ -1283,7 +1281,7 @@ impl InvocationCollectorNode for P<ast::Item> {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ItemKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         match self.kind {
             ItemKind::MacCall(mac) => (mac, self.attrs, AddSemicolon::No),
             _ => unreachable!(),
@@ -1299,7 +1297,7 @@ impl InvocationCollectorNode for P<ast::Item> {
         ItemKind::Delegation(deleg)
     }
     fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
-        P(item)
+        Box::new(item)
     }
     fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
         items.flatten().collect()
@@ -1421,8 +1419,8 @@ impl InvocationCollectorNode for P<ast::Item> {
 }
 
 struct TraitItemTag;
-impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag> {
-    type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
+impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, TraitItemTag> {
+    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;
     type ItemKind = AssocItemKind;
     const KIND: AstFragmentKind = AstFragmentKind::TraitItems;
     fn to_annotatable(self) -> Annotatable {
@@ -1437,7 +1435,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag>
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         let item = self.wrapped;
         match item.kind {
             AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
@@ -1454,7 +1452,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag>
         AssocItemKind::Delegation(deleg)
     }
     fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
-        AstNodeWrapper::new(P(item), TraitItemTag)
+        AstNodeWrapper::new(Box::new(item), TraitItemTag)
     }
     fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
         items.flatten().collect()
@@ -1462,8 +1460,8 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag>
 }
 
 struct ImplItemTag;
-impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag> {
-    type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
+impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, ImplItemTag> {
+    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;
     type ItemKind = AssocItemKind;
     const KIND: AstFragmentKind = AstFragmentKind::ImplItems;
     fn to_annotatable(self) -> Annotatable {
@@ -1478,7 +1476,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         let item = self.wrapped;
         match item.kind {
             AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
@@ -1495,7 +1493,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
         AssocItemKind::Delegation(deleg)
     }
     fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
-        AstNodeWrapper::new(P(item), ImplItemTag)
+        AstNodeWrapper::new(Box::new(item), ImplItemTag)
     }
     fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
         items.flatten().collect()
@@ -1503,8 +1501,8 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
 }
 
 struct TraitImplItemTag;
-impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitImplItemTag> {
-    type OutputTy = SmallVec<[P<ast::AssocItem>; 1]>;
+impl InvocationCollectorNode for AstNodeWrapper<Box<ast::AssocItem>, TraitImplItemTag> {
+    type OutputTy = SmallVec<[Box<ast::AssocItem>; 1]>;
     type ItemKind = AssocItemKind;
     const KIND: AstFragmentKind = AstFragmentKind::TraitImplItems;
     fn to_annotatable(self) -> Annotatable {
@@ -1519,7 +1517,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitImplItem
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         let item = self.wrapped;
         match item.kind {
             AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
@@ -1536,14 +1534,14 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitImplItem
         AssocItemKind::Delegation(deleg)
     }
     fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
-        AstNodeWrapper::new(P(item), TraitImplItemTag)
+        AstNodeWrapper::new(Box::new(item), TraitImplItemTag)
     }
     fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
         items.flatten().collect()
     }
 }
 
-impl InvocationCollectorNode for P<ast::ForeignItem> {
+impl InvocationCollectorNode for Box<ast::ForeignItem> {
     const KIND: AstFragmentKind = AstFragmentKind::ForeignItems;
     fn to_annotatable(self) -> Annotatable {
         Annotatable::ForeignItem(self)
@@ -1557,7 +1555,7 @@ impl InvocationCollectorNode for P<ast::ForeignItem> {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ForeignItemKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         match self.kind {
             ForeignItemKind::MacCall(mac) => (mac, self.attrs, AddSemicolon::No),
             _ => unreachable!(),
@@ -1672,7 +1670,7 @@ impl InvocationCollectorNode for ast::Arm {
 impl InvocationCollectorNode for ast::Stmt {
     const KIND: AstFragmentKind = AstFragmentKind::Stmts;
     fn to_annotatable(self) -> Annotatable {
-        Annotatable::Stmt(P(self))
+        Annotatable::Stmt(Box::new(self))
     }
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_stmts()
@@ -1689,7 +1687,7 @@ impl InvocationCollectorNode for ast::Stmt {
             StmtKind::Let(..) | StmtKind::Empty => false,
         }
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         // We pull macro invocations (both attributes and fn-like macro calls) out of their
         // `StmtKind`s and treat them as statement macro invocations, not as items or expressions.
         let (add_semicolon, mac, attrs) = match self.kind {
@@ -1726,7 +1724,7 @@ impl InvocationCollectorNode for ast::Stmt {
         ItemKind::Delegation(deleg)
     }
     fn from_item(item: ast::Item<Self::ItemKind>) -> Self {
-        ast::Stmt { id: ast::DUMMY_NODE_ID, span: item.span, kind: StmtKind::Item(P(item)) }
+        ast::Stmt { id: ast::DUMMY_NODE_ID, span: item.span, kind: StmtKind::Item(Box::new(item)) }
     }
     fn flatten_outputs(items: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
         items.flatten().collect()
@@ -1769,7 +1767,7 @@ impl InvocationCollectorNode for ast::Crate {
 }
 
 impl InvocationCollectorNode for ast::Ty {
-    type OutputTy = P<ast::Ty>;
+    type OutputTy = Box<ast::Ty>;
     const KIND: AstFragmentKind = AstFragmentKind::Ty;
     fn to_annotatable(self) -> Annotatable {
         unreachable!()
@@ -1793,7 +1791,7 @@ impl InvocationCollectorNode for ast::Ty {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ast::TyKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         match self.kind {
             TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
             _ => unreachable!(),
@@ -1802,7 +1800,7 @@ impl InvocationCollectorNode for ast::Ty {
 }
 
 impl InvocationCollectorNode for ast::Pat {
-    type OutputTy = P<ast::Pat>;
+    type OutputTy = Box<ast::Pat>;
     const KIND: AstFragmentKind = AstFragmentKind::Pat;
     fn to_annotatable(self) -> Annotatable {
         unreachable!()
@@ -1816,7 +1814,7 @@ impl InvocationCollectorNode for ast::Pat {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, PatKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         match self.kind {
             PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
             _ => unreachable!(),
@@ -1825,10 +1823,10 @@ impl InvocationCollectorNode for ast::Pat {
 }
 
 impl InvocationCollectorNode for ast::Expr {
-    type OutputTy = P<ast::Expr>;
+    type OutputTy = Box<ast::Expr>;
     const KIND: AstFragmentKind = AstFragmentKind::Expr;
     fn to_annotatable(self) -> Annotatable {
-        Annotatable::Expr(P(self))
+        Annotatable::Expr(Box::new(self))
     }
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         fragment.make_expr()
@@ -1842,7 +1840,7 @@ impl InvocationCollectorNode for ast::Expr {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ExprKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         match self.kind {
             ExprKind::MacCall(mac) => (mac, self.attrs, AddSemicolon::No),
             _ => unreachable!(),
@@ -1851,8 +1849,8 @@ impl InvocationCollectorNode for ast::Expr {
 }
 
 struct OptExprTag;
-impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
-    type OutputTy = Option<P<ast::Expr>>;
+impl InvocationCollectorNode for AstNodeWrapper<Box<ast::Expr>, OptExprTag> {
+    type OutputTy = Option<Box<ast::Expr>>;
     const KIND: AstFragmentKind = AstFragmentKind::OptExpr;
     fn to_annotatable(self) -> Annotatable {
         Annotatable::Expr(self.wrapped)
@@ -1867,7 +1865,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         let node = self.wrapped;
         match node.kind {
             ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
@@ -1884,13 +1882,13 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
 struct MethodReceiverTag;
 
 impl InvocationCollectorNode for AstNodeWrapper<ast::Expr, MethodReceiverTag> {
-    type OutputTy = AstNodeWrapper<P<ast::Expr>, MethodReceiverTag>;
+    type OutputTy = AstNodeWrapper<Box<ast::Expr>, MethodReceiverTag>;
     const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
     fn descr() -> &'static str {
         "an expression"
     }
     fn to_annotatable(self) -> Annotatable {
-        Annotatable::Expr(P(self.wrapped))
+        Annotatable::Expr(Box::new(self.wrapped))
     }
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
         AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag)
@@ -1901,7 +1899,7 @@ impl InvocationCollectorNode for AstNodeWrapper<ast::Expr, MethodReceiverTag> {
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (P<ast::MacCall>, ast::AttrVec, AddSemicolon) {
+    fn take_mac_call(self) -> (Box<ast::MacCall>, ast::AttrVec, AddSemicolon) {
         let node = self.wrapped;
         match node.kind {
             ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
@@ -2038,7 +2036,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
     }
 
-    fn collect_bang(&mut self, mac: P<ast::MacCall>, kind: AstFragmentKind) -> AstFragment {
+    fn collect_bang(&mut self, mac: Box<ast::MacCall>, kind: AstFragmentKind) -> AstFragment {
         // cache the macro call span so that it can be
         // easily adjusted for incremental compilation
         let span = mac.span();
@@ -2056,7 +2054,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
 
     fn collect_glob_delegation(
         &mut self,
-        item: P<ast::AssocItem>,
+        item: Box<ast::AssocItem>,
         of_trait: bool,
         kind: AstFragmentKind,
     ) -> AstFragment {
@@ -2328,15 +2326,15 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
 }
 
 impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
-    fn flat_map_item(&mut self, node: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
+    fn flat_map_item(&mut self, node: Box<ast::Item>) -> SmallVec<[Box<ast::Item>; 1]> {
         self.flat_map_node(node)
     }
 
     fn flat_map_assoc_item(
         &mut self,
-        node: P<ast::AssocItem>,
+        node: Box<ast::AssocItem>,
         ctxt: AssocCtxt,
-    ) -> SmallVec<[P<ast::AssocItem>; 1]> {
+    ) -> SmallVec<[Box<ast::AssocItem>; 1]> {
         match ctxt {
             AssocCtxt::Trait => self.flat_map_node(AstNodeWrapper::new(node, TraitItemTag)),
             AssocCtxt::Impl { of_trait: false } => {
@@ -2350,8 +2348,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
 
     fn flat_map_foreign_item(
         &mut self,
-        node: P<ast::ForeignItem>,
-    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
+        node: Box<ast::ForeignItem>,
+    ) -> SmallVec<[Box<ast::ForeignItem>; 1]> {
         self.flat_map_node(node)
     }
 
@@ -2446,7 +2444,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
         self.visit_node(AstNodeWrapper::from_mut(node, MethodReceiverTag))
     }
 
-    fn filter_map_expr(&mut self, node: P<ast::Expr>) -> Option<P<ast::Expr>> {
+    fn filter_map_expr(&mut self, node: Box<ast::Expr>) -> Option<Box<ast::Expr>> {
         self.flat_map_node(AstNodeWrapper::new(node, OptExprTag))
     }
 
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 7a280d671f4..5b9d56ee2bc 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -7,29 +7,40 @@ use rustc_macros::Subdiagnostic;
 use rustc_parse::parser::{Parser, Recovery, token_descr};
 use rustc_session::parse::ParseSess;
 use rustc_span::source_map::SourceMap;
-use rustc_span::{ErrorGuaranteed, Ident, Span};
+use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span};
 use tracing::debug;
 
 use super::macro_rules::{MacroRule, NoopTracker, parser_from_cx};
 use crate::expand::{AstFragmentKind, parse_ast_fragment};
 use crate::mbe::macro_parser::ParseResult::*;
 use crate::mbe::macro_parser::{MatcherLoc, NamedParseResult, TtParser};
-use crate::mbe::macro_rules::{Tracker, try_match_macro};
+use crate::mbe::macro_rules::{Tracker, try_match_macro, try_match_macro_attr};
 
 pub(super) fn failed_to_match_macro(
     psess: &ParseSess,
     sp: Span,
     def_span: Span,
     name: Ident,
-    arg: TokenStream,
+    attr_args: Option<&TokenStream>,
+    body: &TokenStream,
     rules: &[MacroRule],
 ) -> (Span, ErrorGuaranteed) {
     debug!("failed to match macro");
+    let def_head_span = if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
+        psess.source_map().guess_head_span(def_span)
+    } else {
+        DUMMY_SP
+    };
+
     // An error occurred, try the expansion again, tracking the expansion closely for better
     // diagnostics.
     let mut tracker = CollectTrackerAndEmitter::new(psess.dcx(), sp);
 
-    let try_success_result = try_match_macro(psess, name, &arg, rules, &mut tracker);
+    let try_success_result = if let Some(attr_args) = attr_args {
+        try_match_macro_attr(psess, name, attr_args, body, rules, &mut tracker)
+    } else {
+        try_match_macro(psess, name, body, rules, &mut tracker)
+    };
 
     if try_success_result.is_ok() {
         // Nonterminal parser recovery might turn failed matches into successful ones,
@@ -47,6 +58,18 @@ pub(super) fn failed_to_match_macro(
 
     let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure
     else {
+        // FIXME: we should report this at macro resolution time, as we do for
+        // `resolve_macro_cannot_use_as_attr`. We can do that once we track multiple macro kinds for a
+        // Def.
+        if attr_args.is_none() && !rules.iter().any(|rule| matches!(rule, MacroRule::Func { .. })) {
+            let msg = format!("macro has no rules for function-like invocation `{name}!`");
+            let mut err = psess.dcx().struct_span_err(sp, msg);
+            if !def_head_span.is_dummy() {
+                let msg = "this macro has no rules for function-like invocation";
+                err.span_label(def_head_span, msg);
+            }
+            return (sp, err.emit());
+        }
         return (sp, psess.dcx().span_delayed_bug(sp, "failed to match a macro"));
     };
 
@@ -54,8 +77,8 @@ pub(super) fn failed_to_match_macro(
 
     let mut err = psess.dcx().struct_span_err(span, parse_failure_msg(&token, None));
     err.span_label(span, label);
-    if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
-        err.span_label(psess.source_map().guess_head_span(def_span), "when calling this macro");
+    if !def_head_span.is_dummy() {
+        err.span_label(def_head_span, "when calling this macro");
     }
 
     annotate_doc_comment(&mut err, psess.source_map(), span);
@@ -79,13 +102,16 @@ pub(super) fn failed_to_match_macro(
     }
 
     // Check whether there's a missing comma in this macro call, like `println!("{}" a);`
-    if let Some((arg, comma_span)) = arg.add_comma() {
+    if attr_args.is_none()
+        && let Some((body, comma_span)) = body.add_comma()
+    {
         for rule in rules {
-            let parser = parser_from_cx(psess, arg.clone(), Recovery::Allowed);
+            let MacroRule::Func { lhs, .. } = rule else { continue };
+            let parser = parser_from_cx(psess, body.clone(), Recovery::Allowed);
             let mut tt_parser = TtParser::new(name);
 
             if let Success(_) =
-                tt_parser.parse_tt(&mut Cow::Borrowed(&parser), &rule.lhs, &mut NoopTracker)
+                tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, &mut NoopTracker)
             {
                 if comma_span.is_dummy() {
                     err.note("you might be missing a comma");
@@ -116,13 +142,13 @@ struct CollectTrackerAndEmitter<'dcx, 'matcher> {
 
 struct BestFailure {
     token: Token,
-    position_in_tokenstream: u32,
+    position_in_tokenstream: (bool, u32),
     msg: &'static str,
     remaining_matcher: MatcherLoc,
 }
 
 impl BestFailure {
-    fn is_better_position(&self, position: u32) -> bool {
+    fn is_better_position(&self, position: (bool, u32)) -> bool {
         position > self.position_in_tokenstream
     }
 }
@@ -142,7 +168,7 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match
         }
     }
 
-    fn after_arm(&mut self, result: &NamedParseResult<Self::Failure>) {
+    fn after_arm(&mut self, in_body: bool, result: &NamedParseResult<Self::Failure>) {
         match result {
             Success(_) => {
                 // Nonterminal parser recovery might turn failed matches into successful ones,
@@ -155,14 +181,15 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match
             Failure((token, approx_position, msg)) => {
                 debug!(?token, ?msg, "a new failure of an arm");
 
+                let position_in_tokenstream = (in_body, *approx_position);
                 if self
                     .best_failure
                     .as_ref()
-                    .is_none_or(|failure| failure.is_better_position(*approx_position))
+                    .is_none_or(|failure| failure.is_better_position(position_in_tokenstream))
                 {
                     self.best_failure = Some(BestFailure {
                         token: *token,
-                        position_in_tokenstream: *approx_position,
+                        position_in_tokenstream,
                         msg,
                         remaining_matcher: self
                             .remaining_matcher
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index bbdff866feb..25987a50366 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -193,15 +193,19 @@ struct MacroState<'a> {
 /// Arguments:
 /// - `psess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
-/// - `lhs` and `rhs` represent the rule
+/// - `args`, `lhs`, and `rhs` represent the rule
 pub(super) fn check_meta_variables(
     psess: &ParseSess,
     node_id: NodeId,
+    args: Option<&TokenTree>,
     lhs: &TokenTree,
     rhs: &TokenTree,
 ) -> Result<(), ErrorGuaranteed> {
     let mut guar = None;
     let mut binders = Binders::default();
+    if let Some(args) = args {
+        check_binders(psess, node_id, args, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar);
+    }
     check_binders(psess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar);
     check_occurrences(psess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut guar);
     guar.map_or(Ok(()), Err)
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 52d38c35f98..37b236a2e26 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -6,12 +6,12 @@ use std::{mem, slice};
 use ast::token::IdentIsRaw;
 use rustc_ast::token::NtPatKind::*;
 use rustc_ast::token::TokenKind::*;
-use rustc_ast::token::{self, NonterminalKind, Token, TokenKind};
-use rustc_ast::tokenstream::{DelimSpan, TokenStream};
+use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind};
+use rustc_ast::tokenstream::{self, DelimSpan, TokenStream};
 use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
+use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan};
 use rustc_feature::Features;
 use rustc_hir as hir;
 use rustc_hir::attrs::AttributeKind;
@@ -23,23 +23,26 @@ use rustc_lint_defs::builtin::{
 use rustc_parse::exp;
 use rustc_parse::parser::{Parser, Recovery};
 use rustc_session::Session;
-use rustc_session::parse::ParseSess;
+use rustc_session::parse::{ParseSess, feature_err};
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::Transparency;
 use rustc_span::{Ident, Span, kw, sym};
 use tracing::{debug, instrument, trace, trace_span};
 
+use super::diagnostics::failed_to_match_macro;
 use super::macro_parser::{NamedMatches, NamedParseResult};
 use super::{SequenceRepetition, diagnostics};
 use crate::base::{
-    DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, SyntaxExtension,
-    SyntaxExtensionKind, TTMacroExpander,
+    AttrProcMacro, DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult,
+    SyntaxExtension, SyntaxExtensionKind, TTMacroExpander,
 };
+use crate::errors;
 use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment};
+use crate::mbe::macro_check::check_meta_variables;
 use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser};
 use crate::mbe::quoted::{RulePart, parse_one_tt};
 use crate::mbe::transcribe::transcribe;
-use crate::mbe::{self, KleeneOp, macro_check};
+use crate::mbe::{self, KleeneOp};
 
 pub(crate) struct ParserAnyMacro<'a> {
     parser: Parser<'a>,
@@ -123,10 +126,17 @@ impl<'a> ParserAnyMacro<'a> {
     }
 }
 
-pub(super) struct MacroRule {
-    pub(super) lhs: Vec<MatcherLoc>,
-    lhs_span: Span,
-    rhs: mbe::TokenTree,
+pub(super) enum MacroRule {
+    /// A function-style rule, for use with `m!()`
+    Func { lhs: Vec<MatcherLoc>, lhs_span: Span, rhs: mbe::TokenTree },
+    /// An attr rule, for use with `#[m]`
+    Attr {
+        args: Vec<MatcherLoc>,
+        args_span: Span,
+        body: Vec<MatcherLoc>,
+        body_span: Span,
+        rhs: mbe::TokenTree,
+    },
 }
 
 pub struct MacroRulesMacroExpander {
@@ -138,10 +148,15 @@ pub struct MacroRulesMacroExpander {
 }
 
 impl MacroRulesMacroExpander {
-    pub fn get_unused_rule(&self, rule_i: usize) -> Option<(&Ident, Span)> {
+    pub fn get_unused_rule(&self, rule_i: usize) -> Option<(&Ident, MultiSpan)> {
         // If the rhs contains an invocation like `compile_error!`, don't report it as unused.
-        let rule = &self.rules[rule_i];
-        if has_compile_error_macro(&rule.rhs) { None } else { Some((&self.name, rule.lhs_span)) }
+        let (span, rhs) = match self.rules[rule_i] {
+            MacroRule::Func { lhs_span, ref rhs, .. } => (MultiSpan::from_span(lhs_span), rhs),
+            MacroRule::Attr { args_span, body_span, ref rhs, .. } => {
+                (MultiSpan::from_spans(vec![args_span, body_span]), rhs)
+            }
+        };
+        if has_compile_error_macro(rhs) { None } else { Some((&self.name, span)) }
     }
 }
 
@@ -165,6 +180,28 @@ impl TTMacroExpander for MacroRulesMacroExpander {
     }
 }
 
+impl AttrProcMacro for MacroRulesMacroExpander {
+    fn expand(
+        &self,
+        cx: &mut ExtCtxt<'_>,
+        sp: Span,
+        args: TokenStream,
+        body: TokenStream,
+    ) -> Result<TokenStream, ErrorGuaranteed> {
+        expand_macro_attr(
+            cx,
+            sp,
+            self.span,
+            self.node_id,
+            self.name,
+            self.transparency,
+            args,
+            body,
+            &self.rules,
+        )
+    }
+}
+
 struct DummyExpander(ErrorGuaranteed);
 
 impl TTMacroExpander for DummyExpander {
@@ -197,7 +234,7 @@ pub(super) trait Tracker<'matcher> {
 
     /// This is called after an arm has been parsed, either successfully or unsuccessfully. When
     /// this is called, `before_match_loc` was called at least once (with a `MatcherLoc::Eof`).
-    fn after_arm(&mut self, _result: &NamedParseResult<Self::Failure>) {}
+    fn after_arm(&mut self, _in_body: bool, _result: &NamedParseResult<Self::Failure>) {}
 
     /// For tracing.
     fn description() -> &'static str;
@@ -245,14 +282,17 @@ fn expand_macro<'cx>(
 
     match try_success_result {
         Ok((rule_index, rule, named_matches)) => {
-            let mbe::TokenTree::Delimited(rhs_span, _, ref rhs) = rule.rhs else {
+            let MacroRule::Func { rhs, .. } = rule else {
+                panic!("try_match_macro returned non-func rule");
+            };
+            let mbe::TokenTree::Delimited(rhs_span, _, rhs) = rhs else {
                 cx.dcx().span_bug(sp, "malformed macro rhs");
             };
-            let arm_span = rule.rhs.span();
+            let arm_span = rhs_span.entire();
 
             // rhs has holes ( `$id` and `$(...)` that need filled)
             let id = cx.current_expansion.id;
-            let tts = match transcribe(psess, &named_matches, rhs, rhs_span, transparency, id) {
+            let tts = match transcribe(psess, &named_matches, rhs, *rhs_span, transparency, id) {
                 Ok(tts) => tts,
                 Err(err) => {
                     let guar = err.emit();
@@ -280,13 +320,76 @@ fn expand_macro<'cx>(
         Err(CanRetry::Yes) => {
             // Retry and emit a better error.
             let (span, guar) =
-                diagnostics::failed_to_match_macro(cx.psess(), sp, def_span, name, arg, rules);
+                failed_to_match_macro(cx.psess(), sp, def_span, name, None, &arg, rules);
             cx.macro_error_and_trace_macros_diag();
             DummyResult::any(span, guar)
         }
     }
 }
 
+/// Expands the rules based macro defined by `rules` for a given attribute `args` and `body`.
+#[instrument(skip(cx, transparency, args, body, rules))]
+fn expand_macro_attr(
+    cx: &mut ExtCtxt<'_>,
+    sp: Span,
+    def_span: Span,
+    node_id: NodeId,
+    name: Ident,
+    transparency: Transparency,
+    args: TokenStream,
+    body: TokenStream,
+    rules: &[MacroRule],
+) -> Result<TokenStream, ErrorGuaranteed> {
+    let psess = &cx.sess.psess;
+    // Macros defined in the current crate have a real node id,
+    // whereas macros from an external crate have a dummy id.
+    let is_local = node_id != DUMMY_NODE_ID;
+
+    if cx.trace_macros() {
+        let msg = format!(
+            "expanding `$[{name}({})] {}`",
+            pprust::tts_to_string(&args),
+            pprust::tts_to_string(&body),
+        );
+        trace_macros_note(&mut cx.expansions, sp, msg);
+    }
+
+    // Track nothing for the best performance.
+    match try_match_macro_attr(psess, name, &args, &body, rules, &mut NoopTracker) {
+        Ok((i, rule, named_matches)) => {
+            let MacroRule::Attr { rhs, .. } = rule else {
+                panic!("try_macro_match_attr returned non-attr rule");
+            };
+            let mbe::TokenTree::Delimited(rhs_span, _, rhs) = rhs else {
+                cx.dcx().span_bug(sp, "malformed macro rhs");
+            };
+
+            let id = cx.current_expansion.id;
+            let tts = transcribe(psess, &named_matches, rhs, *rhs_span, transparency, id)
+                .map_err(|e| e.emit())?;
+
+            if cx.trace_macros() {
+                let msg = format!("to `{}`", pprust::tts_to_string(&tts));
+                trace_macros_note(&mut cx.expansions, sp, msg);
+            }
+
+            if is_local {
+                cx.resolver.record_macro_rule_usage(node_id, i);
+            }
+
+            Ok(tts)
+        }
+        Err(CanRetry::No(guar)) => Err(guar),
+        Err(CanRetry::Yes) => {
+            // Retry and emit a better error.
+            let (_, guar) =
+                failed_to_match_macro(cx.psess(), sp, def_span, name, Some(&args), &body, rules);
+            cx.trace_macros_diag();
+            Err(guar)
+        }
+    }
+}
+
 pub(super) enum CanRetry {
     Yes,
     /// We are not allowed to retry macro expansion as a fatal error has been emitted already.
@@ -327,6 +430,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
     // Try each arm's matchers.
     let mut tt_parser = TtParser::new(name);
     for (i, rule) in rules.iter().enumerate() {
+        let MacroRule::Func { lhs, .. } = rule else { continue };
         let _tracing_span = trace_span!("Matching arm", %i);
 
         // Take a snapshot of the state of pre-expansion gating at this point.
@@ -335,9 +439,9 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
         // are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
         let mut gated_spans_snapshot = mem::take(&mut *psess.gated_spans.spans.borrow_mut());
 
-        let result = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), &rule.lhs, track);
+        let result = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, track);
 
-        track.after_arm(&result);
+        track.after_arm(true, &result);
 
         match result {
             Success(named_matches) => {
@@ -372,6 +476,60 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
     Err(CanRetry::Yes)
 }
 
+/// Try expanding the macro attribute. Returns the index of the successful arm and its
+/// named_matches if it was successful, and nothing if it failed. On failure, it's the caller's job
+/// to use `track` accordingly to record all errors correctly.
+#[instrument(level = "debug", skip(psess, attr_args, attr_body, rules, track), fields(tracking = %T::description()))]
+pub(super) fn try_match_macro_attr<'matcher, T: Tracker<'matcher>>(
+    psess: &ParseSess,
+    name: Ident,
+    attr_args: &TokenStream,
+    attr_body: &TokenStream,
+    rules: &'matcher [MacroRule],
+    track: &mut T,
+) -> Result<(usize, &'matcher MacroRule, NamedMatches), CanRetry> {
+    // This uses the same strategy as `try_match_macro`
+    let args_parser = parser_from_cx(psess, attr_args.clone(), T::recovery());
+    let body_parser = parser_from_cx(psess, attr_body.clone(), T::recovery());
+    let mut tt_parser = TtParser::new(name);
+    for (i, rule) in rules.iter().enumerate() {
+        let MacroRule::Attr { args, body, .. } = rule else { continue };
+
+        let mut gated_spans_snapshot = mem::take(&mut *psess.gated_spans.spans.borrow_mut());
+
+        let result = tt_parser.parse_tt(&mut Cow::Borrowed(&args_parser), args, track);
+        track.after_arm(false, &result);
+
+        let mut named_matches = match result {
+            Success(named_matches) => named_matches,
+            Failure(_) => {
+                mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut());
+                continue;
+            }
+            Error(_, _) => return Err(CanRetry::Yes),
+            ErrorReported(guar) => return Err(CanRetry::No(guar)),
+        };
+
+        let result = tt_parser.parse_tt(&mut Cow::Borrowed(&body_parser), body, track);
+        track.after_arm(true, &result);
+
+        match result {
+            Success(body_named_matches) => {
+                psess.gated_spans.merge(gated_spans_snapshot);
+                named_matches.extend(body_named_matches);
+                return Ok((i, rule, named_matches));
+            }
+            Failure(_) => {
+                mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut())
+            }
+            Error(_, _) => return Err(CanRetry::Yes),
+            ErrorReported(guar) => return Err(CanRetry::No(guar)),
+        }
+    }
+
+    Err(CanRetry::Yes)
+}
+
 /// Converts a macro item into a syntax extension.
 pub fn compile_declarative_macro(
     sess: &Session,
@@ -382,13 +540,13 @@ pub fn compile_declarative_macro(
     span: Span,
     node_id: NodeId,
     edition: Edition,
-) -> (SyntaxExtension, usize) {
-    let mk_syn_ext = |expander| {
-        let kind = SyntaxExtensionKind::LegacyBang(expander);
+) -> (SyntaxExtension, Option<Arc<SyntaxExtension>>, usize) {
+    let mk_syn_ext = |kind| {
         let is_local = is_defined_in_current_crate(node_id);
         SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local)
     };
-    let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), 0);
+    let mk_bang_ext = |expander| mk_syn_ext(SyntaxExtensionKind::LegacyBang(expander));
+    let dummy_syn_ext = |guar| (mk_bang_ext(Arc::new(DummyExpander(guar))), None, 0);
 
     let macro_rules = macro_def.macro_rules;
     let exp_sep = if macro_rules { exp!(Semi) } else { exp!(Comma) };
@@ -401,9 +559,30 @@ pub fn compile_declarative_macro(
     let mut guar = None;
     let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err());
 
+    let mut has_attr_rules = false;
     let mut rules = Vec::new();
 
     while p.token != token::Eof {
+        let args = if p.eat_keyword_noexpect(sym::attr) {
+            has_attr_rules = true;
+            if !features.macro_attr() {
+                feature_err(sess, sym::macro_attr, span, "`macro_rules!` attributes are unstable")
+                    .emit();
+            }
+            if let Some(guar) = check_no_eof(sess, &p, "expected macro attr args") {
+                return dummy_syn_ext(guar);
+            }
+            let args = p.parse_token_tree();
+            check_args_parens(sess, &args);
+            let args = parse_one_tt(args, RulePart::Pattern, sess, node_id, features, edition);
+            check_emission(check_lhs(sess, node_id, &args));
+            if let Some(guar) = check_no_eof(sess, &p, "expected macro attr body") {
+                return dummy_syn_ext(guar);
+            }
+            Some(args)
+        } else {
+            None
+        };
         let lhs_tt = p.parse_token_tree();
         let lhs_tt = parse_one_tt(lhs_tt, RulePart::Pattern, sess, node_id, features, edition);
         check_emission(check_lhs(sess, node_id, &lhs_tt));
@@ -416,7 +595,7 @@ pub fn compile_declarative_macro(
         let rhs_tt = p.parse_token_tree();
         let rhs_tt = parse_one_tt(rhs_tt, RulePart::Body, sess, node_id, features, edition);
         check_emission(check_rhs(sess, &rhs_tt));
-        check_emission(macro_check::check_meta_variables(&sess.psess, node_id, &lhs_tt, &rhs_tt));
+        check_emission(check_meta_variables(&sess.psess, node_id, args.as_ref(), &lhs_tt, &rhs_tt));
         let lhs_span = lhs_tt.span();
         // Convert the lhs into `MatcherLoc` form, which is better for doing the
         // actual matching.
@@ -425,7 +604,17 @@ pub fn compile_declarative_macro(
         } else {
             return dummy_syn_ext(guar.unwrap());
         };
-        rules.push(MacroRule { lhs, lhs_span, rhs: rhs_tt });
+        if let Some(args) = args {
+            let args_span = args.span();
+            let mbe::TokenTree::Delimited(.., delimited) = args else {
+                return dummy_syn_ext(guar.unwrap());
+            };
+            let args = mbe::macro_parser::compute_locs(&delimited.tts);
+            let body_span = lhs_span;
+            rules.push(MacroRule::Attr { args, args_span, body: lhs, body_span, rhs: rhs_tt });
+        } else {
+            rules.push(MacroRule::Func { lhs, lhs_span, rhs: rhs_tt });
+        }
         if p.token == token::Eof {
             break;
         }
@@ -451,9 +640,12 @@ pub fn compile_declarative_macro(
     // Return the number of rules for unused rule linting, if this is a local macro.
     let nrules = if is_defined_in_current_crate(node_id) { rules.len() } else { 0 };
 
-    let expander =
-        Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules });
-    (mk_syn_ext(expander), nrules)
+    let exp = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules });
+    let opt_attr_ext = has_attr_rules.then(|| {
+        let exp = Arc::clone(&exp);
+        Arc::new(mk_syn_ext(SyntaxExtensionKind::Attr(exp)))
+    });
+    (mk_bang_ext(exp), opt_attr_ext, nrules)
 }
 
 fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<ErrorGuaranteed> {
@@ -469,6 +661,18 @@ fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<Err
     None
 }
 
+fn check_args_parens(sess: &Session, args: &tokenstream::TokenTree) {
+    // This does not handle the non-delimited case; that gets handled separately by `check_lhs`.
+    if let tokenstream::TokenTree::Delimited(dspan, _, delim, _) = args
+        && *delim != Delimiter::Parenthesis
+    {
+        sess.dcx().emit_err(errors::MacroArgsBadDelim {
+            span: dspan.entire(),
+            sugg: errors::MacroArgsBadDelimSugg { open: dspan.open, close: dspan.close },
+        });
+    }
+}
+
 fn check_lhs(sess: &Session, node_id: NodeId, lhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed> {
     let e1 = check_lhs_nt_follows(sess, node_id, lhs);
     let e2 = check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index e925052c607..662c67f2d3f 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -1,7 +1,6 @@
 use std::iter::once;
 use std::path::{self, Path, PathBuf};
 
-use rustc_ast::ptr::P;
 use rustc_ast::{AttrVec, Attribute, Inline, Item, ModSpans};
 use rustc_errors::{Diag, ErrorGuaranteed};
 use rustc_parse::{exp, new_parser_from_file, unwrap_or_emit_fatal, validate_attr};
@@ -31,7 +30,7 @@ pub struct ModulePathSuccess {
 }
 
 pub(crate) struct ParsedExternalMod {
-    pub items: ThinVec<P<Item>>,
+    pub items: ThinVec<Box<Item>>,
     pub spans: ModSpans,
     pub file_path: PathBuf,
     pub dir_path: PathBuf,
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index 6e1c6df4bcb..05f9a5aa43f 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -1,5 +1,4 @@
 use rustc_ast::mut_visit::*;
-use rustc_ast::ptr::P;
 use rustc_ast::token::Delimiter;
 use rustc_ast::visit::AssocCtxt;
 use rustc_ast::{self as ast, Safety};
@@ -15,10 +14,10 @@ pub(crate) fn placeholder(
     id: ast::NodeId,
     vis: Option<ast::Visibility>,
 ) -> AstFragment {
-    fn mac_placeholder() -> P<ast::MacCall> {
-        P(ast::MacCall {
+    fn mac_placeholder() -> Box<ast::MacCall> {
+        Box::new(ast::MacCall {
             path: ast::Path { span: DUMMY_SP, segments: ThinVec::new(), tokens: None },
-            args: P(ast::DelimArgs {
+            args: Box::new(ast::DelimArgs {
                 dspan: ast::tokenstream::DelimSpan::dummy(),
                 delim: Delimiter::Parenthesis,
                 tokens: ast::tokenstream::TokenStream::new(Vec::new()),
@@ -35,7 +34,7 @@ pub(crate) fn placeholder(
     });
     let span = DUMMY_SP;
     let expr_placeholder = || {
-        P(ast::Expr {
+        Box::new(ast::Expr {
             id,
             span,
             attrs: ast::AttrVec::new(),
@@ -43,10 +42,17 @@ pub(crate) fn placeholder(
             tokens: None,
         })
     };
-    let ty =
-        || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span, tokens: None });
-    let pat =
-        || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });
+    let ty = || {
+        Box::new(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span, tokens: None })
+    };
+    let pat = || {
+        Box::new(ast::Pat {
+            id,
+            kind: ast::PatKind::MacCall(mac_placeholder()),
+            span,
+            tokens: None,
+        })
+    };
 
     match kind {
         AstFragmentKind::Crate => AstFragment::Crate(ast::Crate {
@@ -59,7 +65,7 @@ pub(crate) fn placeholder(
         AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
         AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
         AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(expr_placeholder()),
-        AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
+        AstFragmentKind::Items => AstFragment::Items(smallvec![Box::new(ast::Item {
             id,
             span,
             vis,
@@ -67,15 +73,17 @@ pub(crate) fn placeholder(
             kind: ast::ItemKind::MacCall(mac_placeholder()),
             tokens: None,
         })]),
-        AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
-            id,
-            span,
-            vis,
-            attrs,
-            kind: ast::AssocItemKind::MacCall(mac_placeholder()),
-            tokens: None,
-        })]),
-        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
+        AstFragmentKind::TraitItems => {
+            AstFragment::TraitItems(smallvec![Box::new(ast::AssocItem {
+                id,
+                span,
+                vis,
+                attrs,
+                kind: ast::AssocItemKind::MacCall(mac_placeholder()),
+                tokens: None,
+            })])
+        }
+        AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![Box::new(ast::AssocItem {
             id,
             span,
             vis,
@@ -84,7 +92,7 @@ pub(crate) fn placeholder(
             tokens: None,
         })]),
         AstFragmentKind::TraitImplItems => {
-            AstFragment::TraitImplItems(smallvec![P(ast::AssocItem {
+            AstFragment::TraitImplItems(smallvec![Box::new(ast::AssocItem {
                 id,
                 span,
                 vis,
@@ -94,7 +102,7 @@ pub(crate) fn placeholder(
             })])
         }
         AstFragmentKind::ForeignItems => {
-            AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
+            AstFragment::ForeignItems(smallvec![Box::new(ast::ForeignItem {
                 id,
                 span,
                 vis,
@@ -103,20 +111,20 @@ pub(crate) fn placeholder(
                 tokens: None,
             })])
         }
-        AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
+        AstFragmentKind::Pat => AstFragment::Pat(Box::new(ast::Pat {
             id,
             span,
             kind: ast::PatKind::MacCall(mac_placeholder()),
             tokens: None,
         })),
-        AstFragmentKind::Ty => AstFragment::Ty(P(ast::Ty {
+        AstFragmentKind::Ty => AstFragment::Ty(Box::new(ast::Ty {
             id,
             span,
             kind: ast::TyKind::MacCall(mac_placeholder()),
             tokens: None,
         })),
         AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
-            let mac = P(ast::MacCallStmt {
+            let mac = Box::new(ast::MacCallStmt {
                 mac: mac_placeholder(),
                 style: ast::MacStmtStyle::Braces,
                 attrs: ast::AttrVec::new(),
@@ -297,7 +305,7 @@ impl MutVisitor for PlaceholderExpander {
         }
     }
 
-    fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
+    fn flat_map_item(&mut self, item: Box<ast::Item>) -> SmallVec<[Box<ast::Item>; 1]> {
         match item.kind {
             ast::ItemKind::MacCall(_) => self.remove(item.id).make_items(),
             _ => walk_flat_map_item(self, item),
@@ -306,9 +314,9 @@ impl MutVisitor for PlaceholderExpander {
 
     fn flat_map_assoc_item(
         &mut self,
-        item: P<ast::AssocItem>,
+        item: Box<ast::AssocItem>,
         ctxt: AssocCtxt,
-    ) -> SmallVec<[P<ast::AssocItem>; 1]> {
+    ) -> SmallVec<[Box<ast::AssocItem>; 1]> {
         match item.kind {
             ast::AssocItemKind::MacCall(_) => {
                 let it = self.remove(item.id);
@@ -324,8 +332,8 @@ impl MutVisitor for PlaceholderExpander {
 
     fn flat_map_foreign_item(
         &mut self,
-        item: P<ast::ForeignItem>,
-    ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
+        item: Box<ast::ForeignItem>,
+    ) -> SmallVec<[Box<ast::ForeignItem>; 1]> {
         match item.kind {
             ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(),
             _ => walk_flat_map_foreign_item(self, item),
@@ -346,7 +354,7 @@ impl MutVisitor for PlaceholderExpander {
         }
     }
 
-    fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
+    fn filter_map_expr(&mut self, expr: Box<ast::Expr>) -> Option<Box<ast::Expr>> {
         match expr.kind {
             ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
             _ => walk_filter_map_expr(self, expr),
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index 84fbbbef061..9bfda8764f5 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_errors::ErrorGuaranteed;
 use rustc_parse::parser::{ForceCollect, Parser};
@@ -161,7 +160,7 @@ impl MultiItemModifier for DeriveProcMacro {
                 Ok(None) => break,
                 Ok(Some(item)) => {
                     if is_stmt {
-                        items.push(Annotatable::Stmt(P(ecx.stmt_item(span, item))));
+                        items.push(Annotatable::Stmt(Box::new(ecx.stmt_item(span, item))));
                     } else {
                         items.push(Annotatable::Item(item));
                     }
diff --git a/compiler/rustc_expand/src/stats.rs b/compiler/rustc_expand/src/stats.rs
index b4c4eac028f..3e40632275b 100644
--- a/compiler/rustc_expand/src/stats.rs
+++ b/compiler/rustc_expand/src/stats.rs
@@ -1,6 +1,5 @@
 use std::iter;
 
-use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, DUMMY_NODE_ID, Expr, ExprKind};
 use rustc_ast_pretty::pprust;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
@@ -41,7 +40,7 @@ pub(crate) fn update_bang_macro_stats(
     ecx: &mut ExtCtxt<'_>,
     fragment_kind: AstFragmentKind,
     span: Span,
-    mac: P<ast::MacCall>,
+    mac: Box<ast::MacCall>,
     fragment: &AstFragment,
 ) {
     // Does this path match any of the include macros, e.g. `include!`?
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index ca71bcebfdd..ae1f57c1ef6 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -554,6 +554,8 @@ declare_features! (
     (unstable, link_arg_attribute, "1.76.0", Some(99427)),
     /// Allows fused `loop`/`match` for direct intraprocedural jumps.
     (incomplete, loop_match, "1.90.0", Some(132306)),
+    /// Allow `macro_rules!` attribute rules
+    (unstable, macro_attr, "CURRENT_RUSTC_VERSION", Some(83527)),
     /// Give access to additional metadata about declarative macro meta-variables.
     (unstable, macro_metavar_expr, "1.61.0", Some(83527)),
     /// Provides a way to concatenate identifiers using metavariable expressions.
diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs
index e02edf5fe24..5f419315467 100644
--- a/compiler/rustc_hir/src/attrs/data_structures.rs
+++ b/compiler/rustc_hir/src/attrs/data_structures.rs
@@ -249,9 +249,6 @@ pub enum AttributeKind {
     /// Represents `#[rustc_allow_incoherent_impl]`.
     AllowIncoherentImpl(Span),
 
-    /// Represents `#[allow_internal_unsafe]`.
-    AllowInternalUnsafe(Span),
-
     /// Represents `#[allow_internal_unstable]`.
     AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
 
diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
index 7ce624dcc55..e3a7f0b97a8 100644
--- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
+++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
@@ -16,7 +16,6 @@ impl AttributeKind {
             Align { .. } => No,
             AllowConstFnUnstable(..) => No,
             AllowIncoherentImpl(..) => No,
-            AllowInternalUnsafe(..) => Yes,
             AllowInternalUnstable(..) => Yes,
             AsPtr(..) => Yes,
             AutomaticallyDerived(..) => Yes,
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 2201d493f2d..339d4e2eab7 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -306,6 +306,11 @@ impl DefKind {
     }
 
     #[inline]
+    pub fn is_adt(self) -> bool {
+        matches!(self, DefKind::Struct | DefKind::Union | DefKind::Enum)
+    }
+
+    #[inline]
     pub fn is_fn_like(self) -> bool {
         matches!(
             self,
@@ -313,6 +318,43 @@ impl DefKind {
         )
     }
 
+    /// Whether the corresponding item has generic parameters, ie. the `generics_of` query works.
+    pub fn has_generics(self) -> bool {
+        match self {
+            DefKind::AnonConst
+            | DefKind::AssocConst
+            | DefKind::AssocFn
+            | DefKind::AssocTy
+            | DefKind::Closure
+            | DefKind::Const
+            | DefKind::Ctor(..)
+            | DefKind::Enum
+            | DefKind::Field
+            | DefKind::Fn
+            | DefKind::ForeignTy
+            | DefKind::Impl { .. }
+            | DefKind::InlineConst
+            | DefKind::OpaqueTy
+            | DefKind::Static { .. }
+            | DefKind::Struct
+            | DefKind::SyntheticCoroutineBody
+            | DefKind::Trait
+            | DefKind::TraitAlias
+            | DefKind::TyAlias
+            | DefKind::Union
+            | DefKind::Variant => true,
+            DefKind::ConstParam
+            | DefKind::ExternCrate
+            | DefKind::ForeignMod
+            | DefKind::GlobalAsm
+            | DefKind::LifetimeParam
+            | DefKind::Macro(_)
+            | DefKind::Mod
+            | DefKind::TyParam
+            | DefKind::Use => false,
+        }
+    }
+
     /// Whether `query get_codegen_attrs` should be used with this definition.
     pub fn has_codegen_attrs(self) -> bool {
         match self {
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 6e5fe3823ab..4441dd6ebd6 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -652,16 +652,16 @@ pub(crate) fn check_intrinsic_type(
         sym::atomic_store => (1, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit),
 
         sym::atomic_xchg
-        | sym::atomic_xadd
-        | sym::atomic_xsub
-        | sym::atomic_and
-        | sym::atomic_nand
-        | sym::atomic_or
-        | sym::atomic_xor
         | sym::atomic_max
         | sym::atomic_min
         | sym::atomic_umax
         | sym::atomic_umin => (1, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)),
+        sym::atomic_xadd
+        | sym::atomic_xsub
+        | sym::atomic_and
+        | sym::atomic_nand
+        | sym::atomic_or
+        | sym::atomic_xor => (2, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(1)], param(0)),
         sym::atomic_fence | sym::atomic_singlethreadfence => (0, 1, Vec::new(), tcx.types.unit),
 
         other => {
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 95f6fba6487..f5770b7312d 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -199,6 +199,11 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir:
 
     resolve_pat(visitor, arm.pat);
     if let Some(guard) = arm.guard {
+        // We introduce a new scope to contain bindings and temporaries from `if let` guards, to
+        // ensure they're dropped before the arm's pattern's bindings. This extends to the end of
+        // the arm body and is the scope of its locals as well.
+        visitor.enter_scope(Scope { local_id: arm.hir_id.local_id, data: ScopeData::MatchGuard });
+        visitor.cx.var_parent = visitor.cx.parent;
         resolve_cond(visitor, guard);
     }
     resolve_expr(visitor, arm.body, false);
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 522409a5ee5..8dd13da4fa7 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -517,8 +517,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
                 projection.args == trait_identity_args
                     // FIXME(return_type_notation): This check should be more robust
                     && !tcx.is_impl_trait_in_trait(projection.def_id)
-                    && tcx.associated_item(projection.def_id).container_id(tcx)
-                        == def_id.to_def_id()
+                    && tcx.parent(projection.def_id) == def_id.to_def_id()
             } else {
                 false
             }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index 3e446b7c656..93b82acf621 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -755,7 +755,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         let limit = if candidates.len() == 5 { 5 } else { 4 };
 
         for (index, &item) in candidates.iter().take(limit).enumerate() {
-            let impl_ = tcx.impl_of_assoc(item).unwrap();
+            let impl_ = tcx.parent(item);
 
             let note_span = if item.is_local() {
                 Some(tcx.def_span(item))
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 7e2bfa9f920..1675aecd2b8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1135,9 +1135,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         );
                     }
                 } else {
+                    let trait_ =
+                        tcx.short_string(bound.print_only_trait_path(), err.long_ty_path());
                     err.note(format!(
-                        "associated {assoc_kind_str} `{assoc_ident}` could derive from `{}`",
-                        bound.print_only_trait_path(),
+                        "associated {assoc_kind_str} `{assoc_ident}` could derive from `{trait_}`",
                     ));
                 }
             }
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index bac4d70103c..1ed0756fdd6 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -159,7 +159,7 @@ hir_typeck_lossy_provenance_ptr2int =
     .suggestion = use `.addr()` to obtain the address of a pointer
     .help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead
 
-hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
+hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty}`
 
 hir_typeck_naked_asm_outside_naked_fn =
     the `naked_asm!` macro can only be used in functions marked with `#[unsafe(naked)]`
@@ -184,7 +184,7 @@ hir_typeck_never_type_fallback_flowing_into_unsafe_path = never type fallback af
 hir_typeck_never_type_fallback_flowing_into_unsafe_union_field = never type fallback affects this union access
     .help = specify the type explicitly
 
-hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
+hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty}`{$trait_missing_method ->
     [true] {""}
     *[other] {" "}in the current scope
 }
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index a8bb6956f10..d15d092b7d3 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -200,11 +200,11 @@ pub(crate) enum ExplicitDestructorCallSugg {
 
 #[derive(Diagnostic)]
 #[diag(hir_typeck_missing_parentheses_in_range, code = E0689)]
-pub(crate) struct MissingParenthesesInRange {
+pub(crate) struct MissingParenthesesInRange<'tcx> {
     #[primary_span]
     #[label(hir_typeck_missing_parentheses_in_range)]
     pub span: Span,
-    pub ty_str: String,
+    pub ty: Ty<'tcx>,
     pub method_name: String,
     #[subdiagnostic]
     pub add_missing_parentheses: Option<AddMissingParenthesesInRange>,
@@ -828,13 +828,13 @@ pub(crate) struct UnlabeledCfInWhileCondition<'a> {
 
 #[derive(Diagnostic)]
 #[diag(hir_typeck_no_associated_item, code = E0599)]
-pub(crate) struct NoAssociatedItem {
+pub(crate) struct NoAssociatedItem<'tcx> {
     #[primary_span]
     pub span: Span,
     pub item_kind: &'static str,
     pub item_ident: Ident,
     pub ty_prefix: Cow<'static, str>,
-    pub ty_str: String,
+    pub ty: Ty<'tcx>,
     pub trait_missing_method: bool,
 }
 
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 454ec7ddcaf..0498a938366 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2745,6 +2745,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let available_field_names = self.available_field_names(variant, expr, skip_fields);
                 if let Some(field_name) =
                     find_best_match_for_name(&available_field_names, field.ident.name, None)
+                    && !(field.ident.name.as_str().parse::<usize>().is_ok()
+                        && field_name.as_str().parse::<usize>().is_ok())
                 {
                     err.span_label(field.ident.span, "unknown field");
                     err.span_suggestion_verbose(
@@ -3321,18 +3323,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else {
             (base_ty, "")
         };
-        for (found_fields, args) in
+        for found_fields in
             self.get_field_candidates_considering_privacy_for_diag(span, ty, mod_id, expr.hir_id)
         {
-            let field_names = found_fields.iter().map(|field| field.name).collect::<Vec<_>>();
+            let field_names = found_fields.iter().map(|field| field.0.name).collect::<Vec<_>>();
             let mut candidate_fields: Vec<_> = found_fields
                 .into_iter()
                 .filter_map(|candidate_field| {
                     self.check_for_nested_field_satisfying_condition_for_diag(
                         span,
-                        &|candidate_field, _| candidate_field.ident(self.tcx()) == field,
+                        &|candidate_field, _| candidate_field == field,
                         candidate_field,
-                        args,
                         vec![],
                         mod_id,
                         expr.hir_id,
@@ -3361,6 +3362,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             } else if let Some(field_name) =
                 find_best_match_for_name(&field_names, field.name, None)
+                && !(field.name.as_str().parse::<usize>().is_ok()
+                    && field_name.as_str().parse::<usize>().is_ok())
             {
                 err.span_suggestion_verbose(
                     field.span,
@@ -3396,7 +3399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         base_ty: Ty<'tcx>,
         mod_id: DefId,
         hir_id: HirId,
-    ) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
+    ) -> Vec<Vec<(Ident, Ty<'tcx>)>> {
         debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
 
         let mut autoderef = self.autoderef(span, base_ty).silence_errors();
@@ -3422,7 +3425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) {
                             return None;
                         }
-                        return Some((
+                        return Some(
                             fields
                                 .iter()
                                 .filter(move |field| {
@@ -3431,9 +3434,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 })
                                 // For compile-time reasons put a limit on number of fields we search
                                 .take(100)
+                                .map(|field_def| {
+                                    (
+                                        field_def.ident(self.tcx).normalize_to_macros_2_0(),
+                                        field_def.ty(self.tcx, args),
+                                    )
+                                })
+                                .collect::<Vec<_>>(),
+                        );
+                    }
+                    ty::Tuple(types) => {
+                        return Some(
+                            types
+                                .iter()
+                                .enumerate()
+                                // For compile-time reasons put a limit on number of fields we search
+                                .take(100)
+                                .map(|(i, ty)| (Ident::from_str(&i.to_string()), ty))
                                 .collect::<Vec<_>>(),
-                            *args,
-                        ));
+                        );
                     }
                     _ => None,
                 }
@@ -3443,56 +3462,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// This method is called after we have encountered a missing field error to recursively
     /// search for the field
+    #[instrument(skip(self, matches, mod_id, hir_id), level = "debug")]
     pub(crate) fn check_for_nested_field_satisfying_condition_for_diag(
         &self,
         span: Span,
-        matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool,
-        candidate_field: &ty::FieldDef,
-        subst: GenericArgsRef<'tcx>,
+        matches: &impl Fn(Ident, Ty<'tcx>) -> bool,
+        (candidate_name, candidate_ty): (Ident, Ty<'tcx>),
         mut field_path: Vec<Ident>,
         mod_id: DefId,
         hir_id: HirId,
     ) -> Option<Vec<Ident>> {
-        debug!(
-            "check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}",
-            span, candidate_field, field_path
-        );
-
         if field_path.len() > 3 {
             // For compile-time reasons and to avoid infinite recursion we only check for fields
             // up to a depth of three
-            None
-        } else {
-            field_path.push(candidate_field.ident(self.tcx).normalize_to_macros_2_0());
-            let field_ty = candidate_field.ty(self.tcx, subst);
-            if matches(candidate_field, field_ty) {
-                return Some(field_path);
-            } else {
-                for (nested_fields, subst) in self
-                    .get_field_candidates_considering_privacy_for_diag(
-                        span, field_ty, mod_id, hir_id,
-                    )
-                {
-                    // recursively search fields of `candidate_field` if it's a ty::Adt
-                    for field in nested_fields {
-                        if let Some(field_path) = self
-                            .check_for_nested_field_satisfying_condition_for_diag(
-                                span,
-                                matches,
-                                field,
-                                subst,
-                                field_path.clone(),
-                                mod_id,
-                                hir_id,
-                            )
-                        {
-                            return Some(field_path);
-                        }
-                    }
+            return None;
+        }
+        field_path.push(candidate_name);
+        if matches(candidate_name, candidate_ty) {
+            return Some(field_path);
+        }
+        for nested_fields in self.get_field_candidates_considering_privacy_for_diag(
+            span,
+            candidate_ty,
+            mod_id,
+            hir_id,
+        ) {
+            // recursively search fields of `candidate_field` if it's a ty::Adt
+            for field in nested_fields {
+                if let Some(field_path) = self.check_for_nested_field_satisfying_condition_for_diag(
+                    span,
+                    matches,
+                    field,
+                    field_path.clone(),
+                    mod_id,
+                    hir_id,
+                ) {
+                    return Some(field_path);
                 }
             }
-            None
         }
+        None
     }
 
     fn check_expr_index(
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 0c0cc752b01..f7430f7af4e 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -376,16 +376,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn suggest_missing_writer(&self, rcvr_ty: Ty<'tcx>, rcvr_expr: &hir::Expr<'tcx>) -> Diag<'_> {
-        let mut file = None;
+    fn suggest_missing_writer(
+        &self,
+        rcvr_ty: Ty<'tcx>,
+        rcvr_expr: &hir::Expr<'tcx>,
+        mut long_ty_path: Option<PathBuf>,
+    ) -> Diag<'_> {
         let mut err = struct_span_code_err!(
             self.dcx(),
             rcvr_expr.span,
             E0599,
             "cannot write into `{}`",
-            self.tcx.short_string(rcvr_ty, &mut file),
+            self.tcx.short_string(rcvr_ty, &mut long_ty_path),
         );
-        *err.long_ty_path() = file;
+        *err.long_ty_path() = long_ty_path;
         err.span_note(
             rcvr_expr.span,
             "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
@@ -403,7 +407,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         self_source: SelfSource<'tcx>,
         method_name: Ident,
-        ty_str_reported: &str,
+        ty: Ty<'tcx>,
         err: &mut Diag<'_>,
     ) {
         #[derive(Debug)]
@@ -478,7 +482,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
 
                 // If the shadowed binding has an itializer expression,
-                // use the initializer expression'ty to try to find the method again.
+                // use the initializer expression's ty to try to find the method again.
                 // For example like:  `let mut x = Vec::new();`,
                 // `Vec::new()` is the itializer expression.
                 if let Some(self_ty) = self.fcx.node_ty_opt(binding.init_hir_id)
@@ -566,17 +570,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let mut span = MultiSpan::from_span(sugg_let.span);
                     span.push_span_label(sugg_let.span,
                             format!("`{rcvr_name}` of type `{self_ty}` that has method `{method_name}` defined earlier here"));
+
+                    let ty = self.tcx.short_string(ty, err.long_ty_path());
                     span.push_span_label(
                         self.tcx.hir_span(recv_id),
-                        format!(
-                            "earlier `{rcvr_name}` shadowed here with type `{ty_str_reported}`"
-                        ),
+                        format!("earlier `{rcvr_name}` shadowed here with type `{ty}`"),
                     );
                     err.span_note(
                         span,
                         format!(
                             "there's an earlier shadowed binding `{rcvr_name}` of type `{self_ty}` \
-                                    that has method `{method_name}` available"
+                             that has method `{method_name}` available"
                         ),
                     );
                 }
@@ -602,15 +606,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
         let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
         let mut ty_file = None;
-        let (ty_str, short_ty_str) =
-            if trait_missing_method && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() {
-                (predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string()))
-            } else {
-                (
-                    tcx.short_string(rcvr_ty, &mut ty_file),
-                    with_forced_trimmed_paths!(rcvr_ty.to_string()),
-                )
-            };
         let is_method = mode == Mode::MethodCall;
         let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
         let similar_candidate = no_match_data.similar_candidate;
@@ -629,15 +624,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // We could pass the file for long types into these two, but it isn't strictly necessary
         // given how targeted they are.
-        if let Err(guar) = self.report_failed_method_call_on_range_end(
-            tcx,
-            rcvr_ty,
-            source,
-            span,
-            item_ident,
-            &short_ty_str,
-            &mut ty_file,
-        ) {
+        if let Err(guar) =
+            self.report_failed_method_call_on_range_end(tcx, rcvr_ty, source, span, item_ident)
+        {
             return guar;
         }
         if let Err(guar) = self.report_failed_method_call_on_numerical_infer_var(
@@ -647,44 +636,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             span,
             item_kind,
             item_ident,
-            &short_ty_str,
             &mut ty_file,
         ) {
             return guar;
         }
         span = item_ident.span;
 
-        // Don't show generic arguments when the method can't be found in any implementation (#81576).
-        let mut ty_str_reported = ty_str.clone();
-        if let ty::Adt(_, generics) = rcvr_ty.kind() {
-            if generics.len() > 0 {
-                let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
-                let candidate_found = autoderef.any(|(ty, _)| {
-                    if let ty::Adt(adt_def, _) = ty.kind() {
-                        self.tcx
-                            .inherent_impls(adt_def.did())
-                            .into_iter()
-                            .any(|def_id| self.associated_value(*def_id, item_ident).is_some())
-                    } else {
-                        false
-                    }
-                });
-                let has_deref = autoderef.step_count() > 0;
-                if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
-                    if let Some((path_string, _)) = ty_str.split_once('<') {
-                        ty_str_reported = path_string.to_string();
-                    }
-                }
-            }
-        }
-
         let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
             tcx.is_diagnostic_item(sym::write_macro, def_id)
                 || tcx.is_diagnostic_item(sym::writeln_macro, def_id)
         }) && item_ident.name == sym::write_fmt;
         let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
-            self.suggest_missing_writer(rcvr_ty, rcvr_expr)
+            self.suggest_missing_writer(rcvr_ty, rcvr_expr, ty_file)
         } else {
+            // Don't show expanded generic arguments when the method can't be found in any
+            // implementation (#81576).
+            let mut ty = rcvr_ty;
+            if let ty::Adt(def, generics) = rcvr_ty.kind() {
+                if generics.len() > 0 {
+                    let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
+                    let candidate_found = autoderef.any(|(ty, _)| {
+                        if let ty::Adt(adt_def, _) = ty.kind() {
+                            self.tcx
+                                .inherent_impls(adt_def.did())
+                                .into_iter()
+                                .any(|def_id| self.associated_value(*def_id, item_ident).is_some())
+                        } else {
+                            false
+                        }
+                    });
+                    let has_deref = autoderef.step_count() > 0;
+                    if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
+                        ty = self.tcx.at(span).type_of(def.did()).instantiate_identity();
+                    }
+                }
+            }
+
             let mut err = self.dcx().create_err(NoAssociatedItem {
                 span,
                 item_kind,
@@ -695,16 +682,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     rcvr_ty.prefix_string(self.tcx)
                 },
-                ty_str: ty_str_reported.clone(),
+                ty,
                 trait_missing_method,
             });
 
             if is_method {
                 self.suggest_use_shadowed_binding_with_method(
-                    source,
-                    item_ident,
-                    &ty_str_reported,
-                    &mut err,
+                    source, item_ident, rcvr_ty, &mut err,
                 );
             }
 
@@ -734,6 +718,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             err
         };
+
         if tcx.sess.source_map().is_multiline(sugg_span) {
             err.span_label(sugg_span.with_hi(span.lo()), "");
         }
@@ -750,6 +735,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if tcx.ty_is_opaque_future(rcvr_ty) && item_ident.name == sym::poll {
+            let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
             err.help(format!(
                 "method `poll` found on `Pin<&mut {ty_str}>`, \
                 see documentation for `std::pin::Pin`"
@@ -1339,7 +1325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                             let OnUnimplementedNote { message, label, notes, .. } = self
                                 .err_ctxt()
-                                .on_unimplemented_note(trait_ref, &obligation, &mut ty_file);
+                                .on_unimplemented_note(trait_ref, &obligation, err.long_ty_path());
                             (message, label, notes)
                         })
                         .unwrap()
@@ -1347,6 +1333,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     (None, None, Vec::new())
                 };
                 let primary_message = primary_message.unwrap_or_else(|| {
+                    let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
                     format!(
                         "the {item_kind} `{item_ident}` exists for {actual_prefix} `{ty_str}`, \
                          but its trait bounds were not satisfied"
@@ -1409,6 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut find_candidate_for_method = false;
 
         let mut label_span_not_found = |err: &mut Diag<'_>| {
+            let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
             if unsatisfied_predicates.is_empty() {
                 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
                 let is_string_or_ref_str = match rcvr_ty.kind() {
@@ -2520,8 +2508,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         source: SelfSource<'tcx>,
         span: Span,
         item_name: Ident,
-        ty_str: &str,
-        long_ty_path: &mut Option<PathBuf>,
     ) -> Result<(), ErrorGuaranteed> {
         if let SelfSource::MethodCall(expr) = source {
             for (_, parent) in tcx.hir_parent_iter(expr.hir_id).take(5) {
@@ -2583,18 +2569,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                     if pick.is_ok() {
                         let range_span = parent_expr.span.with_hi(expr.span.hi());
-                        let mut err = self.dcx().create_err(errors::MissingParenthesesInRange {
+                        return Err(self.dcx().emit_err(errors::MissingParenthesesInRange {
                             span,
-                            ty_str: ty_str.to_string(),
+                            ty: actual,
                             method_name: item_name.as_str().to_string(),
                             add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
                                 func_name: item_name.name.as_str().to_string(),
                                 left: range_span.shrink_to_lo(),
                                 right: range_span.shrink_to_hi(),
                             }),
-                        });
-                        *err.long_ty_path() = long_ty_path.take();
-                        return Err(err.emit());
+                        }));
                     }
                 }
             }
@@ -2610,7 +2594,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         item_kind: &str,
         item_name: Ident,
-        ty_str: &str,
         long_ty_path: &mut Option<PathBuf>,
     ) -> Result<(), ErrorGuaranteed> {
         let found_candidate = all_traits(self.tcx)
@@ -2643,14 +2626,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && !actual.has_concrete_skeleton()
             && let SelfSource::MethodCall(expr) = source
         {
+            let ty_str = self.tcx.short_string(actual, long_ty_path);
             let mut err = struct_span_code_err!(
                 self.dcx(),
                 span,
                 E0689,
-                "can't call {} `{}` on ambiguous numeric type `{}`",
-                item_kind,
-                item_name,
-                ty_str
+                "can't call {item_kind} `{item_name}` on ambiguous numeric type `{ty_str}`"
             );
             *err.long_ty_path() = long_ty_path.take();
             let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
@@ -2792,7 +2773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         if let SelfSource::MethodCall(expr) = source {
             let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
-            for (fields, args) in self.get_field_candidates_considering_privacy_for_diag(
+            for fields in self.get_field_candidates_considering_privacy_for_diag(
                 span,
                 actual,
                 mod_id,
@@ -2831,7 +2812,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 })
                             },
                             candidate_field,
-                            args,
                             vec![],
                             mod_id,
                             expr.hir_id,
@@ -3671,7 +3651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         )
                     {
                         debug!("try_alt_rcvr: pick candidate {:?}", pick);
-                        let did = Some(pick.item.container_id(self.tcx));
+                        let did = pick.item.trait_container(self.tcx);
                         // We don't want to suggest a container type when the missing
                         // method is `.clone()` or `.deref()` otherwise we'd suggest
                         // `Arc::new(foo).clone()`, which is far from what the user wants.
@@ -3720,8 +3700,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     && !alt_rcvr_sugg
                     // `T: !Unpin`
                     && !unpin
-                    // The method isn't `as_ref`, as it would provide a wrong suggestion for `Pin`.
-                    && sym::as_ref != item_name.name
                     // Either `Pin::as_ref` or `Pin::as_mut`.
                     && let Some(pin_call) = pin_call
                     // Search for `item_name` as a method accessible on `Pin<T>`.
@@ -3735,6 +3713,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // We skip some common traits that we don't want to consider because autoderefs
                     // would take care of them.
                     && !skippable.contains(&Some(pick.item.container_id(self.tcx)))
+                    // Do not suggest pinning when the method is directly on `Pin`.
+                    && pick.item.impl_container(self.tcx).map_or(true, |did| {
+                        match self.tcx.type_of(did).skip_binder().kind() {
+                            ty::Adt(def, _) => Some(def.did()) != self.tcx.lang_items().pin_type(),
+                            _ => true,
+                        }
+                    })
                     // We don't want to go through derefs.
                     && pick.autoderefs == 0
                     // Check that the method of the same name that was found on the new `Pin<T>`
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index bf4611e1e34..7dc736e5e6b 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1756,7 +1756,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let missing_parentheses = match (expected.kind(), fields, had_err) {
             // #67037: only do this if we could successfully type-check the expected type against
             // the tuple struct pattern. Otherwise the args could get out of range on e.g.,
-            // `let P() = U;` where `P != U` with `struct P<T>(T);`.
+            // `let P() = U;` where `P != U` with `struct Box<T>(T);`.
             (ty::Adt(_, args), [field], Ok(())) => {
                 let field_ty = self.field_ty(pat_span, field, args);
                 match field_ty.kind() {
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 7379df7c7c7..a2afdc45fa8 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -484,6 +484,7 @@ pub enum NllRegionVariableOrigin {
     Placeholder(ty::PlaceholderRegion),
 
     Existential {
+        name: Option<Symbol>,
         /// If this is true, then this variable was created to represent a lifetime
         /// bound in a `for` binder. For example, it might have been created to
         /// represent the lifetime `'a` in a type like `for<'a> fn(&'a u32)`.
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 8dec8069bc7..3ba224723e3 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -108,7 +108,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
         registered_tools: &RegisteredTools,
         node_id: ast::NodeId,
         attrs: &[ast::Attribute],
-        items: &[rustc_ast::ptr::P<ast::Item>],
+        items: &[Box<ast::Item>],
         name: Symbol,
     ) {
         pre_expansion_lint(sess, features, self.0, registered_tools, (node_id, attrs, items), name);
@@ -371,7 +371,7 @@ fn print_macro_stats(ecx: &ExtCtxt<'_>) {
             // The name won't abut or overlap with the uses value, but it does
             // overlap with the empty part of the uses column. Shrink the width
             // of the uses column to account for the excess name length.
-            uses_w = uses_with_underscores.len() + 1
+            uses_w -= name.len() - name_w;
         };
 
         _ = writeln!(
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 51b10191046..c893b723375 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -14,7 +14,6 @@
 //! [`crate::late_lint_methods!`] invocation in `lib.rs`.
 
 use std::fmt::Write;
-use std::slice;
 
 use ast::token::TokenKind;
 use rustc_abi::BackendRepr;
@@ -22,7 +21,6 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::visit::{FnCtxt, FnKind};
 use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust::expr_to_string;
-use rustc_attr_parsing::AttributeParser;
 use rustc_errors::{Applicability, LintDiagnostic};
 use rustc_feature::GateIssue;
 use rustc_hir as hir;
@@ -251,16 +249,7 @@ impl UnsafeCode {
 
 impl EarlyLintPass for UnsafeCode {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
-        if AttributeParser::parse_limited(
-            cx.builder.sess(),
-            slice::from_ref(attr),
-            sym::allow_internal_unsafe,
-            attr.span,
-            DUMMY_NODE_ID,
-            Some(cx.builder.features()),
-        )
-        .is_some()
-        {
+        if attr.has_name(sym::allow_internal_unsafe) {
             self.report_unsafe(cx, attr.span, BuiltinUnsafe::AllowInternalUnsafe);
         }
     }
diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs
index 7c39d8917ce..1d92cfbc039 100644
--- a/compiler/rustc_lint/src/default_could_be_derived.rs
+++ b/compiler/rustc_lint/src/default_could_be_derived.rs
@@ -62,8 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
         // Look for manual implementations of `Default`.
         let Some(default_def_id) = cx.tcx.get_diagnostic_item(sym::Default) else { return };
         let hir::ImplItemKind::Fn(_sig, body_id) = impl_item.kind else { return };
-        let assoc = cx.tcx.associated_item(impl_item.owner_id);
-        let parent = assoc.container_id(cx.tcx);
+        let parent = cx.tcx.parent(impl_item.owner_id.to_def_id());
         if find_attr!(cx.tcx.get_all_attrs(parent), AttributeKind::AutomaticallyDerived(..)) {
             // We don't care about what `#[derive(Default)]` produces in this lint.
             return;
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 48e3bbb79fa..58205087def 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -4,7 +4,6 @@
 //! resolution, just before AST lowering. These lints are for purely
 //! syntactical lints.
 
-use rustc_ast::ptr::P;
 use rustc_ast::visit::{self as ast_visit, Visitor, walk_list};
 use rustc_ast::{self as ast, HasAttrs};
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -297,7 +296,7 @@ impl<'a> EarlyCheckNode<'a> for (&'a ast::Crate, &'a [ast::Attribute]) {
     }
 }
 
-impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [P<ast::Item>]) {
+impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [Box<ast::Item>]) {
     fn id(self) -> ast::NodeId {
         self.0
     }
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index ac6147b1631..73e69a1791a 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -902,9 +902,8 @@ pub(crate) struct MappingToUnit {
     pub argument_label: Span,
     #[label(lint_map_label)]
     pub map_label: Span,
-    #[suggestion(style = "verbose", code = "{replace}", applicability = "maybe-incorrect")]
+    #[suggestion(style = "verbose", code = "for_each", applicability = "maybe-incorrect")]
     pub suggestion: Span,
-    pub replace: String,
 }
 
 // internal.rs
diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs
index 34210137bde..18a947dc1ee 100644
--- a/compiler/rustc_lint/src/map_unit_fn.rs
+++ b/compiler/rustc_lint/src/map_unit_fn.rs
@@ -1,6 +1,7 @@
-use rustc_hir::{Expr, ExprKind, HirId, Stmt, StmtKind};
-use rustc_middle::ty::{self, Ty};
+use rustc_hir::{Expr, ExprKind, Stmt, StmtKind};
+use rustc_middle::ty::{self};
 use rustc_session::{declare_lint, declare_lint_pass};
+use rustc_span::sym;
 
 use crate::lints::MappingToUnit;
 use crate::{LateContext, LateLintPass, LintContext};
@@ -39,58 +40,43 @@ declare_lint_pass!(MapUnitFn => [MAP_UNIT_FN]);
 
 impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'_>) {
-        if stmt.span.from_expansion() {
+        let StmtKind::Semi(expr) = stmt.kind else {
             return;
-        }
-
-        if let StmtKind::Semi(expr) = stmt.kind
-            && let ExprKind::MethodCall(path, receiver, args, span) = expr.kind
+        };
+        let ExprKind::MethodCall(path, receiver, [arg], span) = expr.kind else {
+            return;
+        };
+        if path.ident.name != sym::map
+            || stmt.span.from_expansion()
+            || receiver.span.from_expansion()
+            || arg.span.from_expansion()
+            || !is_impl_slice(cx, receiver)
+            || !cx
+                .typeck_results()
+                .type_dependent_def_id(expr.hir_id)
+                .is_some_and(|id| cx.tcx.is_diagnostic_item(sym::IteratorMap, id))
         {
-            if path.ident.name.as_str() == "map" {
-                if receiver.span.from_expansion()
-                    || args.iter().any(|e| e.span.from_expansion())
-                    || !is_impl_slice(cx, receiver)
-                    || !is_diagnostic_name(cx, expr.hir_id, "IteratorMap")
-                {
-                    return;
-                }
-                let arg_ty = cx.typeck_results().expr_ty(&args[0]);
-                let default_span = args[0].span;
-                if let ty::FnDef(id, _) = arg_ty.kind() {
-                    let fn_ty = cx.tcx.fn_sig(id).skip_binder();
-                    let ret_ty = fn_ty.output().skip_binder();
-                    if is_unit_type(ret_ty) {
-                        cx.emit_span_lint(
-                            MAP_UNIT_FN,
-                            span,
-                            MappingToUnit {
-                                function_label: cx.tcx.span_of_impl(*id).unwrap_or(default_span),
-                                argument_label: args[0].span,
-                                map_label: span,
-                                suggestion: path.ident.span,
-                                replace: "for_each".to_string(),
-                            },
-                        )
-                    }
-                } else if let ty::Closure(id, subs) = arg_ty.kind() {
-                    let cl_ty = subs.as_closure().sig();
-                    let ret_ty = cl_ty.output().skip_binder();
-                    if is_unit_type(ret_ty) {
-                        cx.emit_span_lint(
-                            MAP_UNIT_FN,
-                            span,
-                            MappingToUnit {
-                                function_label: cx.tcx.span_of_impl(*id).unwrap_or(default_span),
-                                argument_label: args[0].span,
-                                map_label: span,
-                                suggestion: path.ident.span,
-                                replace: "for_each".to_string(),
-                            },
-                        )
-                    }
-                }
-            }
+            return;
         }
+        let (id, sig) = match *cx.typeck_results().expr_ty(arg).kind() {
+            ty::Closure(id, subs) => (id, subs.as_closure().sig()),
+            ty::FnDef(id, _) => (id, cx.tcx.fn_sig(id).skip_binder()),
+            _ => return,
+        };
+        let ret_ty = sig.output().skip_binder();
+        if !(ret_ty.is_unit() || ret_ty.is_never()) {
+            return;
+        }
+        cx.emit_span_lint(
+            MAP_UNIT_FN,
+            span,
+            MappingToUnit {
+                function_label: cx.tcx.span_of_impl(id).unwrap_or(arg.span),
+                argument_label: arg.span,
+                map_label: span,
+                suggestion: path.ident.span,
+            },
+        );
     }
 }
 
@@ -102,18 +88,3 @@ fn is_impl_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     }
     false
 }
-
-fn is_unit_type(ty: Ty<'_>) -> bool {
-    ty.is_unit() || ty.is_never()
-}
-
-fn is_diagnostic_name(cx: &LateContext<'_>, id: HirId, name: &str) -> bool {
-    if let Some(def_id) = cx.typeck_results().type_dependent_def_id(id)
-        && let Some(item) = cx.tcx.get_diagnostic_name(def_id)
-    {
-        if item.as_str() == name {
-            return true;
-        }
-    }
-    false
-}
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 8855766ca98..958e314efab 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -83,7 +83,7 @@ pub fn walk_native_lib_search_dirs<R>(
     // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks
     // we must have the support library stubs in the library search path (#121430).
     if let Some(sdk_root) = apple_sdk_root
-        && sess.target.llvm_target.contains("macabi")
+        && sess.target.env == "macabi"
     {
         f(&sdk_root.join("System/iOSSupport/usr/lib"), false)?;
         f(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"), true)?;
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 00c97a2f738..548c56a97bc 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1530,7 +1530,7 @@ impl<'a> CrateMetadataRef<'a> {
                 let macro_rules = self.root.tables.is_macro_rules.get(self, id);
                 let body =
                     self.root.tables.macro_definition.get(self, id).unwrap().decode((self, sess));
-                ast::MacroDef { macro_rules, body: ast::ptr::P(body) }
+                ast::MacroDef { macro_rules, body: Box::new(body) }
             }
             _ => bug!(),
         }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 0f3896fd9be..df95ed602cd 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -75,24 +75,6 @@ impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>> ProcessQueryValue<'
 }
 
 impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>>
-    ProcessQueryValue<'tcx, ty::EarlyBinder<'tcx, &'tcx [T]>>
-    for Option<DecodeIterator<'a, 'tcx, T>>
-{
-    #[inline(always)]
-    fn process_decoded(
-        self,
-        tcx: TyCtxt<'tcx>,
-        err: impl Fn() -> !,
-    ) -> ty::EarlyBinder<'tcx, &'tcx [T]> {
-        ty::EarlyBinder::bind(if let Some(iter) = self {
-            tcx.arena.alloc_from_iter(iter)
-        } else {
-            err()
-        })
-    }
-}
-
-impl<'a, 'tcx, T: Copy + Decodable<DecodeContext<'a, 'tcx>>>
     ProcessQueryValue<'tcx, Option<&'tcx [T]>> for Option<DecodeIterator<'a, 'tcx, T>>
 {
     #[inline(always)]
diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs
index d632e65104a..34180001f80 100644
--- a/compiler/rustc_metadata/src/rmeta/parameterized.rs
+++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs
@@ -6,7 +6,7 @@ use rustc_index::{Idx, IndexVec};
 use rustc_middle::ty::{Binder, EarlyBinder};
 use rustc_span::Symbol;
 
-use crate::rmeta::{LazyArray, LazyTable, LazyValue};
+use crate::rmeta::{LazyArray, LazyValue};
 
 pub(crate) trait ParameterizedOverTcx: 'static {
     type Value<'tcx>;
@@ -48,10 +48,6 @@ impl<T: ParameterizedOverTcx> ParameterizedOverTcx for LazyArray<T> {
     type Value<'tcx> = LazyArray<T::Value<'tcx>>;
 }
 
-impl<I: 'static, T: ParameterizedOverTcx> ParameterizedOverTcx for LazyTable<I, T> {
-    type Value<'tcx> = LazyTable<I, T::Value<'tcx>>;
-}
-
 macro_rules! trivially_parameterized_over_tcx {
     ($($ty:ty),+ $(,)?) => {
         $(
@@ -154,7 +150,6 @@ parameterized_over_tcx! {
     rustc_middle::mir::CoroutineLayout,
     rustc_middle::mir::interpret::ConstAllocation,
     rustc_middle::ty::Clause,
-    rustc_middle::ty::ClauseKind,
     rustc_middle::ty::Const,
     rustc_middle::ty::ConstConditions,
     rustc_middle::ty::FnSig,
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 28f406fbc96..0671aa20399 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -66,22 +66,6 @@ pub(super) trait FixedSizeEncoding: IsDefault {
     fn write_to_bytes(self, b: &mut Self::ByteArray);
 }
 
-/// This implementation is not used generically, but for reading/writing
-/// concrete `u32` fields in `Lazy*` structures, which may be zero.
-impl FixedSizeEncoding for u32 {
-    type ByteArray = [u8; 4];
-
-    #[inline]
-    fn from_bytes(b: &[u8; 4]) -> Self {
-        Self::from_le_bytes(*b)
-    }
-
-    #[inline]
-    fn write_to_bytes(self, b: &mut [u8; 4]) {
-        *b = self.to_le_bytes();
-    }
-}
-
 impl FixedSizeEncoding for u64 {
     type ByteArray = [u8; 8];
 
@@ -175,14 +159,6 @@ fixed_size_enum! {
 }
 
 fixed_size_enum! {
-    ty::ImplPolarity {
-        ( Positive    )
-        ( Negative    )
-        ( Reservation )
-    }
-}
-
-fixed_size_enum! {
     hir::Constness {
         ( NotConst )
         ( Const    )
@@ -306,45 +282,6 @@ impl FixedSizeEncoding for bool {
     }
 }
 
-impl FixedSizeEncoding for Option<bool> {
-    type ByteArray = [u8; 1];
-
-    #[inline]
-    fn from_bytes(b: &[u8; 1]) -> Self {
-        match b[0] {
-            0 => Some(false),
-            1 => Some(true),
-            2 => None,
-            _ => unreachable!(),
-        }
-    }
-
-    #[inline]
-    fn write_to_bytes(self, b: &mut [u8; 1]) {
-        debug_assert!(!self.is_default());
-        b[0] = match self {
-            Some(false) => 0,
-            Some(true) => 1,
-            None => 2,
-        };
-    }
-}
-
-impl FixedSizeEncoding for UnusedGenericParams {
-    type ByteArray = [u8; 4];
-
-    #[inline]
-    fn from_bytes(b: &[u8; 4]) -> Self {
-        let x: u32 = u32::from_bytes(b);
-        UnusedGenericParams::from_bits(x)
-    }
-
-    #[inline]
-    fn write_to_bytes(self, b: &mut [u8; 4]) {
-        self.bits().write_to_bytes(b);
-    }
-}
-
 // NOTE(eddyb) there could be an impl for `usize`, which would enable a more
 // generic `LazyValue<T>` impl, but in the general case we might not need / want
 // to fit every `usize` in `u32`.
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 800c1af660a..857d041224f 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -96,6 +96,7 @@ impl fmt::Debug for Scope {
             ScopeData::Destruction => write!(fmt, "Destruction({:?})", self.local_id),
             ScopeData::IfThen => write!(fmt, "IfThen({:?})", self.local_id),
             ScopeData::IfThenRescope => write!(fmt, "IfThen[edition2024]({:?})", self.local_id),
+            ScopeData::MatchGuard => write!(fmt, "MatchGuard({:?})", self.local_id),
             ScopeData::Remainder(fsi) => write!(
                 fmt,
                 "Remainder {{ block: {:?}, first_statement_index: {}}}",
@@ -131,6 +132,11 @@ pub enum ScopeData {
     /// whose lifetimes do not cross beyond this scope.
     IfThenRescope,
 
+    /// Scope of the condition and body of a match arm with a guard
+    /// Used for variables introduced in an if-let guard,
+    /// whose lifetimes do not cross beyond this scope.
+    MatchGuard,
+
     /// Scope following a `let id = expr;` binding in a block.
     Remainder(FirstStatementIndex),
 }
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index b02abb5ab43..648709e88e6 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -527,21 +527,28 @@ impl<'tcx> GenericArgs<'tcx> {
     #[inline]
     #[track_caller]
     pub fn type_at(&self, i: usize) -> Ty<'tcx> {
-        self[i].as_type().unwrap_or_else(|| bug!("expected type for param #{} in {:?}", i, self))
+        self[i].as_type().unwrap_or_else(
+            #[track_caller]
+            || bug!("expected type for param #{} in {:?}", i, self),
+        )
     }
 
     #[inline]
     #[track_caller]
     pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
-        self[i]
-            .as_region()
-            .unwrap_or_else(|| bug!("expected region for param #{} in {:?}", i, self))
+        self[i].as_region().unwrap_or_else(
+            #[track_caller]
+            || bug!("expected region for param #{} in {:?}", i, self),
+        )
     }
 
     #[inline]
     #[track_caller]
     pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
-        self[i].as_const().unwrap_or_else(|| bug!("expected const for param #{} in {:?}", i, self))
+        self[i].as_const().unwrap_or_else(
+            #[track_caller]
+            || bug!("expected const for param #{} in {:?}", i, self),
+        )
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 8c0277055cd..73e1661106e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1031,6 +1031,8 @@ pub struct ParamEnvAnd<'tcx, T> {
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
 #[derive(TypeVisitable, TypeFoldable)]
 pub struct TypingEnv<'tcx> {
+    #[type_foldable(identity)]
+    #[type_visitable(ignore)]
     pub typing_mode: TypingMode<'tcx>,
     pub param_env: ParamEnv<'tcx>,
 }
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index b381d62be47..67244e767cb 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2987,7 +2987,7 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> {
     }
 }
 
-#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
 pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>);
 
 impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index 9bf6e3a7590..7dfe2d28051 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -44,7 +44,7 @@ impl RvalueScopes {
                     debug!("temporary_scope({expr_id:?}) = {id:?} [enclosing]");
                     return (Some(id), backwards_incompatible);
                 }
-                ScopeData::IfThenRescope => {
+                ScopeData::IfThenRescope | ScopeData::MatchGuard => {
                     debug!("temporary_scope({expr_id:?}) = {p:?} [enclosing]");
                     return (Some(p), backwards_incompatible);
                 }
diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs
index 7e25a173bf8..94ae5dadd8a 100644
--- a/compiler/rustc_mir_build/src/builder/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs
@@ -428,47 +428,53 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 let arm_source_info = self.source_info(arm.span);
                 let arm_scope = (arm.scope, arm_source_info);
                 let match_scope = self.local_scope();
+                let guard_scope = arm
+                    .guard
+                    .map(|_| region::Scope { data: region::ScopeData::MatchGuard, ..arm.scope });
                 self.in_scope(arm_scope, arm.lint_level, |this| {
-                    let old_dedup_scope =
-                        mem::replace(&mut this.fixed_temps_scope, Some(arm.scope));
-
-                    // `try_to_place` may fail if it is unable to resolve the given
-                    // `PlaceBuilder` inside a closure. In this case, we don't want to include
-                    // a scrutinee place. `scrutinee_place_builder` will fail to be resolved
-                    // if the only match arm is a wildcard (`_`).
-                    // Example:
-                    // ```
-                    // let foo = (0, 1);
-                    // let c = || {
-                    //    match foo { _ => () };
-                    // };
-                    // ```
-                    let scrutinee_place = scrutinee_place_builder.try_to_place(this);
-                    let opt_scrutinee_place =
-                        scrutinee_place.as_ref().map(|place| (Some(place), scrutinee_span));
-                    let scope = this.declare_bindings(
-                        None,
-                        arm.span,
-                        &arm.pattern,
-                        arm.guard,
-                        opt_scrutinee_place,
-                    );
+                    this.opt_in_scope(guard_scope.map(|scope| (scope, arm_source_info)), |this| {
+                        // `if let` guard temps needing deduplicating will be in the guard scope.
+                        let old_dedup_scope =
+                            mem::replace(&mut this.fixed_temps_scope, guard_scope);
+
+                        // `try_to_place` may fail if it is unable to resolve the given
+                        // `PlaceBuilder` inside a closure. In this case, we don't want to include
+                        // a scrutinee place. `scrutinee_place_builder` will fail to be resolved
+                        // if the only match arm is a wildcard (`_`).
+                        // Example:
+                        // ```
+                        // let foo = (0, 1);
+                        // let c = || {
+                        //    match foo { _ => () };
+                        // };
+                        // ```
+                        let scrutinee_place = scrutinee_place_builder.try_to_place(this);
+                        let opt_scrutinee_place =
+                            scrutinee_place.as_ref().map(|place| (Some(place), scrutinee_span));
+                        let scope = this.declare_bindings(
+                            None,
+                            arm.span,
+                            &arm.pattern,
+                            arm.guard,
+                            opt_scrutinee_place,
+                        );
 
-                    let arm_block = this.bind_pattern(
-                        outer_source_info,
-                        branch,
-                        &built_match_tree.fake_borrow_temps,
-                        scrutinee_span,
-                        Some((arm, match_scope)),
-                    );
+                        let arm_block = this.bind_pattern(
+                            outer_source_info,
+                            branch,
+                            &built_match_tree.fake_borrow_temps,
+                            scrutinee_span,
+                            Some((arm, match_scope)),
+                        );
 
-                    this.fixed_temps_scope = old_dedup_scope;
+                        this.fixed_temps_scope = old_dedup_scope;
 
-                    if let Some(source_scope) = scope {
-                        this.source_scope = source_scope;
-                    }
+                        if let Some(source_scope) = scope {
+                            this.source_scope = source_scope;
+                        }
 
-                    this.expr_into_dest(destination, arm_block, arm.body)
+                        this.expr_into_dest(destination, arm_block, arm.body)
+                    })
                 })
                 .into_block()
             })
@@ -2517,7 +2523,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // bindings and temporaries created for and by the guard. As a result, the drop order
             // for the arm will correspond to the binding order of the final sub-branch lowered.
             if matches!(schedule_drops, ScheduleDrops::No) {
-                self.clear_top_scope(arm.scope);
+                self.clear_match_arm_and_guard_scopes(arm.scope);
             }
 
             let source_info = self.source_info(guard_span);
diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs
index 1240b34cf9d..96659873622 100644
--- a/compiler/rustc_mir_build/src/builder/scope.rs
+++ b/compiler/rustc_mir_build/src/builder/scope.rs
@@ -697,6 +697,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         block.and(rv)
     }
 
+    /// Convenience wrapper that executes `f` either within the current scope or a new scope.
+    /// Used for pattern matching, which introduces an additional scope for patterns with guards.
+    pub(crate) fn opt_in_scope<R>(
+        &mut self,
+        opt_region_scope: Option<(region::Scope, SourceInfo)>,
+        f: impl FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
+    ) -> BlockAnd<R> {
+        if let Some(region_scope) = opt_region_scope {
+            self.in_scope(region_scope, LintLevel::Inherited, f)
+        } else {
+            f(self)
+        }
+    }
+
     /// Push a scope onto the stack. You can then build code in this
     /// scope and call `pop_scope` afterwards. Note that these two
     /// calls must be paired; using `in_scope` as a convenience
@@ -1750,17 +1764,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         success_block
     }
 
-    /// Unschedules any drops in the top scope.
+    /// Unschedules any drops in the top two scopes.
     ///
-    /// This is only needed for `match` arm scopes, because they have one
-    /// entrance per pattern, but only one exit.
-    pub(crate) fn clear_top_scope(&mut self, region_scope: region::Scope) {
-        let top_scope = self.scopes.scopes.last_mut().unwrap();
+    /// This is only needed for pattern-matches combining guards and or-patterns: or-patterns lead
+    /// to guards being lowered multiple times before lowering the arm body, so we unschedle drops
+    /// for guards' temporaries and bindings between lowering each instance of an match arm's guard.
+    pub(crate) fn clear_match_arm_and_guard_scopes(&mut self, region_scope: region::Scope) {
+        let [.., arm_scope, guard_scope] = &mut *self.scopes.scopes else {
+            bug!("matches with guards should introduce separate scopes for the pattern and guard");
+        };
 
-        assert_eq!(top_scope.region_scope, region_scope);
+        assert_eq!(arm_scope.region_scope, region_scope);
+        assert_eq!(guard_scope.region_scope.data, region::ScopeData::MatchGuard);
+        assert_eq!(guard_scope.region_scope.local_id, region_scope.local_id);
 
-        top_scope.drops.clear();
-        top_scope.invalidate_cache();
+        arm_scope.drops.clear();
+        arm_scope.invalidate_cache();
+        guard_scope.drops.clear();
+        guard_scope.invalidate_cache();
     }
 }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index a7d5422a3d7..f86a15a8f92 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -800,6 +800,7 @@ where
     let re = regex!("\t?\u{001f}([+-])");
 
     let raw_diff = format!("{:#?}", DebugDiffWithAdapter { new, old, ctxt });
+    let raw_diff = dot::escape_html(&raw_diff);
 
     // Replace newlines in the `Debug` output with `<br/>`
     let raw_diff = raw_diff.replace('\n', r#"<br align="left"/>"#);
diff --git a/compiler/rustc_mir_transform/src/coverage/hir_info.rs b/compiler/rustc_mir_transform/src/coverage/hir_info.rs
new file mode 100644
index 00000000000..28fdc52b06c
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/coverage/hir_info.rs
@@ -0,0 +1,128 @@
+use rustc_hir as hir;
+use rustc_hir::intravisit::{Visitor, walk_expr};
+use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::TyCtxt;
+use rustc_span::Span;
+use rustc_span::def_id::LocalDefId;
+
+/// Function information extracted from HIR by the coverage instrumentor.
+#[derive(Debug)]
+pub(crate) struct ExtractedHirInfo {
+    pub(crate) function_source_hash: u64,
+    pub(crate) is_async_fn: bool,
+    /// The span of the function's signature, if available.
+    /// Must have the same context and filename as the body span.
+    pub(crate) fn_sig_span: Option<Span>,
+    pub(crate) body_span: Span,
+    /// "Holes" are regions within the function body (or its expansions) that
+    /// should not be included in coverage spans for this function
+    /// (e.g. closures and nested items).
+    pub(crate) hole_spans: Vec<Span>,
+}
+
+pub(crate) fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHirInfo {
+    // FIXME(#79625): Consider improving MIR to provide the information needed, to avoid going back
+    // to HIR for it.
+
+    // HACK: For synthetic MIR bodies (async closures), use the def id of the HIR body.
+    if tcx.is_synthetic_mir(def_id) {
+        return extract_hir_info(tcx, tcx.local_parent(def_id));
+    }
+
+    let hir_node = tcx.hir_node_by_def_id(def_id);
+    let fn_body_id = hir_node.body_id().expect("HIR node is a function with body");
+    let hir_body = tcx.hir_body(fn_body_id);
+
+    let maybe_fn_sig = hir_node.fn_sig();
+    let is_async_fn = maybe_fn_sig.is_some_and(|fn_sig| fn_sig.header.is_async());
+
+    let mut body_span = hir_body.value.span;
+
+    use hir::{Closure, Expr, ExprKind, Node};
+    // Unexpand a closure's body span back to the context of its declaration.
+    // This helps with closure bodies that consist of just a single bang-macro,
+    // and also with closure bodies produced by async desugaring.
+    if let Node::Expr(&Expr { kind: ExprKind::Closure(&Closure { fn_decl_span, .. }), .. }) =
+        hir_node
+    {
+        body_span = body_span.find_ancestor_in_same_ctxt(fn_decl_span).unwrap_or(body_span);
+    }
+
+    // The actual signature span is only used if it has the same context and
+    // filename as the body, and precedes the body.
+    let fn_sig_span = maybe_fn_sig.map(|fn_sig| fn_sig.span).filter(|&fn_sig_span| {
+        let source_map = tcx.sess.source_map();
+        let file_idx = |span: Span| source_map.lookup_source_file_idx(span.lo());
+
+        fn_sig_span.eq_ctxt(body_span)
+            && fn_sig_span.hi() <= body_span.lo()
+            && file_idx(fn_sig_span) == file_idx(body_span)
+    });
+
+    let function_source_hash = hash_mir_source(tcx, hir_body);
+
+    let hole_spans = extract_hole_spans_from_hir(tcx, hir_body);
+
+    ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span, body_span, hole_spans }
+}
+
+fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx hir::Body<'tcx>) -> u64 {
+    let owner = hir_body.id().hir_id.owner;
+    tcx.hir_owner_nodes(owner)
+        .opt_hash_including_bodies
+        .expect("hash should be present when coverage instrumentation is enabled")
+        .to_smaller_hash()
+        .as_u64()
+}
+
+fn extract_hole_spans_from_hir<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &hir::Body<'tcx>) -> Vec<Span> {
+    struct HolesVisitor<'tcx> {
+        tcx: TyCtxt<'tcx>,
+        hole_spans: Vec<Span>,
+    }
+
+    impl<'tcx> Visitor<'tcx> for HolesVisitor<'tcx> {
+        /// We have special handling for nested items, but we still want to
+        /// traverse into nested bodies of things that are not considered items,
+        /// such as "anon consts" (e.g. array lengths).
+        type NestedFilter = nested_filter::OnlyBodies;
+
+        fn maybe_tcx(&mut self) -> TyCtxt<'tcx> {
+            self.tcx
+        }
+
+        /// We override `visit_nested_item` instead of `visit_item` because we
+        /// only need the item's span, not the item itself.
+        fn visit_nested_item(&mut self, id: hir::ItemId) -> Self::Result {
+            let span = self.tcx.def_span(id.owner_id.def_id);
+            self.visit_hole_span(span);
+            // Having visited this item, we don't care about its children,
+            // so don't call `walk_item`.
+        }
+
+        // We override `visit_expr` instead of the more specific expression
+        // visitors, so that we have direct access to the expression span.
+        fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+            match expr.kind {
+                hir::ExprKind::Closure(_) | hir::ExprKind::ConstBlock(_) => {
+                    self.visit_hole_span(expr.span);
+                    // Having visited this expression, we don't care about its
+                    // children, so don't call `walk_expr`.
+                }
+
+                // For other expressions, recursively visit as normal.
+                _ => walk_expr(self, expr),
+            }
+        }
+    }
+    impl HolesVisitor<'_> {
+        fn visit_hole_span(&mut self, hole_span: Span) {
+            self.hole_spans.push(hole_span);
+        }
+    }
+
+    let mut visitor = HolesVisitor { tcx, hole_spans: vec![] };
+
+    visitor.visit_body(hir_body);
+    visitor.hole_spans
+}
diff --git a/compiler/rustc_mir_transform/src/coverage/mappings.rs b/compiler/rustc_mir_transform/src/coverage/mappings.rs
index 399978b5915..46fe7c40826 100644
--- a/compiler/rustc_mir_transform/src/coverage/mappings.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mappings.rs
@@ -4,8 +4,8 @@ use rustc_middle::mir::{self, BasicBlock, StatementKind};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
-use crate::coverage::ExtractedHirInfo;
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
+use crate::coverage::hir_info::ExtractedHirInfo;
 use crate::coverage::spans::extract_refined_covspans;
 use crate::coverage::unexpand::unexpand_into_body_span;
 
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index f6945a95a7c..47a87a2e94d 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -1,26 +1,22 @@
-mod counters;
-mod graph;
-mod mappings;
-pub(super) mod query;
-mod spans;
-#[cfg(test)]
-mod tests;
-mod unexpand;
-
-use rustc_hir as hir;
-use rustc_hir::intravisit::{Visitor, walk_expr};
-use rustc_middle::hir::nested_filter;
 use rustc_middle::mir::coverage::{CoverageKind, FunctionCoverageInfo, Mapping, MappingKind};
 use rustc_middle::mir::{self, BasicBlock, Statement, StatementKind, TerminatorKind};
 use rustc_middle::ty::TyCtxt;
-use rustc_span::Span;
-use rustc_span::def_id::LocalDefId;
 use tracing::{debug, debug_span, trace};
 
 use crate::coverage::counters::BcbCountersData;
 use crate::coverage::graph::CoverageGraph;
 use crate::coverage::mappings::ExtractedMappings;
 
+mod counters;
+mod graph;
+mod hir_info;
+mod mappings;
+pub(super) mod query;
+mod spans;
+#[cfg(test)]
+mod tests;
+mod unexpand;
+
 /// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected
 /// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen
 /// to construct the coverage map.
@@ -67,7 +63,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
     let def_id = mir_body.source.def_id();
     let _span = debug_span!("instrument_function_for_coverage", ?def_id).entered();
 
-    let hir_info = extract_hir_info(tcx, def_id.expect_local());
+    let hir_info = hir_info::extract_hir_info(tcx, def_id.expect_local());
 
     // Build the coverage graph, which is a simplified view of the MIR control-flow
     // graph that ignores some details not relevant to coverage instrumentation.
@@ -147,122 +143,3 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb
     let statement = Statement::new(source_info, StatementKind::Coverage(counter_kind));
     data.statements.insert(0, statement);
 }
-
-/// Function information extracted from HIR by the coverage instrumentor.
-#[derive(Debug)]
-struct ExtractedHirInfo {
-    function_source_hash: u64,
-    is_async_fn: bool,
-    /// The span of the function's signature, if available.
-    /// Must have the same context and filename as the body span.
-    fn_sig_span: Option<Span>,
-    body_span: Span,
-    /// "Holes" are regions within the function body (or its expansions) that
-    /// should not be included in coverage spans for this function
-    /// (e.g. closures and nested items).
-    hole_spans: Vec<Span>,
-}
-
-fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHirInfo {
-    // FIXME(#79625): Consider improving MIR to provide the information needed, to avoid going back
-    // to HIR for it.
-
-    // HACK: For synthetic MIR bodies (async closures), use the def id of the HIR body.
-    if tcx.is_synthetic_mir(def_id) {
-        return extract_hir_info(tcx, tcx.local_parent(def_id));
-    }
-
-    let hir_node = tcx.hir_node_by_def_id(def_id);
-    let fn_body_id = hir_node.body_id().expect("HIR node is a function with body");
-    let hir_body = tcx.hir_body(fn_body_id);
-
-    let maybe_fn_sig = hir_node.fn_sig();
-    let is_async_fn = maybe_fn_sig.is_some_and(|fn_sig| fn_sig.header.is_async());
-
-    let mut body_span = hir_body.value.span;
-
-    use hir::{Closure, Expr, ExprKind, Node};
-    // Unexpand a closure's body span back to the context of its declaration.
-    // This helps with closure bodies that consist of just a single bang-macro,
-    // and also with closure bodies produced by async desugaring.
-    if let Node::Expr(&Expr { kind: ExprKind::Closure(&Closure { fn_decl_span, .. }), .. }) =
-        hir_node
-    {
-        body_span = body_span.find_ancestor_in_same_ctxt(fn_decl_span).unwrap_or(body_span);
-    }
-
-    // The actual signature span is only used if it has the same context and
-    // filename as the body, and precedes the body.
-    let fn_sig_span = maybe_fn_sig.map(|fn_sig| fn_sig.span).filter(|&fn_sig_span| {
-        let source_map = tcx.sess.source_map();
-        let file_idx = |span: Span| source_map.lookup_source_file_idx(span.lo());
-
-        fn_sig_span.eq_ctxt(body_span)
-            && fn_sig_span.hi() <= body_span.lo()
-            && file_idx(fn_sig_span) == file_idx(body_span)
-    });
-
-    let function_source_hash = hash_mir_source(tcx, hir_body);
-
-    let hole_spans = extract_hole_spans_from_hir(tcx, hir_body);
-
-    ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span, body_span, hole_spans }
-}
-
-fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx hir::Body<'tcx>) -> u64 {
-    // FIXME(cjgillot) Stop hashing HIR manually here.
-    let owner = hir_body.id().hir_id.owner;
-    tcx.hir_owner_nodes(owner).opt_hash_including_bodies.unwrap().to_smaller_hash().as_u64()
-}
-
-fn extract_hole_spans_from_hir<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &hir::Body<'tcx>) -> Vec<Span> {
-    struct HolesVisitor<'tcx> {
-        tcx: TyCtxt<'tcx>,
-        hole_spans: Vec<Span>,
-    }
-
-    impl<'tcx> Visitor<'tcx> for HolesVisitor<'tcx> {
-        /// We have special handling for nested items, but we still want to
-        /// traverse into nested bodies of things that are not considered items,
-        /// such as "anon consts" (e.g. array lengths).
-        type NestedFilter = nested_filter::OnlyBodies;
-
-        fn maybe_tcx(&mut self) -> TyCtxt<'tcx> {
-            self.tcx
-        }
-
-        /// We override `visit_nested_item` instead of `visit_item` because we
-        /// only need the item's span, not the item itself.
-        fn visit_nested_item(&mut self, id: hir::ItemId) -> Self::Result {
-            let span = self.tcx.def_span(id.owner_id.def_id);
-            self.visit_hole_span(span);
-            // Having visited this item, we don't care about its children,
-            // so don't call `walk_item`.
-        }
-
-        // We override `visit_expr` instead of the more specific expression
-        // visitors, so that we have direct access to the expression span.
-        fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
-            match expr.kind {
-                hir::ExprKind::Closure(_) | hir::ExprKind::ConstBlock(_) => {
-                    self.visit_hole_span(expr.span);
-                    // Having visited this expression, we don't care about its
-                    // children, so don't call `walk_expr`.
-                }
-
-                // For other expressions, recursively visit as normal.
-                _ => walk_expr(self, expr),
-            }
-        }
-    }
-    impl HolesVisitor<'_> {
-        fn visit_hole_span(&mut self, hole_span: Span) {
-            self.hole_spans.push(hole_span);
-        }
-    }
-
-    let mut visitor = HolesVisitor { tcx, hole_spans: vec![] };
-
-    visitor.visit_body(hir_body);
-    visitor.hole_spans
-}
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 0ee42abb195..ae9459dee84 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -7,8 +7,9 @@ use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span};
 use tracing::instrument;
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
+use crate::coverage::hir_info::ExtractedHirInfo;
 use crate::coverage::spans::from_mir::{Hole, RawSpanFromMir, SpanFromMir};
-use crate::coverage::{ExtractedHirInfo, mappings, unexpand};
+use crate::coverage::{mappings, unexpand};
 
 mod from_mir;
 
diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
index 43f80508e4a..6c2dfc59da2 100644
--- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -4,7 +4,13 @@
 //! useful because (unlike MIR building) it runs after type checking, so it can make use of
 //! `TypingMode::PostAnalysis` to provide more precise type information, especially about opaque
 //! types.
+//!
+//! When we're optimizing, we also remove calls to `drop_in_place<T>` when `T` isn't `needs_drop`,
+//! as those are essentially equivalent to `Drop` terminators. While the compiler doesn't insert
+//! them automatically, preferring the built-in instead, they're common in generic code (such as
+//! `Vec::truncate`) so removing them from things like inlined `Vec<u8>` is helpful.
 
+use rustc_hir::LangItem;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use tracing::{debug, trace};
@@ -21,15 +27,26 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
         let mut should_simplify = false;
         for block in body.basic_blocks.as_mut() {
             let terminator = block.terminator_mut();
-            if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
-                let ty = place.ty(&body.local_decls, tcx);
-                if ty.ty.needs_drop(tcx, typing_env) {
-                    continue;
+            let (ty, target) = match terminator.kind {
+                TerminatorKind::Drop { place, target, .. } => {
+                    (place.ty(&body.local_decls, tcx).ty, target)
+                }
+                TerminatorKind::Call { ref func, target: Some(target), .. }
+                    if tcx.sess.mir_opt_level() > 0
+                        && let Some((def_id, generics)) = func.const_fn_def()
+                        && tcx.is_lang_item(def_id, LangItem::DropInPlace) =>
+                {
+                    (generics.type_at(0), target)
                 }
-                debug!("SUCCESS: replacing `drop` with goto({:?})", target);
-                terminator.kind = TerminatorKind::Goto { target };
-                should_simplify = true;
+                _ => continue,
+            };
+
+            if ty.needs_drop(tcx, typing_env) {
+                continue;
             }
+            debug!("SUCCESS: replacing `drop` with goto({:?})", target);
+            terminator.kind = TerminatorKind::Goto { target };
+            should_simplify = true;
         }
 
         // if we applied optimizations, we potentially have some cfg to cleanup to
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 7059ffbf375..aaf1b6c05bf 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -642,7 +642,7 @@ parse_missing_for_in_trait_impl = missing `for` in a trait impl
     .suggestion = add `for` here
 
 parse_missing_in_in_for_loop = missing `in` in `for` loop
-    .use_in_not_of = try using `in` here instead
+    .use_in = try using `in` here instead
     .add_in = try adding `in` here
 
 parse_missing_let_before_mut = missing keyword
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 48ff0394d46..ddb2c545c78 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -585,14 +585,13 @@ pub(crate) struct MissingInInForLoop {
 
 #[derive(Subdiagnostic)]
 pub(crate) enum MissingInInForLoopSub {
+    // User wrote `for pat of expr {}`
     // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect
-    #[suggestion(
-        parse_use_in_not_of,
-        style = "verbose",
-        applicability = "maybe-incorrect",
-        code = "in"
-    )]
+    #[suggestion(parse_use_in, style = "verbose", applicability = "maybe-incorrect", code = "in")]
     InNotOf(#[primary_span] Span),
+    // User wrote `for pat = expr {}`
+    #[suggestion(parse_use_in, style = "verbose", applicability = "maybe-incorrect", code = "in")]
+    InNotEq(#[primary_span] Span),
     #[suggestion(parse_add_in, style = "verbose", applicability = "maybe-incorrect", code = " in ")]
     AddIn(#[primary_span] Span),
 }
diff --git a/compiler/rustc_parse/src/parser/asm.rs b/compiler/rustc_parse/src/parser/asm.rs
index d4d0612a317..41c3b0f0b67 100644
--- a/compiler/rustc_parse/src/parser/asm.rs
+++ b/compiler/rustc_parse/src/parser/asm.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, AsmMacro};
 use rustc_span::{Span, Symbol, kw};
 
@@ -14,7 +13,7 @@ pub struct AsmArg {
 }
 
 pub enum AsmArgKind {
-    Template(P<ast::Expr>),
+    Template(Box<ast::Expr>),
     Operand(Option<Symbol>, ast::InlineAsmOperand),
     Options(Vec<AsmOption>),
     ClobberAbi(Vec<(Symbol, Span)>),
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index e0f810d8c1e..a32cd33a260 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -3,7 +3,6 @@ use std::ops::{Deref, DerefMut};
 
 use ast::token::IdentIsRaw;
 use rustc_ast as ast;
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind};
 use rustc_ast::util::parser::AssocOp;
 use rustc_ast::{
@@ -50,7 +49,7 @@ use crate::{exp, fluent_generated as fluent};
 
 /// Creates a placeholder argument.
 pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param {
-    let pat = P(Pat {
+    let pat = Box::new(Pat {
         id: ast::DUMMY_NODE_ID,
         kind: PatKind::Ident(BindingMode::NONE, ident, None),
         span: ident.span,
@@ -62,23 +61,23 @@ pub(super) fn dummy_arg(ident: Ident, guar: ErrorGuaranteed) -> Param {
         id: ast::DUMMY_NODE_ID,
         pat,
         span: ident.span,
-        ty: P(ty),
+        ty: Box::new(ty),
         is_placeholder: false,
     }
 }
 
 pub(super) trait RecoverQPath: Sized + 'static {
     const PATH_STYLE: PathStyle = PathStyle::Expr;
-    fn to_ty(&self) -> Option<P<Ty>>;
-    fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self;
+    fn to_ty(&self) -> Option<Box<Ty>>;
+    fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self;
 }
 
 impl RecoverQPath for Ty {
     const PATH_STYLE: PathStyle = PathStyle::Type;
-    fn to_ty(&self) -> Option<P<Ty>> {
-        Some(P(self.clone()))
+    fn to_ty(&self) -> Option<Box<Ty>> {
+        Some(Box::new(self.clone()))
     }
-    fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self {
+    fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self {
         Self {
             span: path.span,
             kind: TyKind::Path(qself, path),
@@ -90,10 +89,10 @@ impl RecoverQPath for Ty {
 
 impl RecoverQPath for Pat {
     const PATH_STYLE: PathStyle = PathStyle::Pat;
-    fn to_ty(&self) -> Option<P<Ty>> {
+    fn to_ty(&self) -> Option<Box<Ty>> {
         self.to_ty()
     }
-    fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self {
+    fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self {
         Self {
             span: path.span,
             kind: PatKind::Path(qself, path),
@@ -104,10 +103,10 @@ impl RecoverQPath for Pat {
 }
 
 impl RecoverQPath for Expr {
-    fn to_ty(&self) -> Option<P<Ty>> {
+    fn to_ty(&self) -> Option<Box<Ty>> {
         self.to_ty()
     }
-    fn recovered(qself: Option<P<QSelf>>, path: ast::Path) -> Self {
+    fn recovered(qself: Option<Box<QSelf>>, path: ast::Path) -> Self {
         Self {
             span: path.span,
             kind: ExprKind::Path(qself, path),
@@ -977,7 +976,7 @@ impl<'a> Parser<'a> {
         lo: Span,
         s: BlockCheckMode,
         maybe_struct_name: token::Token,
-    ) -> Option<PResult<'a, P<Block>>> {
+    ) -> Option<PResult<'a, Box<Block>>> {
         if self.token.is_ident() && self.look_ahead(1, |t| t == &token::Colon) {
             // We might be having a struct literal where people forgot to include the path:
             // fn foo() -> Foo {
@@ -1042,7 +1041,7 @@ impl<'a> Parser<'a> {
         token: token::Token,
         lo: Span,
         decl_hi: Span,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         err.span_label(lo.to(decl_hi), "while parsing the body of this closure");
         let guar = match before.kind {
             token::OpenBrace if token.kind != token::OpenBrace => {
@@ -1260,7 +1259,7 @@ impl<'a> Parser<'a> {
     pub(super) fn check_mistyped_turbofish_with_multiple_type_params(
         &mut self,
         mut e: Diag<'a>,
-        expr: &mut P<Expr>,
+        expr: &mut Box<Expr>,
     ) -> PResult<'a, ErrorGuaranteed> {
         if let ExprKind::Binary(binop, _, _) = &expr.kind
             && let ast::BinOpKind::Lt = binop.node
@@ -1443,7 +1442,7 @@ impl<'a> Parser<'a> {
         &mut self,
         inner_op: &Expr,
         outer_op: &Spanned<AssocOp>,
-    ) -> PResult<'a, Option<P<Expr>>> {
+    ) -> PResult<'a, Option<Box<Expr>>> {
         debug_assert!(
             outer_op.node.is_comparison(),
             "check_no_chained_comparison: {:?} is not comparison",
@@ -1595,7 +1594,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Swift lets users write `Ty?` to mean `Option<Ty>`. Parse the construct and recover from it.
-    pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P<Ty>) -> P<Ty> {
+    pub(super) fn maybe_recover_from_question_mark(&mut self, ty: Box<Ty>) -> Box<Ty> {
         if self.token == token::Question {
             self.bump();
             let guar = self.dcx().emit_err(QuestionMarkInType {
@@ -1690,10 +1689,10 @@ impl<'a> Parser<'a> {
 
     pub(super) fn recover_from_prefix_increment(
         &mut self,
-        operand_expr: P<Expr>,
+        operand_expr: Box<Expr>,
         op_span: Span,
         start_stmt: bool,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr };
         let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre };
         self.recover_from_inc_dec(operand_expr, kind, op_span)
@@ -1701,10 +1700,10 @@ impl<'a> Parser<'a> {
 
     pub(super) fn recover_from_postfix_increment(
         &mut self,
-        operand_expr: P<Expr>,
+        operand_expr: Box<Expr>,
         op_span: Span,
         start_stmt: bool,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let kind = IncDecRecovery {
             standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
             op: IncOrDec::Inc,
@@ -1715,10 +1714,10 @@ impl<'a> Parser<'a> {
 
     pub(super) fn recover_from_postfix_decrement(
         &mut self,
-        operand_expr: P<Expr>,
+        operand_expr: Box<Expr>,
         op_span: Span,
         start_stmt: bool,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let kind = IncDecRecovery {
             standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
             op: IncOrDec::Dec,
@@ -1729,10 +1728,10 @@ impl<'a> Parser<'a> {
 
     fn recover_from_inc_dec(
         &mut self,
-        base: P<Expr>,
+        base: Box<Expr>,
         kind: IncDecRecovery,
         op_span: Span,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let mut err = self.dcx().struct_span_err(
             op_span,
             format!("Rust has no {} {} operator", kind.fixity, kind.op.name()),
@@ -1833,8 +1832,8 @@ impl<'a> Parser<'a> {
     /// tail, and combines them into a `<Ty>::AssocItem` expression/pattern/type.
     pub(super) fn maybe_recover_from_bad_qpath<T: RecoverQPath>(
         &mut self,
-        base: P<T>,
-    ) -> PResult<'a, P<T>> {
+        base: Box<T>,
+    ) -> PResult<'a, Box<T>> {
         if !self.may_recover() {
             return Ok(base);
         }
@@ -1853,8 +1852,8 @@ impl<'a> Parser<'a> {
     pub(super) fn maybe_recover_from_bad_qpath_stage_2<T: RecoverQPath>(
         &mut self,
         ty_span: Span,
-        ty: P<Ty>,
-    ) -> PResult<'a, P<T>> {
+        ty: Box<Ty>,
+    ) -> PResult<'a, Box<T>> {
         self.expect(exp!(PathSep))?;
 
         let mut path = ast::Path { segments: ThinVec::new(), span: DUMMY_SP, tokens: None };
@@ -1867,7 +1866,7 @@ impl<'a> Parser<'a> {
         });
 
         let path_span = ty_span.shrink_to_hi(); // Use an empty path since `position == 0`.
-        Ok(P(T::recovered(Some(P(QSelf { ty, path_span, position: 0 })), path)))
+        Ok(Box::new(T::recovered(Some(Box::new(QSelf { ty, path_span, position: 0 })), path)))
     }
 
     /// This function gets called in places where a semicolon is NOT expected and if there's a
@@ -1970,7 +1969,7 @@ impl<'a> Parser<'a> {
     pub(super) fn recover_incorrect_await_syntax(
         &mut self,
         await_sp: Span,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let (hi, expr, is_question) = if self.token == token::Bang {
             // Handle `await!(<expr>)`.
             self.recover_await_macro()?
@@ -1982,7 +1981,7 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(expr)
     }
 
-    fn recover_await_macro(&mut self) -> PResult<'a, (Span, P<Expr>, bool)> {
+    fn recover_await_macro(&mut self) -> PResult<'a, (Span, Box<Expr>, bool)> {
         self.expect(exp!(Bang))?;
         self.expect(exp!(OpenParen))?;
         let expr = self.parse_expr()?;
@@ -1990,7 +1989,7 @@ impl<'a> Parser<'a> {
         Ok((self.prev_token.span, expr, false))
     }
 
-    fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, P<Expr>, bool)> {
+    fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, Box<Expr>, bool)> {
         let is_question = self.eat(exp!(Question)); // Handle `await? <expr>`.
         let expr = if self.token == token::OpenBrace {
             // Handle `await { <expr> }`.
@@ -2052,7 +2051,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, P<Expr>> {
+    pub(super) fn try_macro_suggestion(&mut self) -> PResult<'a, Box<Expr>> {
         let is_try = self.token.is_keyword(kw::Try);
         let is_questionmark = self.look_ahead(1, |t| t == &token::Bang); //check for !
         let is_open = self.look_ahead(2, |t| t == &token::OpenParen); //check for (
@@ -2124,7 +2123,7 @@ impl<'a> Parser<'a> {
         close: ExpTokenPair<'_>,
         lo: Span,
         err: Diag<'a>,
-    ) -> P<Expr> {
+    ) -> Box<Expr> {
         let guar = err.emit();
         // Recover from parse error, callers expect the closing delim to be consumed.
         self.consume_block(open, close, ConsumeClosingDelim::Yes);
@@ -2244,7 +2243,7 @@ impl<'a> Parser<'a> {
     pub(super) fn parameter_without_type(
         &mut self,
         err: &mut Diag<'_>,
-        pat: P<ast::Pat>,
+        pat: Box<ast::Pat>,
         require_name: bool,
         first_param: bool,
     ) -> Option<Ident> {
@@ -2346,7 +2345,7 @@ impl<'a> Parser<'a> {
         None
     }
 
-    pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
+    pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (Box<ast::Pat>, Box<ast::Ty>)> {
         let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?;
         self.expect(exp!(Colon))?;
         let ty = self.parse_ty()?;
@@ -2354,8 +2353,12 @@ impl<'a> Parser<'a> {
         self.dcx().emit_err(PatternMethodParamWithoutBody { span: pat.span });
 
         // Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
-        let pat =
-            P(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID, tokens: None });
+        let pat = Box::new(Pat {
+            kind: PatKind::Wild,
+            span: pat.span,
+            id: ast::DUMMY_NODE_ID,
+            tokens: None,
+        });
         Ok((pat, ty))
     }
 
@@ -2506,7 +2509,7 @@ impl<'a> Parser<'a> {
     /// - Single-segment paths (i.e. standalone generic const parameters).
     /// All other expressions that can be parsed will emit an error suggesting the expression be
     /// wrapped in braces.
-    pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, P<Expr>> {
+    pub(super) fn handle_unambiguous_unbraced_const_arg(&mut self) -> PResult<'a, Box<Expr>> {
         let start = self.token.span;
         let attrs = self.parse_outer_attributes()?;
         let (expr, _) =
@@ -2688,7 +2691,7 @@ impl<'a> Parser<'a> {
     pub(crate) fn recover_unbraced_const_arg_that_can_begin_ty(
         &mut self,
         mut snapshot: SnapshotParser<'a>,
-    ) -> Option<P<ast::Expr>> {
+    ) -> Option<Box<ast::Expr>> {
         match (|| {
             let attrs = self.parse_outer_attributes()?;
             snapshot.parse_expr_res(Restrictions::CONST_EXPR, attrs)
@@ -2724,9 +2727,9 @@ impl<'a> Parser<'a> {
     /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
     pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
         &mut self,
-        mut first_pat: P<Pat>,
+        mut first_pat: Box<Pat>,
         expected: Option<Expected>,
-    ) -> P<Pat> {
+    ) -> Box<Pat> {
         if token::Colon != self.token.kind {
             return first_pat;
         }
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 35b987cf50f..d0604f76317 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -6,7 +6,6 @@ use core::ops::{Bound, ControlFlow};
 use ast::mut_visit::{self, MutVisitor};
 use ast::token::IdentIsRaw;
 use ast::{CoroutineKind, ForLoopKind, GenBlockKind, MatchKind, Pat, Path, PathSegment, Recovered};
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind};
 use rustc_ast::tokenstream::TokenTree;
 use rustc_ast::util::case::Case;
@@ -56,7 +55,7 @@ pub(super) enum DestructuredFloat {
 impl<'a> Parser<'a> {
     /// Parses an expression.
     #[inline]
-    pub fn parse_expr(&mut self) -> PResult<'a, P<Expr>> {
+    pub fn parse_expr(&mut self) -> PResult<'a, Box<Expr>> {
         self.current_closure.take();
 
         let attrs = self.parse_outer_attributes()?;
@@ -64,7 +63,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an expression, forcing tokens to be collected.
-    pub fn parse_expr_force_collect(&mut self) -> PResult<'a, P<Expr>> {
+    pub fn parse_expr_force_collect(&mut self) -> PResult<'a, Box<Expr>> {
         self.current_closure.take();
 
         // If the expression is associative (e.g. `1 + 2`), then any preceding
@@ -90,7 +89,10 @@ impl<'a> Parser<'a> {
         self.parse_expr().map(|value| AnonConst { id: DUMMY_NODE_ID, value })
     }
 
-    fn parse_expr_catch_underscore(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
+    fn parse_expr_catch_underscore(
+        &mut self,
+        restrictions: Restrictions,
+    ) -> PResult<'a, Box<Expr>> {
         let attrs = self.parse_outer_attributes()?;
         match self.parse_expr_res(restrictions, attrs) {
             Ok((expr, _)) => Ok(expr),
@@ -109,7 +111,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a sequence of expressions delimited by parentheses.
-    fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<P<Expr>>> {
+    fn parse_expr_paren_seq(&mut self) -> PResult<'a, ThinVec<Box<Expr>>> {
         self.parse_paren_comma_seq(|p| p.parse_expr_catch_underscore(Restrictions::empty()))
             .map(|(r, _)| r)
     }
@@ -120,7 +122,7 @@ impl<'a> Parser<'a> {
         &mut self,
         r: Restrictions,
         attrs: AttrWrapper,
-    ) -> PResult<'a, (P<Expr>, bool)> {
+    ) -> PResult<'a, (Box<Expr>, bool)> {
         self.with_res(r, |this| this.parse_expr_assoc_with(Bound::Unbounded, attrs))
     }
 
@@ -131,7 +133,7 @@ impl<'a> Parser<'a> {
         &mut self,
         min_prec: Bound<ExprPrecedence>,
         attrs: AttrWrapper,
-    ) -> PResult<'a, (P<Expr>, bool)> {
+    ) -> PResult<'a, (Box<Expr>, bool)> {
         let lhs = if self.token.is_range_separator() {
             return self.parse_expr_prefix_range(attrs).map(|res| (res, false));
         } else {
@@ -147,8 +149,8 @@ impl<'a> Parser<'a> {
         &mut self,
         min_prec: Bound<ExprPrecedence>,
         starts_stmt: bool,
-        mut lhs: P<Expr>,
-    ) -> PResult<'a, (P<Expr>, bool)> {
+        mut lhs: Box<Expr>,
+    ) -> PResult<'a, (Box<Expr>, bool)> {
         let mut parsed_something = false;
         if !self.should_continue_as_assoc_expr(&lhs) {
             return Ok((lhs, parsed_something));
@@ -414,10 +416,10 @@ impl<'a> Parser<'a> {
     fn parse_expr_range(
         &mut self,
         prec: ExprPrecedence,
-        lhs: P<Expr>,
+        lhs: Box<Expr>,
         limits: RangeLimits,
         cur_op_span: Span,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let rhs = if self.is_at_start_of_range_notation_rhs() {
             let maybe_lt = self.token;
             let attrs = self.parse_outer_attributes()?;
@@ -448,7 +450,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`.
-    fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> {
+    fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> {
         if !attrs.is_empty() {
             let err = errors::DotDotRangeAttribute { span: self.token.span };
             self.dcx().emit_err(err);
@@ -490,7 +492,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a prefix-unary-operator expr.
-    fn parse_expr_prefix(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> {
+    fn parse_expr_prefix(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> {
         let lo = self.token.span;
 
         macro_rules! make_it {
@@ -564,7 +566,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
+    fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, Box<Expr>)> {
         self.bump();
         let attrs = self.parse_outer_attributes()?;
         let expr = if self.token.is_range_separator() {
@@ -653,12 +655,12 @@ impl<'a> Parser<'a> {
 
     fn parse_assoc_op_cast(
         &mut self,
-        lhs: P<Expr>,
+        lhs: Box<Expr>,
         lhs_span: Span,
         op_span: Span,
-        expr_kind: fn(P<Expr>, P<Ty>) -> ExprKind,
-    ) -> PResult<'a, P<Expr>> {
-        let mk_expr = |this: &mut Self, lhs: P<Expr>, rhs: P<Ty>| {
+        expr_kind: fn(Box<Expr>, Box<Ty>) -> ExprKind,
+    ) -> PResult<'a, Box<Expr>> {
+        let mk_expr = |this: &mut Self, lhs: Box<Expr>, rhs: Box<Ty>| {
             this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span), expr_kind(lhs, rhs))
         };
 
@@ -873,7 +875,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `a.b` or `a(13)` or `a[4]` or just `a`.
-    fn parse_expr_dot_or_call(&mut self, attrs: AttrWrapper) -> PResult<'a, P<Expr>> {
+    fn parse_expr_dot_or_call(&mut self, attrs: AttrWrapper) -> PResult<'a, Box<Expr>> {
         self.collect_tokens_for_expr(attrs, |this, attrs| {
             let base = this.parse_expr_bottom()?;
             let span = this.interpolated_or_expr_span(&base);
@@ -884,9 +886,9 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_expr_dot_or_call_with(
         &mut self,
         mut attrs: ast::AttrVec,
-        mut e: P<Expr>,
+        mut e: Box<Expr>,
         lo: Span,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let mut res = ensure_sufficient_stack(|| {
             loop {
                 let has_question =
@@ -945,8 +947,8 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_dot_suffix_expr(
         &mut self,
         lo: Span,
-        base: P<Expr>,
-    ) -> PResult<'a, P<Expr>> {
+        base: Box<Expr>,
+    ) -> PResult<'a, Box<Expr>> {
         // At this point we've consumed something like `expr.` and `self.token` holds the token
         // after the dot.
         match self.token.uninterpolate().kind {
@@ -1232,10 +1234,10 @@ impl<'a> Parser<'a> {
         &self,
         lo: Span,
         ident_span: Span,
-        base: P<Expr>,
+        base: Box<Expr>,
         field: Symbol,
         suffix: Option<Symbol>,
-    ) -> P<Expr> {
+    ) -> Box<Expr> {
         if let Some(suffix) = suffix {
             self.expect_no_tuple_index_suffix(ident_span, suffix);
         }
@@ -1243,7 +1245,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a function call expression, `expr(...)`.
-    fn parse_expr_fn_call(&mut self, lo: Span, fun: P<Expr>) -> P<Expr> {
+    fn parse_expr_fn_call(&mut self, lo: Span, fun: Box<Expr>) -> Box<Expr> {
         let snapshot = if self.token == token::OpenParen {
             Some((self.create_snapshot_for_diagnostic(), fun.kind.clone()))
         } else {
@@ -1267,9 +1269,9 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         open_paren: Span,
-        seq: PResult<'a, P<Expr>>,
+        seq: PResult<'a, Box<Expr>>,
         snapshot: Option<(SnapshotParser<'a>, ExprKind)>,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         match (self.may_recover(), seq, snapshot) {
             (true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
                 snapshot.bump(); // `(`
@@ -1325,7 +1327,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse an indexing expression `expr[...]`.
-    fn parse_expr_index(&mut self, lo: Span, base: P<Expr>) -> PResult<'a, P<Expr>> {
+    fn parse_expr_index(&mut self, lo: Span, base: Box<Expr>) -> PResult<'a, Box<Expr>> {
         let prev_span = self.prev_token.span;
         let open_delim_span = self.token.span;
         self.bump(); // `[`
@@ -1339,7 +1341,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Assuming we have just parsed `.`, continue parsing into an expression.
-    fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
+    fn parse_dot_suffix(&mut self, self_arg: Box<Expr>, lo: Span) -> PResult<'a, Box<Expr>> {
         if self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await)) {
             return Ok(self.mk_await_expr(self_arg, lo));
         }
@@ -1404,7 +1406,7 @@ impl<'a> Parser<'a> {
     ///
     /// N.B., this does not parse outer attributes, and is private because it only works
     /// correctly if called from `parse_expr_dot_or_call`.
-    fn parse_expr_bottom(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_bottom(&mut self) -> PResult<'a, Box<Expr>> {
         maybe_recover_from_interpolated_ty_qpath!(self, true);
 
         let span = self.token.span;
@@ -1556,7 +1558,7 @@ impl<'a> Parser<'a> {
         })
     }
 
-    fn parse_expr_lit(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_lit(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.token.span;
         match self.parse_opt_token_lit() {
             Some((token_lit, _)) => {
@@ -1567,7 +1569,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
+    fn parse_expr_tuple_parens(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> {
         let lo = self.token.span;
         self.expect(exp!(OpenParen))?;
         let (es, trailing_comma) = match self.parse_seq_to_end(
@@ -1596,7 +1598,7 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(expr)
     }
 
-    fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair<'_>) -> PResult<'a, P<Expr>> {
+    fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair<'_>) -> PResult<'a, Box<Expr>> {
         let lo = self.token.span;
         self.bump(); // `[` or other open delim
 
@@ -1627,7 +1629,7 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(expr)
     }
 
-    fn parse_expr_path_start(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_path_start(&mut self) -> PResult<'a, Box<Expr>> {
         let maybe_eq_tok = self.prev_token;
         let (qself, path) = if self.eat_lt() {
             let lt_span = self.prev_token.span;
@@ -1653,7 +1655,7 @@ impl<'a> Parser<'a> {
                 self.dcx().emit_err(errors::MacroInvocationWithQualifiedPath(path.span));
             }
             let lo = path.span;
-            let mac = P(MacCall { path, args: self.parse_delim_args()? });
+            let mac = Box::new(MacCall { path, args: self.parse_delim_args()? });
             (lo.to(self.prev_token.span), ExprKind::MacCall(mac))
         } else if self.check(exp!(OpenBrace))
             && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path)
@@ -1675,7 +1677,7 @@ impl<'a> Parser<'a> {
         &mut self,
         label_: Label,
         mut consume_colon: bool,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let lo = label_.ident.span;
         let label = Some(label_);
         let ate_colon = self.eat(exp!(Colon));
@@ -1810,7 +1812,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
-    fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
+    fn recover_do_catch(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.token.span;
 
         self.bump(); // `do`
@@ -1823,12 +1825,12 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse an expression if the token can begin one.
-    fn parse_expr_opt(&mut self) -> PResult<'a, Option<P<Expr>>> {
+    fn parse_expr_opt(&mut self) -> PResult<'a, Option<Box<Expr>>> {
         Ok(if self.token.can_begin_expr() { Some(self.parse_expr()?) } else { None })
     }
 
     /// Parse `"return" expr?`.
-    fn parse_expr_return(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_return(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.prev_token.span;
         let kind = ExprKind::Ret(self.parse_expr_opt()?);
         let expr = self.mk_expr(lo.to(self.prev_token.span), kind);
@@ -1836,7 +1838,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse `"do" "yeet" expr?`.
-    fn parse_expr_yeet(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_yeet(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.token.span;
 
         self.bump(); // `do`
@@ -1851,7 +1853,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse `"become" expr`, with `"become"` token already eaten.
-    fn parse_expr_become(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_become(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.prev_token.span;
         let kind = ExprKind::Become(self.parse_expr()?);
         let span = lo.to(self.prev_token.span);
@@ -1868,7 +1870,7 @@ impl<'a> Parser<'a> {
     /// `break 'lbl: loop {}`); a labeled break with an unlabeled loop as its value
     /// expression only gets a warning for compatibility reasons; and a labeled break
     /// with a labeled loop does not even get a warning because there is no ambiguity.
-    fn parse_expr_break(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_break(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.prev_token.span;
         let mut label = self.eat_label();
         let kind = if self.token == token::Colon
@@ -1930,7 +1932,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse `"continue" label?`.
-    fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
+    fn parse_expr_continue(&mut self, lo: Span) -> PResult<'a, Box<Expr>> {
         let mut label = self.eat_label();
 
         // Recover `continue label` -> `continue 'label`
@@ -1947,7 +1949,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse `"yield" expr?`.
-    fn parse_expr_yield(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_yield(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.prev_token.span;
         let kind = ExprKind::Yield(YieldKind::Prefix(self.parse_expr_opt()?));
         let span = lo.to(self.prev_token.span);
@@ -1957,7 +1959,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse `builtin # ident(args,*)`.
-    fn parse_expr_builtin(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_builtin(&mut self) -> PResult<'a, Box<Expr>> {
         self.parse_builtin(|this, lo, ident| {
             Ok(match ident.name {
                 sym::offset_of => Some(this.parse_expr_offset_of(lo)?),
@@ -2005,7 +2007,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Built-in macro for `offset_of!` expressions.
-    pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
+    pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, Box<Expr>> {
         let container = self.parse_ty()?;
         self.expect(exp!(Comma))?;
 
@@ -2033,7 +2035,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Built-in macro for type ascription expressions.
-    pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, P<Expr>> {
+    pub(crate) fn parse_expr_type_ascribe(&mut self, lo: Span) -> PResult<'a, Box<Expr>> {
         let expr = self.parse_expr()?;
         self.expect(exp!(Comma))?;
         let ty = self.parse_ty()?;
@@ -2045,7 +2047,7 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         kind: UnsafeBinderCastKind,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let expr = self.parse_expr()?;
         let ty = if self.eat(exp!(Comma)) { Some(self.parse_ty()?) } else { None };
         let span = lo.to(self.token.span);
@@ -2155,7 +2157,7 @@ impl<'a> Parser<'a> {
     /// Keep this in sync with `Token::can_begin_literal_maybe_minus` and
     /// `Lit::from_token` (excluding unary negation).
     fn eat_token_lit(&mut self) -> Option<token::Lit> {
-        let check_expr = |expr: P<Expr>| {
+        let check_expr = |expr: Box<Expr>| {
             if let ast::ExprKind::Lit(token_lit) = expr.kind {
                 Some(token_lit)
             } else if let ast::ExprKind::Unary(UnOp::Neg, inner) = &expr.kind
@@ -2243,7 +2245,7 @@ impl<'a> Parser<'a> {
 
     /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`).
     /// Keep this in sync with `Token::can_begin_literal_maybe_minus`.
-    pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
+    pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, Box<Expr>> {
         if let Some(expr) = self.eat_metavar_seq_with_matcher(
             |mv_kind| matches!(mv_kind, MetaVarKind::Expr { .. }),
             |this| {
@@ -2290,7 +2292,7 @@ impl<'a> Parser<'a> {
     /// Emits a suggestion if it looks like the user meant an array but
     /// accidentally used braces, causing the code to be interpreted as a block
     /// expression.
-    fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<P<Expr>> {
+    fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option<Box<Expr>> {
         let mut snapshot = self.create_snapshot_for_diagnostic();
         match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) {
             Ok(arr) => {
@@ -2360,7 +2362,7 @@ impl<'a> Parser<'a> {
         opt_label: Option<Label>,
         lo: Span,
         blk_mode: BlockCheckMode,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         if self.may_recover() && self.is_array_like_block() {
             if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo) {
                 return Ok(arr);
@@ -2383,13 +2385,13 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a block which takes no attributes and has no label
-    fn parse_simple_block(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_simple_block(&mut self) -> PResult<'a, Box<Expr>> {
         let blk = self.parse_block()?;
         Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None)))
     }
 
     /// Parses a closure expression (e.g., `move |args| expr`).
-    fn parse_expr_closure(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_closure(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.token.span;
 
         let before = self.prev_token;
@@ -2494,7 +2496,7 @@ impl<'a> Parser<'a> {
     }
 
     /// If an explicit return type is given, require a block to appear (RFC 968).
-    fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, P<Expr>> {
+    fn parse_closure_block_body(&mut self, ret_span: Span) -> PResult<'a, Box<Expr>> {
         if self.may_recover()
             && self.token.can_begin_expr()
             && self.token.kind != TokenKind::OpenBrace
@@ -2565,7 +2567,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses the `|arg, arg|` header of a closure.
-    fn parse_fn_block_decl(&mut self) -> PResult<'a, (P<FnDecl>, Span)> {
+    fn parse_fn_block_decl(&mut self) -> PResult<'a, (Box<FnDecl>, Span)> {
         let arg_start = self.token.span.lo();
 
         let inputs = if self.eat(exp!(OrOr)) {
@@ -2587,7 +2589,7 @@ impl<'a> Parser<'a> {
         let output =
             self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes, RecoverReturnSign::Yes)?;
 
-        Ok((P(FnDecl { inputs, output }), arg_span))
+        Ok((Box::new(FnDecl { inputs, output }), arg_span))
     }
 
     /// Parses a parameter in a closure header (e.g., `|arg, arg|`).
@@ -2618,7 +2620,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an `if` expression (`if` token already eaten).
-    fn parse_expr_if(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_if(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.prev_token.span;
         // Scoping code checks the top level edition of the `if`; let's match it here.
         // The `CondChecker` also checks the edition of the `let` itself, just to make sure.
@@ -2627,7 +2629,7 @@ impl<'a> Parser<'a> {
         self.parse_if_after_cond(lo, cond)
     }
 
-    fn parse_if_after_cond(&mut self, lo: Span, mut cond: P<Expr>) -> PResult<'a, P<Expr>> {
+    fn parse_if_after_cond(&mut self, lo: Span, mut cond: Box<Expr>) -> PResult<'a, Box<Expr>> {
         let cond_span = cond.span;
         // Tries to interpret `cond` as either a missing expression if it's a block,
         // or as an unfinished expression if it's a binop and the RHS is a block.
@@ -2737,7 +2739,10 @@ impl<'a> Parser<'a> {
     /// i.e. the same span we use to later decide whether the drop behaviour should be that of
     /// edition `..=2021` or that of `2024..`.
     // Public because it is used in rustfmt forks such as https://github.com/tucant/rustfmt/blob/30c83df9e1db10007bdd16dafce8a86b404329b2/src/parse/macros/html.rs#L57 for custom if expressions.
-    pub fn parse_expr_cond(&mut self, let_chains_policy: LetChainsPolicy) -> PResult<'a, P<Expr>> {
+    pub fn parse_expr_cond(
+        &mut self,
+        let_chains_policy: LetChainsPolicy,
+    ) -> PResult<'a, Box<Expr>> {
         let attrs = self.parse_outer_attributes()?;
         let (mut cond, _) =
             self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, attrs)?;
@@ -2748,7 +2753,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a `let $pat = $expr` pseudo-expression.
-    fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, P<Expr>> {
+    fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, Box<Expr>> {
         let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) {
             let err = errors::ExpectedExpressionFoundLet {
                 span: self.token.span,
@@ -2790,7 +2795,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an `else { ... }` expression (`else` token already eaten).
-    fn parse_expr_else(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_else(&mut self) -> PResult<'a, Box<Expr>> {
         let else_span = self.prev_token.span; // `else`
         let attrs = self.parse_outer_attributes()?; // For recovery.
         let expr = if self.eat_keyword(exp!(If)) {
@@ -2888,7 +2893,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn error_on_extra_if(&mut self, cond: &P<Expr>) -> PResult<'a, ()> {
+    fn error_on_extra_if(&mut self, cond: &Box<Expr>) -> PResult<'a, ()> {
         if let ExprKind::Binary(Spanned { span: binop_span, node: binop }, _, right) = &cond.kind
             && let BinOpKind::And = binop
             && let ExprKind::If(cond, ..) = &right.kind
@@ -2901,7 +2906,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_for_head(&mut self) -> PResult<'a, (P<Pat>, P<Expr>)> {
+    fn parse_for_head(&mut self) -> PResult<'a, (Box<Pat>, Box<Expr>)> {
         let begin_paren = if self.token == token::OpenParen {
             // Record whether we are about to parse `for (`.
             // This is used below for recovery in case of `for ( $stuff ) $block`
@@ -2967,7 +2972,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `for await? <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
-    fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
+    fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> {
         let is_await =
             self.token_uninterpolated_span().at_least_rust_2018() && self.eat_keyword(exp!(Await));
 
@@ -3028,6 +3033,8 @@ impl<'a> Parser<'a> {
             let span = self.token.span;
             self.bump();
             (span, errors::MissingInInForLoopSub::InNotOf)
+        } else if self.eat(exp!(Eq)) {
+            (self.prev_token.span, errors::MissingInInForLoopSub::InNotEq)
         } else {
             (self.prev_token.span.between(self.token.span), errors::MissingInInForLoopSub::AddIn)
         };
@@ -3036,7 +3043,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a `while` or `while let` expression (`while` token already eaten).
-    fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
+    fn parse_expr_while(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> {
         let policy = LetChainsPolicy::EditionDependent { current_edition: lo.edition() };
         let cond = self.parse_expr_cond(policy).map_err(|mut err| {
             err.span_label(lo, "while parsing the condition of this `while` expression");
@@ -3064,7 +3071,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `loop { ... }` (`loop` token already eaten).
-    fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
+    fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, Box<Expr>> {
         let loop_span = self.prev_token.span;
         let (attrs, body) = self.parse_inner_attrs_and_block(
             // Only suggest moving erroneous block label to the loop header
@@ -3094,7 +3101,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a `match ... { ... }` expression (`match` token already eaten).
-    fn parse_expr_match(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_expr_match(&mut self) -> PResult<'a, Box<Expr>> {
         let match_span = self.prev_token.span;
         let attrs = self.parse_outer_attributes()?;
         let (scrutinee, _) = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, attrs)?;
@@ -3108,9 +3115,9 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         match_span: Span,
-        scrutinee: P<Expr>,
+        scrutinee: Box<Expr>,
         match_kind: MatchKind,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         if let Err(mut e) = self.expect(exp!(OpenBrace)) {
             if self.token == token::Semi {
                 e.span_suggestion_short(
@@ -3167,7 +3174,7 @@ impl<'a> Parser<'a> {
     /// Attempt to recover from match arm body with statements and no surrounding braces.
     fn parse_arm_body_missing_braces(
         &mut self,
-        first_expr: &P<Expr>,
+        first_expr: &Box<Expr>,
         arrow_span: Span,
     ) -> Option<(Span, ErrorGuaranteed)> {
         if self.token != token::Semi {
@@ -3439,7 +3446,7 @@ impl<'a> Parser<'a> {
         })
     }
 
-    fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<P<Expr>>> {
+    fn parse_match_arm_guard(&mut self) -> PResult<'a, Option<Box<Expr>>> {
         // Used to check the `if_let_guard` feature mostly by scanning
         // `&&` tokens.
         fn has_let_expr(expr: &Expr) -> bool {
@@ -3470,7 +3477,7 @@ impl<'a> Parser<'a> {
         Ok(Some(cond))
     }
 
-    fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (P<Pat>, Option<P<Expr>>)> {
+    fn parse_match_arm_pat_and_guard(&mut self) -> PResult<'a, (Box<Pat>, Option<Box<Expr>>)> {
         if self.token == token::OpenParen {
             let left = self.token.span;
             let pat = self.parse_pat_no_top_guard(
@@ -3510,7 +3517,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_match_guard_condition(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_match_guard_condition(&mut self) -> PResult<'a, Box<Expr>> {
         let attrs = self.parse_outer_attributes()?;
         match self.parse_expr_res(Restrictions::ALLOW_LET | Restrictions::IN_IF_GUARD, attrs) {
             Ok((expr, _)) => Ok(expr),
@@ -3544,7 +3551,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a `try {...}` expression (`try` token already eaten).
-    fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
+    fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, Box<Expr>> {
         let (attrs, body) = self.parse_inner_attrs_and_block(None)?;
         if self.eat_keyword(exp!(Catch)) {
             Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span }))
@@ -3573,7 +3580,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses an `async move? {...}` or `gen move? {...}` expression.
-    fn parse_gen_block(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_gen_block(&mut self) -> PResult<'a, Box<Expr>> {
         let lo = self.token.span;
         let kind = if self.eat_keyword(exp!(Async)) {
             if self.eat_keyword(exp!(Gen)) { GenBlockKind::AsyncGen } else { GenBlockKind::Async }
@@ -3622,9 +3629,9 @@ impl<'a> Parser<'a> {
 
     fn maybe_parse_struct_expr(
         &mut self,
-        qself: &Option<P<ast::QSelf>>,
+        qself: &Option<Box<ast::QSelf>>,
         path: &ast::Path,
-    ) -> Option<PResult<'a, P<Expr>>> {
+    ) -> Option<PResult<'a, Box<Expr>>> {
         let struct_allowed = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL);
         if struct_allowed || self.is_certainly_not_a_block() {
             if let Err(err) = self.expect(exp!(OpenBrace)) {
@@ -3818,10 +3825,10 @@ impl<'a> Parser<'a> {
     /// Precondition: already parsed the '{'.
     pub(super) fn parse_expr_struct(
         &mut self,
-        qself: Option<P<ast::QSelf>>,
+        qself: Option<Box<ast::QSelf>>,
         pth: ast::Path,
         recover: bool,
-    ) -> PResult<'a, P<Expr>> {
+    ) -> PResult<'a, Box<Expr>> {
         let lo = pth.span;
         let (fields, base, recovered_async) =
             self.parse_struct_fields(pth.clone(), recover, exp!(CloseBrace))?;
@@ -3830,7 +3837,7 @@ impl<'a> Parser<'a> {
         let expr = if let Some(guar) = recovered_async {
             ExprKind::Err(guar)
         } else {
-            ExprKind::Struct(P(ast::StructExpr { qself, path: pth, fields, rest: base }))
+            ExprKind::Struct(Box::new(ast::StructExpr { qself, path: pth, fields, rest: base }))
         };
         Ok(self.mk_expr(span, expr))
     }
@@ -3945,14 +3952,14 @@ impl<'a> Parser<'a> {
         self.dcx().emit_err(errors::LeftArrowOperator { span });
     }
 
-    fn mk_assign_op(&self, assign_op: AssignOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
+    fn mk_assign_op(&self, assign_op: AssignOp, lhs: Box<Expr>, rhs: Box<Expr>) -> ExprKind {
         ExprKind::AssignOp(assign_op, lhs, rhs)
     }
 
     fn mk_range(
         &mut self,
-        start: Option<P<Expr>>,
-        end: Option<P<Expr>>,
+        start: Option<Box<Expr>>,
+        end: Option<Box<Expr>>,
         limits: RangeLimits,
     ) -> ExprKind {
         if end.is_none() && limits == RangeLimits::Closed {
@@ -3963,51 +3970,56 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn mk_unary(&self, unop: UnOp, expr: P<Expr>) -> ExprKind {
+    fn mk_unary(&self, unop: UnOp, expr: Box<Expr>) -> ExprKind {
         ExprKind::Unary(unop, expr)
     }
 
-    fn mk_binary(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
+    fn mk_binary(&self, binop: BinOp, lhs: Box<Expr>, rhs: Box<Expr>) -> ExprKind {
         ExprKind::Binary(binop, lhs, rhs)
     }
 
-    fn mk_index(&self, expr: P<Expr>, idx: P<Expr>, brackets_span: Span) -> ExprKind {
+    fn mk_index(&self, expr: Box<Expr>, idx: Box<Expr>, brackets_span: Span) -> ExprKind {
         ExprKind::Index(expr, idx, brackets_span)
     }
 
-    fn mk_call(&self, f: P<Expr>, args: ThinVec<P<Expr>>) -> ExprKind {
+    fn mk_call(&self, f: Box<Expr>, args: ThinVec<Box<Expr>>) -> ExprKind {
         ExprKind::Call(f, args)
     }
 
-    fn mk_await_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> {
+    fn mk_await_expr(&mut self, self_arg: Box<Expr>, lo: Span) -> Box<Expr> {
         let span = lo.to(self.prev_token.span);
         let await_expr = self.mk_expr(span, ExprKind::Await(self_arg, self.prev_token.span));
         self.recover_from_await_method_call();
         await_expr
     }
 
-    fn mk_use_expr(&mut self, self_arg: P<Expr>, lo: Span) -> P<Expr> {
+    fn mk_use_expr(&mut self, self_arg: Box<Expr>, lo: Span) -> Box<Expr> {
         let span = lo.to(self.prev_token.span);
         let use_expr = self.mk_expr(span, ExprKind::Use(self_arg, self.prev_token.span));
         self.recover_from_use();
         use_expr
     }
 
-    pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
-        P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
+    pub(crate) fn mk_expr_with_attrs(
+        &self,
+        span: Span,
+        kind: ExprKind,
+        attrs: AttrVec,
+    ) -> Box<Expr> {
+        Box::new(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
     }
 
-    pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P<Expr> {
+    pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> Box<Expr> {
         self.mk_expr_with_attrs(span, kind, AttrVec::new())
     }
 
-    pub(super) fn mk_expr_err(&self, span: Span, guar: ErrorGuaranteed) -> P<Expr> {
+    pub(super) fn mk_expr_err(&self, span: Span, guar: ErrorGuaranteed) -> Box<Expr> {
         self.mk_expr(span, ExprKind::Err(guar))
     }
 
     /// Create expression span ensuring the span of the parent node
     /// is larger than the span of lhs and rhs, including the attributes.
-    fn mk_expr_sp(&self, lhs: &P<Expr>, lhs_span: Span, op_span: Span, rhs_span: Span) -> Span {
+    fn mk_expr_sp(&self, lhs: &Box<Expr>, lhs_span: Span, op_span: Span, rhs_span: Span) -> Span {
         lhs.attrs
             .iter()
             .find(|a| a.style == AttrStyle::Outer)
@@ -4019,8 +4031,8 @@ impl<'a> Parser<'a> {
     fn collect_tokens_for_expr(
         &mut self,
         attrs: AttrWrapper,
-        f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P<Expr>>,
-    ) -> PResult<'a, P<Expr>> {
+        f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, Box<Expr>>,
+    ) -> PResult<'a, Box<Expr>> {
         self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
             let res = f(this, attrs)?;
             let trailing = Trailing::from(
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 86326341a75..4a8530a2b38 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -308,9 +308,7 @@ impl<'a> Parser<'a> {
 
     /// Parses an experimental fn contract
     /// (`contract_requires(WWW) contract_ensures(ZZZ)`)
-    pub(super) fn parse_contract(
-        &mut self,
-    ) -> PResult<'a, Option<rustc_ast::ptr::P<ast::FnContract>>> {
+    pub(super) fn parse_contract(&mut self) -> PResult<'a, Option<Box<ast::FnContract>>> {
         let requires = if self.eat_keyword_noexpect(exp!(ContractRequires).kw) {
             self.psess.gated_spans.gate(sym::contracts_internals, self.prev_token.span);
             let precond = self.parse_expr()?;
@@ -328,7 +326,7 @@ impl<'a> Parser<'a> {
         if requires.is_none() && ensures.is_none() {
             Ok(None)
         } else {
-            Ok(Some(rustc_ast::ptr::P(ast::FnContract { requires, ensures })))
+            Ok(Some(Box::new(ast::FnContract { requires, ensures })))
         }
     }
 
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index cb7c5649433..14a90e74049 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -3,7 +3,6 @@ use std::mem;
 
 use ast::token::IdentIsRaw;
 use rustc_ast::ast::*;
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast::util::case::Case;
@@ -56,12 +55,12 @@ impl<'a> Parser<'a> {
     pub fn parse_mod(
         &mut self,
         term: ExpTokenPair<'_>,
-    ) -> PResult<'a, (AttrVec, ThinVec<P<Item>>, ModSpans)> {
+    ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
         let lo = self.token.span;
         let attrs = self.parse_inner_attributes()?;
 
         let post_attr_lo = self.token.span;
-        let mut items: ThinVec<P<_>> = ThinVec::new();
+        let mut items: ThinVec<Box<_>> = ThinVec::new();
 
         // There shouldn't be any stray semicolons before or after items.
         // `parse_item` consumes the appropriate semicolons so any leftover is an error.
@@ -116,9 +115,9 @@ impl<'a> Parser<'a> {
 }
 
 impl<'a> Parser<'a> {
-    pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<P<Item>>> {
+    pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Box<Item>>> {
         let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
-        self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(P))
+        self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(Box::new))
     }
 
     fn parse_item_(
@@ -327,7 +326,7 @@ impl<'a> Parser<'a> {
                 self.recover_missing_kw_before_item()?;
             }
             // MACRO INVOCATION ITEM
-            ItemKind::MacCall(P(self.parse_item_macro(vis)?))
+            ItemKind::MacCall(Box::new(self.parse_item_macro(vis)?))
         } else {
             return Ok(None);
         };
@@ -951,7 +950,7 @@ impl<'a> Parser<'a> {
     pub fn parse_impl_item(
         &mut self,
         force_collect: ForceCollect,
-    ) -> PResult<'a, Option<Option<P<AssocItem>>>> {
+    ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
         let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
         self.parse_assoc_item(fn_parse_mode, force_collect)
     }
@@ -959,7 +958,7 @@ impl<'a> Parser<'a> {
     pub fn parse_trait_item(
         &mut self,
         force_collect: ForceCollect,
-    ) -> PResult<'a, Option<Option<P<AssocItem>>>> {
+    ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
         let fn_parse_mode =
             FnParseMode { req_name: |edition| edition >= Edition::Edition2018, req_body: false };
         self.parse_assoc_item(fn_parse_mode, force_collect)
@@ -970,7 +969,7 @@ impl<'a> Parser<'a> {
         &mut self,
         fn_parse_mode: FnParseMode,
         force_collect: ForceCollect,
-    ) -> PResult<'a, Option<Option<P<AssocItem>>>> {
+    ) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
         Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
             |Item { attrs, id, span, vis, kind, tokens }| {
                 let kind = match AssocItemKind::try_from(kind) {
@@ -997,7 +996,7 @@ impl<'a> Parser<'a> {
                         _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"),
                     },
                 };
-                Some(P(Item { attrs, id, span, vis, kind, tokens }))
+                Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
             },
         ))
     }
@@ -1237,7 +1236,7 @@ impl<'a> Parser<'a> {
     pub fn parse_foreign_item(
         &mut self,
         force_collect: ForceCollect,
-    ) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
+    ) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
         let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false };
         Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
             |Item { attrs, id, span, vis, kind, tokens }| {
@@ -1263,7 +1262,7 @@ impl<'a> Parser<'a> {
                         _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"),
                     },
                 };
-                Some(P(Item { attrs, id, span, vis, kind, tokens }))
+                Some(Box::new(Item { attrs, id, span, vis, kind, tokens }))
             },
         ))
     }
@@ -1424,7 +1423,9 @@ impl<'a> Parser<'a> {
     /// ```ebnf
     /// Const = "const" ($ident | "_") Generics ":" $ty (= $expr)? WhereClause ";" ;
     /// ```
-    fn parse_const_item(&mut self) -> PResult<'a, (Ident, Generics, P<Ty>, Option<P<ast::Expr>>)> {
+    fn parse_const_item(
+        &mut self,
+    ) -> PResult<'a, (Ident, Generics, Box<Ty>, Option<Box<ast::Expr>>)> {
         let ident = self.parse_ident_or_underscore()?;
 
         let mut generics = self.parse_generics()?;
@@ -1517,7 +1518,7 @@ impl<'a> Parser<'a> {
         &mut self,
         colon_present: bool,
         m: Option<Mutability>,
-    ) -> P<Ty> {
+    ) -> Box<Ty> {
         // Construct the error and stash it away with the hope
         // that typeck will later enrich the error with a type.
         let kind = match m {
@@ -1537,7 +1538,7 @@ impl<'a> Parser<'a> {
 
         // The user intended that the type be inferred,
         // so treat this as if the user wrote e.g. `const A: _ = expr;`.
-        P(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None })
+        Box::new(Ty { kind: TyKind::Infer, span, id: ast::DUMMY_NODE_ID, tokens: None })
     }
 
     /// Parses an enum declaration.
@@ -2207,7 +2208,7 @@ impl<'a> Parser<'a> {
             let arrow = TokenTree::token_alone(token::FatArrow, pspan.between(bspan)); // `=>`
             let tokens = TokenStream::new(vec![params, arrow, body]);
             let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi());
-            P(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
+            Box::new(DelimArgs { dspan, delim: Delimiter::Brace, tokens })
         } else {
             self.unexpected_any()?
         };
@@ -2409,7 +2410,7 @@ impl<'a> Parser<'a> {
         sig_lo: Span,
         vis: &Visibility,
         case: Case,
-    ) -> PResult<'a, (Ident, FnSig, Generics, Option<P<FnContract>>, Option<P<Block>>)> {
+    ) -> PResult<'a, (Ident, FnSig, Generics, Option<Box<FnContract>>, Option<Box<Block>>)> {
         let fn_span = self.token.span;
         let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn`
         let ident = self.parse_ident()?; // `foo`
@@ -2539,7 +2540,7 @@ impl<'a> Parser<'a> {
         sig_hi: &mut Span,
         req_body: bool,
         fn_params_end: Option<Span>,
-    ) -> PResult<'a, Option<P<Block>>> {
+    ) -> PResult<'a, Option<Box<Block>>> {
         let has_semi = if req_body {
             self.token == TokenKind::Semi
         } else {
@@ -2939,8 +2940,8 @@ impl<'a> Parser<'a> {
         req_name: ReqName,
         ret_allow_plus: AllowPlus,
         recover_return_sign: RecoverReturnSign,
-    ) -> PResult<'a, P<FnDecl>> {
-        Ok(P(FnDecl {
+    ) -> PResult<'a, Box<FnDecl>> {
+        Ok(Box::new(FnDecl {
             inputs: self.parse_fn_params(req_name)?,
             output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
         }))
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 90491e53249..0a8a0203013 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -25,7 +25,6 @@ pub(crate) use expr::ForbiddenLetReason;
 pub(crate) use item::FnParseMode;
 pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
 use path::PathStyle;
-use rustc_ast::ptr::P;
 use rustc_ast::token::{
     self, IdentIsRaw, InvisibleOrigin, MetaVarKind, NtExprKind, NtPatKind, Token, TokenKind,
 };
@@ -1286,7 +1285,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses inline const expressions.
-    fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P<Expr>> {
+    fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, Box<Expr>> {
         self.expect_keyword(exp!(Const))?;
         let (attrs, blk) = self.parse_inner_attrs_and_block(None)?;
         let anon_const = AnonConst {
@@ -1343,9 +1342,9 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_delim_args(&mut self) -> PResult<'a, P<DelimArgs>> {
+    fn parse_delim_args(&mut self) -> PResult<'a, Box<DelimArgs>> {
         if let Some(args) = self.parse_delim_args_inner() {
-            Ok(P(args))
+            Ok(Box::new(args))
         } else {
             self.unexpected_any()
         }
@@ -1470,7 +1469,7 @@ impl<'a> Parser<'a> {
                 let path = self.parse_path(PathStyle::Mod)?; // `path`
                 self.expect(exp!(CloseParen))?; // `)`
                 let vis = VisibilityKind::Restricted {
-                    path: P(path),
+                    path: Box::new(path),
                     id: ast::DUMMY_NODE_ID,
                     shorthand: false,
                 };
@@ -1487,7 +1486,7 @@ impl<'a> Parser<'a> {
                 let path = self.parse_path(PathStyle::Mod)?; // `crate`/`super`/`self`
                 self.expect(exp!(CloseParen))?; // `)`
                 let vis = VisibilityKind::Restricted {
-                    path: P(path),
+                    path: Box::new(path),
                     id: ast::DUMMY_NODE_ID,
                     shorthand: true,
                 };
@@ -1652,14 +1651,14 @@ pub enum ParseNtResult {
     Tt(TokenTree),
     Ident(Ident, IdentIsRaw),
     Lifetime(Ident, IdentIsRaw),
-    Item(P<ast::Item>),
-    Block(P<ast::Block>),
-    Stmt(P<ast::Stmt>),
-    Pat(P<ast::Pat>, NtPatKind),
-    Expr(P<ast::Expr>, NtExprKind),
-    Literal(P<ast::Expr>),
-    Ty(P<ast::Ty>),
-    Meta(P<ast::AttrItem>),
-    Path(P<ast::Path>),
-    Vis(P<ast::Visibility>),
+    Item(Box<ast::Item>),
+    Block(Box<ast::Block>),
+    Stmt(Box<ast::Stmt>),
+    Pat(Box<ast::Pat>, NtPatKind),
+    Expr(Box<ast::Expr>, NtExprKind),
+    Literal(Box<ast::Expr>),
+    Ty(Box<ast::Ty>),
+    Meta(Box<ast::AttrItem>),
+    Path(Box<ast::Path>),
+    Vis(Box<ast::Visibility>),
 }
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 7c83e96c160..42eb07858c2 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::token::NtExprKind::*;
 use rustc_ast::token::NtPatKind::*;
 use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, NonterminalKind, Token};
@@ -129,7 +128,7 @@ impl<'a> Parser<'a> {
                 Ok(ParseNtResult::Block(self.collect_tokens_no_attrs(|this| this.parse_block())?))
             }
             NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
-                Some(stmt) => Ok(ParseNtResult::Stmt(P(stmt))),
+                Some(stmt) => Ok(ParseNtResult::Stmt(Box::new(stmt))),
                 None => {
                     Err(self.dcx().create_err(UnexpectedNonterminal::Statement(self.token.span)))
                 }
@@ -170,16 +169,15 @@ impl<'a> Parser<'a> {
                     }))
                 }
             }
-            NonterminalKind::Path => Ok(ParseNtResult::Path(P(
-                self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?
+            NonterminalKind::Path => Ok(ParseNtResult::Path(Box::new(
+                self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?,
             ))),
             NonterminalKind::Meta => {
-                Ok(ParseNtResult::Meta(P(self.parse_attr_item(ForceCollect::Yes)?)))
-            }
-            NonterminalKind::Vis => {
-                Ok(ParseNtResult::Vis(P(self
-                    .collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?)))
+                Ok(ParseNtResult::Meta(Box::new(self.parse_attr_item(ForceCollect::Yes)?)))
             }
+            NonterminalKind::Vis => Ok(ParseNtResult::Vis(Box::new(
+                self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?,
+            ))),
             NonterminalKind::Lifetime => {
                 // We want to keep `'keyword` parsing, just like `keyword` is still
                 // an ident for nonterminal purposes.
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 64653ee2a04..a415849b915 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,7 +1,6 @@
 use std::ops::Bound;
 
 use rustc_ast::mut_visit::{self, MutVisitor};
-use rustc_ast::ptr::P;
 use rustc_ast::token::NtPatKind::*;
 use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token};
 use rustc_ast::util::parser::ExprPrecedence;
@@ -108,7 +107,7 @@ impl<'a> Parser<'a> {
         rc: RecoverComma,
         ra: RecoverColon,
         rt: CommaRecoveryMode,
-    ) -> PResult<'a, P<Pat>> {
+    ) -> PResult<'a, Box<Pat>> {
         let pat = self.parse_pat_no_top_guard(expected, rc, ra, rt)?;
 
         if self.eat_keyword(exp!(If)) {
@@ -131,7 +130,7 @@ impl<'a> Parser<'a> {
         &mut self,
         expected: Option<Expected>,
         syntax_loc: Option<PatternLocation>,
-    ) -> PResult<'a, P<Pat>> {
+    ) -> PResult<'a, Box<Pat>> {
         self.parse_pat_with_range_pat(true, expected, syntax_loc)
     }
 
@@ -150,7 +149,7 @@ impl<'a> Parser<'a> {
         rc: RecoverComma,
         ra: RecoverColon,
         rt: CommaRecoveryMode,
-    ) -> PResult<'a, P<Pat>> {
+    ) -> PResult<'a, Box<Pat>> {
         self.parse_pat_no_top_guard_inner(expected, rc, ra, rt, None).map(|(pat, _)| pat)
     }
 
@@ -163,7 +162,7 @@ impl<'a> Parser<'a> {
         ra: RecoverColon,
         rt: CommaRecoveryMode,
         syntax_loc: Option<PatternLocation>,
-    ) -> PResult<'a, (P<Pat>, bool)> {
+    ) -> PResult<'a, (Box<Pat>, bool)> {
         // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
         // suggestions (which bothers rustfix).
         //
@@ -253,7 +252,7 @@ impl<'a> Parser<'a> {
         expected: Option<Expected>,
         rc: RecoverComma,
         syntax_loc: PatternLocation,
-    ) -> PResult<'a, (P<Pat>, bool)> {
+    ) -> PResult<'a, (Box<Pat>, bool)> {
         // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
         // or-patterns so that we can detect when a user tries to use it. This allows us to print a
         // better error message.
@@ -301,7 +300,7 @@ impl<'a> Parser<'a> {
     ///
     /// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false`
     /// otherwise).
-    pub(super) fn parse_fn_param_pat_colon(&mut self) -> PResult<'a, (P<Pat>, bool)> {
+    pub(super) fn parse_fn_param_pat_colon(&mut self) -> PResult<'a, (Box<Pat>, bool)> {
         // In order to get good UX, we first recover in the case of a leading vert for an illegal
         // top-level or-pat. Normally, this means recovering both `|` and `||`, but in this case,
         // a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that
@@ -685,7 +684,7 @@ impl<'a> Parser<'a> {
         PatVisitor { parser: self, stmt, arm: None, field: None }.visit_stmt(stmt);
     }
 
-    fn eat_metavar_pat(&mut self) -> Option<P<Pat>> {
+    fn eat_metavar_pat(&mut self) -> Option<Box<Pat>> {
         // Must try both kinds of pattern nonterminals.
         if let Some(pat) = self.eat_metavar_seq_with_matcher(
             |mv_kind| matches!(mv_kind, MetaVarKind::Pat(PatParam { .. })),
@@ -713,7 +712,7 @@ impl<'a> Parser<'a> {
         allow_range_pat: bool,
         expected: Option<Expected>,
         syntax_loc: Option<PatternLocation>,
-    ) -> PResult<'a, P<Pat>> {
+    ) -> PResult<'a, Box<Pat>> {
         maybe_recover_from_interpolated_ty_qpath!(self, true);
 
         if let Some(pat) = self.eat_metavar_pat() {
@@ -909,7 +908,7 @@ impl<'a> Parser<'a> {
     /// e.g. [F#][and] where they are called AND-patterns.
     ///
     /// [and]: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching
-    fn recover_intersection_pat(&mut self, lhs: P<Pat>) -> PResult<'a, P<Pat>> {
+    fn recover_intersection_pat(&mut self, lhs: Box<Pat>) -> PResult<'a, Box<Pat>> {
         if self.token != token::At {
             // Next token is not `@` so it's not going to be an intersection pattern.
             return Ok(lhs);
@@ -1091,7 +1090,7 @@ impl<'a> Parser<'a> {
 
     /// Turn all by-value immutable bindings in a pattern into mutable bindings.
     /// Returns `true` if any change was made.
-    fn make_all_value_bindings_mutable(pat: &mut P<Pat>) -> bool {
+    fn make_all_value_bindings_mutable(pat: &mut Box<Pat>) -> bool {
         struct AddMut(bool);
         impl MutVisitor for AddMut {
             fn visit_pat(&mut self, pat: &mut Pat) {
@@ -1139,7 +1138,7 @@ impl<'a> Parser<'a> {
     fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> {
         self.bump();
         let args = self.parse_delim_args()?;
-        let mac = P(MacCall { path, args });
+        let mac = Box::new(MacCall { path, args });
         Ok(PatKind::MacCall(mac))
     }
 
@@ -1147,7 +1146,7 @@ impl<'a> Parser<'a> {
         &mut self,
         err: Diag<'a>,
         expected: Option<Expected>,
-    ) -> PResult<'a, P<Pat>> {
+    ) -> PResult<'a, Box<Pat>> {
         err.cancel();
 
         let expected = Expected::to_string_or_fallback(expected);
@@ -1182,7 +1181,7 @@ impl<'a> Parser<'a> {
     /// `$begin $form` has already been parsed.
     fn parse_pat_range_begin_with(
         &mut self,
-        begin: P<Expr>,
+        begin: Box<Expr>,
         re: Spanned<RangeEnd>,
     ) -> PResult<'a, PatKind> {
         let end = if self.is_pat_range_end_start(0) {
@@ -1262,7 +1261,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a range pattern end bound
-    fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
+    fn parse_pat_range_end(&mut self) -> PResult<'a, Box<Expr>> {
         // recover leading `(`
         let open_paren = (self.may_recover() && self.eat_noexpect(&token::OpenParen))
             .then_some(self.prev_token.span);
@@ -1380,7 +1379,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
-    fn parse_pat_struct(&mut self, qself: Option<P<QSelf>>, path: Path) -> PResult<'a, PatKind> {
+    fn parse_pat_struct(&mut self, qself: Option<Box<QSelf>>, path: Path) -> PResult<'a, PatKind> {
         if qself.is_some() {
             // Feature gate the use of qualified paths in patterns
             self.psess.gated_spans.gate(sym::more_qualified_paths, path.span);
@@ -1400,7 +1399,7 @@ impl<'a> Parser<'a> {
     /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
     fn parse_pat_tuple_struct(
         &mut self,
-        qself: Option<P<QSelf>>,
+        qself: Option<Box<QSelf>>,
         path: Path,
     ) -> PResult<'a, PatKind> {
         let (fields, _) = self.parse_paren_comma_seq(|p| {
@@ -1749,11 +1748,11 @@ impl<'a> Parser<'a> {
         })
     }
 
-    pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> P<Pat> {
+    pub(super) fn mk_pat_ident(&self, span: Span, ann: BindingMode, ident: Ident) -> Box<Pat> {
         self.mk_pat(span, PatKind::Ident(ann, ident, None))
     }
 
-    pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
-        P(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
+    pub(super) fn mk_pat(&self, span: Span, kind: PatKind) -> Box<Pat> {
+        Box::new(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
     }
 }
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 8e65ab99c5e..a6ec3ea4245 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -1,7 +1,6 @@
 use std::mem;
 
 use ast::token::IdentIsRaw;
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, MetaVarKind, Token, TokenKind};
 use rustc_ast::{
     self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemConstraint,
@@ -75,7 +74,7 @@ impl<'a> Parser<'a> {
     /// `<T as U>::a`
     /// `<T as U>::F::a<S>` (without disambiguator)
     /// `<T as U>::F::a::<S>` (with disambiguator)
-    pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (P<QSelf>, Path)> {
+    pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (Box<QSelf>, Path)> {
         let lo = self.prev_token.span;
         let ty = self.parse_ty()?;
 
@@ -105,7 +104,7 @@ impl<'a> Parser<'a> {
             self.expect(exp!(PathSep))?;
         }
 
-        let qself = P(QSelf { ty, path_span, position: path.segments.len() });
+        let qself = Box::new(QSelf { ty, path_span, position: path.segments.len() });
         if !is_import_coupler {
             self.parse_path_segments(&mut path.segments, style, None)?;
         }
@@ -380,7 +379,7 @@ impl<'a> Parser<'a> {
                             .emit_err(errors::BadReturnTypeNotationOutput { span, suggestion });
                     }
 
-                    P(ast::GenericArgs::ParenthesizedElided(span))
+                    Box::new(ast::GenericArgs::ParenthesizedElided(span))
                 } else {
                     // `(T, U) -> R`
 
@@ -842,7 +841,7 @@ impl<'a> Parser<'a> {
     /// - A literal.
     /// - A numeric literal prefixed by `-`.
     /// - A single-segment path.
-    pub(super) fn expr_is_valid_const_arg(&self, expr: &P<rustc_ast::Expr>) -> bool {
+    pub(super) fn expr_is_valid_const_arg(&self, expr: &Box<rustc_ast::Expr>) -> bool {
         match &expr.kind {
             ast::ExprKind::Block(_, _)
             | ast::ExprKind::Lit(_)
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 2fa6520f2a4..7aacb674253 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -4,7 +4,6 @@ use std::ops::Bound;
 
 use ast::Label;
 use rustc_ast as ast;
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind};
 use rustc_ast::util::classify::{self, TrailingBrace};
 use rustc_ast::{
@@ -157,7 +156,7 @@ impl<'a> Parser<'a> {
             FnParseMode { req_name: |_| true, req_body: true },
             force_collect,
         )? {
-            self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))
+            self.mk_stmt(lo.to(item.span), StmtKind::Item(Box::new(item)))
         } else if self.eat(exp!(Semi)) {
             // Do not attempt to parse an expression if we're done here.
             self.error_outer_attrs(attrs);
@@ -246,7 +245,7 @@ impl<'a> Parser<'a> {
             _ => MacStmtStyle::NoBraces,
         };
 
-        let mac = P(MacCall { path, args });
+        let mac = Box::new(MacCall { path, args });
 
         let kind = if (style == MacStmtStyle::Braces
             && !matches!(self.token.kind, token::Dot | token::Question))
@@ -256,7 +255,7 @@ impl<'a> Parser<'a> {
                     | token::Eof
                     | token::CloseInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Stmt))
             ) {
-            StmtKind::MacCall(P(MacCallStmt { mac, style, attrs, tokens: None }))
+            StmtKind::MacCall(Box::new(MacCallStmt { mac, style, attrs, tokens: None }))
         } else {
             // Since none of the above applied, this is an expression statement macro.
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
@@ -307,7 +306,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a local variable declaration.
-    fn parse_local(&mut self, super_: Option<Span>, attrs: AttrVec) -> PResult<'a, P<Local>> {
+    fn parse_local(&mut self, super_: Option<Span>, attrs: AttrVec) -> PResult<'a, Box<Local>> {
         let lo = super_.unwrap_or(self.prev_token.span);
 
         if self.token.is_keyword(kw::Const) && self.look_ahead(1, |t| t.is_ident()) {
@@ -409,7 +408,7 @@ impl<'a> Parser<'a> {
             }
         };
         let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span };
-        Ok(P(ast::Local {
+        Ok(Box::new(ast::Local {
             super_,
             ty,
             pat,
@@ -463,7 +462,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses the RHS of a local variable declaration (e.g., `= 14;`).
-    fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<P<Expr>>> {
+    fn parse_initializer(&mut self, eq_optional: bool) -> PResult<'a, Option<Box<Expr>>> {
         let eq_consumed = match self.token.kind {
             token::PlusEq
             | token::MinusEq
@@ -494,7 +493,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a block. No inner attributes are allowed.
-    pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
+    pub fn parse_block(&mut self) -> PResult<'a, Box<Block>> {
         let (attrs, block) = self.parse_inner_attrs_and_block(None)?;
         if let [.., last] = &*attrs {
             let suggest_to_outer = match &last.kind {
@@ -679,7 +678,7 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_inner_attrs_and_block(
         &mut self,
         loop_header: Option<Span>,
-    ) -> PResult<'a, (AttrVec, P<Block>)> {
+    ) -> PResult<'a, (AttrVec, Box<Block>)> {
         self.parse_block_common(self.token.span, BlockCheckMode::Default, loop_header)
     }
 
@@ -692,7 +691,7 @@ impl<'a> Parser<'a> {
         lo: Span,
         blk_mode: BlockCheckMode,
         loop_header: Option<Span>,
-    ) -> PResult<'a, (AttrVec, P<Block>)> {
+    ) -> PResult<'a, (AttrVec, Box<Block>)> {
         if let Some(block) = self.eat_metavar_seq(MetaVarKind::Block, |this| this.parse_block()) {
             return Ok((AttrVec::new(), block));
         }
@@ -718,7 +717,7 @@ impl<'a> Parser<'a> {
         lo: Span,
         s: BlockCheckMode,
         recover: AttemptLocalParseRecovery,
-    ) -> PResult<'a, P<Block>> {
+    ) -> PResult<'a, Box<Block>> {
         let mut stmts = ThinVec::new();
         let mut snapshot = None;
         while !self.eat(exp!(CloseBrace)) {
@@ -1050,8 +1049,8 @@ impl<'a> Parser<'a> {
         stmts: ThinVec<Stmt>,
         rules: BlockCheckMode,
         span: Span,
-    ) -> P<Block> {
-        P(Block { stmts, id: DUMMY_NODE_ID, rules, span, tokens: None })
+    ) -> Box<Block> {
+        Box::new(Block { stmts, id: DUMMY_NODE_ID, rules, span, tokens: None })
     }
 
     pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
@@ -1062,7 +1061,7 @@ impl<'a> Parser<'a> {
         self.mk_stmt(span, StmtKind::Expr(self.mk_expr_err(span, guar)))
     }
 
-    pub(super) fn mk_block_err(&self, span: Span, guar: ErrorGuaranteed) -> P<Block> {
+    pub(super) fn mk_block_err(&self, span: Span, guar: ErrorGuaranteed) -> Box<Block> {
         self.mk_block(thin_vec![self.mk_stmt_err(span, guar)], BlockCheckMode::Default, span)
     }
 }
diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs
index 43a1d779a75..a6e7266e71b 100644
--- a/compiler/rustc_parse/src/parser/tests.rs
+++ b/compiler/rustc_parse/src/parser/tests.rs
@@ -8,7 +8,6 @@ use std::sync::{Arc, Mutex};
 use std::{io, str};
 
 use ast::token::IdentIsRaw;
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token};
 use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_ast::{self as ast, PatKind, visit};
@@ -2240,7 +2239,7 @@ fn parse_item_from_source_str(
     name: FileName,
     source: String,
     psess: &ParseSess,
-) -> PResult<'_, Option<P<ast::Item>>> {
+) -> PResult<'_, Option<Box<ast::Item>>> {
     unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source))
         .parse_item(ForceCollect::No)
 }
@@ -2251,12 +2250,12 @@ fn sp(a: u32, b: u32) -> Span {
 }
 
 /// Parses a string, return an expression.
-fn string_to_expr(source_str: String) -> P<ast::Expr> {
+fn string_to_expr(source_str: String) -> Box<ast::Expr> {
     with_error_checking_parse(source_str, &psess(), |p| p.parse_expr())
 }
 
 /// Parses a string, returns an item.
-fn string_to_item(source_str: String) -> Option<P<ast::Item>> {
+fn string_to_item(source_str: String) -> Option<Box<ast::Item>> {
     with_error_checking_parse(source_str, &psess(), |p| p.parse_item(ForceCollect::No))
 }
 
@@ -2520,7 +2519,7 @@ fn ttdelim_span() {
         name: FileName,
         source: String,
         psess: &ParseSess,
-    ) -> PResult<'_, P<ast::Expr>> {
+    ) -> PResult<'_, Box<ast::Expr>> {
         unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)).parse_expr()
     }
 
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 59048e42e6f..0d479731e73 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, IdentIsRaw, MetaVarKind, Token, TokenKind};
 use rustc_ast::util::case::Case;
 use rustc_ast::{
@@ -105,7 +104,7 @@ fn can_begin_dyn_bound_in_edition_2015(t: &Token) -> bool {
 
 impl<'a> Parser<'a> {
     /// Parses a type.
-    pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
+    pub fn parse_ty(&mut self) -> PResult<'a, Box<Ty>> {
         // Make sure deeply nested types don't overflow the stack.
         ensure_sufficient_stack(|| {
             self.parse_ty_common(
@@ -122,7 +121,7 @@ impl<'a> Parser<'a> {
     pub(super) fn parse_ty_with_generics_recovery(
         &mut self,
         ty_params: &Generics,
-    ) -> PResult<'a, P<Ty>> {
+    ) -> PResult<'a, Box<Ty>> {
         self.parse_ty_common(
             AllowPlus::Yes,
             AllowCVariadic::No,
@@ -136,7 +135,7 @@ impl<'a> Parser<'a> {
     /// Parse a type suitable for a function or function pointer parameter.
     /// The difference from `parse_ty` is that this version allows `...`
     /// (`CVarArgs`) at the top level of the type.
-    pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
+    pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, Box<Ty>> {
         self.parse_ty_common(
             AllowPlus::Yes,
             AllowCVariadic::Yes,
@@ -153,7 +152,7 @@ impl<'a> Parser<'a> {
     ///     `+` is prohibited to maintain operator priority (P(+) < P(&)).
     /// Example 2: `value1 as TYPE + value2`
     ///     `+` is prohibited to avoid interactions with expression grammar.
-    pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
+    pub(super) fn parse_ty_no_plus(&mut self) -> PResult<'a, Box<Ty>> {
         self.parse_ty_common(
             AllowPlus::No,
             AllowCVariadic::No,
@@ -166,7 +165,7 @@ impl<'a> Parser<'a> {
 
     /// Parses a type following an `as` cast. Similar to `parse_ty_no_plus`, but signaling origin
     /// for better diagnostics involving `?`.
-    pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, P<Ty>> {
+    pub(super) fn parse_as_cast_ty(&mut self) -> PResult<'a, Box<Ty>> {
         self.parse_ty_common(
             AllowPlus::No,
             AllowCVariadic::No,
@@ -177,7 +176,7 @@ impl<'a> Parser<'a> {
         )
     }
 
-    pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
+    pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, Box<Ty>> {
         self.parse_ty_common(
             AllowPlus::Yes,
             AllowCVariadic::No,
@@ -190,7 +189,7 @@ impl<'a> Parser<'a> {
 
     /// Parse a type without recovering `:` as `->` to avoid breaking code such
     /// as `where fn() : for<'a>`.
-    pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, P<Ty>> {
+    pub(super) fn parse_ty_for_where_clause(&mut self) -> PResult<'a, Box<Ty>> {
         self.parse_ty_common(
             AllowPlus::Yes,
             AllowCVariadic::No,
@@ -250,7 +249,7 @@ impl<'a> Parser<'a> {
         recover_return_sign: RecoverReturnSign,
         ty_generics: Option<&Generics>,
         recover_question_mark: RecoverQuestionMark,
-    ) -> PResult<'a, P<Ty>> {
+    ) -> PResult<'a, Box<Ty>> {
         let allow_qpath_recovery = recover_qpath == RecoverQPath::Yes;
         maybe_recover_from_interpolated_ty_qpath!(self, allow_qpath_recovery);
         if self.token == token::Pound && self.look_ahead(1, |t| *t == token::OpenBracket) {
@@ -425,7 +424,7 @@ impl<'a> Parser<'a> {
         let span = lo.to(self.prev_token.span);
         self.psess.gated_spans.gate(sym::unsafe_binders, span);
 
-        Ok(TyKind::UnsafeBinder(P(UnsafeBinderTy { generic_params, inner_ty })))
+        Ok(TyKind::UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, inner_ty })))
     }
 
     /// Parses either:
@@ -610,7 +609,7 @@ impl<'a> Parser<'a> {
     /// - `[u8, 5]` → suggests using `;`, return a Array type
     /// - `[u8 5]` → suggests using `;`, return a Array type
     /// Consider to add more cases in the future.
-    fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: P<Ty>) -> PResult<'a, TyKind> {
+    fn maybe_recover_array_ty_without_semi(&mut self, elt_ty: Box<Ty>) -> PResult<'a, TyKind> {
         let span = self.token.span;
         let token_descr = super::token_descr(&self.token);
         let mut err =
@@ -773,7 +772,13 @@ impl<'a> Parser<'a> {
         let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
 
         let decl_span = span_start.to(self.prev_token.span);
-        Ok(TyKind::FnPtr(P(FnPtrTy { ext, safety, generic_params: params, decl, decl_span })))
+        Ok(TyKind::FnPtr(Box::new(FnPtrTy {
+            ext,
+            safety,
+            generic_params: params,
+            decl,
+            decl_span,
+        })))
     }
 
     /// Recover from function pointer types with a generic parameter list (e.g. `fn<'a>(&'a str)`).
@@ -915,7 +920,7 @@ impl<'a> Parser<'a> {
         let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
         if self.eat(exp!(Bang)) {
             // Macro invocation in type position
-            Ok(TyKind::MacCall(P(MacCall { path, args: self.parse_delim_args()? })))
+            Ok(TyKind::MacCall(Box::new(MacCall { path, args: self.parse_delim_args()? })))
         } else if allow_plus == AllowPlus::Yes && self.check_plus() {
             // `Trait1 + Trait2 + 'a`
             self.parse_remaining_bounds_path(ThinVec::new(), path, lo, true, ast::Parens::No)
@@ -1015,7 +1020,7 @@ impl<'a> Parser<'a> {
         let bound = GenericBound::Outlives(lt);
         if let ast::Parens::Yes = parens {
             // FIXME(Centril): Consider not erroring here and accepting `('lt)` instead,
-            // possibly introducing `GenericBound::Paren(P<GenericBound>)`?
+            // possibly introducing `GenericBound::Paren(Box<GenericBound>)`?
             self.recover_paren_lifetime(lo)?;
         }
         Ok(bound)
@@ -1317,12 +1322,14 @@ impl<'a> Parser<'a> {
                     segments: thin_vec![ast::PathSegment {
                         ident: Ident::new(sym::Fn, fn_token_span),
                         id: DUMMY_NODE_ID,
-                        args: Some(P(ast::GenericArgs::Parenthesized(ast::ParenthesizedArgs {
-                            span: args_lo.to(self.prev_token.span),
-                            inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
-                            inputs_span: args_lo.until(decl.output.span()),
-                            output: decl.output.clone(),
-                        }))),
+                        args: Some(Box::new(ast::GenericArgs::Parenthesized(
+                            ast::ParenthesizedArgs {
+                                span: args_lo.to(self.prev_token.span),
+                                inputs: decl.inputs.iter().map(|a| a.ty.clone()).collect(),
+                                inputs_span: args_lo.until(decl.output.span()),
+                                output: decl.output.clone(),
+                            }
+                        ))),
                     }],
                     tokens: None,
                 })
@@ -1464,7 +1471,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> P<Ty> {
-        P(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
+    pub(super) fn mk_ty(&self, span: Span, kind: TyKind) -> Box<Ty> {
+        Box::new(Ty { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
     }
 }
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 4a1f01cc5c8..6a28fe2617e 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -29,7 +29,7 @@ passes_allow_incoherent_impl =
     `rustc_allow_incoherent_impl` attribute should be applied to impl items
     .label = the only currently supported targets are inherent methods
 
-passes_macro_only_attribute =
+passes_allow_internal_unstable =
     attribute should be applied to a macro
     .label = not a macro
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index d768aa6a8dd..10c532b436a 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -207,9 +207,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => {
                     self.check_const_continue(hir_id, *attr_span, target)
                 }
-                Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span)) => {
-                    self.check_allow_internal_unsafe(hir_id, *attr_span, span, target, attrs)
-                }
                 Attribute::Parsed(AttributeKind::AllowInternalUnstable(_, first_span)) => {
                     self.check_allow_internal_unstable(hir_id, *first_span, span, target, attrs)
                 }
@@ -416,6 +413,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                             // internal
                             | sym::prelude_import
                             | sym::panic_handler
+                            | sym::allow_internal_unsafe
                             | sym::lang
                             | sym::needs_allocator
                             | sym::default_lib_allocator
@@ -2214,49 +2212,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 
     /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros.
     /// (Allows proc_macro functions)
-    fn check_allow_internal_unstable(
-        &self,
-        hir_id: HirId,
-        attr_span: Span,
-        span: Span,
-        target: Target,
-        attrs: &[Attribute],
-    ) {
-        self.check_macro_only_attr(
-            hir_id,
-            attr_span,
-            span,
-            target,
-            attrs,
-            "allow_internal_unstable",
-        )
-    }
-
-    /// Outputs an error for `#[allow_internal_unsafe]` which can only be applied to macros.
-    /// (Allows proc_macro functions)
-    fn check_allow_internal_unsafe(
-        &self,
-        hir_id: HirId,
-        attr_span: Span,
-        span: Span,
-        target: Target,
-        attrs: &[Attribute],
-    ) {
-        self.check_macro_only_attr(hir_id, attr_span, span, target, attrs, "allow_internal_unsafe")
-    }
-
-    /// Outputs an error for attributes that can only be applied to macros, such as
-    /// `#[allow_internal_unsafe]` and `#[allow_internal_unstable]`.
-    /// (Allows proc_macro functions)
     // FIXME(jdonszelmann): if possible, move to attr parsing
-    fn check_macro_only_attr(
+    fn check_allow_internal_unstable(
         &self,
         hir_id: HirId,
         attr_span: Span,
         span: Span,
         target: Target,
         attrs: &[Attribute],
-        attr_name: &str,
     ) {
         match target {
             Target::Fn => {
@@ -2275,14 +2238,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             // erroneously allowed it and some crates used it accidentally, to be compatible
             // with crates depending on them, we can't throw an error here.
             Target::Field | Target::Arm => {
-                self.inline_attr_str_error_without_macro_def(hir_id, attr_span, attr_name);
+                self.inline_attr_str_error_without_macro_def(
+                    hir_id,
+                    attr_span,
+                    "allow_internal_unstable",
+                );
                 return;
             }
             // otherwise continue out of the match
             _ => {}
         }
 
-        self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span });
+        self.tcx.dcx().emit_err(errors::AllowInternalUnstable { attr_span, span });
     }
 
     /// Checks if the items on the `#[debugger_visualizer]` attribute are valid.
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 10b30fbe8c9..c6ab6b0d601 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -643,8 +643,8 @@ pub(crate) struct UsedStatic {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_macro_only_attribute)]
-pub(crate) struct MacroOnlyAttribute {
+#[diag(passes_allow_internal_unstable)]
+pub(crate) struct AllowInternalUnstable {
     #[primary_span]
     pub attr_span: Span,
     #[label]
diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs
index 6ee325dce03..c83610da1aa 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -44,11 +44,11 @@ impl Node {
 /// For example, `ast::Visitor` has `visit_ident`, but `Ident`s are always
 /// stored inline within other AST nodes, so we don't implement `visit_ident`
 /// here. In contrast, we do implement `visit_expr` because `ast::Expr` is
-/// always stored as `P<ast::Expr>`, and every such expression should be
+/// always stored as `Box<ast::Expr>`, and every such expression should be
 /// measured separately.
 ///
 /// In general, a `visit_foo` method should be implemented here if the
-/// corresponding `Foo` type is always stored on its own, e.g.: `P<Foo>`,
+/// corresponding `Foo` type is always stored on its own, e.g.: `Box<Foo>`,
 /// `Box<Foo>`, `Vec<Foo>`, `Box<[Foo]>`.
 ///
 /// There are some types in the AST and HIR tree that the visitors do not have
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index c5056b9df76..e2f223325df 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -268,93 +268,51 @@ fn lookup_const_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ConstSt
     None
 }
 
-/// A private tree-walker for producing an `Index`.
-struct Annotator<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    implications: UnordMap<Symbol, Symbol>,
-}
-
-impl<'tcx> Annotator<'tcx> {
-    /// Determine the stability for a node based on its attributes and inherited stability. The
-    /// stability is recorded in the index and used as the parent. If the node is a function,
-    /// `fn_sig` is its signature.
-    #[instrument(level = "trace", skip(self))]
-    fn annotate(&mut self, def_id: LocalDefId) {
-        if !self.tcx.features().staged_api() {
-            return;
-        }
+fn stability_implications(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> UnordMap<Symbol, Symbol> {
+    let mut implications = UnordMap::default();
 
-        if let Some(stability) = self.tcx.lookup_stability(def_id)
+    let mut register_implication = |def_id| {
+        if let Some(stability) = tcx.lookup_stability(def_id)
             && let StabilityLevel::Unstable { implied_by: Some(implied_by), .. } = stability.level
         {
-            self.implications.insert(implied_by, stability.feature);
+            implications.insert(implied_by, stability.feature);
         }
 
-        if let Some(stability) = self.tcx.lookup_const_stability(def_id)
+        if let Some(stability) = tcx.lookup_const_stability(def_id)
             && let StabilityLevel::Unstable { implied_by: Some(implied_by), .. } = stability.level
         {
-            self.implications.insert(implied_by, stability.feature);
+            implications.insert(implied_by, stability.feature);
         }
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for Annotator<'tcx> {
-    /// Because stability levels are scoped lexically, we want to walk
-    /// nested items in the context of the outer item, so enable
-    /// deep-walking.
-    type NestedFilter = nested_filter::All;
-
-    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
-        self.tcx
-    }
+    };
 
-    fn visit_item(&mut self, i: &'tcx Item<'tcx>) {
-        match i.kind {
-            hir::ItemKind::Struct(_, _, ref sd) => {
-                if let Some(ctor_def_id) = sd.ctor_def_id() {
-                    self.annotate(ctor_def_id);
+    if tcx.features().staged_api() {
+        register_implication(CRATE_DEF_ID);
+        for def_id in tcx.hir_crate_items(()).definitions() {
+            register_implication(def_id);
+            let def_kind = tcx.def_kind(def_id);
+            if def_kind.is_adt() {
+                let adt = tcx.adt_def(def_id);
+                for variant in adt.variants() {
+                    if variant.def_id != def_id.to_def_id() {
+                        register_implication(variant.def_id.expect_local());
+                    }
+                    for field in &variant.fields {
+                        register_implication(field.did.expect_local());
+                    }
+                    if let Some(ctor_def_id) = variant.ctor_def_id() {
+                        register_implication(ctor_def_id.expect_local())
+                    }
+                }
+            }
+            if def_kind.has_generics() {
+                for param in tcx.generics_of(def_id).own_params.iter() {
+                    register_implication(param.def_id.expect_local())
                 }
             }
-            _ => {}
-        }
-
-        self.annotate(i.owner_id.def_id);
-        intravisit::walk_item(self, i)
-    }
-
-    fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
-        self.annotate(ti.owner_id.def_id);
-        intravisit::walk_trait_item(self, ti);
-    }
-
-    fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
-        self.annotate(ii.owner_id.def_id);
-        intravisit::walk_impl_item(self, ii);
-    }
-
-    fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) {
-        self.annotate(var.def_id);
-        if let Some(ctor_def_id) = var.data.ctor_def_id() {
-            self.annotate(ctor_def_id);
         }
-
-        intravisit::walk_variant(self, var)
     }
 
-    fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) {
-        self.annotate(s.def_id);
-        intravisit::walk_field_def(self, s);
-    }
-
-    fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
-        self.annotate(i.owner_id.def_id);
-        intravisit::walk_foreign_item(self, i);
-    }
-
-    fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
-        self.annotate(p.def_id);
-        intravisit::walk_generic_param(self, p);
-    }
+    implications
 }
 
 struct MissingStabilityAnnotations<'tcx> {
@@ -566,13 +524,6 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
     }
 }
 
-fn stability_implications(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> UnordMap<Symbol, Symbol> {
-    let mut annotator = Annotator { tcx, implications: Default::default() };
-    annotator.annotate(CRATE_DEF_ID);
-    tcx.hir_walk_toplevel_module(&mut annotator);
-    annotator.implications
-}
-
 /// Cross-references the feature names of unstable APIs with enabled
 /// features and possibly prints errors.
 fn check_mod_unstable_api_usage(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index 9a9e0db964c..12f653a1337 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -1130,16 +1130,16 @@ impl<Cx: PatCx> ConstructorSet<Cx> {
                         seen_false = true;
                     }
                 }
-                if seen_false {
-                    present.push(Bool(false));
-                } else {
-                    missing.push(Bool(false));
-                }
                 if seen_true {
                     present.push(Bool(true));
                 } else {
                     missing.push(Bool(true));
                 }
+                if seen_false {
+                    present.push(Bool(false));
+                } else {
+                    missing.push(Bool(false));
+                }
             }
             ConstructorSet::Integers { range_1, range_2 } => {
                 let seen_ranges: Vec<_> =
diff --git a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
index 14ca0d057f0..4ad64f81560 100644
--- a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
+++ b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
@@ -176,6 +176,9 @@ fn test_witnesses() {
         ),
         vec!["Enum::Variant1(_)", "Enum::Variant2(_)", "_"],
     );
+
+    // Assert we put `true` before `false`.
+    assert_witnesses(AllOfThem, Ty::Bool, Vec::new(), vec!["true", "false"]);
 }
 
 #[test]
diff --git a/compiler/rustc_public/src/mir/pretty.rs b/compiler/rustc_public/src/mir/pretty.rs
index 3183c020772..9dd1ce4de0e 100644
--- a/compiler/rustc_public/src/mir/pretty.rs
+++ b/compiler/rustc_public/src/mir/pretty.rs
@@ -100,7 +100,7 @@ fn pretty_statement<W: Write>(writer: &mut W, statement: &StatementKind) -> io::
             writeln!(writer, "{INDENT}FakeRead({cause:?}, {place:?});")
         }
         StatementKind::SetDiscriminant { place, variant_index } => {
-            writeln!(writer, "{INDENT}discriminant({place:?} = {};", variant_index.to_index())
+            writeln!(writer, "{INDENT}discriminant({place:?}) = {};", variant_index.to_index())
         }
         StatementKind::Deinit(place) => writeln!(writer, "Deinit({place:?};"),
         StatementKind::StorageLive(local) => {
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 39e9a9cc58a..ceef558c0cf 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -243,7 +243,7 @@ resolve_lowercase_self =
     .suggestion = try using `Self`
 
 resolve_macro_cannot_use_as_attr =
-    `{$ident}` exists, but a declarative macro cannot be used as an attribute macro
+    `{$ident}` exists, but has no `attr` rules
 
 resolve_macro_cannot_use_as_derive =
      `{$ident}` exists, but a declarative macro cannot be used as a derive macro
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 517e20e0619..66f79585d92 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1,4 +1,3 @@
-use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast::{
     self as ast, CRATE_NODE_ID, Crate, ItemKind, ModKind, NodeId, Path, join_path_idents,
@@ -3347,7 +3346,7 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
     }
 }
 
-fn search_for_any_use_in_items(items: &[P<ast::Item>]) -> Option<Span> {
+fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
     for item in items {
         if let ItemKind::Use(..) = item.kind
             && is_span_suitable_for_use_injection(item.span)
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 80e57a4fa3d..092bb6fc4f9 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -631,9 +631,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 };
 
                 match result {
-                    Ok((binding, flags))
-                        if sub_namespace_match(binding.macro_kind(), macro_kind) =>
-                    {
+                    Ok((binding, flags)) => {
+                        let binding_macro_kind = binding.macro_kind();
+                        // If we're looking for an attribute, that might be supported by a
+                        // `macro_rules!` macro.
+                        // FIXME: Replace this with tracking multiple macro kinds for one Def.
+                        if !(sub_namespace_match(binding_macro_kind, macro_kind)
+                            || (binding_macro_kind == Some(MacroKind::Bang)
+                                && macro_kind == Some(MacroKind::Attr)
+                                && this
+                                    .get_macro(binding.res())
+                                    .is_some_and(|macro_data| macro_data.attr_ext.is_some())))
+                        {
+                            return None;
+                        }
+
                         if finalize.is_none() || matches!(scope_set, ScopeSet::Late(..)) {
                             return Some(Ok(binding));
                         }
@@ -710,7 +722,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             innermost_result = Some((binding, flags));
                         }
                     }
-                    Ok(..) | Err(Determinacy::Determined) => {}
+                    Err(Determinacy::Determined) => {}
                     Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined,
                 }
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index fb6f5725704..8f0c08c3998 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -12,7 +12,6 @@ use std::collections::BTreeSet;
 use std::collections::hash_map::Entry;
 use std::mem::{replace, swap, take};
 
-use rustc_ast::ptr::P;
 use rustc_ast::visit::{
     AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, try_visit, visit_opt, walk_list,
 };
@@ -670,7 +669,7 @@ pub(crate) struct UnnecessaryQualification<'ra> {
 #[derive(Default, Debug)]
 struct DiagMetadata<'ast> {
     /// The current trait's associated items' ident, used for diagnostic suggestions.
-    current_trait_assoc_items: Option<&'ast [P<AssocItem>]>,
+    current_trait_assoc_items: Option<&'ast [Box<AssocItem>]>,
 
     /// The current self type if inside an impl (used for better errors).
     current_self_type: Option<Ty>,
@@ -720,7 +719,7 @@ struct DiagMetadata<'ast> {
     current_type_path: Option<&'ast Ty>,
 
     /// The current impl items (used to suggest).
-    current_impl_items: Option<&'ast [P<AssocItem>]>,
+    current_impl_items: Option<&'ast [Box<AssocItem>]>,
 
     /// When processing impl trait
     currently_processing_impl_trait: Option<(TraitRef, Ty)>,
@@ -3038,7 +3037,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
     }
 
     /// When evaluating a `trait` use its associated types' idents for suggestions in E0412.
-    fn resolve_trait_items(&mut self, trait_items: &'ast [P<AssocItem>]) {
+    fn resolve_trait_items(&mut self, trait_items: &'ast [Box<AssocItem>]) {
         let trait_assoc_items =
             replace(&mut self.diag_metadata.current_trait_assoc_items, Some(trait_items));
 
@@ -3179,7 +3178,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         opt_trait_reference: &'ast Option<TraitRef>,
         self_type: &'ast Ty,
         item_id: NodeId,
-        impl_items: &'ast [P<AssocItem>],
+        impl_items: &'ast [Box<AssocItem>],
     ) {
         debug!("resolve_implementation");
         // If applicable, create a rib for the type parameters.
@@ -3671,7 +3670,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
     /// pattern as a whole counts as a never pattern (since it's definitionallly unreachable).
     fn compute_and_check_or_pat_binding_map(
         &mut self,
-        pats: &[P<Pat>],
+        pats: &[Box<Pat>],
     ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
         let mut missing_vars = FxIndexMap::default();
         let mut inconsistent_vars = FxIndexMap::default();
@@ -4109,7 +4108,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
     fn smart_resolve_path(
         &mut self,
         id: NodeId,
-        qself: &Option<P<QSelf>>,
+        qself: &Option<Box<QSelf>>,
         path: &Path,
         source: PathSource<'_, 'ast, '_>,
     ) {
@@ -4126,7 +4125,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn smart_resolve_path_fragment(
         &mut self,
-        qself: &Option<P<QSelf>>,
+        qself: &Option<Box<QSelf>>,
         path: &[Segment],
         source: PathSource<'_, 'ast, '_>,
         finalize: Finalize,
@@ -4434,7 +4433,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
     // Resolve in alternative namespaces if resolution in the primary namespace fails.
     fn resolve_qpath_anywhere(
         &mut self,
-        qself: &Option<P<QSelf>>,
+        qself: &Option<Box<QSelf>>,
         path: &[Segment],
         primary_ns: Namespace,
         span: Span,
@@ -4485,7 +4484,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
     /// Handles paths that may refer to associated items.
     fn resolve_qpath(
         &mut self,
-        qself: &Option<P<QSelf>>,
+        qself: &Option<Box<QSelf>>,
         path: &[Segment],
         ns: Namespace,
         finalize: Finalize,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 19cd45294eb..0807142a7c3 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -4,7 +4,6 @@ use std::borrow::Cow;
 use std::iter;
 use std::ops::Deref;
 
-use rustc_ast::ptr::P;
 use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt, Visitor, walk_ty};
 use rustc_ast::{
     self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind,
@@ -2150,7 +2149,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         err: &mut Diag<'_>,
         path_span: Span,
         call_span: Span,
-        args: &[P<Expr>],
+        args: &[Box<Expr>],
     ) {
         if def_id.is_local() {
             // Doing analysis on local `DefId`s would cause infinite recursion.
@@ -3788,7 +3787,7 @@ fn mk_where_bound_predicate(
             ident: last.ident,
             gen_args: None,
             kind: ast::AssocItemConstraintKind::Equality {
-                term: ast::Term::Ty(ast::ptr::P(ast::Ty {
+                term: ast::Term::Ty(Box::new(ast::Ty {
                     kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()),
                     id: DUMMY_NODE_ID,
                     span: DUMMY_SP,
@@ -3805,7 +3804,7 @@ fn mk_where_bound_predicate(
             Some(_) => return None,
             None => {
                 second_last.args =
-                    Some(ast::ptr::P(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
+                    Some(Box::new(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
                         args: ThinVec::from([added_constraint]),
                         span: DUMMY_SP,
                     })));
@@ -3818,7 +3817,7 @@ fn mk_where_bound_predicate(
 
     let new_where_bound_predicate = ast::WhereBoundPredicate {
         bound_generic_params: ThinVec::new(),
-        bounded_ty: ast::ptr::P(ty.clone()),
+        bounded_ty: Box::new(ty.clone()),
         bounds: vec![ast::GenericBound::Trait(ast::PolyTraitRef {
             bound_generic_params: ThinVec::new(),
             modifiers: ast::TraitBoundModifiers::NONE,
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index e5df23a86cb..23f44ff1658 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1029,13 +1029,14 @@ struct DeriveData {
 
 struct MacroData {
     ext: Arc<SyntaxExtension>,
+    attr_ext: Option<Arc<SyntaxExtension>>,
     nrules: usize,
     macro_rules: bool,
 }
 
 impl MacroData {
     fn new(ext: Arc<SyntaxExtension>) -> MacroData {
-        MacroData { ext, nrules: 0, macro_rules: false }
+        MacroData { ext, attr_ext: None, nrules: 0, macro_rules: false }
     }
 }
 
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index dae3c9dfad5..9173d0d3ea5 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -842,7 +842,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 }
                 _ => None,
             },
-            None => self.get_macro(res).map(|macro_data| Arc::clone(&macro_data.ext)),
+            None => self.get_macro(res).map(|macro_data| match kind {
+                Some(MacroKind::Attr) if let Some(ref ext) = macro_data.attr_ext => Arc::clone(ext),
+                _ => Arc::clone(&macro_data.ext),
+            }),
         };
         Ok((ext, res))
     }
@@ -1178,7 +1181,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         node_id: NodeId,
         edition: Edition,
     ) -> MacroData {
-        let (mut ext, mut nrules) = compile_declarative_macro(
+        let (mut ext, mut attr_ext, mut nrules) = compile_declarative_macro(
             self.tcx.sess,
             self.tcx.features(),
             macro_def,
@@ -1195,13 +1198,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 // The macro is a built-in, replace its expander function
                 // while still taking everything else from the source code.
                 ext.kind = builtin_ext_kind.clone();
+                attr_ext = None;
                 nrules = 0;
             } else {
                 self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident });
             }
         }
 
-        MacroData { ext: Arc::new(ext), nrules, macro_rules: macro_def.macro_rules }
+        MacroData { ext: Arc::new(ext), attr_ext, nrules, macro_rules: macro_def.macro_rules }
     }
 
     fn path_accessible(
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 36197950221..acbed7a9eed 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -280,6 +280,7 @@ symbols! {
         IterPeekable,
         Iterator,
         IteratorItem,
+        IteratorMap,
         Layout,
         Left,
         LinkedList,
@@ -1311,6 +1312,7 @@ symbols! {
         lt,
         m68k_target_feature,
         macro_at_most_once_rep,
+        macro_attr,
         macro_attributes_in_derive_output,
         macro_concat,
         macro_escape,
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index aa6d1ec7009..da9f96ce37d 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -51,14 +51,14 @@ impl Arch {
         })
     }
 
-    fn target_cpu(self, abi: TargetAbi) -> &'static str {
+    fn target_cpu(self, env: TargetEnv) -> &'static str {
         match self {
             Armv7k => "cortex-a8",
             Armv7s => "swift", // iOS 10 is only supported on iPhone 5 or higher.
-            Arm64 => match abi {
-                TargetAbi::Normal => "apple-a7",
-                TargetAbi::Simulator => "apple-a12",
-                TargetAbi::MacCatalyst => "apple-a12",
+            Arm64 => match env {
+                TargetEnv::Normal => "apple-a7",
+                TargetEnv::Simulator => "apple-a12",
+                TargetEnv::MacCatalyst => "apple-a12",
             },
             Arm64e => "apple-a12",
             Arm64_32 => "apple-s4",
@@ -83,14 +83,14 @@ impl Arch {
 }
 
 #[derive(Copy, Clone, PartialEq)]
-pub(crate) enum TargetAbi {
+pub(crate) enum TargetEnv {
     Normal,
     Simulator,
     MacCatalyst,
 }
 
-impl TargetAbi {
-    fn target_abi(self) -> &'static str {
+impl TargetEnv {
+    fn target_env(self) -> &'static str {
         match self {
             Self::Normal => "",
             Self::MacCatalyst => "macabi",
@@ -104,13 +104,20 @@ impl TargetAbi {
 pub(crate) fn base(
     os: &'static str,
     arch: Arch,
-    abi: TargetAbi,
+    env: TargetEnv,
 ) -> (TargetOptions, StaticCow<str>, StaticCow<str>) {
     let mut opts = TargetOptions {
-        abi: abi.target_abi().into(),
         llvm_floatabi: Some(FloatAbi::Hard),
         os: os.into(),
-        cpu: arch.target_cpu(abi).into(),
+        env: env.target_env().into(),
+        // NOTE: We originally set `cfg(target_abi = "macabi")` / `cfg(target_abi = "sim")`,
+        // before it was discovered that those are actually environments:
+        // https://github.com/rust-lang/rust/issues/133331
+        //
+        // But let's continue setting them for backwards compatibility.
+        // FIXME(madsmtm): Warn about using these in the future.
+        abi: env.target_env().into(),
+        cpu: arch.target_cpu(env).into(),
         link_env_remove: link_env_remove(os),
         vendor: "apple".into(),
         linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No),
@@ -168,14 +175,14 @@ pub(crate) fn base(
         // All Apple x86-32 targets have SSE2.
         opts.rustc_abi = Some(RustcAbi::X86Sse2);
     }
-    (opts, unversioned_llvm_target(os, arch, abi), arch.target_arch())
+    (opts, unversioned_llvm_target(os, arch, env), arch.target_arch())
 }
 
 /// Generate part of the LLVM target triple.
 ///
 /// See `rustc_codegen_ssa::back::versioned_llvm_target` for the full triple passed to LLVM and
 /// Clang.
-fn unversioned_llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow<str> {
+fn unversioned_llvm_target(os: &str, arch: Arch, env: TargetEnv) -> StaticCow<str> {
     let arch = arch.target_name();
     // Convert to the "canonical" OS name used by LLVM:
     // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L236-L282
@@ -187,10 +194,10 @@ fn unversioned_llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow<st
         "visionos" => "xros",
         _ => unreachable!("tried to get LLVM target OS for non-Apple platform"),
     };
-    let environment = match abi {
-        TargetAbi::Normal => "",
-        TargetAbi::MacCatalyst => "-macabi",
-        TargetAbi::Simulator => "-simulator",
+    let environment = match env {
+        TargetEnv::Normal => "",
+        TargetEnv::MacCatalyst => "-macabi",
+        TargetEnv::Simulator => "-simulator",
     };
     format!("{arch}-apple-{os}{environment}").into()
 }
@@ -309,7 +316,7 @@ impl OSVersion {
     /// This matches what LLVM does, see in part:
     /// <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L1900-L1932>
     pub fn minimum_deployment_target(target: &Target) -> Self {
-        let (major, minor, patch) = match (&*target.os, &*target.arch, &*target.abi) {
+        let (major, minor, patch) = match (&*target.os, &*target.arch, &*target.env) {
             ("macos", "aarch64", _) => (11, 0, 0),
             ("ios", "aarch64", "macabi") => (14, 0, 0),
             ("ios", "aarch64", "sim") => (14, 0, 0),
diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs
index 391f3470104..bca86ce33c3 100644
--- a/compiler/rustc_target/src/spec/base/apple/tests.rs
+++ b/compiler/rustc_target/src/spec/base/apple/tests.rs
@@ -6,7 +6,7 @@ use crate::spec::targets::{
 };
 
 #[test]
-fn simulator_targets_set_abi() {
+fn simulator_targets_set_env() {
     let all_sim_targets = [
         x86_64_apple_ios::target(),
         x86_64_apple_tvos::target(),
@@ -18,7 +18,9 @@ fn simulator_targets_set_abi() {
     ];
 
     for target in &all_sim_targets {
-        assert_eq!(target.abi, "sim")
+        assert_eq!(target.env, "sim");
+        // Ensure backwards compat
+        assert_eq!(target.abi, "sim");
     }
 }
 
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index 4dd39877715..e1960472555 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index 769a7b6c391..3b522c34522 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index 4bb2f73e4f9..4d6a3103ee3 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst);
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetEnv::MacCatalyst);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index 7d04034e759..d366ed26482 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index ec92a40e255..7aef6f96e1c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index 74fbe5a89ca..f0d17db873b 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
index dc595fbe7b6..22ce52e637f 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
index 06ff1bfb2f0..21739ba9fdb 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
index 23596271107..2e88f95f1dd 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index bad9f6c1485..272dc682dc0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
index 4c3a2f43743..564ac2cd708 100644
--- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64_32, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64_32, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index 326f2b16d59..86e178a9572 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index 01c6f0b888d..dae3f77d7ae 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
index cad3650bda1..a99fc5dc68c 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
index 8103d132cea..df58559848a 100644
--- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::Armv7k, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Armv7k, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
index ba9edd71461..63259043b73 100644
--- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Armv7s, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("ios", Arch::Armv7s, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index 29865fcd4c4..a919be765a2 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     // i386-apple-ios is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let (opts, llvm_target, arch) = base("ios", Arch::I386, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("ios", Arch::I386, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index d1339c57b00..96c477d5236 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index eba595ba7dd..53e2cb469ee 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index df45f430ecb..d74a688fa0f 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     // x86_64-apple-ios is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
index ee0c2bf31cd..193e26f94c9 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::MacCatalyst);
+    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetEnv::MacCatalyst);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index 80ca80013f0..e69bd17a049 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     // x86_64-apple-tvos is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let (opts, llvm_target, arch) = base("tvos", Arch::X86_64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("tvos", Arch::X86_64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
index c503baedb8b..9490ca6aa36 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::X86_64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("watchos", Arch::X86_64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index e64556c4132..67b5a160a89 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
+    let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetEnv::Normal);
     opts.max_atomic_width = Some(128);
     opts.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 8232da4df43..fcb25025087 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -171,8 +171,6 @@ trait_selection_fps_remove_ref = consider removing the reference
 trait_selection_fps_use_ref = consider using a reference
 trait_selection_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
 
-trait_selection_full_type_written = the full type name has been written to '{$path}'
-
 trait_selection_ignored_diagnostic_option = `{$option_name}` is ignored due to previous definition of `{$option_name}`
     .other_label = `{$option_name}` is first declared here
     .label = `{$option_name}` is already declared here
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index ed8229154a9..1c890821b1d 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -1930,7 +1930,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         &self,
         trace: &TypeTrace<'tcx>,
         terr: TypeError<'tcx>,
-        path: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> Vec<TypeErrorAdditionalDiags> {
         let mut suggestions = Vec::new();
         let span = trace.cause.span;
@@ -2009,7 +2009,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         })
         | ObligationCauseCode::BlockTailExpression(.., source)) = code
             && let hir::MatchSource::TryDesugar(_) = source
-            && let Some((expected_ty, found_ty)) = self.values_str(trace.values, &trace.cause, path)
+            && let Some((expected_ty, found_ty)) =
+                self.values_str(trace.values, &trace.cause, long_ty_path)
         {
             suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert {
                 found: found_ty.content(),
@@ -2139,11 +2140,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         &self,
         values: ValuePairs<'tcx>,
         cause: &ObligationCause<'tcx>,
-        file: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> Option<(DiagStyledString, DiagStyledString)> {
         match values {
             ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
-            ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, file),
+            ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, long_ty_path),
             ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
             ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
             ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
@@ -2183,7 +2184,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     fn expected_found_str_term(
         &self,
         exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
-        path: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> Option<(DiagStyledString, DiagStyledString)> {
         let exp_found = self.resolve_vars_if_possible(exp_found);
         if exp_found.references_error() {
@@ -2200,11 +2201,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 let exp_s = exp.content();
                 let fnd_s = fnd.content();
                 if exp_s.len() > len {
-                    let exp_s = self.tcx.short_string(expected, path);
+                    let exp_s = self.tcx.short_string(expected, long_ty_path);
                     exp = DiagStyledString::highlighted(exp_s);
                 }
                 if fnd_s.len() > len {
-                    let fnd_s = self.tcx.short_string(found, path);
+                    let fnd_s = self.tcx.short_string(found, long_ty_path);
                     fnd = DiagStyledString::highlighted(fnd_s);
                 }
                 (exp, fnd)
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 966f117a1bf..ec2287ed516 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -436,8 +436,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
-                was_written: false,
-                path: Default::default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -447,8 +445,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
-                was_written: false,
-                path: Default::default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
                 span,
@@ -458,8 +454,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
-                was_written: false,
-                path: Default::default(),
             }),
         }
     }
@@ -496,7 +490,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             return self.bad_inference_failure_err(failure_span, arg_data, error_code);
         };
 
-        let (source_kind, name, path) = kind.ty_localized_msg(self);
+        let (source_kind, name, long_ty_path) = kind.ty_localized_msg(self);
         let failure_span = if should_label_span && !failure_span.overlaps(span) {
             Some(failure_span)
         } else {
@@ -628,7 +622,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
             }
         }
-        match error_code {
+        let mut err = match error_code {
             TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
                 span,
                 source_kind,
@@ -637,8 +631,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
-                was_written: path.is_some(),
-                path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -648,8 +640,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
-                was_written: path.is_some(),
-                path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
                 span,
@@ -659,10 +649,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
-                was_written: path.is_some(),
-                path: path.unwrap_or_default(),
             }),
-        }
+        };
+        *err.long_ty_path() = long_ty_path;
+        err
     }
 }
 
@@ -726,22 +716,24 @@ impl<'tcx> InferSource<'tcx> {
 
 impl<'tcx> InferSourceKind<'tcx> {
     fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Option<PathBuf>) {
-        let mut path = None;
+        let mut long_ty_path = None;
         match *self {
             InferSourceKind::LetBinding { ty, .. }
             | InferSourceKind::ClosureArg { ty, .. }
             | InferSourceKind::ClosureReturn { ty, .. } => {
                 if ty.is_closure() {
-                    ("closure", closure_as_fn_str(infcx, ty), path)
+                    ("closure", closure_as_fn_str(infcx, ty), long_ty_path)
                 } else if !ty.is_ty_or_numeric_infer() {
-                    ("normal", infcx.tcx.short_string(ty, &mut path), path)
+                    ("normal", infcx.tcx.short_string(ty, &mut long_ty_path), long_ty_path)
                 } else {
-                    ("other", String::new(), path)
+                    ("other", String::new(), long_ty_path)
                 }
             }
             // FIXME: We should be able to add some additional info here.
             InferSourceKind::GenericArg { .. }
-            | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new(), path),
+            | InferSourceKind::FullyQualifiedMethodCall { .. } => {
+                ("other", String::new(), long_ty_path)
+            }
         }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index 129d0963a75..8f0f6d0bf26 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -653,7 +653,6 @@ impl<T> Trait<T> for X {
             )
         );
         let impl_comparison = matches!(cause_code, ObligationCauseCode::CompareImplItem { .. });
-        let assoc = tcx.associated_item(proj_ty.def_id);
         if impl_comparison {
             // We do not want to suggest calling functions when the reason of the
             // type error is a comparison of an `impl` with its `trait`.
@@ -661,7 +660,7 @@ impl<T> Trait<T> for X {
             let point_at_assoc_fn = if callable_scope
                 && self.point_at_methods_that_satisfy_associated_type(
                     diag,
-                    assoc.container_id(tcx),
+                    tcx.parent(proj_ty.def_id),
                     current_method_ident,
                     proj_ty.def_id,
                     values.expected,
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
index cdf1402252a..af912227ce4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
@@ -169,7 +169,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         let predicate = self.resolve_vars_if_possible(obligation.predicate);
         let span = obligation.cause.span;
-        let mut file = None;
+        let mut long_ty_path = None;
 
         debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
 
@@ -211,19 +211,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     self.tcx.as_lang_item(trait_pred.def_id()),
                     Some(LangItem::Sized | LangItem::MetaSized)
                 ) {
-                    match self.tainted_by_errors() {
-                        None => {
-                            let err = self.emit_inference_failure_err(
+                    return match self.tainted_by_errors() {
+                        None => self
+                            .emit_inference_failure_err(
                                 obligation.cause.body_id,
                                 span,
                                 trait_pred.self_ty().skip_binder().into(),
                                 TypeAnnotationNeeded::E0282,
                                 false,
-                            );
-                            return err.emit();
-                        }
-                        Some(e) => return e,
-                    }
+                            )
+                            .emit(),
+                        Some(e) => e,
+                    };
                 }
 
                 // Typically, this ambiguity should only happen if
@@ -260,8 +259,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         span,
                         E0283,
                         "type annotations needed: cannot satisfy `{}`",
-                        self.tcx.short_string(predicate, &mut file),
+                        self.tcx.short_string(predicate, &mut long_ty_path),
                     )
+                    .with_long_ty_path(long_ty_path)
                 };
 
                 let mut ambiguities = compute_applicable_impls_for_diagnostics(
@@ -307,7 +307,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         err.cancel();
                         return e;
                     }
-                    let pred = self.tcx.short_string(predicate, &mut file);
+                    let pred = self.tcx.short_string(predicate, &mut err.long_ty_path());
                     err.note(format!("cannot satisfy `{pred}`"));
                     let impl_candidates =
                         self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
@@ -512,6 +512,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     true,
                 )
             }
+
             ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
                 if let Err(e) = predicate.error_reported() {
                     return e;
@@ -536,7 +537,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     .filter_map(ty::GenericArg::as_term)
                     .chain([data.term])
                     .find(|g| g.has_non_region_infer());
-                let predicate = self.tcx.short_string(predicate, &mut file);
+                let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
                 if let Some(term) = term {
                     self.emit_inference_failure_err(
                         obligation.cause.body_id,
@@ -546,6 +547,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         true,
                     )
                     .with_note(format!("cannot satisfy `{predicate}`"))
+                    .with_long_ty_path(long_ty_path)
                 } else {
                     // If we can't find a generic parameter, just print a generic error
                     struct_span_code_err!(
@@ -555,6 +557,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         "type annotations needed: cannot satisfy `{predicate}`",
                     )
                     .with_span_label(span, format!("cannot satisfy `{predicate}`"))
+                    .with_long_ty_path(long_ty_path)
                 }
             }
 
@@ -568,17 +571,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 let term =
                     data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer());
                 if let Some(term) = term {
-                    let err = self.emit_inference_failure_err(
+                    self.emit_inference_failure_err(
                         obligation.cause.body_id,
                         span,
                         term,
                         TypeAnnotationNeeded::E0284,
                         true,
-                    );
-                    err
+                    )
                 } else {
                     // If we can't find a generic parameter, just print a generic error
-                    let predicate = self.tcx.short_string(predicate, &mut file);
+                    let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
                     struct_span_code_err!(
                         self.dcx(),
                         span,
@@ -586,6 +588,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         "type annotations needed: cannot satisfy `{predicate}`",
                     )
                     .with_span_label(span, format!("cannot satisfy `{predicate}`"))
+                    .with_long_ty_path(long_ty_path)
                 }
             }
 
@@ -597,13 +600,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     TypeAnnotationNeeded::E0284,
                     true,
                 ),
+
             ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
                 if term.is_infer() =>
             {
                 if let Some(e) = self.tainted_by_errors() {
                     return e;
                 }
-                let alias = self.tcx.short_string(alias, &mut file);
+                let alias = self.tcx.short_string(alias, &mut long_ty_path);
                 struct_span_code_err!(
                     self.dcx(),
                     span,
@@ -611,37 +615,34 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     "type annotations needed: cannot normalize `{alias}`",
                 )
                 .with_span_label(span, format!("cannot normalize `{alias}`"))
+                .with_long_ty_path(long_ty_path)
             }
+
             ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(sym)) => {
                 if let Some(e) = self.tainted_by_errors() {
                     return e;
                 }
 
-                let mut err;
-
                 if self.tcx.features().staged_api() {
-                    err = self.dcx().struct_span_err(
+                    self.dcx().struct_span_err(
                         span,
                         format!("unstable feature `{sym}` is used without being enabled."),
-                    );
-
-                    err.help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`"));
+                    ).with_help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`"))
                 } else {
-                    err = feature_err_unstable_feature_bound(
+                    feature_err_unstable_feature_bound(
                         &self.tcx.sess,
                         sym,
                         span,
                         format!("use of unstable library feature `{sym}`"),
-                    );
+                    )
                 }
-                err
             }
 
             _ => {
                 if let Some(e) = self.tainted_by_errors() {
                     return e;
                 }
-                let predicate = self.tcx.short_string(predicate, &mut file);
+                let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
                 struct_span_code_err!(
                     self.dcx(),
                     span,
@@ -649,9 +650,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     "type annotations needed: cannot satisfy `{predicate}`",
                 )
                 .with_span_label(span, format!("cannot satisfy `{predicate}`"))
+                .with_long_ty_path(long_ty_path)
             }
         };
-        *err.long_ty_path() = file;
         self.note_obligation_cause(&mut err, obligation);
         err.emit()
     }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index a9e346a5cdb..62859329de3 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -208,16 +208,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                                      performs a conversion on the error value \
                                                      using the `From` trait";
                         let (message, notes, append_const_msg) = if is_try_conversion {
+                            let ty = self.tcx.short_string(
+                                main_trait_predicate.skip_binder().self_ty(),
+                                &mut long_ty_file,
+                            );
                             // We have a `-> Result<_, E1>` and `gives_E2()?`.
                             (
-                                Some(format!(
-                                    "`?` couldn't convert the error to `{}`",
-                                    main_trait_predicate.skip_binder().self_ty(),
-                                )),
+                                Some(format!("`?` couldn't convert the error to `{ty}`")),
                                 vec![question_mark_message.to_owned()],
                                 Some(AppendConstMessage::Default),
                             )
                         } else if is_question_mark {
+                            let main_trait_predicate =
+                                self.tcx.short_string(main_trait_predicate, &mut long_ty_file);
                             // Similar to the case above, but in this case the conversion is for a
                             // trait object: `-> Result<_, Box<dyn Error>` and `gives_E()?` when
                             // `E: Error` isn't met.
@@ -233,7 +236,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             (message, notes, append_const_msg)
                         };
 
-                        let err_msg = self.get_standard_error_message(
+                        let default_err_msg = || self.get_standard_error_message(
                             main_trait_predicate,
                             message,
                             None,
@@ -258,7 +261,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                     );
                                 }
                                 GetSafeTransmuteErrorAndReason::Default => {
-                                    (err_msg, None)
+                                    (default_err_msg(), None)
                                 }
                                 GetSafeTransmuteErrorAndReason::Error {
                                     err_msg,
@@ -266,7 +269,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 } => (err_msg, safe_transmute_explanation),
                             }
                         } else {
-                            (err_msg, None)
+                            (default_err_msg(), None)
                         };
 
                         let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
@@ -279,15 +282,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
                         if let Some(ret_span) = self.return_type_span(&obligation) {
                             if is_try_conversion {
+                                let ty = self.tcx.short_string(
+                                    main_trait_predicate.skip_binder().self_ty(),
+                                    err.long_ty_path(),
+                                );
                                 err.span_label(
                                     ret_span,
-                                    format!(
-                                        "expected `{}` because of this",
-                                        main_trait_predicate.skip_binder().self_ty()
-                                    ),
+                                    format!("expected `{ty}` because of this"),
                                 );
                             } else if is_question_mark {
-                                err.span_label(ret_span, format!("required `{main_trait_predicate}` because of this"));
+                                let main_trait_predicate =
+                                    self.tcx.short_string(main_trait_predicate, err.long_ty_path());
+                                err.span_label(
+                                    ret_span,
+                                    format!("required `{main_trait_predicate}` because of this"),
+                                );
                             }
                         }
 
@@ -303,6 +312,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             &obligation,
                             leaf_trait_predicate,
                             pre_message,
+                            err.long_ty_path(),
                         );
 
                         self.check_for_binding_assigned_block_without_tail_expression(
@@ -414,11 +424,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 } else {
                                     vec![(span.shrink_to_hi(), format!(" as {}", cand.self_ty()))]
                                 };
+                                let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path());
+                                let ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path());
                                 err.multipart_suggestion(
                                     format!(
-                                        "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`",
-                                        cand.print_trait_sugared(),
-                                        cand.self_ty(),
+                                        "the trait `{trait_}` is implemented for fn pointer \
+                                         `{ty}`, try casting using `as`",
                                     ),
                                     suggestion,
                                     Applicability::MaybeIncorrect,
@@ -522,7 +533,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                     <https://github.com/rust-lang/rust/issues/48950> \
                                     for more information)",
                                 );
-                                err.help("did you intend to use the type `()` here instead?");
+                                err.help("you might have intended to use the type `()` here instead");
                             }
                         }
 
@@ -722,10 +733,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }
 
             SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => {
+                let expected_ty_str = self.tcx.short_string(expected_ty, &mut long_ty_file);
+                let ct_str = self.tcx.short_string(ct, &mut long_ty_file);
                 let mut diag = self.dcx().struct_span_err(
                     span,
-                    format!("the constant `{ct}` is not of type `{expected_ty}`"),
+                    format!("the constant `{ct_str}` is not of type `{expected_ty_str}`"),
                 );
+                diag.long_ty_path = long_ty_file;
 
                 self.note_type_err(
                     &mut diag,
@@ -1118,9 +1132,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 .must_apply_modulo_regions()
             {
                 if !suggested {
+                    let err_ty = self.tcx.short_string(err_ty, err.long_ty_path());
                     err.span_label(span, format!("this has type `Result<_, {err_ty}>`"));
                 }
             } else {
+                let err_ty = self.tcx.short_string(err_ty, err.long_ty_path());
                 err.span_label(
                     span,
                     format!(
@@ -1156,12 +1172,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 );
             }
             (ty::Adt(def, _), None) if def.did().is_local() => {
+                let trait_path = self.tcx.short_string(
+                    trait_pred.skip_binder().trait_ref.print_only_trait_path(),
+                    err.long_ty_path(),
+                );
                 err.span_note(
                     self.tcx.def_span(def.did()),
-                    format!(
-                        "`{self_ty}` needs to implement `{}`",
-                        trait_pred.skip_binder().trait_ref.print_only_trait_path(),
-                    ),
+                    format!("`{self_ty}` needs to implement `{trait_path}`"),
                 );
             }
             (ty::Adt(def, _), Some(ty)) if def.did().is_local() => {
@@ -1195,13 +1212,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             bug!()
         };
 
+        let mut file = None;
+        let ty_str = self.tcx.short_string(ty, &mut file);
         let mut diag = match ty.kind() {
             ty::Float(_) => {
                 struct_span_code_err!(
                     self.dcx(),
                     span,
                     E0741,
-                    "`{ty}` is forbidden as the type of a const generic parameter",
+                    "`{ty_str}` is forbidden as the type of a const generic parameter",
                 )
             }
             ty::FnPtr(..) => {
@@ -1226,7 +1245,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     self.dcx(),
                     span,
                     E0741,
-                    "`{ty}` must implement `ConstParamTy` to be used as the type of a const generic parameter",
+                    "`{ty_str}` must implement `ConstParamTy` to be used as the type of a const generic parameter",
                 );
                 // Only suggest derive if this isn't a derived obligation,
                 // and the struct is local.
@@ -1258,21 +1277,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     self.dcx(),
                     span,
                     E0741,
-                    "`{ty}` can't be used as a const parameter type",
+                    "`{ty_str}` can't be used as a const parameter type",
                 )
             }
         };
+        diag.long_ty_path = file;
 
         let mut code = obligation.cause.code();
         let mut pred = obligation.predicate.as_trait_clause();
         while let Some((next_code, next_pred)) = code.parent_with_predicate() {
             if let Some(pred) = pred {
                 self.enter_forall(pred, |pred| {
-                    diag.note(format!(
-                        "`{}` must implement `{}`, but it does not",
-                        pred.self_ty(),
-                        pred.print_modifiers_and_trait_path()
-                    ));
+                    let ty = self.tcx.short_string(pred.self_ty(), diag.long_ty_path());
+                    let trait_path = self
+                        .tcx
+                        .short_string(pred.print_modifiers_and_trait_path(), diag.long_ty_path());
+                    diag.note(format!("`{ty}` must implement `{trait_path}`, but it does not"));
                 })
             }
             code = next_code;
@@ -1584,7 +1604,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         projection_term: ty::AliasTerm<'tcx>,
         normalized_ty: ty::Term<'tcx>,
         expected_ty: ty::Term<'tcx>,
-        file: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> Option<(String, Span, Option<Span>)> {
         let trait_def_id = projection_term.trait_def_id(self.tcx);
         let self_ty = projection_term.self_ty();
@@ -1624,17 +1644,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 };
                 let item = match self_ty.kind() {
                     ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
-                    _ => self.tcx.short_string(self_ty, file),
+                    _ => self.tcx.short_string(self_ty, long_ty_path),
                 };
+                let expected_ty = self.tcx.short_string(expected_ty, long_ty_path);
+                let normalized_ty = self.tcx.short_string(normalized_ty, long_ty_path);
                 Some((format!(
                     "expected `{item}` to return `{expected_ty}`, but it returns `{normalized_ty}`",
                 ), span, closure_span))
             } else if self.tcx.is_lang_item(trait_def_id, LangItem::Future) {
+                let self_ty = self.tcx.short_string(self_ty, long_ty_path);
+                let expected_ty = self.tcx.short_string(expected_ty, long_ty_path);
+                let normalized_ty = self.tcx.short_string(normalized_ty, long_ty_path);
                 Some((format!(
                     "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
                      resolves to `{normalized_ty}`"
                 ), span, None))
             } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
+                let self_ty = self.tcx.short_string(self_ty, long_ty_path);
+                let expected_ty = self.tcx.short_string(expected_ty, long_ty_path);
+                let normalized_ty = self.tcx.short_string(normalized_ty, long_ty_path);
                 Some((format!(
                     "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
                      yields `{normalized_ty}`"
@@ -2097,12 +2125,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
                     if let [TypeError::Sorts(exp_found)] = &terrs[..] {
                         let exp_found = self.resolve_vars_if_possible(*exp_found);
+                        let expected =
+                            self.tcx.short_string(exp_found.expected, err.long_ty_path());
+                        let found = self.tcx.short_string(exp_found.found, err.long_ty_path());
                         err.highlighted_help(vec![
                             StringPart::normal("for that trait implementation, "),
                             StringPart::normal("expected `"),
-                            StringPart::highlighted(exp_found.expected.to_string()),
+                            StringPart::highlighted(expected),
                             StringPart::normal("`, found `"),
-                            StringPart::highlighted(exp_found.found.to_string()),
+                            StringPart::highlighted(found),
                             StringPart::normal("`"),
                         ]);
                         self.suggest_function_pointers_impl(None, &exp_found, err);
@@ -2135,11 +2166,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         (ty::FnPtr(..), _) => (" implemented for fn pointer `", ""),
                         _ => (" implemented for `", ""),
                     };
+                let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path());
+                let self_ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path());
                 err.highlighted_help(vec![
-                    StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())),
+                    StringPart::normal(format!("the trait `{trait_}` ",)),
                     StringPart::highlighted("is"),
                     StringPart::normal(desc),
-                    StringPart::highlighted(cand.self_ty().to_string()),
+                    StringPart::highlighted(self_ty),
                     StringPart::normal("`"),
                     StringPart::normal(mention_castable),
                 ]);
@@ -2159,9 +2192,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 .into_iter()
                 .map(|c| {
                     if all_traits_equal {
-                        format!("\n  {}", c.self_ty())
+                        format!("\n  {}", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
                     } else {
-                        format!("\n  `{}` implements `{}`", c.self_ty(), c.print_only_trait_path())
+                        format!(
+                            "\n  `{}` implements `{}`",
+                            self.tcx.short_string(c.self_ty(), err.long_ty_path()),
+                            self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
+                        )
                     }
                 })
                 .collect();
@@ -2477,7 +2514,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         predicate_constness: Option<ty::BoundConstness>,
         append_const_msg: Option<AppendConstMessage>,
         post_message: String,
-        long_ty_file: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> String {
         message
             .and_then(|cannot_do_this| {
@@ -2503,7 +2540,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     "the trait bound `{}` is not satisfied{post_message}",
                     self.tcx.short_string(
                         trait_predicate.print_with_bound_constness(predicate_constness),
-                        long_ty_file,
+                        long_ty_path,
                     ),
                 )
             })
@@ -2608,8 +2645,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             dst_min_align,
                         } => {
                             format!(
-                                "the minimum alignment of `{src}` ({src_min_align}) should \
-                        be greater than that of `{dst}` ({dst_min_align})"
+                                "the minimum alignment of `{src}` ({src_min_align}) should be \
+                                 greater than that of `{dst}` ({dst_min_align})"
                             )
                         }
                         rustc_transmute::Reason::DstIsMoreUnique => {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
index 5765dfd891d..bb5c6469f34 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
@@ -99,7 +99,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
         obligation: &PredicateObligation<'tcx>,
-        long_ty_file: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> OnUnimplementedNote {
         if trait_pred.polarity() != ty::PredicatePolarity::Positive {
             return OnUnimplementedNote::default();
@@ -281,7 +281,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
                         if let Some(ty) = trait_pred.trait_ref.args[param.index as usize].as_type()
                         {
-                            self.tcx.short_string(ty, long_ty_file)
+                            self.tcx.short_string(ty, long_ty_path)
                         } else {
                             trait_pred.trait_ref.args[param.index as usize].to_string()
                         }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 718cff6d135..ae72178c052 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3,6 +3,7 @@
 use std::assert_matches::debug_assert_matches;
 use std::borrow::Cow;
 use std::iter;
+use std::path::PathBuf;
 
 use itertools::{EitherOrBoth, Itertools};
 use rustc_abi::ExternAbi;
@@ -737,7 +738,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 get_name(err, &local.pat.kind)
             }
             // Different to previous arm because one is `&hir::Local` and the other
-            // is `P<hir::Local>`.
+            // is `Box<hir::Local>`.
             hir::Node::LetStmt(local) => get_name(err, &local.pat.kind),
             _ => None,
         }
@@ -1369,6 +1370,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 );
                 let self_ty_str =
                     self.tcx.short_string(old_pred.self_ty().skip_binder(), err.long_ty_path());
+                let trait_path = self
+                    .tcx
+                    .short_string(old_pred.print_modifiers_and_trait_path(), err.long_ty_path());
+
                 if has_custom_message {
                     err.note(msg);
                 } else {
@@ -1376,10 +1381,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
                 err.span_label(
                     span,
-                    format!(
-                        "the trait `{}` is not implemented for `{self_ty_str}`",
-                        old_pred.print_modifiers_and_trait_path()
-                    ),
+                    format!("the trait `{trait_path}` is not implemented for `{self_ty_str}`"),
                 );
             };
 
@@ -3333,17 +3335,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     tcx.async_fn_trait_kind_from_def_id(data.parent_trait_pred.def_id()).is_some();
 
                 if !is_upvar_tys_infer_tuple && !is_builtin_async_fn_trait {
-                    let ty_str = tcx.short_string(ty, err.long_ty_path());
-                    let msg = format!("required because it appears within the type `{ty_str}`");
+                    let mut msg = || {
+                        let ty_str = tcx.short_string(ty, err.long_ty_path());
+                        format!("required because it appears within the type `{ty_str}`")
+                    };
                     match ty.kind() {
-                        ty::Adt(def, _) => match tcx.opt_item_ident(def.did()) {
-                            Some(ident) => {
-                                err.span_note(ident.span, msg);
-                            }
-                            None => {
-                                err.note(msg);
+                        ty::Adt(def, _) => {
+                            let msg = msg();
+                            match tcx.opt_item_ident(def.did()) {
+                                Some(ident) => {
+                                    err.span_note(ident.span, msg);
+                                }
+                                None => {
+                                    err.note(msg);
+                                }
                             }
-                        },
+                        }
                         ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                             // If the previous type is async fn, this is the future generated by the body of an async function.
                             // Avoid printing it twice (it was already printed in the `ty::Coroutine` arm below).
@@ -3363,6 +3370,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             {
                                 // See comment above; skip printing twice.
                             } else {
+                                let msg = msg();
                                 err.span_note(tcx.def_span(def_id), msg);
                             }
                         }
@@ -3392,6 +3400,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes");
                         }
                         _ => {
+                            let msg = msg();
                             err.note(msg);
                         }
                     };
@@ -3441,7 +3450,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
                 let self_ty_str =
                     tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
-                let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();
+                let trait_name = tcx.short_string(
+                    parent_trait_pred.print_modifiers_and_trait_path(),
+                    err.long_ty_path(),
+                );
                 let msg = format!("required for `{self_ty_str}` to implement `{trait_name}`");
                 let mut is_auto_trait = false;
                 match tcx.hir_get_if_local(data.impl_or_alias_def_id) {
@@ -3539,10 +3551,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         parent_trait_pred.skip_binder().self_ty(),
                         err.long_ty_path(),
                     );
-                    err.note(format!(
-                        "required for `{self_ty}` to implement `{}`",
-                        parent_trait_pred.print_modifiers_and_trait_path()
-                    ));
+                    let trait_path = tcx.short_string(
+                        parent_trait_pred.print_modifiers_and_trait_path(),
+                        err.long_ty_path(),
+                    );
+                    err.note(format!("required for `{self_ty}` to implement `{trait_path}`"));
                 }
                 // #74711: avoid a stack overflow
                 ensure_sufficient_stack(|| {
@@ -3558,15 +3571,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 });
             }
             ObligationCauseCode::ImplDerivedHost(ref data) => {
-                let self_ty =
-                    self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty());
-                let msg = format!(
-                    "required for `{self_ty}` to implement `{} {}`",
-                    data.derived.parent_host_pred.skip_binder().constness,
+                let self_ty = tcx.short_string(
+                    self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty()),
+                    err.long_ty_path(),
+                );
+                let trait_path = tcx.short_string(
                     data.derived
                         .parent_host_pred
                         .map_bound(|pred| pred.trait_ref)
                         .print_only_trait_path(),
+                    err.long_ty_path(),
+                );
+                let msg = format!(
+                    "required for `{self_ty}` to implement `{} {trait_path}`",
+                    data.derived.parent_host_pred.skip_binder().constness,
                 );
                 match tcx.hir_get_if_local(data.impl_def_id) {
                     Some(Node::Item(hir::Item {
@@ -5351,6 +5369,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
     obligation: &PredicateObligation<'tcx>,
     trait_predicate: ty::PolyTraitPredicate<'tcx>,
     pre_message: String,
+    long_ty_path: &mut Option<PathBuf>,
 ) -> String {
     if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
         "consider using `()`, or a `Result`".to_owned()
@@ -5369,7 +5388,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
             format!(
                 "{pre_message}the trait `{}` is not implemented for{desc} `{}`",
                 trait_predicate.print_modifiers_and_trait_path(),
-                tcx.short_string(trait_predicate.self_ty().skip_binder(), &mut None),
+                tcx.short_string(trait_predicate.self_ty().skip_binder(), long_ty_path),
             )
         } else {
             // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 7901d52dffb..af241099c01 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,5 +1,3 @@
-use std::path::PathBuf;
-
 use rustc_ast::Path;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::codes::*;
@@ -224,9 +222,6 @@ pub struct AnnotationRequired<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(trait_selection_full_type_written)]
-    pub was_written: bool,
-    pub path: PathBuf,
 }
 
 // Copy of `AnnotationRequired` for E0283
@@ -245,9 +240,6 @@ pub struct AmbiguousImpl<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(trait_selection_full_type_written)]
-    pub was_written: bool,
-    pub path: PathBuf,
 }
 
 // Copy of `AnnotationRequired` for E0284
@@ -266,9 +258,6 @@ pub struct AmbiguousReturn<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(trait_selection_full_type_written)]
-    pub was_written: bool,
-    pub path: PathBuf,
 }
 
 // Used when a better one isn't available
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index af2e000e340..89d1dd8cf23 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -39,7 +39,7 @@ fn fn_sig_for_fn_abi<'tcx>(
             tcx.thread_local_ptr_ty(instance.def_id()),
             false,
             hir::Safety::Safe,
-            rustc_abi::ExternAbi::Unadjusted,
+            rustc_abi::ExternAbi::Rust,
         );
     }
 
@@ -268,20 +268,21 @@ fn fn_abi_of_instance<'tcx>(
 }
 
 // Handle safe Rust thin and wide pointers.
-fn adjust_for_rust_scalar<'tcx>(
+fn arg_attrs_for_rust_scalar<'tcx>(
     cx: LayoutCx<'tcx>,
-    attrs: &mut ArgAttributes,
     scalar: Scalar,
     layout: TyAndLayout<'tcx>,
     offset: Size,
     is_return: bool,
     drop_target_pointee: Option<Ty<'tcx>>,
-) {
+) -> ArgAttributes {
+    let mut attrs = ArgAttributes::new();
+
     // Booleans are always a noundef i1 that needs to be zero-extended.
     if scalar.is_bool() {
         attrs.ext(ArgExtension::Zext);
         attrs.set(ArgAttribute::NoUndef);
-        return;
+        return attrs;
     }
 
     if !scalar.is_uninit_valid() {
@@ -289,7 +290,7 @@ fn adjust_for_rust_scalar<'tcx>(
     }
 
     // Only pointer types handled below.
-    let Scalar::Initialized { value: Pointer(_), valid_range } = scalar else { return };
+    let Scalar::Initialized { value: Pointer(_), valid_range } = scalar else { return attrs };
 
     // Set `nonnull` if the validity range excludes zero, or for the argument to `drop_in_place`,
     // which must be nonnull per its documented safety requirements.
@@ -358,6 +359,8 @@ fn adjust_for_rust_scalar<'tcx>(
             }
         }
     }
+
+    attrs
 }
 
 /// Ensure that the ABI makes basic sense.
@@ -471,9 +474,10 @@ fn fn_abi_new_uncached<'tcx>(
     let (caller_location, determined_fn_def_id, is_virtual_call) = if let Some(instance) = instance
     {
         let is_virtual_call = matches!(instance.def, ty::InstanceKind::Virtual(..));
+        let is_tls_shim_call = matches!(instance.def, ty::InstanceKind::ThreadLocalShim(_));
         (
             instance.def.requires_caller_location(tcx).then(|| tcx.caller_location_ty()),
-            if is_virtual_call { None } else { Some(instance.def_id()) },
+            if is_virtual_call || is_tls_shim_call { None } else { Some(instance.def_id()) },
             is_virtual_call,
         )
     } else {
@@ -530,17 +534,7 @@ fn fn_abi_new_uncached<'tcx>(
         };
 
         let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
-            let mut attrs = ArgAttributes::new();
-            adjust_for_rust_scalar(
-                *cx,
-                &mut attrs,
-                scalar,
-                *layout,
-                offset,
-                is_return,
-                drop_target_pointee,
-            );
-            attrs
+            arg_attrs_for_rust_scalar(*cx, scalar, *layout, offset, is_return, drop_target_pointee)
         });
 
         if arg.layout.is_zst() {
@@ -563,6 +557,7 @@ fn fn_abi_new_uncached<'tcx>(
         c_variadic: sig.c_variadic,
         fixed_count: inputs.len() as u32,
         conv,
+        // FIXME return false for tls shim
         can_unwind: fn_can_unwind(
             tcx,
             // Since `#[rustc_nounwind]` can change unwinding, we cannot infer unwinding by `fn_def_id` for a virtual call.
@@ -575,8 +570,9 @@ fn fn_abi_new_uncached<'tcx>(
         &mut fn_abi,
         sig.abi,
         // If this is a virtual call, we cannot pass the `fn_def_id`, as it might call other
-        // functions from vtable. Internally, `deduced_param_attrs` attempts to infer attributes by
-        // visit the function body.
+        // functions from vtable. And for a tls shim, passing the `fn_def_id` would refer to
+        // the underlying static. Internally, `deduced_param_attrs` attempts to infer attributes
+        // by visit the function body.
         determined_fn_def_id,
     );
     debug!("fn_abi_new_uncached = {:?}", fn_abi);
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 189afa32852..10d48526fd2 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -15,13 +15,12 @@ use crate::lift::Lift;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
 use crate::{self as ty, Interner};
 
-/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
+/// `Binder` is a binder for higher-ranked lifetimes or types. It is part of the
 /// compiler's representation for things like `for<'a> Fn(&'a isize)`
-/// (which would be represented by the type `PolyTraitRef ==
-/// Binder<I, TraitRef>`). Note that when we instantiate,
-/// erase, or otherwise "discharge" these bound vars, we change the
-/// type from `Binder<I, T>` to just `T` (see
-/// e.g., `liberate_late_bound_regions`).
+/// (which would be represented by the type `PolyTraitRef == Binder<I, TraitRef>`).
+///
+/// See <https://rustc-dev-guide.rust-lang.org/ty_module/instantiating_binders.html>
+/// for more details.
 ///
 /// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
 #[derive_where(Clone; I: Interner, T: Clone)]
@@ -154,22 +153,19 @@ impl<I: Interner, T: TypeVisitable<I>> TypeSuperVisitable<I> for Binder<I, T> {
 }
 
 impl<I: Interner, T> Binder<I, T> {
-    /// Skips the binder and returns the "bound" value. This is a
-    /// risky thing to do because it's easy to get confused about
-    /// De Bruijn indices and the like. It is usually better to
-    /// discharge the binder using `no_bound_vars` or
-    /// `instantiate_bound_regions` or something like
-    /// that. `skip_binder` is only valid when you are either
-    /// extracting data that has nothing to do with bound vars, you
-    /// are doing some sort of test that does not involve bound
-    /// regions, or you are being very careful about your depth
-    /// accounting.
+    /// Returns the value contained inside of this `for<'a>`. Accessing generic args
+    /// in the returned value is generally incorrect.
+    ///
+    /// Please read <https://rustc-dev-guide.rust-lang.org/ty_module/instantiating_binders.html>
+    /// before using this function. It is usually better to discharge the binder using
+    /// `no_bound_vars` or `instantiate_bound_regions` or something like that.
     ///
-    /// Some examples where `skip_binder` is reasonable:
+    /// `skip_binder` is only valid when you are either extracting data that does not reference
+    /// any generic arguments, e.g. a `DefId`, or when you're making sure you only pass the
+    /// value to things which can handle escaping bound vars.
     ///
-    /// - extracting the `DefId` from a PolyTraitRef;
-    /// - comparing the self type of a PolyTraitRef to see if it is equal to
-    ///   a type parameter `X`, since the type `X` does not reference any regions
+    /// See existing uses of `.skip_binder()` in `rustc_trait_selection::traits::select`
+    /// or `rustc_next_trait_solver` for examples.
     pub fn skip_binder(self) -> T {
         self.value
     }
@@ -355,12 +351,11 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
     }
 }
 
-/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
+/// Similar to [`Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
 /// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call
 /// `instantiate`.
 ///
-/// If you don't have anything to `instantiate`, you may be looking for
-/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder).
+/// See <https://rustc-dev-guide.rust-lang.org/ty_module/early_binder.html> for more details.
 #[derive_where(Clone; I: Interner, T: Clone)]
 #[derive_where(Copy; I: Interner, T: Copy)]
 #[derive_where(PartialEq; I: Interner, T: PartialEq)]
@@ -423,17 +418,22 @@ impl<I: Interner, T> EarlyBinder<I, T> {
         EarlyBinder { value, _tcx: PhantomData }
     }
 
-    /// Skips the binder and returns the "bound" value.
-    /// This can be used to extract data that does not depend on generic parameters
-    /// (e.g., getting the `DefId` of the inner value or getting the number of
-    /// arguments of an `FnSig`). Otherwise, consider using
-    /// [`instantiate_identity`](EarlyBinder::instantiate_identity).
+    /// Skips the binder and returns the "bound" value. Accessing generic args
+    /// in the returned value is generally incorrect.
+    ///
+    /// Please read <https://rustc-dev-guide.rust-lang.org/ty_module/early_binder.html>
+    /// before using this function.
+    ///
+    /// Only use this to extract data that does not depend on generic parameters, e.g.
+    /// to get the `DefId` of the inner value or the number of arguments ofan `FnSig`,
+    /// or while making sure to only pass the value to functions which are explicitly
+    /// set up to handle these uninstantiated generic parameters.
     ///
     /// To skip the binder on `x: &EarlyBinder<I, T>` to obtain `&T`, leverage
     /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`.
     ///
-    /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
-    /// the analogous operation on [`super::Binder`].
+    /// See also [`Binder::skip_binder`](Binder::skip_binder), which is
+    /// the analogous operation on [`Binder`].
     pub fn skip_binder(self) -> T {
         self.value
     }
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index c66a83662d7..0cb8d8902c6 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -199,7 +199,6 @@ impl<I: Interner> CanonicalVarKind<I> {
 /// usize or f32). In order to faithfully reproduce a type, we need to
 /// know what set of types a given type variable can be unified with.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(
     feature = "nightly",
     derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 4be38d4e702..70a8509b513 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -92,15 +92,10 @@ rustc_index::newtype_index! {
 
 /// An inference variable for a const, for use in const generics.
 #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
-#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext))]
 pub enum InferConst {
     /// Infer the value of the const.
-    Var(
-        #[type_foldable(identity)]
-        #[type_visitable(ignore)]
-        ConstVid,
-    ),
+    Var(ConstVid),
     /// A fresh const variable. See `infer::freshen` for more details.
     Fresh(u32),
 }
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index b4873c8c71c..e6462a97f8a 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -1,7 +1,6 @@
 use derive_where::derive_where;
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
-use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
 
 use crate::fold::TypeFoldable;
 use crate::inherent::*;
@@ -20,7 +19,6 @@ use crate::{self as ty, Interner};
 /// If neither of these functions are available, feel free to reach out to
 /// t-types for help.
 #[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
-#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
 #[cfg_attr(
     feature = "nightly",
     derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index b0752a85faf..7ee0962721f 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -920,7 +920,11 @@ impl char {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_alphanumeric(self) -> bool {
-        self.is_alphabetic() || self.is_numeric()
+        if self.is_ascii() {
+            self.is_ascii_alphanumeric()
+        } else {
+            unicode::Alphabetic(self) || unicode::N(self)
+        }
     }
 
     /// Returns `true` if this `char` has the general category for control codes.
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 05b0522c202..7228ad0ed6d 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -150,69 +150,63 @@ pub unsafe fn atomic_xchg<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src:
 
 /// Adds to the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_add` method. For example, [`AtomicIsize::fetch_add`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xadd<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_xadd<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Subtract from the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_sub` method. For example, [`AtomicIsize::fetch_sub`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xsub<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_xsub<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Bitwise and with the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_and` method. For example, [`AtomicBool::fetch_and`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_and<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_and<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Bitwise nand with the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`AtomicBool`] type via the `fetch_nand` method. For example, [`AtomicBool::fetch_nand`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_nand<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_nand<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Bitwise or with the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_or` method. For example, [`AtomicBool::fetch_or`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_or<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_or<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Bitwise xor with the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_xor` method. For example, [`AtomicBool::fetch_xor`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xor<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_xor<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Maximum with the current value using a signed comparison.
 /// `T` must be a signed integer type.
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 70c02ead358..44a6895f90a 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -2293,7 +2293,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_add(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_add(self.p.get(), val, order).cast() }
     }
 
     /// Offsets the pointer's address by subtracting `val` *bytes*, returning the
@@ -2318,9 +2318,10 @@ impl<T> AtomicPtr<T> {
     /// #![feature(strict_provenance_atomic_ptr)]
     /// use core::sync::atomic::{AtomicPtr, Ordering};
     ///
-    /// let atom = AtomicPtr::<i64>::new(core::ptr::without_provenance_mut(1));
-    /// assert_eq!(atom.fetch_byte_sub(1, Ordering::Relaxed).addr(), 1);
-    /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 0);
+    /// let mut arr = [0i64, 1];
+    /// let atom = AtomicPtr::<i64>::new(&raw mut arr[1]);
+    /// assert_eq!(atom.fetch_byte_sub(8, Ordering::Relaxed).addr(), (&raw const arr[1]).addr());
+    /// assert_eq!(atom.load(Ordering::Relaxed).addr(), (&raw const arr[0]).addr());
     /// ```
     #[inline]
     #[cfg(target_has_atomic = "ptr")]
@@ -2328,7 +2329,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_sub(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_sub(self.p.get(), val, order).cast() }
     }
 
     /// Performs a bitwise "or" operation on the address of the current pointer,
@@ -2379,7 +2380,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_or(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_or(self.p.get(), val, order).cast() }
     }
 
     /// Performs a bitwise "and" operation on the address of the current
@@ -2429,7 +2430,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_and(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_and(self.p.get(), val, order).cast() }
     }
 
     /// Performs a bitwise "xor" operation on the address of the current
@@ -2477,7 +2478,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_xor(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_xor(self.p.get(), val, order).cast() }
     }
 
     /// Returns a mutable pointer to the underlying pointer.
@@ -3981,15 +3982,15 @@ unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_add<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_add`.
     unsafe {
         match order {
-            Relaxed => intrinsics::atomic_xadd::<T, { AO::Relaxed }>(dst, val),
-            Acquire => intrinsics::atomic_xadd::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_xadd::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_xadd::<T, { AO::AcqRel }>(dst, val),
-            SeqCst => intrinsics::atomic_xadd::<T, { AO::SeqCst }>(dst, val),
+            Relaxed => intrinsics::atomic_xadd::<T, U, { AO::Relaxed }>(dst, val),
+            Acquire => intrinsics::atomic_xadd::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_xadd::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_xadd::<T, U, { AO::AcqRel }>(dst, val),
+            SeqCst => intrinsics::atomic_xadd::<T, U, { AO::SeqCst }>(dst, val),
         }
     }
 }
@@ -3998,15 +3999,15 @@ unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_sub<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_sub`.
     unsafe {
         match order {
-            Relaxed => intrinsics::atomic_xsub::<T, { AO::Relaxed }>(dst, val),
-            Acquire => intrinsics::atomic_xsub::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_xsub::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_xsub::<T, { AO::AcqRel }>(dst, val),
-            SeqCst => intrinsics::atomic_xsub::<T, { AO::SeqCst }>(dst, val),
+            Relaxed => intrinsics::atomic_xsub::<T, U, { AO::Relaxed }>(dst, val),
+            Acquire => intrinsics::atomic_xsub::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_xsub::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_xsub::<T, U, { AO::AcqRel }>(dst, val),
+            SeqCst => intrinsics::atomic_xsub::<T, U, { AO::SeqCst }>(dst, val),
         }
     }
 }
@@ -4147,15 +4148,15 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>(
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_and<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_and`
     unsafe {
         match order {
-            Relaxed => intrinsics::atomic_and::<T, { AO::Relaxed }>(dst, val),
-            Acquire => intrinsics::atomic_and::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_and::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_and::<T, { AO::AcqRel }>(dst, val),
-            SeqCst => intrinsics::atomic_and::<T, { AO::SeqCst }>(dst, val),
+            Relaxed => intrinsics::atomic_and::<T, U, { AO::Relaxed }>(dst, val),
+            Acquire => intrinsics::atomic_and::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_and::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_and::<T, U, { AO::AcqRel }>(dst, val),
+            SeqCst => intrinsics::atomic_and::<T, U, { AO::SeqCst }>(dst, val),
         }
     }
 }
@@ -4163,15 +4164,15 @@ unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_nand<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_nand`
     unsafe {
         match order {
-            Relaxed => intrinsics::atomic_nand::<T, { AO::Relaxed }>(dst, val),
-            Acquire => intrinsics::atomic_nand::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_nand::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_nand::<T, { AO::AcqRel }>(dst, val),
-            SeqCst => intrinsics::atomic_nand::<T, { AO::SeqCst }>(dst, val),
+            Relaxed => intrinsics::atomic_nand::<T, U, { AO::Relaxed }>(dst, val),
+            Acquire => intrinsics::atomic_nand::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_nand::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_nand::<T, U, { AO::AcqRel }>(dst, val),
+            SeqCst => intrinsics::atomic_nand::<T, U, { AO::SeqCst }>(dst, val),
         }
     }
 }
@@ -4179,15 +4180,15 @@ unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_or<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_or`
     unsafe {
         match order {
-            SeqCst => intrinsics::atomic_or::<T, { AO::SeqCst }>(dst, val),
-            Acquire => intrinsics::atomic_or::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_or::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_or::<T, { AO::AcqRel }>(dst, val),
-            Relaxed => intrinsics::atomic_or::<T, { AO::Relaxed }>(dst, val),
+            SeqCst => intrinsics::atomic_or::<T, U, { AO::SeqCst }>(dst, val),
+            Acquire => intrinsics::atomic_or::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_or::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_or::<T, U, { AO::AcqRel }>(dst, val),
+            Relaxed => intrinsics::atomic_or::<T, U, { AO::Relaxed }>(dst, val),
         }
     }
 }
@@ -4195,15 +4196,15 @@ unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_xor<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_xor`
     unsafe {
         match order {
-            SeqCst => intrinsics::atomic_xor::<T, { AO::SeqCst }>(dst, val),
-            Acquire => intrinsics::atomic_xor::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_xor::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_xor::<T, { AO::AcqRel }>(dst, val),
-            Relaxed => intrinsics::atomic_xor::<T, { AO::Relaxed }>(dst, val),
+            SeqCst => intrinsics::atomic_xor::<T, U, { AO::SeqCst }>(dst, val),
+            Acquire => intrinsics::atomic_xor::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_xor::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_xor::<T, U, { AO::AcqRel }>(dst, val),
+            Relaxed => intrinsics::atomic_xor::<T, U, { AO::Relaxed }>(dst, val),
         }
     }
 }
diff --git a/library/coretests/tests/floats/f128.rs b/library/coretests/tests/floats/f128.rs
index 36d6a20a944..ac4a2066530 100644
--- a/library/coretests/tests/floats/f128.rs
+++ b/library/coretests/tests/floats/f128.rs
@@ -15,21 +15,6 @@ const TOL: f128 = 1e-12;
 /// signs.
 const TOL_PRECISE: f128 = 1e-28;
 
-/// Smallest number
-const TINY_BITS: u128 = 0x1;
-
-/// Next smallest number
-const TINY_UP_BITS: u128 = 0x2;
-
-/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
-const MAX_DOWN_BITS: u128 = 0x7ffefffffffffffffffffffffffffffe;
-
-/// Zeroed exponent, full significant
-const LARGEST_SUBNORMAL_BITS: u128 = 0x0000ffffffffffffffffffffffffffff;
-
-/// Exponent = 0b1, zeroed significand
-const SMALLEST_NORMAL_BITS: u128 = 0x00010000000000000000000000000000;
-
 /// First pattern over the mantissa
 const NAN_MASK1: u128 = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
 
@@ -40,106 +25,6 @@ const NAN_MASK2: u128 = 0x00005555555555555555555555555555;
 // the intrinsics.
 
 #[test]
-#[cfg(any(miri, target_has_reliable_f128_math))]
-fn test_abs() {
-    assert_biteq!(f128::INFINITY.abs(), f128::INFINITY);
-    assert_biteq!(1f128.abs(), 1f128);
-    assert_biteq!(0f128.abs(), 0f128);
-    assert_biteq!((-0f128).abs(), 0f128);
-    assert_biteq!((-1f128).abs(), 1f128);
-    assert_biteq!(f128::NEG_INFINITY.abs(), f128::INFINITY);
-    assert_biteq!((1f128 / f128::NEG_INFINITY).abs(), 0f128);
-    assert!(f128::NAN.abs().is_nan());
-}
-
-#[test]
-fn test_is_sign_positive() {
-    assert!(f128::INFINITY.is_sign_positive());
-    assert!(1f128.is_sign_positive());
-    assert!(0f128.is_sign_positive());
-    assert!(!(-0f128).is_sign_positive());
-    assert!(!(-1f128).is_sign_positive());
-    assert!(!f128::NEG_INFINITY.is_sign_positive());
-    assert!(!(1f128 / f128::NEG_INFINITY).is_sign_positive());
-    assert!(f128::NAN.is_sign_positive());
-    assert!(!(-f128::NAN).is_sign_positive());
-}
-
-#[test]
-fn test_is_sign_negative() {
-    assert!(!f128::INFINITY.is_sign_negative());
-    assert!(!1f128.is_sign_negative());
-    assert!(!0f128.is_sign_negative());
-    assert!((-0f128).is_sign_negative());
-    assert!((-1f128).is_sign_negative());
-    assert!(f128::NEG_INFINITY.is_sign_negative());
-    assert!((1f128 / f128::NEG_INFINITY).is_sign_negative());
-    assert!(!f128::NAN.is_sign_negative());
-    assert!((-f128::NAN).is_sign_negative());
-}
-
-#[test]
-fn test_next_up() {
-    let tiny = f128::from_bits(TINY_BITS);
-    let tiny_up = f128::from_bits(TINY_UP_BITS);
-    let max_down = f128::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
-    assert_biteq!(f128::NEG_INFINITY.next_up(), f128::MIN);
-    assert_biteq!(f128::MIN.next_up(), -max_down);
-    assert_biteq!((-1.0 - f128::EPSILON).next_up(), -1.0f128);
-    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_biteq!((-tiny_up).next_up(), -tiny);
-    assert_biteq!((-tiny).next_up(), -0.0f128);
-    assert_biteq!((-0.0f128).next_up(), tiny);
-    assert_biteq!(0.0f128.next_up(), tiny);
-    assert_biteq!(tiny.next_up(), tiny_up);
-    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_biteq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
-    assert_biteq!(f128::MAX.next_up(), f128::INFINITY);
-    assert_biteq!(f128::INFINITY.next_up(), f128::INFINITY);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f128::NAN;
-    let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
-    let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
-    assert_biteq!(nan0.next_up(), nan0);
-    assert_biteq!(nan1.next_up(), nan1);
-    assert_biteq!(nan2.next_up(), nan2);
-}
-
-#[test]
-fn test_next_down() {
-    let tiny = f128::from_bits(TINY_BITS);
-    let tiny_up = f128::from_bits(TINY_UP_BITS);
-    let max_down = f128::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f128::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f128::from_bits(SMALLEST_NORMAL_BITS);
-    assert_biteq!(f128::NEG_INFINITY.next_down(), f128::NEG_INFINITY);
-    assert_biteq!(f128::MIN.next_down(), f128::NEG_INFINITY);
-    assert_biteq!((-max_down).next_down(), f128::MIN);
-    assert_biteq!((-1.0f128).next_down(), -1.0 - f128::EPSILON);
-    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_biteq!((-tiny).next_down(), -tiny_up);
-    assert_biteq!((-0.0f128).next_down(), -tiny);
-    assert_biteq!((0.0f128).next_down(), -tiny);
-    assert_biteq!(tiny.next_down(), 0.0f128);
-    assert_biteq!(tiny_up.next_down(), tiny);
-    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_biteq!((1.0 + f128::EPSILON).next_down(), 1.0f128);
-    assert_biteq!(f128::MAX.next_down(), max_down);
-    assert_biteq!(f128::INFINITY.next_down(), f128::MAX);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f128::NAN;
-    let nan1 = f128::from_bits(f128::NAN.to_bits() ^ 0x002a_aaaa);
-    let nan2 = f128::from_bits(f128::NAN.to_bits() ^ 0x0055_5555);
-    assert_biteq!(nan0.next_down(), nan0);
-    assert_biteq!(nan1.next_down(), nan1);
-    assert_biteq!(nan2.next_down(), nan2);
-}
-
-#[test]
 #[cfg(not(miri))]
 #[cfg(target_has_reliable_f128_math)]
 fn test_mul_add() {
@@ -194,19 +79,6 @@ fn test_powi() {
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f128_math)]
-fn test_sqrt_domain() {
-    assert!(f128::NAN.sqrt().is_nan());
-    assert!(f128::NEG_INFINITY.sqrt().is_nan());
-    assert!((-1.0f128).sqrt().is_nan());
-    assert_biteq!((-0.0f128).sqrt(), -0.0);
-    assert_biteq!(0.0f128.sqrt(), 0.0);
-    assert_biteq!(1.0f128.sqrt(), 1.0);
-    assert_biteq!(f128::INFINITY.sqrt(), f128::INFINITY);
-}
-
-#[test]
 fn test_to_degrees() {
     let pi: f128 = consts::PI;
     let nan: f128 = f128::NAN;
@@ -261,168 +133,6 @@ fn test_float_bits_conv() {
 }
 
 #[test]
-#[should_panic]
-fn test_clamp_min_greater_than_max() {
-    let _ = 1.0f128.clamp(3.0, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_is_nan() {
-    let _ = 1.0f128.clamp(f128::NAN, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_max_is_nan() {
-    let _ = 1.0f128.clamp(3.0, f128::NAN);
-}
-
-#[test]
-fn test_total_cmp() {
-    use core::cmp::Ordering;
-
-    fn quiet_bit_mask() -> u128 {
-        1 << (f128::MANTISSA_DIGITS - 2)
-    }
-
-    // FIXME(f16_f128): test subnormals when powf is available
-    // fn min_subnorm() -> f128 {
-    //     f128::MIN_POSITIVE / f128::powf(2.0, f128::MANTISSA_DIGITS as f128 - 1.0)
-    // }
-
-    // fn max_subnorm() -> f128 {
-    //     f128::MIN_POSITIVE - min_subnorm()
-    // }
-
-    fn q_nan() -> f128 {
-        f128::from_bits(f128::NAN.to_bits() | quiet_bit_mask())
-    }
-
-    fn s_nan() -> f128 {
-        f128::from_bits((f128::NAN.to_bits() & !quiet_bit_mask()) + 42)
-    }
-
-    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Equal, (-f128::INFINITY).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Equal, (-f128::MAX).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Equal, (-2.5_f128).total_cmp(&-2.5));
-    assert_eq!(Ordering::Equal, (-1.0_f128).total_cmp(&-1.0));
-    assert_eq!(Ordering::Equal, (-1.5_f128).total_cmp(&-1.5));
-    assert_eq!(Ordering::Equal, (-0.5_f128).total_cmp(&-0.5));
-    assert_eq!(Ordering::Equal, (-f128::MIN_POSITIVE).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Equal, (-0.0_f128).total_cmp(&-0.0));
-    assert_eq!(Ordering::Equal, 0.0_f128.total_cmp(&0.0));
-    // assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Equal, f128::MIN_POSITIVE.total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, 0.5_f128.total_cmp(&0.5));
-    assert_eq!(Ordering::Equal, 1.0_f128.total_cmp(&1.0));
-    assert_eq!(Ordering::Equal, 1.5_f128.total_cmp(&1.5));
-    assert_eq!(Ordering::Equal, 2.5_f128.total_cmp(&2.5));
-    assert_eq!(Ordering::Equal, f128::MAX.total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Equal, f128::INFINITY.total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
-    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Less, (-f128::INFINITY).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Less, (-f128::MAX).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-2.5_f128).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-1.5_f128).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-1.0_f128).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-0.5_f128).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-f128::MIN_POSITIVE).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
-    // assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-0.0_f128).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, 0.0_f128.total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
-    // assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, f128::MIN_POSITIVE.total_cmp(&0.5));
-    assert_eq!(Ordering::Less, 0.5_f128.total_cmp(&1.0));
-    assert_eq!(Ordering::Less, 1.0_f128.total_cmp(&1.5));
-    assert_eq!(Ordering::Less, 1.5_f128.total_cmp(&2.5));
-    assert_eq!(Ordering::Less, 2.5_f128.total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Less, f128::MAX.total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Less, f128::INFINITY.total_cmp(&s_nan()));
-    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Greater, (-f128::INFINITY).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Greater, (-f128::MAX).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Greater, (-2.5_f128).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Greater, (-1.5_f128).total_cmp(&-2.5));
-    assert_eq!(Ordering::Greater, (-1.0_f128).total_cmp(&-1.5));
-    assert_eq!(Ordering::Greater, (-0.5_f128).total_cmp(&-1.0));
-    assert_eq!(Ordering::Greater, (-f128::MIN_POSITIVE).total_cmp(&-0.5));
-    // assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Greater, (-0.0_f128).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Greater, 0.0_f128.total_cmp(&-0.0));
-    // assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
-    // assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Greater, f128::MIN_POSITIVE.total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Greater, 0.5_f128.total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, 1.0_f128.total_cmp(&0.5));
-    assert_eq!(Ordering::Greater, 1.5_f128.total_cmp(&1.0));
-    assert_eq!(Ordering::Greater, 2.5_f128.total_cmp(&1.5));
-    assert_eq!(Ordering::Greater, f128::MAX.total_cmp(&2.5));
-    assert_eq!(Ordering::Greater, f128::INFINITY.total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f128::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f128::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
-}
-
-#[test]
 fn test_algebraic() {
     let a: f128 = 123.0;
     let b: f128 = 456.0;
diff --git a/library/coretests/tests/floats/f16.rs b/library/coretests/tests/floats/f16.rs
index 351c008a37b..bb9c8a002fe 100644
--- a/library/coretests/tests/floats/f16.rs
+++ b/library/coretests/tests/floats/f16.rs
@@ -21,21 +21,6 @@ const TOL_P2: f16 = 0.5;
 #[allow(unused)]
 const TOL_P4: f16 = 10.0;
 
-/// Smallest number
-const TINY_BITS: u16 = 0x1;
-
-/// Next smallest number
-const TINY_UP_BITS: u16 = 0x2;
-
-/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
-const MAX_DOWN_BITS: u16 = 0x7bfe;
-
-/// Zeroed exponent, full significant
-const LARGEST_SUBNORMAL_BITS: u16 = 0x03ff;
-
-/// Exponent = 0b1, zeroed significand
-const SMALLEST_NORMAL_BITS: u16 = 0x0400;
-
 /// First pattern over the mantissa
 const NAN_MASK1: u16 = 0x02aa;
 
@@ -46,106 +31,6 @@ const NAN_MASK2: u16 = 0x0155;
 // the intrinsics.
 
 #[test]
-#[cfg(any(miri, target_has_reliable_f16_math))]
-fn test_abs() {
-    assert_biteq!(f16::INFINITY.abs(), f16::INFINITY);
-    assert_biteq!(1f16.abs(), 1f16);
-    assert_biteq!(0f16.abs(), 0f16);
-    assert_biteq!((-0f16).abs(), 0f16);
-    assert_biteq!((-1f16).abs(), 1f16);
-    assert_biteq!(f16::NEG_INFINITY.abs(), f16::INFINITY);
-    assert_biteq!((1f16 / f16::NEG_INFINITY).abs(), 0f16);
-    assert!(f16::NAN.abs().is_nan());
-}
-
-#[test]
-fn test_is_sign_positive() {
-    assert!(f16::INFINITY.is_sign_positive());
-    assert!(1f16.is_sign_positive());
-    assert!(0f16.is_sign_positive());
-    assert!(!(-0f16).is_sign_positive());
-    assert!(!(-1f16).is_sign_positive());
-    assert!(!f16::NEG_INFINITY.is_sign_positive());
-    assert!(!(1f16 / f16::NEG_INFINITY).is_sign_positive());
-    assert!(f16::NAN.is_sign_positive());
-    assert!(!(-f16::NAN).is_sign_positive());
-}
-
-#[test]
-fn test_is_sign_negative() {
-    assert!(!f16::INFINITY.is_sign_negative());
-    assert!(!1f16.is_sign_negative());
-    assert!(!0f16.is_sign_negative());
-    assert!((-0f16).is_sign_negative());
-    assert!((-1f16).is_sign_negative());
-    assert!(f16::NEG_INFINITY.is_sign_negative());
-    assert!((1f16 / f16::NEG_INFINITY).is_sign_negative());
-    assert!(!f16::NAN.is_sign_negative());
-    assert!((-f16::NAN).is_sign_negative());
-}
-
-#[test]
-fn test_next_up() {
-    let tiny = f16::from_bits(TINY_BITS);
-    let tiny_up = f16::from_bits(TINY_UP_BITS);
-    let max_down = f16::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
-    assert_biteq!(f16::NEG_INFINITY.next_up(), f16::MIN);
-    assert_biteq!(f16::MIN.next_up(), -max_down);
-    assert_biteq!((-1.0 - f16::EPSILON).next_up(), -1.0f16);
-    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_biteq!((-tiny_up).next_up(), -tiny);
-    assert_biteq!((-tiny).next_up(), -0.0f16);
-    assert_biteq!((-0.0f16).next_up(), tiny);
-    assert_biteq!(0.0f16.next_up(), tiny);
-    assert_biteq!(tiny.next_up(), tiny_up);
-    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_biteq!(1.0f16.next_up(), 1.0 + f16::EPSILON);
-    assert_biteq!(f16::MAX.next_up(), f16::INFINITY);
-    assert_biteq!(f16::INFINITY.next_up(), f16::INFINITY);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f16::NAN;
-    let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
-    assert_biteq!(nan0.next_up(), nan0);
-    assert_biteq!(nan1.next_up(), nan1);
-    assert_biteq!(nan2.next_up(), nan2);
-}
-
-#[test]
-fn test_next_down() {
-    let tiny = f16::from_bits(TINY_BITS);
-    let tiny_up = f16::from_bits(TINY_UP_BITS);
-    let max_down = f16::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f16::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f16::from_bits(SMALLEST_NORMAL_BITS);
-    assert_biteq!(f16::NEG_INFINITY.next_down(), f16::NEG_INFINITY);
-    assert_biteq!(f16::MIN.next_down(), f16::NEG_INFINITY);
-    assert_biteq!((-max_down).next_down(), f16::MIN);
-    assert_biteq!((-1.0f16).next_down(), -1.0 - f16::EPSILON);
-    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_biteq!((-tiny).next_down(), -tiny_up);
-    assert_biteq!((-0.0f16).next_down(), -tiny);
-    assert_biteq!((0.0f16).next_down(), -tiny);
-    assert_biteq!(tiny.next_down(), 0.0f16);
-    assert_biteq!(tiny_up.next_down(), tiny);
-    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_biteq!((1.0 + f16::EPSILON).next_down(), 1.0f16);
-    assert_biteq!(f16::MAX.next_down(), max_down);
-    assert_biteq!(f16::INFINITY.next_down(), f16::MAX);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f16::NAN;
-    let nan1 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f16::from_bits(f16::NAN.to_bits() ^ NAN_MASK2);
-    assert_biteq!(nan0.next_down(), nan0);
-    assert_biteq!(nan1.next_down(), nan1);
-    assert_biteq!(nan2.next_down(), nan2);
-}
-
-#[test]
 #[cfg(not(miri))]
 #[cfg(target_has_reliable_f16_math)]
 fn test_mul_add() {
@@ -196,19 +81,6 @@ fn test_powi() {
 }
 
 #[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_sqrt_domain() {
-    assert!(f16::NAN.sqrt().is_nan());
-    assert!(f16::NEG_INFINITY.sqrt().is_nan());
-    assert!((-1.0f16).sqrt().is_nan());
-    assert_biteq!((-0.0f16).sqrt(), -0.0);
-    assert_biteq!(0.0f16.sqrt(), 0.0);
-    assert_biteq!(1.0f16.sqrt(), 1.0);
-    assert_biteq!(f16::INFINITY.sqrt(), f16::INFINITY);
-}
-
-#[test]
 fn test_to_degrees() {
     let pi: f16 = consts::PI;
     let nan: f16 = f16::NAN;
@@ -260,172 +132,6 @@ fn test_float_bits_conv() {
 }
 
 #[test]
-#[should_panic]
-fn test_clamp_min_greater_than_max() {
-    let _ = 1.0f16.clamp(3.0, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_is_nan() {
-    let _ = 1.0f16.clamp(f16::NAN, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_max_is_nan() {
-    let _ = 1.0f16.clamp(3.0, f16::NAN);
-}
-
-#[test]
-#[cfg(not(miri))]
-#[cfg(target_has_reliable_f16_math)]
-fn test_total_cmp() {
-    use core::cmp::Ordering;
-
-    fn quiet_bit_mask() -> u16 {
-        1 << (f16::MANTISSA_DIGITS - 2)
-    }
-
-    fn min_subnorm() -> f16 {
-        f16::MIN_POSITIVE / f16::powf(2.0, f16::MANTISSA_DIGITS as f16 - 1.0)
-    }
-
-    fn max_subnorm() -> f16 {
-        f16::MIN_POSITIVE - min_subnorm()
-    }
-
-    fn q_nan() -> f16 {
-        f16::from_bits(f16::NAN.to_bits() | quiet_bit_mask())
-    }
-
-    // FIXME(f16_f128): Tests involving sNaN are disabled because without optimizations,
-    // `total_cmp` is getting incorrectly lowered to code that includes a `extend`/`trunc` round
-    // trip, which quiets sNaNs. See: https://github.com/llvm/llvm-project/issues/104915
-    // fn s_nan() -> f16 {
-    //     f16::from_bits((f16::NAN.to_bits() & !quiet_bit_mask()) + 42)
-    // }
-
-    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
-    // assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Equal, (-f16::INFINITY).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Equal, (-f16::MAX).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Equal, (-2.5_f16).total_cmp(&-2.5));
-    assert_eq!(Ordering::Equal, (-1.0_f16).total_cmp(&-1.0));
-    assert_eq!(Ordering::Equal, (-1.5_f16).total_cmp(&-1.5));
-    assert_eq!(Ordering::Equal, (-0.5_f16).total_cmp(&-0.5));
-    assert_eq!(Ordering::Equal, (-f16::MIN_POSITIVE).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Equal, (-0.0_f16).total_cmp(&-0.0));
-    assert_eq!(Ordering::Equal, 0.0_f16.total_cmp(&0.0));
-    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Equal, f16::MIN_POSITIVE.total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, 0.5_f16.total_cmp(&0.5));
-    assert_eq!(Ordering::Equal, 1.0_f16.total_cmp(&1.0));
-    assert_eq!(Ordering::Equal, 1.5_f16.total_cmp(&1.5));
-    assert_eq!(Ordering::Equal, 2.5_f16.total_cmp(&2.5));
-    assert_eq!(Ordering::Equal, f16::MAX.total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Equal, f16::INFINITY.total_cmp(&f16::INFINITY));
-    // assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
-    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
-
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Less, (-f16::INFINITY).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Less, (-f16::MAX).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-2.5_f16).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-1.5_f16).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-1.0_f16).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-0.5_f16).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-f16::MIN_POSITIVE).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-0.0_f16).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, 0.0_f16.total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, f16::MIN_POSITIVE.total_cmp(&0.5));
-    assert_eq!(Ordering::Less, 0.5_f16.total_cmp(&1.0));
-    assert_eq!(Ordering::Less, 1.0_f16.total_cmp(&1.5));
-    assert_eq!(Ordering::Less, 1.5_f16.total_cmp(&2.5));
-    assert_eq!(Ordering::Less, 2.5_f16.total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Less, f16::MAX.total_cmp(&f16::INFINITY));
-    // assert_eq!(Ordering::Less, f16::INFINITY.total_cmp(&s_nan()));
-    // assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
-
-    // assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
-    // assert_eq!(Ordering::Greater, (-f16::INFINITY).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Greater, (-f16::MAX).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Greater, (-2.5_f16).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Greater, (-1.5_f16).total_cmp(&-2.5));
-    assert_eq!(Ordering::Greater, (-1.0_f16).total_cmp(&-1.5));
-    assert_eq!(Ordering::Greater, (-0.5_f16).total_cmp(&-1.0));
-    assert_eq!(Ordering::Greater, (-f16::MIN_POSITIVE).total_cmp(&-0.5));
-    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Greater, (-0.0_f16).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Greater, 0.0_f16.total_cmp(&-0.0));
-    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
-    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Greater, f16::MIN_POSITIVE.total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Greater, 0.5_f16.total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, 1.0_f16.total_cmp(&0.5));
-    assert_eq!(Ordering::Greater, 1.5_f16.total_cmp(&1.0));
-    assert_eq!(Ordering::Greater, 2.5_f16.total_cmp(&1.5));
-    assert_eq!(Ordering::Greater, f16::MAX.total_cmp(&2.5));
-    assert_eq!(Ordering::Greater, f16::INFINITY.total_cmp(&f16::MAX));
-    // assert_eq!(Ordering::Greater, s_nan().total_cmp(&f16::INFINITY));
-    // assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
-
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f16::INFINITY));
-    // assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
-
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::INFINITY));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MAX));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f16::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MIN_POSITIVE));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::MAX));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f16::INFINITY));
-    // assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
-}
-
-#[test]
 fn test_algebraic() {
     let a: f16 = 123.0;
     let b: f16 = 456.0;
diff --git a/library/coretests/tests/floats/f32.rs b/library/coretests/tests/floats/f32.rs
index 267b0e4e294..e77e44655dc 100644
--- a/library/coretests/tests/floats/f32.rs
+++ b/library/coretests/tests/floats/f32.rs
@@ -3,21 +3,6 @@ use core::f32::consts;
 
 use super::{assert_approx_eq, assert_biteq};
 
-/// Smallest number
-const TINY_BITS: u32 = 0x1;
-
-/// Next smallest number
-const TINY_UP_BITS: u32 = 0x2;
-
-/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
-const MAX_DOWN_BITS: u32 = 0x7f7f_fffe;
-
-/// Zeroed exponent, full significant
-const LARGEST_SUBNORMAL_BITS: u32 = 0x007f_ffff;
-
-/// Exponent = 0b1, zeroed significand
-const SMALLEST_NORMAL_BITS: u32 = 0x0080_0000;
-
 /// First pattern over the mantissa
 const NAN_MASK1: u32 = 0x002a_aaaa;
 
@@ -29,117 +14,6 @@ const NAN_MASK2: u32 = 0x0055_5555;
 /// They serve as a way to get an idea of the real precision of floating point operations on different platforms.
 const APPROX_DELTA: f32 = if cfg!(miri) { 1e-4 } else { 1e-6 };
 
-#[test]
-fn test_abs() {
-    assert_biteq!(f32::INFINITY.abs(), f32::INFINITY);
-    assert_biteq!(1f32.abs(), 1f32);
-    assert_biteq!(0f32.abs(), 0f32);
-    assert_biteq!((-0f32).abs(), 0f32);
-    assert_biteq!((-1f32).abs(), 1f32);
-    assert_biteq!(f32::NEG_INFINITY.abs(), f32::INFINITY);
-    assert_biteq!((1f32 / f32::NEG_INFINITY).abs(), 0f32);
-    assert!(f32::NAN.abs().is_nan());
-}
-
-#[test]
-fn test_signum() {
-    assert_biteq!(f32::INFINITY.signum(), 1f32);
-    assert_biteq!(1f32.signum(), 1f32);
-    assert_biteq!(0f32.signum(), 1f32);
-    assert_biteq!((-0f32).signum(), -1f32);
-    assert_biteq!((-1f32).signum(), -1f32);
-    assert_biteq!(f32::NEG_INFINITY.signum(), -1f32);
-    assert_biteq!((1f32 / f32::NEG_INFINITY).signum(), -1f32);
-    assert!(f32::NAN.signum().is_nan());
-}
-
-#[test]
-fn test_is_sign_positive() {
-    assert!(f32::INFINITY.is_sign_positive());
-    assert!(1f32.is_sign_positive());
-    assert!(0f32.is_sign_positive());
-    assert!(!(-0f32).is_sign_positive());
-    assert!(!(-1f32).is_sign_positive());
-    assert!(!f32::NEG_INFINITY.is_sign_positive());
-    assert!(!(1f32 / f32::NEG_INFINITY).is_sign_positive());
-    assert!(f32::NAN.is_sign_positive());
-    assert!(!(-f32::NAN).is_sign_positive());
-}
-
-#[test]
-fn test_is_sign_negative() {
-    assert!(!f32::INFINITY.is_sign_negative());
-    assert!(!1f32.is_sign_negative());
-    assert!(!0f32.is_sign_negative());
-    assert!((-0f32).is_sign_negative());
-    assert!((-1f32).is_sign_negative());
-    assert!(f32::NEG_INFINITY.is_sign_negative());
-    assert!((1f32 / f32::NEG_INFINITY).is_sign_negative());
-    assert!(!f32::NAN.is_sign_negative());
-    assert!((-f32::NAN).is_sign_negative());
-}
-
-#[test]
-fn test_next_up() {
-    let tiny = f32::from_bits(TINY_BITS);
-    let tiny_up = f32::from_bits(TINY_UP_BITS);
-    let max_down = f32::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
-    assert_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN);
-    assert_biteq!(f32::MIN.next_up(), -max_down);
-    assert_biteq!((-1.0f32 - f32::EPSILON).next_up(), -1.0f32);
-    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_biteq!((-tiny_up).next_up(), -tiny);
-    assert_biteq!((-tiny).next_up(), -0.0f32);
-    assert_biteq!((-0.0f32).next_up(), tiny);
-    assert_biteq!(0.0f32.next_up(), tiny);
-    assert_biteq!(tiny.next_up(), tiny_up);
-    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_biteq!(1.0f32.next_up(), 1.0 + f32::EPSILON);
-    assert_biteq!(f32::MAX.next_up(), f32::INFINITY);
-    assert_biteq!(f32::INFINITY.next_up(), f32::INFINITY);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f32::NAN;
-    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
-    assert_biteq!(nan0.next_up(), nan0);
-    assert_biteq!(nan1.next_up(), nan1);
-    assert_biteq!(nan2.next_up(), nan2);
-}
-
-#[test]
-fn test_next_down() {
-    let tiny = f32::from_bits(TINY_BITS);
-    let tiny_up = f32::from_bits(TINY_UP_BITS);
-    let max_down = f32::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
-    assert_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
-    assert_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY);
-    assert_biteq!((-max_down).next_down(), f32::MIN);
-    assert_biteq!((-1.0f32).next_down(), -1.0 - f32::EPSILON);
-    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_biteq!((-tiny).next_down(), -tiny_up);
-    assert_biteq!((-0.0f32).next_down(), -tiny);
-    assert_biteq!((0.0f32).next_down(), -tiny);
-    assert_biteq!(tiny.next_down(), 0.0f32);
-    assert_biteq!(tiny_up.next_down(), tiny);
-    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_biteq!((1.0 + f32::EPSILON).next_down(), 1.0f32);
-    assert_biteq!(f32::MAX.next_down(), max_down);
-    assert_biteq!(f32::INFINITY.next_down(), f32::MAX);
-
-    // Check that NaNs roundtrip.
-    let nan0 = f32::NAN;
-    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
-    assert_biteq!(nan0.next_down(), nan0);
-    assert_biteq!(nan1.next_down(), nan1);
-    assert_biteq!(nan2.next_down(), nan2);
-}
-
 // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
 #[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)]
 #[test]
@@ -187,17 +61,6 @@ fn test_powi() {
 }
 
 #[test]
-fn test_sqrt_domain() {
-    assert!(f32::NAN.sqrt().is_nan());
-    assert!(f32::NEG_INFINITY.sqrt().is_nan());
-    assert!((-1.0f32).sqrt().is_nan());
-    assert_biteq!((-0.0f32).sqrt(), -0.0);
-    assert_biteq!(0.0f32.sqrt(), 0.0);
-    assert_biteq!(1.0f32.sqrt(), 1.0);
-    assert_biteq!(f32::INFINITY.sqrt(), f32::INFINITY);
-}
-
-#[test]
 fn test_to_degrees() {
     let pi: f32 = consts::PI;
     let nan: f32 = f32::NAN;
@@ -250,167 +113,6 @@ fn test_float_bits_conv() {
 }
 
 #[test]
-#[should_panic]
-fn test_clamp_min_greater_than_max() {
-    let _ = 1.0f32.clamp(3.0, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_is_nan() {
-    let _ = 1.0f32.clamp(f32::NAN, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_max_is_nan() {
-    let _ = 1.0f32.clamp(3.0, f32::NAN);
-}
-
-#[test]
-fn test_total_cmp() {
-    use core::cmp::Ordering;
-
-    fn quiet_bit_mask() -> u32 {
-        1 << (f32::MANTISSA_DIGITS - 2)
-    }
-
-    fn min_subnorm() -> f32 {
-        f32::MIN_POSITIVE / f32::powf(2.0, f32::MANTISSA_DIGITS as f32 - 1.0)
-    }
-
-    fn max_subnorm() -> f32 {
-        f32::MIN_POSITIVE - min_subnorm()
-    }
-
-    fn q_nan() -> f32 {
-        f32::from_bits(f32::NAN.to_bits() | quiet_bit_mask())
-    }
-
-    fn s_nan() -> f32 {
-        f32::from_bits((f32::NAN.to_bits() & !quiet_bit_mask()) + 42)
-    }
-
-    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Equal, (-f32::INFINITY).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Equal, (-f32::MAX).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Equal, (-2.5_f32).total_cmp(&-2.5));
-    assert_eq!(Ordering::Equal, (-1.0_f32).total_cmp(&-1.0));
-    assert_eq!(Ordering::Equal, (-1.5_f32).total_cmp(&-1.5));
-    assert_eq!(Ordering::Equal, (-0.5_f32).total_cmp(&-0.5));
-    assert_eq!(Ordering::Equal, (-f32::MIN_POSITIVE).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Equal, (-0.0_f32).total_cmp(&-0.0));
-    assert_eq!(Ordering::Equal, 0.0_f32.total_cmp(&0.0));
-    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Equal, f32::MIN_POSITIVE.total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, 0.5_f32.total_cmp(&0.5));
-    assert_eq!(Ordering::Equal, 1.0_f32.total_cmp(&1.0));
-    assert_eq!(Ordering::Equal, 1.5_f32.total_cmp(&1.5));
-    assert_eq!(Ordering::Equal, 2.5_f32.total_cmp(&2.5));
-    assert_eq!(Ordering::Equal, f32::MAX.total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Equal, f32::INFINITY.total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
-    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Less, (-f32::INFINITY).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Less, (-f32::MAX).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-2.5_f32).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-1.5_f32).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-1.0_f32).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-0.5_f32).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-f32::MIN_POSITIVE).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-0.0_f32).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, 0.0_f32.total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, f32::MIN_POSITIVE.total_cmp(&0.5));
-    assert_eq!(Ordering::Less, 0.5_f32.total_cmp(&1.0));
-    assert_eq!(Ordering::Less, 1.0_f32.total_cmp(&1.5));
-    assert_eq!(Ordering::Less, 1.5_f32.total_cmp(&2.5));
-    assert_eq!(Ordering::Less, 2.5_f32.total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Less, f32::MAX.total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Less, f32::INFINITY.total_cmp(&s_nan()));
-    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Greater, (-f32::INFINITY).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Greater, (-f32::MAX).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Greater, (-2.5_f32).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Greater, (-1.5_f32).total_cmp(&-2.5));
-    assert_eq!(Ordering::Greater, (-1.0_f32).total_cmp(&-1.5));
-    assert_eq!(Ordering::Greater, (-0.5_f32).total_cmp(&-1.0));
-    assert_eq!(Ordering::Greater, (-f32::MIN_POSITIVE).total_cmp(&-0.5));
-    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Greater, (-0.0_f32).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Greater, 0.0_f32.total_cmp(&-0.0));
-    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
-    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Greater, f32::MIN_POSITIVE.total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Greater, 0.5_f32.total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, 1.0_f32.total_cmp(&0.5));
-    assert_eq!(Ordering::Greater, 1.5_f32.total_cmp(&1.0));
-    assert_eq!(Ordering::Greater, 2.5_f32.total_cmp(&1.5));
-    assert_eq!(Ordering::Greater, f32::MAX.total_cmp(&2.5));
-    assert_eq!(Ordering::Greater, f32::INFINITY.total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
-}
-
-#[test]
 fn test_algebraic() {
     let a: f32 = 123.0;
     let b: f32 = 456.0;
diff --git a/library/coretests/tests/floats/f64.rs b/library/coretests/tests/floats/f64.rs
index 735b7a76515..fea9cc19b39 100644
--- a/library/coretests/tests/floats/f64.rs
+++ b/library/coretests/tests/floats/f64.rs
@@ -3,136 +3,12 @@ use core::f64::consts;
 
 use super::{assert_approx_eq, assert_biteq};
 
-/// Smallest number
-const TINY_BITS: u64 = 0x1;
-
-/// Next smallest number
-const TINY_UP_BITS: u64 = 0x2;
-
-/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
-const MAX_DOWN_BITS: u64 = 0x7fef_ffff_ffff_fffe;
-
-/// Zeroed exponent, full significant
-const LARGEST_SUBNORMAL_BITS: u64 = 0x000f_ffff_ffff_ffff;
-
-/// Exponent = 0b1, zeroed significand
-const SMALLEST_NORMAL_BITS: u64 = 0x0010_0000_0000_0000;
-
 /// First pattern over the mantissa
 const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa;
 
 /// Second pattern over the mantissa
 const NAN_MASK2: u64 = 0x0005_5555_5555_5555;
 
-#[test]
-fn test_abs() {
-    assert_biteq!(f64::INFINITY.abs(), f64::INFINITY);
-    assert_biteq!(1f64.abs(), 1f64);
-    assert_biteq!(0f64.abs(), 0f64);
-    assert_biteq!((-0f64).abs(), 0f64);
-    assert_biteq!((-1f64).abs(), 1f64);
-    assert_biteq!(f64::NEG_INFINITY.abs(), f64::INFINITY);
-    assert_biteq!((1f64 / f64::NEG_INFINITY).abs(), 0f64);
-    assert!(f64::NAN.abs().is_nan());
-}
-
-#[test]
-fn test_signum() {
-    assert_biteq!(f64::INFINITY.signum(), 1f64);
-    assert_biteq!(1f64.signum(), 1f64);
-    assert_biteq!(0f64.signum(), 1f64);
-    assert_biteq!((-0f64).signum(), -1f64);
-    assert_biteq!((-1f64).signum(), -1f64);
-    assert_biteq!(f64::NEG_INFINITY.signum(), -1f64);
-    assert_biteq!((1f64 / f64::NEG_INFINITY).signum(), -1f64);
-    assert!(f64::NAN.signum().is_nan());
-}
-
-#[test]
-fn test_is_sign_positive() {
-    assert!(f64::INFINITY.is_sign_positive());
-    assert!(1f64.is_sign_positive());
-    assert!(0f64.is_sign_positive());
-    assert!(!(-0f64).is_sign_positive());
-    assert!(!(-1f64).is_sign_positive());
-    assert!(!f64::NEG_INFINITY.is_sign_positive());
-    assert!(!(1f64 / f64::NEG_INFINITY).is_sign_positive());
-    assert!(f64::NAN.is_sign_positive());
-    assert!(!(-f64::NAN).is_sign_positive());
-}
-
-#[test]
-fn test_is_sign_negative() {
-    assert!(!f64::INFINITY.is_sign_negative());
-    assert!(!1f64.is_sign_negative());
-    assert!(!0f64.is_sign_negative());
-    assert!((-0f64).is_sign_negative());
-    assert!((-1f64).is_sign_negative());
-    assert!(f64::NEG_INFINITY.is_sign_negative());
-    assert!((1f64 / f64::NEG_INFINITY).is_sign_negative());
-    assert!(!f64::NAN.is_sign_negative());
-    assert!((-f64::NAN).is_sign_negative());
-}
-
-#[test]
-fn test_next_up() {
-    let tiny = f64::from_bits(TINY_BITS);
-    let tiny_up = f64::from_bits(TINY_UP_BITS);
-    let max_down = f64::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
-    assert_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN);
-    assert_biteq!(f64::MIN.next_up(), -max_down);
-    assert_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0f64);
-    assert_biteq!((-smallest_normal).next_up(), -largest_subnormal);
-    assert_biteq!((-tiny_up).next_up(), -tiny);
-    assert_biteq!((-tiny).next_up(), -0.0f64);
-    assert_biteq!((-0.0f64).next_up(), tiny);
-    assert_biteq!(0.0f64.next_up(), tiny);
-    assert_biteq!(tiny.next_up(), tiny_up);
-    assert_biteq!(largest_subnormal.next_up(), smallest_normal);
-    assert_biteq!(1.0f64.next_up(), 1.0 + f64::EPSILON);
-    assert_biteq!(f64::MAX.next_up(), f64::INFINITY);
-    assert_biteq!(f64::INFINITY.next_up(), f64::INFINITY);
-
-    let nan0 = f64::NAN;
-    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
-    assert_biteq!(nan0.next_up(), nan0);
-    assert_biteq!(nan1.next_up(), nan1);
-    assert_biteq!(nan2.next_up(), nan2);
-}
-
-#[test]
-fn test_next_down() {
-    let tiny = f64::from_bits(TINY_BITS);
-    let tiny_up = f64::from_bits(TINY_UP_BITS);
-    let max_down = f64::from_bits(MAX_DOWN_BITS);
-    let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
-    let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
-    assert_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY);
-    assert_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY);
-    assert_biteq!((-max_down).next_down(), f64::MIN);
-    assert_biteq!((-1.0f64).next_down(), -1.0 - f64::EPSILON);
-    assert_biteq!((-largest_subnormal).next_down(), -smallest_normal);
-    assert_biteq!((-tiny).next_down(), -tiny_up);
-    assert_biteq!((-0.0f64).next_down(), -tiny);
-    assert_biteq!((0.0f64).next_down(), -tiny);
-    assert_biteq!(tiny.next_down(), 0.0f64);
-    assert_biteq!(tiny_up.next_down(), tiny);
-    assert_biteq!(smallest_normal.next_down(), largest_subnormal);
-    assert_biteq!((1.0 + f64::EPSILON).next_down(), 1.0f64);
-    assert_biteq!(f64::MAX.next_down(), max_down);
-    assert_biteq!(f64::INFINITY.next_down(), f64::MAX);
-
-    let nan0 = f64::NAN;
-    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
-    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
-    assert_biteq!(nan0.next_down(), nan0);
-    assert_biteq!(nan1.next_down(), nan1);
-    assert_biteq!(nan2.next_down(), nan2);
-}
-
 // FIXME(#140515): mingw has an incorrect fma https://sourceforge.net/p/mingw-w64/bugs/848/
 #[cfg_attr(all(target_os = "windows", target_env = "gnu", not(target_abi = "llvm")), ignore)]
 #[test]
@@ -180,17 +56,6 @@ fn test_powi() {
 }
 
 #[test]
-fn test_sqrt_domain() {
-    assert!(f64::NAN.sqrt().is_nan());
-    assert!(f64::NEG_INFINITY.sqrt().is_nan());
-    assert!((-1.0f64).sqrt().is_nan());
-    assert_biteq!((-0.0f64).sqrt(), -0.0);
-    assert_biteq!(0.0f64.sqrt(), 0.0);
-    assert_biteq!(1.0f64.sqrt(), 1.0);
-    assert_biteq!(f64::INFINITY.sqrt(), f64::INFINITY);
-}
-
-#[test]
 fn test_to_degrees() {
     let pi: f64 = consts::PI;
     let nan: f64 = f64::NAN;
@@ -241,167 +106,6 @@ fn test_float_bits_conv() {
 }
 
 #[test]
-#[should_panic]
-fn test_clamp_min_greater_than_max() {
-    let _ = 1.0f64.clamp(3.0, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_min_is_nan() {
-    let _ = 1.0f64.clamp(f64::NAN, 1.0);
-}
-
-#[test]
-#[should_panic]
-fn test_clamp_max_is_nan() {
-    let _ = 1.0f64.clamp(3.0, f64::NAN);
-}
-
-#[test]
-fn test_total_cmp() {
-    use core::cmp::Ordering;
-
-    fn quiet_bit_mask() -> u64 {
-        1 << (f64::MANTISSA_DIGITS - 2)
-    }
-
-    fn min_subnorm() -> f64 {
-        f64::MIN_POSITIVE / f64::powf(2.0, f64::MANTISSA_DIGITS as f64 - 1.0)
-    }
-
-    fn max_subnorm() -> f64 {
-        f64::MIN_POSITIVE - min_subnorm()
-    }
-
-    fn q_nan() -> f64 {
-        f64::from_bits(f64::NAN.to_bits() | quiet_bit_mask())
-    }
-
-    fn s_nan() -> f64 {
-        f64::from_bits((f64::NAN.to_bits() & !quiet_bit_mask()) + 42)
-    }
-
-    assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Equal, (-f64::INFINITY).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Equal, (-f64::MAX).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Equal, (-2.5_f64).total_cmp(&-2.5));
-    assert_eq!(Ordering::Equal, (-1.0_f64).total_cmp(&-1.0));
-    assert_eq!(Ordering::Equal, (-1.5_f64).total_cmp(&-1.5));
-    assert_eq!(Ordering::Equal, (-0.5_f64).total_cmp(&-0.5));
-    assert_eq!(Ordering::Equal, (-f64::MIN_POSITIVE).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Equal, (-0.0_f64).total_cmp(&-0.0));
-    assert_eq!(Ordering::Equal, 0.0_f64.total_cmp(&0.0));
-    assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Equal, f64::MIN_POSITIVE.total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Equal, 0.5_f64.total_cmp(&0.5));
-    assert_eq!(Ordering::Equal, 1.0_f64.total_cmp(&1.0));
-    assert_eq!(Ordering::Equal, 1.5_f64.total_cmp(&1.5));
-    assert_eq!(Ordering::Equal, 2.5_f64.total_cmp(&2.5));
-    assert_eq!(Ordering::Equal, f64::MAX.total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Equal, f64::INFINITY.total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
-    assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Less, (-f64::INFINITY).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Less, (-f64::MAX).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-2.5_f64).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-1.5_f64).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-1.0_f64).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-0.5_f64).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-f64::MIN_POSITIVE).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-0.0_f64).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, 0.0_f64.total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, f64::MIN_POSITIVE.total_cmp(&0.5));
-    assert_eq!(Ordering::Less, 0.5_f64.total_cmp(&1.0));
-    assert_eq!(Ordering::Less, 1.0_f64.total_cmp(&1.5));
-    assert_eq!(Ordering::Less, 1.5_f64.total_cmp(&2.5));
-    assert_eq!(Ordering::Less, 2.5_f64.total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Less, f64::MAX.total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Less, f64::INFINITY.total_cmp(&s_nan()));
-    assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
-
-    assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
-    assert_eq!(Ordering::Greater, (-f64::INFINITY).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Greater, (-f64::MAX).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Greater, (-2.5_f64).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Greater, (-1.5_f64).total_cmp(&-2.5));
-    assert_eq!(Ordering::Greater, (-1.0_f64).total_cmp(&-1.5));
-    assert_eq!(Ordering::Greater, (-0.5_f64).total_cmp(&-1.0));
-    assert_eq!(Ordering::Greater, (-f64::MIN_POSITIVE).total_cmp(&-0.5));
-    assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Greater, (-0.0_f64).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Greater, 0.0_f64.total_cmp(&-0.0));
-    assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
-    assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Greater, f64::MIN_POSITIVE.total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Greater, 0.5_f64.total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Greater, 1.0_f64.total_cmp(&0.5));
-    assert_eq!(Ordering::Greater, 1.5_f64.total_cmp(&1.0));
-    assert_eq!(Ordering::Greater, 2.5_f64.total_cmp(&1.5));
-    assert_eq!(Ordering::Greater, f64::MAX.total_cmp(&2.5));
-    assert_eq!(Ordering::Greater, f64::INFINITY.total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Greater, s_nan().total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
-
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::MIN_POSITIVE));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::MAX));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY));
-    assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
-}
-
-#[test]
 fn test_algebraic() {
     let a: f64 = 123.0;
     let b: f64 = 456.0;
diff --git a/library/coretests/tests/floats/mod.rs b/library/coretests/tests/floats/mod.rs
index 43431bba695..2c2a07920d0 100644
--- a/library/coretests/tests/floats/mod.rs
+++ b/library/coretests/tests/floats/mod.rs
@@ -2,34 +2,80 @@ use std::num::FpCategory as Fp;
 use std::ops::{Add, Div, Mul, Rem, Sub};
 
 trait TestableFloat {
+    /// Unsigned int with the same size, for converting to/from bits.
+    type Int;
     /// Set the default tolerance for float comparison based on the type.
     const APPROX: Self;
+    const ZERO: Self;
+    const ONE: Self;
     const MIN_POSITIVE_NORMAL: Self;
     const MAX_SUBNORMAL: Self;
+    /// Smallest number
+    const TINY: Self;
+    /// Next smallest number
+    const TINY_UP: Self;
+    /// Exponent = 0b11...10, Significand 0b1111..10. Min val > 0
+    const MAX_DOWN: Self;
+    /// First pattern over the mantissa
+    const NAN_MASK1: Self::Int;
+    /// Second pattern over the mantissa
+    const NAN_MASK2: Self::Int;
 }
 
 impl TestableFloat for f16 {
+    type Int = u16;
     const APPROX: Self = 1e-3;
+    const ZERO: Self = 0.0;
+    const ONE: Self = 1.0;
     const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE;
     const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down();
+    const TINY: Self = Self::from_bits(0x1);
+    const TINY_UP: Self = Self::from_bits(0x2);
+    const MAX_DOWN: Self = Self::from_bits(0x7bfe);
+    const NAN_MASK1: Self::Int = 0x02aa;
+    const NAN_MASK2: Self::Int = 0x0155;
 }
 
 impl TestableFloat for f32 {
+    type Int = u32;
     const APPROX: Self = 1e-6;
+    const ZERO: Self = 0.0;
+    const ONE: Self = 1.0;
     const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE;
     const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down();
+    const TINY: Self = Self::from_bits(0x1);
+    const TINY_UP: Self = Self::from_bits(0x2);
+    const MAX_DOWN: Self = Self::from_bits(0x7f7f_fffe);
+    const NAN_MASK1: Self::Int = 0x002a_aaaa;
+    const NAN_MASK2: Self::Int = 0x0055_5555;
 }
 
 impl TestableFloat for f64 {
+    type Int = u64;
     const APPROX: Self = 1e-6;
+    const ZERO: Self = 0.0;
+    const ONE: Self = 1.0;
     const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE;
     const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down();
+    const TINY: Self = Self::from_bits(0x1);
+    const TINY_UP: Self = Self::from_bits(0x2);
+    const MAX_DOWN: Self = Self::from_bits(0x7fef_ffff_ffff_fffe);
+    const NAN_MASK1: Self::Int = 0x000a_aaaa_aaaa_aaaa;
+    const NAN_MASK2: Self::Int = 0x0005_5555_5555_5555;
 }
 
 impl TestableFloat for f128 {
+    type Int = u128;
     const APPROX: Self = 1e-9;
+    const ZERO: Self = 0.0;
+    const ONE: Self = 1.0;
     const MIN_POSITIVE_NORMAL: Self = Self::MIN_POSITIVE;
     const MAX_SUBNORMAL: Self = Self::MIN_POSITIVE.next_down();
+    const TINY: Self = Self::from_bits(0x1);
+    const TINY_UP: Self = Self::from_bits(0x2);
+    const MAX_DOWN: Self = Self::from_bits(0x7ffefffffffffffffffffffffffffffe);
+    const NAN_MASK1: Self::Int = 0x0000aaaaaaaaaaaaaaaaaaaaaaaaaaaa;
+    const NAN_MASK2: Self::Int = 0x00005555555555555555555555555555;
 }
 
 /// Determine the tolerance for values of the argument type.
@@ -342,15 +388,14 @@ float_test! {
         f128: #[cfg(any(miri, target_has_reliable_f128))],
     },
     test<Float> {
-        let zero: Float = 0.0;
-        assert_biteq!(0.0, zero);
-        assert!(!zero.is_infinite());
-        assert!(zero.is_finite());
-        assert!(zero.is_sign_positive());
-        assert!(!zero.is_sign_negative());
-        assert!(!zero.is_nan());
-        assert!(!zero.is_normal());
-        assert!(matches!(zero.classify(), Fp::Zero));
+        assert_biteq!(0.0, Float::ZERO);
+        assert!(!Float::ZERO.is_infinite());
+        assert!(Float::ZERO.is_finite());
+        assert!(Float::ZERO.is_sign_positive());
+        assert!(!Float::ZERO.is_sign_negative());
+        assert!(!Float::ZERO.is_nan());
+        assert!(!Float::ZERO.is_normal());
+        assert!(matches!(Float::ZERO.classify(), Fp::Zero));
     }
 }
 
@@ -381,15 +426,14 @@ float_test! {
         f128: #[cfg(any(miri, target_has_reliable_f128))],
     },
     test<Float> {
-        let one: Float = 1.0;
-        assert_biteq!(1.0, one);
-        assert!(!one.is_infinite());
-        assert!(one.is_finite());
-        assert!(one.is_sign_positive());
-        assert!(!one.is_sign_negative());
-        assert!(!one.is_nan());
-        assert!(one.is_normal());
-        assert!(matches!(one.classify(), Fp::Normal));
+        assert_biteq!(1.0, Float::ONE);
+        assert!(!Float::ONE.is_infinite());
+        assert!(Float::ONE.is_finite());
+        assert!(Float::ONE.is_sign_positive());
+        assert!(!Float::ONE.is_sign_negative());
+        assert!(!Float::ONE.is_nan());
+        assert!(Float::ONE.is_normal());
+        assert!(matches!(Float::ONE.classify(), Fp::Normal));
     }
 }
 
@@ -403,11 +447,10 @@ float_test! {
         let nan: Float = Float::NAN;
         let inf: Float = Float::INFINITY;
         let neg_inf: Float = Float::NEG_INFINITY;
-        let zero: Float = 0.0;
         let pos: Float = 5.3;
         let neg: Float = -10.732;
         assert!(nan.is_nan());
-        assert!(!zero.is_nan());
+        assert!(!Float::ZERO.is_nan());
         assert!(!pos.is_nan());
         assert!(!neg.is_nan());
         assert!(!inf.is_nan());
@@ -425,13 +468,12 @@ float_test! {
         let nan: Float = Float::NAN;
         let inf: Float = Float::INFINITY;
         let neg_inf: Float = Float::NEG_INFINITY;
-        let zero: Float = 0.0;
         let pos: Float = 42.8;
         let neg: Float = -109.2;
         assert!(!nan.is_infinite());
         assert!(inf.is_infinite());
         assert!(neg_inf.is_infinite());
-        assert!(!zero.is_infinite());
+        assert!(!Float::ZERO.is_infinite());
         assert!(!pos.is_infinite());
         assert!(!neg.is_infinite());
     }
@@ -447,13 +489,12 @@ float_test! {
         let nan: Float = Float::NAN;
         let inf: Float = Float::INFINITY;
         let neg_inf: Float = Float::NEG_INFINITY;
-        let zero: Float = 0.0;
         let pos: Float = 42.8;
         let neg: Float = -109.2;
         assert!(!nan.is_finite());
         assert!(!inf.is_finite());
         assert!(!neg_inf.is_finite());
-        assert!(zero.is_finite());
+        assert!(Float::ZERO.is_finite());
         assert!(pos.is_finite());
         assert!(neg.is_finite());
     }
@@ -469,15 +510,13 @@ float_test! {
         let nan: Float = Float::NAN;
         let inf: Float = Float::INFINITY;
         let neg_inf: Float = Float::NEG_INFINITY;
-        let zero: Float = 0.0;
         let neg_zero: Float = -0.0;
-        let one : Float = 1.0;
         assert!(!nan.is_normal());
         assert!(!inf.is_normal());
         assert!(!neg_inf.is_normal());
-        assert!(!zero.is_normal());
+        assert!(!Float::ZERO.is_normal());
         assert!(!neg_zero.is_normal());
-        assert!(one.is_normal());
+        assert!(Float::ONE.is_normal());
         assert!(Float::MIN_POSITIVE_NORMAL.is_normal());
         assert!(!Float::MAX_SUBNORMAL.is_normal());
     }
@@ -492,15 +531,13 @@ float_test! {
         let nan: Float = Float::NAN;
         let inf: Float = Float::INFINITY;
         let neg_inf: Float = Float::NEG_INFINITY;
-        let zero: Float = 0.0;
         let neg_zero: Float = -0.0;
-        let one: Float = 1.0;
         assert!(matches!(nan.classify(), Fp::Nan));
         assert!(matches!(inf.classify(), Fp::Infinite));
         assert!(matches!(neg_inf.classify(), Fp::Infinite));
-        assert!(matches!(zero.classify(), Fp::Zero));
+        assert!(matches!(Float::ZERO.classify(), Fp::Zero));
         assert!(matches!(neg_zero.classify(), Fp::Zero));
-        assert!(matches!(one.classify(), Fp::Normal));
+        assert!(matches!(Float::ONE.classify(), Fp::Normal));
         assert!(matches!(Float::MIN_POSITIVE_NORMAL.classify(), Fp::Normal));
         assert!(matches!(Float::MAX_SUBNORMAL.classify(), Fp::Subnormal));
     }
@@ -720,10 +757,14 @@ float_test! {
         f128: #[cfg(any(miri, target_has_reliable_f128_math))],
     },
     test<Float> {
-        assert_biteq!((-1.0 as Float).abs(), 1.0);
-        assert_biteq!((1.0 as Float).abs(), 1.0);
-        assert_biteq!(Float::NEG_INFINITY.abs(), Float::INFINITY);
         assert_biteq!(Float::INFINITY.abs(), Float::INFINITY);
+        assert_biteq!(Float::ONE.abs(), Float::ONE);
+        assert_biteq!(Float::ZERO.abs(), Float::ZERO);
+        assert_biteq!((-Float::ZERO).abs(), Float::ZERO);
+        assert_biteq!((-Float::ONE).abs(), Float::ONE);
+        assert_biteq!(Float::NEG_INFINITY.abs(), Float::INFINITY);
+        assert_biteq!((Float::ONE / Float::NEG_INFINITY).abs(), Float::ZERO);
+        assert!(Float::NAN.abs().is_nan());
     }
 }
 
@@ -951,3 +992,351 @@ float_test! {
         assert!(Float::NEG_INFINITY.fract().is_nan());
     }
 }
+
+float_test! {
+    name: signum,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16_math))],
+        f128: #[cfg(any(miri, target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert_biteq!(Float::INFINITY.signum(), Float::ONE);
+        assert_biteq!(Float::ONE.signum(), Float::ONE);
+        assert_biteq!(Float::ZERO.signum(), Float::ONE);
+        assert_biteq!((-Float::ZERO).signum(), -Float::ONE);
+        assert_biteq!((-Float::ONE).signum(), -Float::ONE);
+        assert_biteq!(Float::NEG_INFINITY.signum(), -Float::ONE);
+        assert_biteq!((Float::ONE / Float::NEG_INFINITY).signum(), -Float::ONE);
+        assert!(Float::NAN.signum().is_nan());
+    }
+}
+
+float_test! {
+    name: is_sign_positive,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        assert!(Float::INFINITY.is_sign_positive());
+        assert!(Float::ONE.is_sign_positive());
+        assert!(Float::ZERO.is_sign_positive());
+        assert!(!(-Float::ZERO).is_sign_positive());
+        assert!(!(-Float::ONE).is_sign_positive());
+        assert!(!Float::NEG_INFINITY.is_sign_positive());
+        assert!(!(Float::ONE / Float::NEG_INFINITY).is_sign_positive());
+        assert!(Float::NAN.is_sign_positive());
+        assert!(!(-Float::NAN).is_sign_positive());
+    }
+}
+
+float_test! {
+    name: is_sign_negative,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        assert!(!Float::INFINITY.is_sign_negative());
+        assert!(!Float::ONE.is_sign_negative());
+        assert!(!Float::ZERO.is_sign_negative());
+        assert!((-Float::ZERO).is_sign_negative());
+        assert!((-Float::ONE).is_sign_negative());
+        assert!(Float::NEG_INFINITY.is_sign_negative());
+        assert!((Float::ONE / Float::NEG_INFINITY).is_sign_negative());
+        assert!(!Float::NAN.is_sign_negative());
+        assert!((-Float::NAN).is_sign_negative());
+    }
+}
+
+float_test! {
+    name: next_up,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        assert_biteq!(Float::NEG_INFINITY.next_up(), Float::MIN);
+        assert_biteq!(Float::MIN.next_up(), -Float::MAX_DOWN);
+        assert_biteq!((-Float::ONE - Float::EPSILON).next_up(), -Float::ONE);
+        assert_biteq!((-Float::MIN_POSITIVE_NORMAL).next_up(), -Float::MAX_SUBNORMAL);
+        assert_biteq!((-Float::TINY_UP).next_up(), -Float::TINY);
+        assert_biteq!((-Float::TINY).next_up(), -Float::ZERO);
+        assert_biteq!((-Float::ZERO).next_up(), Float::TINY);
+        assert_biteq!(Float::ZERO.next_up(), Float::TINY);
+        assert_biteq!(Float::TINY.next_up(), Float::TINY_UP);
+        assert_biteq!(Float::MAX_SUBNORMAL.next_up(), Float::MIN_POSITIVE_NORMAL);
+        assert_biteq!(Float::ONE.next_up(), 1.0 + Float::EPSILON);
+        assert_biteq!(Float::MAX.next_up(), Float::INFINITY);
+        assert_biteq!(Float::INFINITY.next_up(), Float::INFINITY);
+
+        // Check that NaNs roundtrip.
+        let nan0 = Float::NAN;
+        let nan1 = Float::from_bits(Float::NAN.to_bits() ^ Float::NAN_MASK1);
+        let nan2 = Float::from_bits(Float::NAN.to_bits() ^ Float::NAN_MASK2);
+        assert_biteq!(nan0.next_up(), nan0);
+        assert_biteq!(nan1.next_up(), nan1);
+        assert_biteq!(nan2.next_up(), nan2);
+    }
+}
+
+float_test! {
+    name: next_down,
+    attrs: {
+        f16: #[cfg(any(miri, target_has_reliable_f16))],
+        f128: #[cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        assert_biteq!(Float::NEG_INFINITY.next_down(), Float::NEG_INFINITY);
+        assert_biteq!(Float::MIN.next_down(), Float::NEG_INFINITY);
+        assert_biteq!((-Float::MAX_DOWN).next_down(), Float::MIN);
+        assert_biteq!((-Float::ONE).next_down(), -1.0 - Float::EPSILON);
+        assert_biteq!((-Float::MAX_SUBNORMAL).next_down(), -Float::MIN_POSITIVE_NORMAL);
+        assert_biteq!((-Float::TINY).next_down(), -Float::TINY_UP);
+        assert_biteq!((-Float::ZERO).next_down(), -Float::TINY);
+        assert_biteq!((Float::ZERO).next_down(), -Float::TINY);
+        assert_biteq!(Float::TINY.next_down(), Float::ZERO);
+        assert_biteq!(Float::TINY_UP.next_down(), Float::TINY);
+        assert_biteq!(Float::MIN_POSITIVE_NORMAL.next_down(), Float::MAX_SUBNORMAL);
+        assert_biteq!((1.0 + Float::EPSILON).next_down(), Float::ONE);
+        assert_biteq!(Float::MAX.next_down(), Float::MAX_DOWN);
+        assert_biteq!(Float::INFINITY.next_down(), Float::MAX);
+
+        // Check that NaNs roundtrip.
+        let nan0 = Float::NAN;
+        let nan1 = Float::from_bits(Float::NAN.to_bits() ^ Float::NAN_MASK1);
+        let nan2 = Float::from_bits(Float::NAN.to_bits() ^ Float::NAN_MASK2);
+        assert_biteq!(nan0.next_down(), nan0);
+        assert_biteq!(nan1.next_down(), nan1);
+        assert_biteq!(nan2.next_down(), nan2);
+    }
+}
+
+// FIXME(f16_f128,miri): many of these have to be disabled since miri does not yet support
+// the intrinsics.
+
+float_test! {
+    name: sqrt_domain,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+        f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        assert!(Float::NAN.sqrt().is_nan());
+        assert!(Float::NEG_INFINITY.sqrt().is_nan());
+        assert!((-Float::ONE).sqrt().is_nan());
+        assert_biteq!((-Float::ZERO).sqrt(), -Float::ZERO);
+        assert_biteq!(Float::ZERO.sqrt(), Float::ZERO);
+        assert_biteq!(Float::ONE.sqrt(), Float::ONE);
+        assert_biteq!(Float::INFINITY.sqrt(), Float::INFINITY);
+    }
+}
+
+float_test! {
+    name: clamp_min_greater_than_max,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[should_panic, cfg(any(miri, target_has_reliable_f16))],
+        f32: #[should_panic],
+        f64: #[should_panic],
+        f128: #[should_panic, cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let _ = Float::ONE.clamp(3.0, 1.0);
+    }
+}
+
+float_test! {
+    name: clamp_min_is_nan,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[should_panic, cfg(any(miri, target_has_reliable_f16))],
+        f32: #[should_panic],
+        f64: #[should_panic],
+        f128: #[should_panic, cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let _ = Float::ONE.clamp(Float::NAN, 1.0);
+    }
+}
+
+float_test! {
+    name: clamp_max_is_nan,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[should_panic, cfg(any(miri, target_has_reliable_f16))],
+        f32: #[should_panic],
+        f64: #[should_panic],
+        f128: #[should_panic, cfg(any(miri, target_has_reliable_f128))],
+    },
+    test<Float> {
+        let _ = Float::ONE.clamp(3.0, Float::NAN);
+    }
+}
+
+float_test! {
+    name: total_cmp,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[cfg(all(not(miri), target_has_reliable_f16_math))],
+        f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        use core::cmp::Ordering;
+
+        fn quiet_bit_mask() -> <Float as TestableFloat>::Int {
+            1 << (Float::MANTISSA_DIGITS - 2)
+        }
+
+        fn q_nan() -> Float {
+            Float::from_bits(Float::NAN.to_bits() | quiet_bit_mask())
+        }
+
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-q_nan(), &-q_nan()));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::INFINITY, &-Float::INFINITY));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::MAX, &-Float::MAX));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-2.5, &-2.5));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-1.0, &-1.0));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-1.5, &-1.5));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-0.5, &-0.5));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::MIN_POSITIVE, &-Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::MAX_SUBNORMAL, &-Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-Float::TINY, &-Float::TINY));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-0.0, &-0.0));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&0.0, &0.0));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&Float::TINY, &Float::TINY));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&Float::MAX_SUBNORMAL, &Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&Float::MIN_POSITIVE, &Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&0.5, &0.5));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&1.0, &1.0));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&1.5, &1.5));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&2.5, &2.5));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&Float::MAX, &Float::MAX));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&Float::INFINITY, &Float::INFINITY));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&q_nan(), &q_nan()));
+
+        assert_eq!(Ordering::Less, Float::total_cmp(&-Float::INFINITY, &-Float::MAX));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-Float::MAX, &-2.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-2.5, &-1.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-1.5, &-1.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-1.0, &-0.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-0.5, &-Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-Float::MIN_POSITIVE, &-Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-Float::MAX_SUBNORMAL, &-Float::TINY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-Float::TINY, &-0.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-0.0, &0.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&0.0, &Float::TINY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&Float::TINY, &Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Less, Float::total_cmp(&Float::MAX_SUBNORMAL, &Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, Float::total_cmp(&Float::MIN_POSITIVE, &0.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&0.5, &1.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&1.0, &1.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&1.5, &2.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&2.5, &Float::MAX));
+        assert_eq!(Ordering::Less, Float::total_cmp(&Float::MAX, &Float::INFINITY));
+
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-Float::MAX, &-Float::INFINITY));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-2.5, &-Float::MAX));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-1.5, &-2.5));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-1.0, &-1.5));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-0.5, &-1.0));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-Float::MIN_POSITIVE, &-0.5));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-Float::MAX_SUBNORMAL, &-Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-Float::TINY, &-Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-0.0, &-Float::TINY));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&0.0, &-0.0));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&Float::TINY, &0.0));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&Float::MAX_SUBNORMAL, &Float::TINY));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&Float::MIN_POSITIVE, &Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&0.5, &Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&1.0, &0.5));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&1.5, &1.0));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&2.5, &1.5));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&Float::MAX, &2.5));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&Float::INFINITY, &Float::MAX));
+
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::INFINITY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::MAX));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-2.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-1.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-1.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-0.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-Float::TINY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-0.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &0.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::TINY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &0.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &1.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &1.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &2.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::MAX));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &Float::INFINITY));
+
+    }
+}
+
+// FIXME(f16): Tests involving sNaN are disabled because without optimizations, `total_cmp` is
+// getting incorrectly lowered to code that includes a `extend`/`trunc` round trip, which quiets
+// sNaNs. See: https://github.com/llvm/llvm-project/issues/104915
+
+float_test! {
+    name: total_cmp_s_nan,
+    attrs: {
+        const: #[cfg(false)],
+        f16: #[cfg(false)],
+        f128: #[cfg(all(not(miri), target_has_reliable_f128_math))],
+    },
+    test<Float> {
+        use core::cmp::Ordering;
+
+        fn quiet_bit_mask() -> <Float as TestableFloat>::Int {
+            1 << (Float::MANTISSA_DIGITS - 2)
+        }
+
+        fn q_nan() -> Float {
+            Float::from_bits(Float::NAN.to_bits() | quiet_bit_mask())
+        }
+
+        fn s_nan() -> Float {
+            Float::from_bits((Float::NAN.to_bits() & !quiet_bit_mask()) + 42)
+        }
+        assert_eq!(Ordering::Equal, Float::total_cmp(&-s_nan(), &-s_nan()));
+        assert_eq!(Ordering::Equal, Float::total_cmp(&s_nan(), &s_nan()));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-s_nan()));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-Float::INFINITY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&Float::INFINITY, &s_nan()));
+        assert_eq!(Ordering::Less, Float::total_cmp(&s_nan(), &q_nan()));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-s_nan(), &-q_nan()));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&-Float::INFINITY, &-s_nan()));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&s_nan(), &Float::INFINITY));
+        assert_eq!(Ordering::Greater, Float::total_cmp(&q_nan(), &s_nan()));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &-s_nan()));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-q_nan(), &s_nan()));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-Float::INFINITY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-Float::MAX));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-2.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-1.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-1.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-0.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-Float::TINY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &-0.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &0.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &Float::TINY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &Float::MAX_SUBNORMAL));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &Float::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &0.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &1.0));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &1.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &2.5));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &Float::MAX));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &Float::INFINITY));
+        assert_eq!(Ordering::Less, Float::total_cmp(&-s_nan(), &s_nan()));
+    }
+}
diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs
index ebfabaafc79..42a7dbdf8b8 100644
--- a/library/std/src/sys/pal/wasm/atomics/thread.rs
+++ b/library/std/src/sys/pal/wasm/atomics/thread.rs
@@ -56,6 +56,10 @@ impl Thread {
     pub fn join(self) {}
 }
 
+pub(crate) fn current_os_id() -> Option<u64> {
+    None
+}
+
 pub fn available_parallelism() -> io::Result<NonZero<usize>> {
     unsupported()
 }
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index e1ee0773107..79174eb281f 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -23,8 +23,7 @@ use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld
 use crate::core::build_steps::{dist, llvm};
 use crate::core::builder;
 use crate::core::builder::{
-    Builder, Cargo, Kind, PathSet, RunConfig, ShouldRun, Step, StepMetadata, TaskPath,
-    crate_description,
+    Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
 };
 use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
 use crate::utils::build_stamp;
@@ -1539,99 +1538,131 @@ impl Step for RustcLink {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct CodegenBackend {
+pub struct GccCodegenBackend {
     compilers: RustcPrivateCompilers,
-    backend: CodegenBackendKind,
 }
 
-fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
-    let mut needs_codegen_cfg = false;
-    for path_set in &run.paths {
-        needs_codegen_cfg = match path_set {
-            PathSet::Set(set) => set.iter().any(|p| is_codegen_cfg_needed(p, run)),
-            PathSet::Suite(suite) => is_codegen_cfg_needed(suite, run),
-        }
+impl Step for GccCodegenBackend {
+    type Output = BuildStamp;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.alias("rustc_codegen_gcc").alias("cg_gcc")
     }
-    needs_codegen_cfg
-}
 
-pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(GccCodegenBackend {
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
+        });
+    }
 
-fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
-    let path = path.path.to_str().unwrap();
+    #[cfg_attr(
+        feature = "tracing",
+        instrument(
+            level = "debug",
+            name = "GccCodegenBackend::run",
+            skip_all,
+            fields(
+                compilers = ?self.compilers,
+            ),
+        ),
+    )]
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let target = self.compilers.target();
+        let build_compiler = self.compilers.build_compiler();
 
-    let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
-    let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
+        let stamp = build_stamp::codegen_backend_stamp(
+            builder,
+            build_compiler,
+            target,
+            &CodegenBackendKind::Gcc,
+        );
 
-    if path.contains(CODEGEN_BACKEND_PREFIX) {
-        let mut needs_codegen_backend_config = true;
-        for backend in run.builder.config.codegen_backends(run.target) {
-            if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend.name())) {
-                needs_codegen_backend_config = false;
-            }
-        }
-        if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
-            && needs_codegen_backend_config
-        {
-            run.builder.info(
-                "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
-                HELP: add backend to codegen-backends in bootstrap.toml.",
+        if builder.config.keep_stage.contains(&build_compiler.stage) {
+            trace!("`keep-stage` requested");
+            builder.info(
+                "WARNING: Using a potentially old codegen backend. \
+                This may not behave well.",
             );
-            return true;
+            // Codegen backends are linked separately from this step today, so we don't do
+            // anything here.
+            return stamp;
         }
+
+        let mut cargo = builder::Cargo::new(
+            builder,
+            build_compiler,
+            Mode::Codegen,
+            SourceType::InTree,
+            target,
+            Kind::Build,
+        );
+        cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml"));
+        rustc_cargo_env(builder, &mut cargo, target);
+
+        let gcc = builder.ensure(Gcc { target });
+        add_cg_gcc_cargo_flags(&mut cargo, &gcc);
+
+        let _guard = builder.msg_rustc_tool(
+            Kind::Build,
+            build_compiler.stage,
+            "codegen backend gcc",
+            build_compiler.host,
+            target,
+        );
+        let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
+        write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
     }
 
-    false
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(
+            StepMetadata::build("rustc_codegen_gcc", self.compilers.target())
+                .built_by(self.compilers.build_compiler()),
+        )
+    }
 }
 
-impl Step for CodegenBackend {
-    type Output = ();
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct CraneliftCodegenBackend {
+    pub compilers: RustcPrivateCompilers,
+}
+
+impl Step for CraneliftCodegenBackend {
+    type Output = BuildStamp;
     const ONLY_HOSTS: bool = true;
-    /// Only the backends specified in the `codegen-backends` entry of `bootstrap.toml` are built.
-    const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.paths(&["compiler/rustc_codegen_cranelift", "compiler/rustc_codegen_gcc"])
+        run.alias("rustc_codegen_cranelift").alias("cg_clif")
     }
 
     fn make_run(run: RunConfig<'_>) {
-        if needs_codegen_config(&run) {
-            return;
-        }
-
-        for backend in run.builder.config.codegen_backends(run.target) {
-            if backend.is_llvm() {
-                continue; // Already built as part of rustc
-            }
-
-            run.builder.ensure(CodegenBackend {
-                compilers: RustcPrivateCompilers::new(
-                    run.builder,
-                    run.builder.top_stage,
-                    run.target,
-                ),
-                backend: backend.clone(),
-            });
-        }
+        run.builder.ensure(CraneliftCodegenBackend {
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
+        });
     }
 
     #[cfg_attr(
         feature = "tracing",
         instrument(
             level = "debug",
-            name = "CodegenBackend::run",
+            name = "CraneliftCodegenBackend::run",
             skip_all,
             fields(
                 compilers = ?self.compilers,
-                backend = ?self.backend,
             ),
         ),
     )]
-    fn run(self, builder: &Builder<'_>) {
-        let backend = self.backend;
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
         let target = self.compilers.target();
         let build_compiler = self.compilers.build_compiler();
 
+        let stamp = build_stamp::codegen_backend_stamp(
+            builder,
+            build_compiler,
+            target,
+            &CodegenBackendKind::Cranelift,
+        );
+
         if builder.config.keep_stage.contains(&build_compiler.stage) {
             trace!("`keep-stage` requested");
             builder.info(
@@ -1640,11 +1671,9 @@ impl Step for CodegenBackend {
             );
             // Codegen backends are linked separately from this step today, so we don't do
             // anything here.
-            return;
+            return stamp;
         }
 
-        let out_dir = builder.cargo_out(build_compiler, Mode::Codegen, target);
-
         let mut cargo = builder::Cargo::new(
             builder,
             build_compiler,
@@ -1655,71 +1684,67 @@ impl Step for CodegenBackend {
         );
         cargo
             .arg("--manifest-path")
-            .arg(builder.src.join(format!("compiler/{}/Cargo.toml", backend.crate_name())));
+            .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml"));
         rustc_cargo_env(builder, &mut cargo, target);
 
-        // Ideally, we'd have a separate step for the individual codegen backends,
-        // like we have in tests (test::CodegenGCC) but that would require a lot of restructuring.
-        // If the logic gets more complicated, it should probably be done.
-        if backend.is_gcc() {
-            let gcc = builder.ensure(Gcc { target });
-            add_cg_gcc_cargo_flags(&mut cargo, &gcc);
-        }
-
-        let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");
-
         let _guard = builder.msg_rustc_tool(
             Kind::Build,
             build_compiler.stage,
-            format_args!("codegen backend {}", backend.name()),
+            "codegen backend cranelift",
             build_compiler.host,
             target,
         );
-        let files = run_cargo(builder, cargo, vec![], &tmp_stamp, vec![], false, false);
-        if builder.config.dry_run() {
-            return;
-        }
-        let mut files = files.into_iter().filter(|f| {
-            let filename = f.file_name().unwrap().to_str().unwrap();
-            is_dylib(f) && filename.contains("rustc_codegen_")
-        });
-        let codegen_backend = match files.next() {
-            Some(f) => f,
-            None => panic!("no dylibs built for codegen backend?"),
-        };
-        if let Some(f) = files.next() {
-            panic!(
-                "codegen backend built two dylibs:\n{}\n{}",
-                codegen_backend.display(),
-                f.display()
-            );
-        }
-        let stamp = build_stamp::codegen_backend_stamp(builder, build_compiler, target, &backend);
-        let codegen_backend = codegen_backend.to_str().unwrap();
-        t!(stamp.add_stamp(codegen_backend).write());
+        let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false);
+        write_codegen_backend_stamp(stamp, files, builder.config.dry_run())
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
         Some(
-            StepMetadata::build(&self.backend.crate_name(), self.compilers.target())
+            StepMetadata::build("rustc_codegen_cranelift", self.compilers.target())
                 .built_by(self.compilers.build_compiler()),
         )
     }
 }
 
+/// Write filtered `files` into the passed build stamp and returns it.
+fn write_codegen_backend_stamp(
+    mut stamp: BuildStamp,
+    files: Vec<PathBuf>,
+    dry_run: bool,
+) -> BuildStamp {
+    if dry_run {
+        return stamp;
+    }
+
+    let mut files = files.into_iter().filter(|f| {
+        let filename = f.file_name().unwrap().to_str().unwrap();
+        is_dylib(f) && filename.contains("rustc_codegen_")
+    });
+    let codegen_backend = match files.next() {
+        Some(f) => f,
+        None => panic!("no dylibs built for codegen backend?"),
+    };
+    if let Some(f) = files.next() {
+        panic!("codegen backend built two dylibs:\n{}\n{}", codegen_backend.display(), f.display());
+    }
+
+    let codegen_backend = codegen_backend.to_str().unwrap();
+    stamp = stamp.add_stamp(codegen_backend);
+    t!(stamp.write());
+    stamp
+}
+
 /// Creates the `codegen-backends` folder for a compiler that's about to be
 /// assembled as a complete compiler.
 ///
-/// This will take the codegen artifacts produced by `compiler` and link them
+/// This will take the codegen artifacts recorded in the given `stamp` and link them
 /// into an appropriate location for `target_compiler` to be a functional
 /// compiler.
 fn copy_codegen_backends_to_sysroot(
     builder: &Builder<'_>,
-    compiler: Compiler,
+    stamp: BuildStamp,
     target_compiler: Compiler,
 ) {
-    let target = target_compiler.host;
-
     // Note that this step is different than all the other `*Link` steps in
     // that it's not assembling a bunch of libraries but rather is primarily
     // moving the codegen backend into place. The codegen backend of rustc is
@@ -1735,25 +1760,18 @@ fn copy_codegen_backends_to_sysroot(
         return;
     }
 
-    for backend in builder.config.codegen_backends(target) {
-        if backend.is_llvm() {
-            continue; // Already built as part of rustc
-        }
-
-        let stamp = build_stamp::codegen_backend_stamp(builder, compiler, target, backend);
-        if stamp.path().exists() {
-            let dylib = t!(fs::read_to_string(stamp.path()));
-            let file = Path::new(&dylib);
-            let filename = file.file_name().unwrap().to_str().unwrap();
-            // change `librustc_codegen_cranelift-xxxxxx.so` to
-            // `librustc_codegen_cranelift-release.so`
-            let target_filename = {
-                let dash = filename.find('-').unwrap();
-                let dot = filename.find('.').unwrap();
-                format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
-            };
-            builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
-        }
+    if stamp.path().exists() {
+        let dylib = t!(fs::read_to_string(stamp.path()));
+        let file = Path::new(&dylib);
+        let filename = file.file_name().unwrap().to_str().unwrap();
+        // change `librustc_codegen_cranelift-xxxxxx.so` to
+        // `librustc_codegen_cranelift-release.so`
+        let target_filename = {
+            let dash = filename.find('-').unwrap();
+            let dot = filename.find('.').unwrap();
+            format!("{}-{}{}", &filename[..dash], builder.rust_release(), &filename[dot..])
+        };
+        builder.copy_link(file, &dst.join(target_filename), FileType::NativeLibrary);
     }
 }
 
@@ -2162,44 +2180,52 @@ impl Step for Assemble {
         );
         build_compiler.stage = actual_stage;
 
-        #[cfg(feature = "tracing")]
-        let _codegen_backend_span =
-            span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
-        for backend in builder.config.codegen_backends(target_compiler.host) {
-            if backend.is_llvm() {
-                debug!("llvm codegen backend is already built as part of rustc");
-                continue; // Already built as part of rustc
-            }
+        let mut codegen_backend_stamps = vec![];
+        {
+            #[cfg(feature = "tracing")]
+            let _codegen_backend_span =
+                span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
+
+            for backend in builder.config.enabled_codegen_backends(target_compiler.host) {
+                // FIXME: this is a horrible hack used to make `x check` work when other codegen
+                // backends are enabled.
+                // `x check` will check stage 1 rustc, which copies its rmetas to the stage0 sysroot.
+                // Then it checks codegen backends, which correctly use these rmetas.
+                // Then it needs to check std, but for that it needs to build stage 1 rustc.
+                // This copies the build rmetas into the stage0 sysroot, effectively poisoning it,
+                // because we then have both check and build rmetas in the same sysroot.
+                // That would be fine on its own. However, when another codegen backend is enabled,
+                // then building stage 1 rustc implies also building stage 1 codegen backend (even if
+                // it isn't used for anything). And since that tries to use the poisoned
+                // rmetas, it fails to build.
+                // We don't actually need to build rustc-private codegen backends for checking std,
+                // so instead we skip that.
+                // Note: this would be also an issue for other rustc-private tools, but that is "solved"
+                // by check::Std being last in the list of checked things (see
+                // `Builder::get_step_descriptions`).
+                if builder.kind == Kind::Check && builder.top_stage == 1 {
+                    continue;
+                }
 
-            // FIXME: this is a horrible hack used to make `x check` work when other codegen
-            // backends are enabled.
-            // `x check` will check stage 1 rustc, which copies its rmetas to the stage0 sysroot.
-            // Then it checks codegen backends, which correctly use these rmetas.
-            // Then it needs to check std, but for that it needs to build stage 1 rustc.
-            // This copies the build rmetas into the stage0 sysroot, effectively poisoning it,
-            // because we then have both check and build rmetas in the same sysroot.
-            // That would be fine on its own. However, when another codegen backend is enabled,
-            // then building stage 1 rustc implies also building stage 1 codegen backend (even if
-            // it isn't used for anything). And since that tries to use the poisoned
-            // rmetas, it fails to build.
-            // We don't actually need to build rustc-private codegen backends for checking std,
-            // so instead we skip that.
-            // Note: this would be also an issue for other rustc-private tools, but that is "solved"
-            // by check::Std being last in the list of checked things (see
-            // `Builder::get_step_descriptions`).
-            if builder.kind == Kind::Check && builder.top_stage == 1 {
-                continue;
+                let prepare_compilers = || {
+                    RustcPrivateCompilers::from_build_and_target_compiler(
+                        build_compiler,
+                        target_compiler,
+                    )
+                };
+
+                let stamp = match backend {
+                    CodegenBackendKind::Cranelift => {
+                        builder.ensure(CraneliftCodegenBackend { compilers: prepare_compilers() })
+                    }
+                    CodegenBackendKind::Gcc => {
+                        builder.ensure(GccCodegenBackend { compilers: prepare_compilers() })
+                    }
+                    CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue,
+                };
+                codegen_backend_stamps.push(stamp);
             }
-            builder.ensure(CodegenBackend {
-                compilers: RustcPrivateCompilers::from_build_and_target_compiler(
-                    build_compiler,
-                    target_compiler,
-                ),
-                backend: backend.clone(),
-            });
         }
-        #[cfg(feature = "tracing")]
-        drop(_codegen_backend_span);
 
         let stage = target_compiler.stage;
         let host = target_compiler.host;
@@ -2260,7 +2286,9 @@ impl Step for Assemble {
         }
 
         debug!("copying codegen backends to sysroot");
-        copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
+        for stamp in codegen_backend_stamps {
+            copy_codegen_backends_to_sysroot(builder, stamp, target_compiler);
+        }
 
         if builder.config.lld_enabled {
             let lld_wrapper =
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index cbbfb6b6a11..3fbc8cdbcd5 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1389,38 +1389,39 @@ impl Step for Miri {
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct CodegenBackend {
-    pub compiler: Compiler,
-    pub backend: CodegenBackendKind,
+pub struct CraneliftCodegenBackend {
+    pub build_compiler: Compiler,
 }
 
-impl Step for CodegenBackend {
+impl Step for CraneliftCodegenBackend {
     type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("compiler/rustc_codegen_cranelift")
+        // We only want to build the cranelift backend in `x dist` if the backend was enabled
+        // in rust.codegen-backends.
+        // Sadly, we don't have access to the actual target for which we're disting clif here..
+        // So we just use the host target.
+        let clif_enabled_by_default = run
+            .builder
+            .config
+            .enabled_codegen_backends(run.builder.host_target)
+            .contains(&CodegenBackendKind::Cranelift);
+        run.alias("rustc_codegen_cranelift").default_condition(clif_enabled_by_default)
     }
 
     fn make_run(run: RunConfig<'_>) {
-        for backend in run.builder.config.codegen_backends(run.target) {
-            if backend.is_llvm() {
-                continue; // Already built as part of rustc
-            }
-
-            run.builder.ensure(CodegenBackend {
-                compiler: run.builder.compiler(run.builder.top_stage, run.target),
-                backend: backend.clone(),
-            });
-        }
+        run.builder.ensure(CraneliftCodegenBackend {
+            build_compiler: run.builder.compiler_for(
+                run.builder.top_stage,
+                run.builder.config.host_target,
+                run.target,
+            ),
+        });
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        if builder.config.dry_run() {
-            return None;
-        }
-
         // This prevents rustc_codegen_cranelift from being built for "dist"
         // or "install" on the stable/beta channels. It is not yet stable and
         // should not be included.
@@ -1428,46 +1429,39 @@ impl Step for CodegenBackend {
             return None;
         }
 
-        if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend) {
-            return None;
-        }
-
-        if self.backend.is_cranelift() && !target_supports_cranelift_backend(self.compiler.host) {
+        let target = self.build_compiler.host;
+        let compilers =
+            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
+        if !target_supports_cranelift_backend(target) {
             builder.info("target not supported by rustc_codegen_cranelift. skipping");
             return None;
         }
 
-        let compiler = self.compiler;
-        let backend = self.backend;
+        let mut tarball = Tarball::new(builder, "rustc-codegen-cranelift", &target.triple);
+        tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
+        tarball.is_preview(true);
+        tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
 
-        let mut tarball = Tarball::new(
-            builder,
-            &format!("rustc-codegen-{}", backend.name()),
-            &compiler.host.triple,
-        );
-        if backend.is_cranelift() {
-            tarball.set_overlay(OverlayKind::RustcCodegenCranelift);
-        } else {
-            panic!("Unknown codegen backend {}", backend.name());
+        builder.ensure(compile::CraneliftCodegenBackend { compilers });
+
+        if builder.config.dry_run() {
+            return None;
         }
-        tarball.is_preview(true);
-        tarball.add_legal_and_readme_to(format!("share/doc/{}", backend.crate_name()));
 
-        let src = builder.sysroot(compiler);
-        let backends_src = builder.sysroot_codegen_backends(compiler);
+        let src = builder.sysroot(self.build_compiler);
+        let backends_src = builder.sysroot_codegen_backends(self.build_compiler);
         let backends_rel = backends_src
             .strip_prefix(src)
             .unwrap()
-            .strip_prefix(builder.sysroot_libdir_relative(compiler))
+            .strip_prefix(builder.sysroot_libdir_relative(self.build_compiler))
             .unwrap();
         // Don't use custom libdir here because ^lib/ will be resolved again with installer
         let backends_dst = PathBuf::from("lib").join(backends_rel);
 
-        let backend_name = backend.crate_name();
         let mut found_backend = false;
         for backend in fs::read_dir(&backends_src).unwrap() {
             let file_name = backend.unwrap().file_name();
-            if file_name.to_str().unwrap().contains(&backend_name) {
+            if file_name.to_str().unwrap().contains("rustc_codegen_cranelift") {
                 tarball.add_file(
                     backends_src.join(file_name),
                     &backends_dst,
@@ -1480,6 +1474,13 @@ impl Step for CodegenBackend {
 
         Some(tarball.generate())
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(
+            StepMetadata::dist("rustc_codegen_cranelift", self.build_compiler.host)
+                .built_by(self.build_compiler),
+        )
+    }
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -1590,9 +1591,8 @@ impl Step for Extended {
         add_component!("clippy" => Clippy { build_compiler: compiler, target });
         add_component!("miri" => Miri { build_compiler: compiler, target });
         add_component!("analysis" => Analysis { compiler, target });
-        add_component!("rustc-codegen-cranelift" => CodegenBackend {
-            compiler: builder.compiler(stage, target),
-            backend: CodegenBackendKind::Cranelift,
+        add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
+            build_compiler: compiler,
         });
         add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
             build_compiler: compiler,
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index f628330e9ed..acee78dcf59 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -12,7 +12,7 @@ use crate::core::config::{Config, TargetSelection};
 use crate::utils::exec::command;
 use crate::utils::helpers::t;
 use crate::utils::tarball::GeneratedTarball;
-use crate::{CodegenBackendKind, Compiler, Kind};
+use crate::{Compiler, Kind};
 
 #[cfg(target_os = "illumos")]
 const SHELL: &str = "bash";
@@ -274,9 +274,8 @@ install!((self, builder, _config),
         install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball);
     };
     RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), only_hosts: true, {
-        if let Some(tarball) = builder.ensure(dist::CodegenBackend {
-            compiler: self.compiler,
-            backend: CodegenBackendKind::Cranelift,
+        if let Some(tarball) = builder.ensure(dist::CraneliftCodegenBackend {
+            build_compiler: self.compiler,
         }) {
             install_sh(builder, "rustc-codegen-cranelift", self.compiler.stage, Some(self.target), &tarball);
         } else {
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 721ba6ca459..065a39a4e71 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -986,6 +986,7 @@ impl Step for Enzyme {
             .env("LLVM_CONFIG_REAL", &llvm_config)
             .define("LLVM_ENABLE_ASSERTIONS", "ON")
             .define("ENZYME_EXTERNAL_SHARED_LIB", "ON")
+            .define("ENZYME_BC_LOADER", "OFF")
             .define("LLVM_DIR", builder.llvm_out(target));
 
         cfg.build();
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 66332c0b3e8..32c3ef53e12 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -3478,7 +3478,11 @@ impl Step for CodegenCranelift {
             return;
         }
 
-        if !builder.config.codegen_backends(run.target).contains(&CodegenBackendKind::Cranelift) {
+        if !builder
+            .config
+            .enabled_codegen_backends(run.target)
+            .contains(&CodegenBackendKind::Cranelift)
+        {
             builder.info("cranelift not in rust.codegen-backends. skipping");
             return;
         }
@@ -3605,7 +3609,7 @@ impl Step for CodegenGCC {
             return;
         }
 
-        if !builder.config.codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
+        if !builder.config.enabled_codegen_backends(run.target).contains(&CodegenBackendKind::Gcc) {
             builder.info("gcc not in rust.codegen-backends. skipping");
             return;
         }
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 7b0ef942abe..aa00cd03c5b 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -334,7 +334,8 @@ pub fn prepare_tool_cargo(
 /// Determines how to build a `ToolTarget`, i.e. which compiler should be used to compile it.
 /// The compiler stage is automatically bumped if we need to cross-compile a stage 1 tool.
 pub enum ToolTargetBuildMode {
-    /// Build the tool using rustc that corresponds to the selected CLI stage.
+    /// Build the tool for the given `target` using rustc that corresponds to the top CLI
+    /// stage.
     Build(TargetSelection),
     /// Build the tool so that it can be attached to the sysroot of the passed compiler.
     /// Since we always dist stage 2+, the compiler that builds the tool in this case has to be
@@ -366,7 +367,10 @@ pub(crate) fn get_tool_target_compiler(
     } else {
         // If we are cross-compiling a stage 1 tool, we cannot do that with a stage 0 compiler,
         // so we auto-bump the tool's stage to 2, which means we need a stage 1 compiler.
-        builder.compiler(build_compiler_stage.max(1), builder.host_target)
+        let build_compiler = builder.compiler(build_compiler_stage.max(1), builder.host_target);
+        // We also need the host stdlib to compile host code (proc macros/build scripts)
+        builder.std(build_compiler, builder.host_target);
+        build_compiler
     };
     builder.std(compiler, target);
     compiler
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index e15941938f1..163a498d4b4 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -959,7 +959,8 @@ impl<'a> Builder<'a> {
                 compile::Std,
                 compile::Rustc,
                 compile::Assemble,
-                compile::CodegenBackend,
+                compile::CraneliftCodegenBackend,
+                compile::GccCodegenBackend,
                 compile::StartupObjects,
                 tool::BuildManifest,
                 tool::Rustbook,
@@ -1150,7 +1151,7 @@ impl<'a> Builder<'a> {
                 dist::JsonDocs,
                 dist::Mingw,
                 dist::Rustc,
-                dist::CodegenBackend,
+                dist::CraneliftCodegenBackend,
                 dist::Std,
                 dist::RustcDev,
                 dist::Analysis,
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 5361347da90..4c7766e58c1 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -976,6 +976,22 @@ mod snapshot {
     }
 
     #[test]
+    fn build_cargo_cross() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("build")
+                .paths(&["cargo"])
+                .hosts(&[TEST_TRIPLE_1])
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 1 <host> -> std 1 <target1>
+        [build] rustc 1 <host> -> cargo 2 <target1>
+        ");
+    }
+
+    #[test]
     fn dist_default_stage() {
         let ctx = TestCtx::new();
         assert_eq!(ctx.config("dist").path("compiler").create_config().stage, 2);
@@ -1272,6 +1288,42 @@ mod snapshot {
         ");
     }
 
+    // Enable dist cranelift tarball by default with `x dist` if cranelift is enabled in
+    // `rust.codegen-backends`.
+    #[test]
+    fn dist_cranelift_by_default() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx
+                .config("dist")
+                .args(&["--set", "rust.codegen-backends=['llvm', 'cranelift']"])
+                .render_steps(), @r"
+        [build] rustc 0 <host> -> UnstableBookGen 1 <host>
+        [build] rustc 0 <host> -> Rustbook 1 <host>
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 0 <host> -> rustc_codegen_cranelift 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 1 <host> -> rustc 2 <host>
+        [build] rustc 1 <host> -> rustc_codegen_cranelift 2 <host>
+        [build] rustdoc 2 <host>
+        [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+        [build] rustc 1 <host> -> error-index 2 <host>
+        [doc] rustc 1 <host> -> error-index 2 <host>
+        [build] rustc 2 <host> -> std 2 <host>
+        [build] rustc 0 <host> -> LintDocs 1 <host>
+        [build] rustc 0 <host> -> RustInstaller 1 <host>
+        [dist] docs <host>
+        [doc] std 2 <host> crates=[]
+        [dist] mingw <host>
+        [build] rustc 0 <host> -> GenerateCopyright 1 <host>
+        [dist] rustc <host>
+        [dist] rustc 1 <host> -> rustc_codegen_cranelift 2 <host>
+        [dist] rustc 1 <host> -> std 1 <host>
+        [dist] src <>
+        ");
+    }
+
     #[test]
     fn check_compiler_no_explicit_stage() {
         let ctx = TestCtx::new();
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 2c008f957d9..eb1ac8c637f 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1977,19 +1977,24 @@ impl Config {
             .unwrap_or(self.profiler)
     }
 
-    pub fn codegen_backends(&self, target: TargetSelection) -> &[CodegenBackendKind] {
+    /// Returns codegen backends that should be:
+    /// - Built and added to the sysroot when we build the compiler.
+    /// - Distributed when `x dist` is executed (if the codegen backend has a dist step).
+    pub fn enabled_codegen_backends(&self, target: TargetSelection) -> &[CodegenBackendKind] {
         self.target_config
             .get(&target)
             .and_then(|cfg| cfg.codegen_backends.as_deref())
             .unwrap_or(&self.rust_codegen_backends)
     }
 
-    pub fn jemalloc(&self, target: TargetSelection) -> bool {
-        self.target_config.get(&target).and_then(|cfg| cfg.jemalloc).unwrap_or(self.jemalloc)
+    /// Returns the codegen backend that should be configured as the *default* codegen backend
+    /// for a rustc compiled by bootstrap.
+    pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<CodegenBackendKind> {
+        self.enabled_codegen_backends(target).first().cloned()
     }
 
-    pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<CodegenBackendKind> {
-        self.codegen_backends(target).first().cloned()
+    pub fn jemalloc(&self, target: TargetSelection) -> bool {
+        self.target_config.get(&target).and_then(|cfg| cfg.jemalloc).unwrap_or(self.jemalloc)
     }
 
     pub fn rpath_enabled(&self, target: TargetSelection) -> bool {
@@ -2004,7 +2009,7 @@ impl Config {
     }
 
     pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
-        self.codegen_backends(target).contains(&CodegenBackendKind::Llvm)
+        self.enabled_codegen_backends(target).contains(&CodegenBackendKind::Llvm)
     }
 
     pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {
diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs
index b95fb236fa1..3dab8d1d96d 100644
--- a/src/bootstrap/src/core/config/toml/rust.rs
+++ b/src/bootstrap/src/core/config/toml/rust.rs
@@ -3,7 +3,6 @@
 
 use serde::{Deserialize, Deserializer};
 
-use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX;
 use crate::core::config::toml::TomlConfig;
 use crate::core::config::{DebuginfoLevel, Merge, ReplaceOpt, StringOrBool};
 use crate::{BTreeSet, CodegenBackendKind, HashSet, PathBuf, TargetSelection, define_config, exit};
@@ -391,6 +390,8 @@ pub(crate) fn parse_codegen_backends(
     backends: Vec<String>,
     section: &str,
 ) -> Vec<CodegenBackendKind> {
+    const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
+
     let mut found_backends = vec![];
     for backend in &backends {
         if let Some(stripped) = backend.strip_prefix(CODEGEN_BACKEND_PREFIX) {
diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
index d4b71dbd4f4..c6f68f7a1e8 100644
--- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md
+++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
@@ -56,6 +56,17 @@ Rust programs can be built for these targets by specifying `--target`, if
 $ rustc --target aarch64-apple-ios-macabi your-code.rs
 ```
 
+The target can be differentiated from the iOS targets with the
+`target_env = "macabi"` cfg (or `target_abi = "macabi"` before Rust CURRENT_RUSTC_VERSION).
+
+```rust
+if cfg!(target_env = "macabi") {
+    // Do something only on Mac Catalyst.
+}
+```
+
+This is similar to the `TARGET_OS_MACCATALYST` define in C code.
+
 ## Testing
 
 Mac Catalyst binaries can be run directly on macOS 10.15 Catalina or newer.
diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md
index 64325554ab6..586afa65226 100644
--- a/src/doc/rustc/src/platform-support/apple-ios.md
+++ b/src/doc/rustc/src/platform-support/apple-ios.md
@@ -66,6 +66,20 @@ Rust programs can be built for these targets by specifying `--target`, if
 $ rustc --target aarch64-apple-ios your-code.rs
 ```
 
+The simulator variants can be differentiated from the variants running
+on-device with the `target_env = "sim"` cfg (or `target_abi = "sim"` before
+Rust CURRENT_RUSTC_VERSION).
+
+```rust
+if cfg!(all(target_vendor = "apple", target_env = "sim")) {
+    // Do something on the iOS/tvOS/visionOS/watchOS Simulator.
+} {
+    // Everything else, like Windows and non-Simulator iOS.
+}
+```
+
+This is similar to the `TARGET_OS_SIMULATOR` define in C code.
+
 ## Testing
 
 There is no support for running the Rust or standard library testsuite at the
diff --git a/src/doc/unstable-book/src/compiler-environment-variables/COLORTERM.md b/src/doc/unstable-book/src/compiler-environment-variables/COLORTERM.md
new file mode 100644
index 00000000000..f5be63b796c
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-environment-variables/COLORTERM.md
@@ -0,0 +1,5 @@
+# `COLORTERM`
+
+This environment variable is used by [`-Zterminal-urls`] to detect if URLs are supported by the terminal emulator.
+
+[`-Zterminal-urls`]: ../compiler-flags/terminal-urls.html
diff --git a/src/doc/unstable-book/src/compiler-environment-variables/QNX_TARGET.md b/src/doc/unstable-book/src/compiler-environment-variables/QNX_TARGET.md
new file mode 100644
index 00000000000..46511598e70
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-environment-variables/QNX_TARGET.md
@@ -0,0 +1,11 @@
+# `QNX_TARGET`
+
+----
+
+This environment variable is mandatory when linking on `nto-qnx*_iosock` platforms. It is used to determine an `-L` path to pass to the QNX linker.
+
+You should [set this variable] by running `source qnxsdp-env.sh`.
+See [the QNX docs] for more background information.
+
+[set this variable]: https://www.qnx.com/developers/docs/qsc/com.qnx.doc.qsc.inst_larg_org/topic/build_server_developer_steps.html
+[the QNX docs]: https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.io_sock/topic/migrate_app.html.
diff --git a/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md b/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md
new file mode 100644
index 00000000000..be9ed02f54d
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-environment-variables/SDKROOT.md
@@ -0,0 +1,6 @@
+# `SDKROOT`
+
+This environment variable is used on Apple targets.
+It is passed through to the linker (currently either as `-isysroot` or `-syslibroot`).
+
+Note that this variable is not always respected. When the SDKROOT is clearly wrong (e.g. when the platform of the SDK does not match the `--target` used by rustc), this is ignored and rustc does its own detection.
diff --git a/src/doc/unstable-book/src/compiler-environment-variables/TERM.md b/src/doc/unstable-book/src/compiler-environment-variables/TERM.md
new file mode 100644
index 00000000000..9208fd378a3
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-environment-variables/TERM.md
@@ -0,0 +1,5 @@
+# `TERM`
+
+This environment variable is used by [`-Zterminal-urls`] to detect if URLs are supported by the terminal emulator.
+
+[`-Zterminal-urls`]: ../compiler-flags/terminal-urls.html
diff --git a/src/doc/unstable-book/src/compiler-flags/terminal-urls.md b/src/doc/unstable-book/src/compiler-flags/terminal-urls.md
new file mode 100644
index 00000000000..a5427978f25
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/terminal-urls.md
@@ -0,0 +1,13 @@
+# `-Z terminal-urls`
+
+The tracking feature for this issue is [#125586]
+
+[#125586]: https://github.com/rust-lang/rust/issues/125586
+
+---
+
+This flag takes either a boolean or the string "auto".
+
+When enabled, use the OSC 8 hyperlink terminal specification to print hyperlinks in the compiler output.
+Use "auto" to try and autodetect whether the terminal emulator supports hyperlinks.
+Currently, "auto" only enables hyperlinks if `COLORTERM=truecolor` and `TERM=xterm-256color`.
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
index 121f9493435..d9566c9f55c 100644
--- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -19,7 +19,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 - M68k
 - CSKY
 - SPARC
-- LoongArch32
 
 ## Register classes
 
@@ -54,8 +53,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | CSKY         | `freg`         | `f[0-31]`                          | `f`                  |
 | SPARC        | `reg`          | `r[2-29]`                          | `r`                  |
 | SPARC        | `yreg`         | `y`                                | Only clobbers        |
-| LoongArch32  | `reg`          | `$r1`, `$r[4-20]`, `$r[23,30]`     | `r`                  |
-| LoongArch32  | `freg`         | `$f[0-31]`                         | `f`                  |
 
 > **Notes**:
 > - NVPTX doesn't have a fixed register set, so named registers are not supported.
@@ -94,8 +91,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | CSKY         | `freg`                          | None           | `f32`,                                  |
 | SPARC        | `reg`                           | None           | `i8`, `i16`, `i32`, `i64` (SPARC64 only) |
 | SPARC        | `yreg`                          | N/A            | Only clobbers                           |
-| LoongArch32  | `reg`                           | None           | `i8`, `i16`, `i32`, `f32`               |
-| LoongArch32  | `freg`                          | None           | `f32`, `f64`                            |
 
 ## Register aliases
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 743ed2b5045..7194c2fcede 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1662,7 +1662,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
             }
 
             let trait_segments = &p.segments[..p.segments.len() - 1];
-            let trait_def = cx.tcx.associated_item(p.res.def_id()).container_id(cx.tcx);
+            let trait_def = cx.tcx.parent(p.res.def_id());
             let trait_ = self::Path {
                 res: Res::Def(DefKind::Trait, trait_def),
                 segments: trait_segments.iter().map(|x| clean_path_segment(x, cx)).collect(),
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 80399cf3842..918b292466d 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -602,6 +602,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It
         search_type,
         aliases,
         deprecation,
+        is_unstable: item.stability(tcx).map(|x| x.is_unstable()).unwrap_or(false),
     };
     cache.search_index.push(index_item);
 }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index a46253237db..95259847075 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -139,6 +139,7 @@ pub(crate) struct IndexItem {
     pub(crate) search_type: Option<IndexItemFunctionType>,
     pub(crate) aliases: Box<[Symbol]>,
     pub(crate) deprecation: Option<Deprecation>,
+    pub(crate) is_unstable: bool,
 }
 
 /// A type used for the search index.
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index e2f86b8a854..93c9df8c049 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -93,6 +93,7 @@ pub(crate) fn build_index(
                 ),
                 aliases: item.attrs.get_doc_aliases(),
                 deprecation: item.deprecation(tcx),
+                is_unstable: item.stability(tcx).is_some_and(|x| x.is_unstable()),
             });
         }
     }
@@ -655,6 +656,7 @@ pub(crate) fn build_index(
             let mut parents_backref_queue = VecDeque::new();
             let mut functions = String::with_capacity(self.items.len());
             let mut deprecated = Vec::with_capacity(self.items.len());
+            let mut unstable = Vec::with_capacity(self.items.len());
 
             let mut type_backref_queue = VecDeque::new();
 
@@ -711,6 +713,9 @@ pub(crate) fn build_index(
                     // bitmasks always use 1-indexing for items, with 0 as the crate itself
                     deprecated.push(u32::try_from(index + 1).unwrap());
                 }
+                if item.is_unstable {
+                    unstable.push(u32::try_from(index + 1).unwrap());
+                }
             }
 
             for (index, path) in &revert_extra_paths {
@@ -749,6 +754,7 @@ pub(crate) fn build_index(
             crate_data.serialize_field("r", &re_exports)?;
             crate_data.serialize_field("b", &self.associated_item_disambiguators)?;
             crate_data.serialize_field("c", &bitmap_to_string(&deprecated))?;
+            crate_data.serialize_field("u", &bitmap_to_string(&unstable))?;
             crate_data.serialize_field("e", &bitmap_to_string(&self.empty_desc))?;
             crate_data.serialize_field("P", &param_names)?;
             if has_aliases {
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index a9589764547..b082b65ab57 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -449,6 +449,8 @@ declare namespace rustdoc {
      * of `p`) but is used for modules items like free functions.
      *
      * `c` is an array of item indices that are deprecated.
+     *
+     * `u` is an array of item indices that are unstable.
      */
     type RawSearchIndexCrate = {
     doc: string,
@@ -463,6 +465,7 @@ declare namespace rustdoc {
     p: Array<[number, string] | [number, string, number] | [number, string, number, number] | [number, string, number, number, string]>,
     b: Array<[number, String]>,
     c: string,
+    u: string,
     r: Array<[number, number]>,
     P: Array<[number, string]>,
     };
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 2caf214ff73..10e01b4e262 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -1465,6 +1465,11 @@ class DocSearch {
          */
         this.searchIndexEmptyDesc = new Map();
         /**
+         * @type {Map<String, RoaringBitmap>}
+         */
+        this.searchIndexUnstable = new Map();
+
+        /**
          *  @type {Uint32Array}
          */
         this.functionTypeFingerprint = new Uint32Array(0);
@@ -2052,9 +2057,10 @@ class DocSearch {
             };
             const descShardList = [descShard];
 
-            // Deprecated items and items with no description
+            // Deprecated and unstable items and items with no description
             this.searchIndexDeprecated.set(crate, new RoaringBitmap(crateCorpus.c));
             this.searchIndexEmptyDesc.set(crate, new RoaringBitmap(crateCorpus.e));
+            this.searchIndexUnstable.set(crate, new RoaringBitmap(crateCorpus.u));
             let descIndex = 0;
 
             /**
@@ -3326,6 +3332,25 @@ class DocSearch {
                     return a - b;
                 }
 
+                // sort unstable items later
+                // FIXME: there is some doubt if this is the most effecient way to implement this.
+                // alternative options include:
+                // * put is_unstable on each item when the index is built.
+                //   increases memory usage but avoids a hashmap lookup.
+                // * put is_unstable on each item before sorting.
+                //   better worst case performance but worse average case performance.
+                a = Number(
+                    // @ts-expect-error
+                    this.searchIndexUnstable.get(aaa.item.crate).contains(aaa.item.bitIndex),
+                );
+                b = Number(
+                    // @ts-expect-error
+                    this.searchIndexUnstable.get(bbb.item.crate).contains(bbb.item.bitIndex),
+                );
+                if (a !== b) {
+                    return a - b;
+                }
+
                 // sort by crate (current crate comes first)
                 a = Number(aaa.item.crate !== preferredCrate);
                 b = Number(bbb.item.crate !== preferredCrate);
@@ -3340,6 +3365,13 @@ class DocSearch {
                     return a - b;
                 }
 
+                // sort doc alias items later
+                a = Number(aaa.item.is_alias === true);
+                b = Number(bbb.item.is_alias === true);
+                if (a !== b) {
+                    return a - b;
+                }
+
                 // sort by item name (lexicographically larger goes later)
                 let aw = aaa.word;
                 let bw = bbb.word;
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index 38cf7e3822a..07a8eb5d886 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use rustc_ast::node_id::{NodeId, NodeMap};
-use rustc_ast::ptr::P;
 use rustc_ast::visit::{Visitor, walk_expr};
 use rustc_ast::{Crate, Expr, ExprKind, Item, ItemKind, MacroDef, ModKind, Ty, TyKind, UseTreeKind};
 use rustc_errors::Applicability;
@@ -124,7 +123,7 @@ impl Visitor<'_> for ImportUsageVisitor {
 }
 
 impl SingleComponentPathImports {
-    fn check_mod(&mut self, items: &[P<Item>]) {
+    fn check_mod(&mut self, items: &[Box<Item>]) {
         // keep track of imports reused with `self` keyword, such as `self::crypto_hash` in the example
         // below. Removing the `use crypto_hash;` would make this a compile error
         // ```
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index bd8420917f5..e9ad578da2f 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -7,13 +7,14 @@ use clippy_utils::msrvs::{self, MsrvStack};
 use clippy_utils::over;
 use rustc_ast::PatKind::*;
 use rustc_ast::mut_visit::*;
-use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, DUMMY_NODE_ID, Mutability, Pat, PatKind};
 use rustc_ast_pretty::pprust;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::DUMMY_SP;
+// import needed to shadow `PatKind::Box` glob-imported above
+use std::boxed::Box;
 use std::cell::Cell;
 use std::mem;
 use thin_vec::{ThinVec, thin_vec};
@@ -97,7 +98,7 @@ fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
         return;
     }
 
-    let mut pat = P(pat.clone());
+    let mut pat = Box::new(pat.clone());
 
     // Nix all the paren patterns everywhere so that they aren't in our way.
     remove_all_parens(&mut pat);
@@ -119,7 +120,7 @@ fn lint_unnested_or_patterns(cx: &EarlyContext<'_>, pat: &Pat) {
 }
 
 /// Remove all `(p)` patterns in `pat`.
-fn remove_all_parens(pat: &mut P<Pat>) {
+fn remove_all_parens(pat: &mut Box<Pat>) {
     #[derive(Default)]
     struct Visitor {
         /// If is not in the outer most pattern. This is needed to avoid removing the outermost
@@ -142,7 +143,7 @@ fn remove_all_parens(pat: &mut P<Pat>) {
 }
 
 /// Insert parens where necessary according to Rust's precedence rules for patterns.
-fn insert_necessary_parens(pat: &mut P<Pat>) {
+fn insert_necessary_parens(pat: &mut Box<Pat>) {
     struct Visitor;
     impl MutVisitor for Visitor {
         fn visit_pat(&mut self, pat: &mut Pat) {
@@ -154,7 +155,7 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
                 Ref(p, Mutability::Not) if matches!(p.kind, Ident(BindingMode::MUT, ..)) => p, // `&(mut x)`
                 _ => return,
             };
-            target.kind = Paren(P(take_pat(target)));
+            target.kind = Paren(Box::new(take_pat(target)));
         }
     }
     Visitor.visit_pat(pat);
@@ -162,7 +163,7 @@ fn insert_necessary_parens(pat: &mut P<Pat>) {
 
 /// Unnest or-patterns `p0 | ... | p1` in the pattern `pat`.
 /// For example, this would transform `Some(0) | FOO | Some(2)` into `Some(0 | 2) | FOO`.
-fn unnest_or_patterns(pat: &mut P<Pat>) -> bool {
+fn unnest_or_patterns(pat: &mut Box<Pat>) -> bool {
     struct Visitor {
         changed: bool,
     }
@@ -222,7 +223,7 @@ macro_rules! always_pat {
 /// Focus on `focus_idx` in `alternatives`,
 /// attempting to extend it with elements of the same constructor `C`
 /// in `alternatives[focus_idx + 1..]`.
-fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: usize) -> bool {
+fn transform_with_focus_on_idx(alternatives: &mut ThinVec<Box<Pat>>, focus_idx: usize) -> bool {
     // Extract the kind; we'll need to make some changes in it.
     let mut focus_kind = mem::replace(&mut alternatives[focus_idx].kind, Wild);
     // We'll focus on `alternatives[focus_idx]`,
@@ -303,12 +304,12 @@ fn transform_with_focus_on_idx(alternatives: &mut ThinVec<P<Pat>>, focus_idx: us
 /// So when we fixate on some `ident_k: pat_k`, we try to find `ident_k` in the other pattern
 /// and check that all `fp_i` where `i ∈ ((0...n) \ k)` between two patterns are equal.
 fn extend_with_struct_pat(
-    qself1: Option<&P<ast::QSelf>>,
+    qself1: Option<&Box<ast::QSelf>>,
     path1: &ast::Path,
     fps1: &mut [ast::PatField],
     rest1: ast::PatFieldsRest,
     start: usize,
-    alternatives: &mut ThinVec<P<Pat>>,
+    alternatives: &mut ThinVec<Box<Pat>>,
 ) -> bool {
     (0..fps1.len()).any(|idx| {
         let pos_in_2 = Cell::new(None); // The element `k`.
@@ -346,11 +347,11 @@ fn extend_with_struct_pat(
 /// while also requiring `ps1[..n] ~ ps2[..n]` (pre) and `ps1[n + 1..] ~ ps2[n + 1..]` (post),
 /// where `~` denotes semantic equality.
 fn extend_with_matching_product(
-    targets: &mut [P<Pat>],
+    targets: &mut [Box<Pat>],
     start: usize,
-    alternatives: &mut ThinVec<P<Pat>>,
-    predicate: impl Fn(&PatKind, &[P<Pat>], usize) -> bool,
-    extract: impl Fn(PatKind) -> ThinVec<P<Pat>>,
+    alternatives: &mut ThinVec<Box<Pat>>,
+    predicate: impl Fn(&PatKind, &[Box<Pat>], usize) -> bool,
+    extract: impl Fn(PatKind) -> ThinVec<Box<Pat>>,
 ) -> bool {
     (0..targets.len()).any(|idx| {
         let tail_or = drain_matching(
@@ -377,14 +378,14 @@ fn take_pat(from: &mut Pat) -> Pat {
 
 /// Extend `target` as an or-pattern with the alternatives
 /// in `tail_or` if there are any and return if there were.
-fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<P<Pat>>) -> bool {
-    fn extend(target: &mut Pat, mut tail_or: ThinVec<P<Pat>>) {
+fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<Box<Pat>>) -> bool {
+    fn extend(target: &mut Pat, mut tail_or: ThinVec<Box<Pat>>) {
         match target {
             // On an existing or-pattern in the target, append to it.
             Pat { kind: Or(ps), .. } => ps.append(&mut tail_or),
             // Otherwise convert the target to an or-pattern.
             target => {
-                let mut init_or = thin_vec![P(take_pat(target))];
+                let mut init_or = thin_vec![Box::new(take_pat(target))];
                 init_or.append(&mut tail_or);
                 target.kind = Or(init_or);
             },
@@ -403,10 +404,10 @@ fn extend_with_tail_or(target: &mut Pat, tail_or: ThinVec<P<Pat>>) -> bool {
 // Only elements beginning with `start` are considered for extraction.
 fn drain_matching(
     start: usize,
-    alternatives: &mut ThinVec<P<Pat>>,
+    alternatives: &mut ThinVec<Box<Pat>>,
     predicate: impl Fn(&PatKind) -> bool,
-    extract: impl Fn(PatKind) -> P<Pat>,
-) -> ThinVec<P<Pat>> {
+    extract: impl Fn(PatKind) -> Box<Pat>,
+) -> ThinVec<Box<Pat>> {
     let mut tail_or = ThinVec::new();
     let mut idx = 0;
 
@@ -438,15 +439,15 @@ fn drain_matching(
 fn extend_with_matching(
     target: &mut Pat,
     start: usize,
-    alternatives: &mut ThinVec<P<Pat>>,
+    alternatives: &mut ThinVec<Box<Pat>>,
     predicate: impl Fn(&PatKind) -> bool,
-    extract: impl Fn(PatKind) -> P<Pat>,
+    extract: impl Fn(PatKind) -> Box<Pat>,
 ) -> bool {
     extend_with_tail_or(target, drain_matching(start, alternatives, predicate, extract))
 }
 
 /// Are the patterns in `ps1` and `ps2` equal save for `ps1[idx]` compared to `ps2[idx]`?
-fn eq_pre_post(ps1: &[P<Pat>], ps2: &[P<Pat>], idx: usize) -> bool {
+fn eq_pre_post(ps1: &[Box<Pat>], ps2: &[Box<Pat>], idx: usize) -> bool {
     ps1.len() == ps2.len()
         && ps1[idx].is_rest() == ps2[idx].is_rest() // Avoid `[x, ..] | [x, 0]` => `[x, .. | 0]`.
         && over(&ps1[..idx], &ps2[..idx], |l, r| eq_pat(l, r))
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 96f0273c439..0312bf56e59 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -5,7 +5,6 @@
 #![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
 
 use crate::{both, over};
-use rustc_ast::ptr::P;
 use rustc_ast::{self as ast, *};
 use rustc_span::symbol::Ident;
 use std::mem;
@@ -83,11 +82,11 @@ pub fn eq_field_pat(l: &PatField, r: &PatField) -> bool {
         && over(&l.attrs, &r.attrs, eq_attr)
 }
 
-pub fn eq_qself(l: &P<QSelf>, r: &P<QSelf>) -> bool {
+pub fn eq_qself(l: &Box<QSelf>, r: &Box<QSelf>) -> bool {
     l.position == r.position && eq_ty(&l.ty, &r.ty)
 }
 
-pub fn eq_maybe_qself(l: Option<&P<QSelf>>, r: Option<&P<QSelf>>) -> bool {
+pub fn eq_maybe_qself(l: Option<&Box<QSelf>>, r: Option<&Box<QSelf>>) -> bool {
     match (l, r) {
         (Some(l), Some(r)) => eq_qself(l, r),
         (None, None) => true,
@@ -130,7 +129,7 @@ pub fn eq_generic_arg(l: &GenericArg, r: &GenericArg) -> bool {
     }
 }
 
-pub fn eq_expr_opt(l: Option<&P<Expr>>, r: Option<&P<Expr>>) -> bool {
+pub fn eq_expr_opt(l: Option<&Box<Expr>>, r: Option<&Box<Expr>>) -> bool {
     both(l, r, |l, r| eq_expr(l, r))
 }
 
@@ -727,7 +726,7 @@ pub fn eq_fn_header(l: &FnHeader, r: &FnHeader) -> bool {
 }
 
 #[expect(clippy::ref_option, reason = "This is the type how it is stored in the AST")]
-pub fn eq_opt_fn_contract(l: &Option<P<FnContract>>, r: &Option<P<FnContract>>) -> bool {
+pub fn eq_opt_fn_contract(l: &Option<Box<FnContract>>, r: &Option<Box<FnContract>>) -> bool {
     match (l, r) {
         (Some(l), Some(r)) => {
             eq_expr_opt(l.requires.as_ref(), r.requires.as_ref()) && eq_expr_opt(l.ensures.as_ref(), r.ensures.as_ref())
diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs
index 30d8537b51a..33a02eb29fd 100644
--- a/src/tools/compiletest/src/directives/tests.rs
+++ b/src/tools/compiletest/src/directives/tests.rs
@@ -637,6 +637,7 @@ fn matches_env() {
         ("x86_64-unknown-linux-gnu", "gnu"),
         ("x86_64-fortanix-unknown-sgx", "sgx"),
         ("arm-unknown-linux-musleabi", "musl"),
+        ("aarch64-apple-ios-macabi", "macabi"),
     ];
     for (target, env) in envs {
         let config: Config = cfg().target(target).build();
@@ -647,11 +648,7 @@ fn matches_env() {
 
 #[test]
 fn matches_abi() {
-    let abis = [
-        ("aarch64-apple-ios-macabi", "macabi"),
-        ("x86_64-unknown-linux-gnux32", "x32"),
-        ("arm-unknown-linux-gnueabi", "eabi"),
-    ];
+    let abis = [("x86_64-unknown-linux-gnux32", "x32"), ("arm-unknown-linux-gnueabi", "eabi")];
     for (target, abi) in abis {
         let config: Config = cfg().target(target).build();
         assert!(config.matches_abi(abi), "{target} {abi}");
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index f283a625f97..debf67e2741 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1766,7 +1766,7 @@ impl<'test> TestCx<'test> {
 
         match self.config.compare_mode {
             Some(CompareMode::Polonius) => {
-                rustc.args(&["-Zpolonius"]);
+                rustc.args(&["-Zpolonius=next"]);
             }
             Some(CompareMode::NextSolver) => {
                 rustc.args(&["-Znext-solver"]);
diff --git a/src/tools/enzyme b/src/tools/enzyme
-Subproject 2cccfba93c1650f26f1cf8be8aa875a7c1d23fb
+Subproject 58af4e9e6c047534ba059b12af17cecb8a2e9f9
diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs
index bcc3e9ec885..e6341252927 100644
--- a/src/tools/miri/src/intrinsics/atomic.rs
+++ b/src/tools/miri/src/intrinsics/atomic.rs
@@ -105,27 +105,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             "or" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord))?;
             }
             "xor" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord))?;
             }
             "and" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord))?;
             }
             "nand" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord))?;
             }
             "xadd" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord))?;
             }
             "xsub" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord))?;
             }
             "min" => {
@@ -231,15 +231,14 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
         let place = this.deref_pointer(place)?;
         let rhs = this.read_immediate(rhs)?;
 
-        if !place.layout.ty.is_integral() && !place.layout.ty.is_raw_ptr() {
+        if !(place.layout.ty.is_integral() || place.layout.ty.is_raw_ptr())
+            || !(rhs.layout.ty.is_integral() || rhs.layout.ty.is_raw_ptr())
+        {
             span_bug!(
                 this.cur_span(),
                 "atomic arithmetic operations only work on integer and raw pointer types",
             );
         }
-        if rhs.layout.ty != place.layout.ty {
-            span_bug!(this.cur_span(), "atomic arithmetic operation type mismatch");
-        }
 
         let old = match atomic_op {
             AtomicOp::Min =>
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index 73d671121f6..3c3f2c28535 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -50,17 +50,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             // Some more operations are possible with atomics.
-            // The return value always has the provenance of the *left* operand.
+            // The RHS must be `usize`.
             Add | Sub | BitOr | BitAnd | BitXor => {
                 assert!(left.layout.ty.is_raw_ptr());
-                assert!(right.layout.ty.is_raw_ptr());
+                assert_eq!(right.layout.ty, this.tcx.types.usize);
                 let ptr = left.to_scalar().to_pointer(this)?;
                 // We do the actual operation with usize-typed scalars.
                 let left = ImmTy::from_uint(ptr.addr().bytes(), this.machine.layouts.usize);
-                let right = ImmTy::from_uint(
-                    right.to_scalar().to_target_usize(this)?,
-                    this.machine.layouts.usize,
-                );
                 let result = this.binary_op(bin_op, &left, &right)?;
                 // Construct a new pointer with the provenance of `ptr` (the LHS).
                 let result_ptr = Pointer::new(
diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr
index 29c56ca81f7..a2a4be30eca 100644
--- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr
+++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr
@@ -11,7 +11,7 @@ note: inside `_::__rg_oom`
   --> tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC
    |
 LL | #[alloc_error_handler]
-   | ---------------------- in this procedural macro expansion
+   | ---------------------- in this attribute macro expansion
 LL | fn alloc_error_handler(layout: Layout) -> ! {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs
index bdff671802c..4e525be3fe3 100644
--- a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs
@@ -127,11 +127,11 @@ where
 
 // The following items are what `rustc` macro can be parsed into :
 // link: https://github.com/rust-lang/rust/blob/9ebf47851a357faa4cd97f4b1dc7835f6376e639/src/libsyntax/ext/expand.rs#L141
-// * Expr(P<ast::Expr>)                     -> token_tree_to_expr
-// * Pat(P<ast::Pat>)                       -> token_tree_to_pat
-// * Ty(P<ast::Ty>)                         -> token_tree_to_ty
+// * Expr(Box<ast::Expr>)                     -> token_tree_to_expr
+// * Pat(Box<ast::Pat>)                       -> token_tree_to_pat
+// * Ty(Box<ast::Ty>)                         -> token_tree_to_ty
 // * Stmts(SmallVec<[ast::Stmt; 1]>)        -> token_tree_to_stmts
-// * Items(SmallVec<[P<ast::Item>; 1]>)     -> token_tree_to_items
+// * Items(SmallVec<[Box<ast::Item>; 1]>)     -> token_tree_to_items
 //
 // * TraitItems(SmallVec<[ast::TraitItem; 1]>)
 // * AssocItems(SmallVec<[ast::AssocItem; 1]>)
diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs
index 034ecde068a..2f388197ea1 100644
--- a/src/tools/rustfmt/src/chains.rs
+++ b/src/tools/rustfmt/src/chains.rs
@@ -58,7 +58,7 @@
 use std::borrow::Cow;
 use std::cmp::min;
 
-use rustc_ast::{ast, ptr};
+use rustc_ast::ast;
 use rustc_span::{BytePos, Span, symbol};
 use tracing::debug;
 
@@ -187,7 +187,7 @@ enum ChainItemKind {
     MethodCall(
         ast::PathSegment,
         Vec<ast::GenericArg>,
-        ThinVec<ptr::P<ast::Expr>>,
+        ThinVec<Box<ast::Expr>>,
     ),
     StructField(symbol::Ident),
     TupleField(symbol::Ident, bool),
@@ -343,7 +343,7 @@ impl ChainItem {
     fn rewrite_method_call(
         method_name: symbol::Ident,
         types: &[ast::GenericArg],
-        args: &[ptr::P<ast::Expr>],
+        args: &[Box<ast::Expr>],
         span: Span,
         context: &RewriteContext<'_>,
         shape: Shape,
diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index 61e148cdf18..bb10a7946b8 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -1,4 +1,4 @@
-use rustc_ast::{ast, ptr};
+use rustc_ast::ast;
 use rustc_span::Span;
 use thin_vec::thin_vec;
 use tracing::debug;
@@ -165,7 +165,7 @@ fn rewrite_closure_with_block(
     let block = ast::Block {
         stmts: thin_vec![ast::Stmt {
             id: ast::NodeId::root(),
-            kind: ast::StmtKind::Expr(ptr::P(body.clone())),
+            kind: ast::StmtKind::Expr(Box::new(body.clone())),
             span: body.span,
         }],
         id: ast::NodeId::root(),
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 08aedff2b20..975f9be44e4 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -3,7 +3,7 @@ use std::cmp::min;
 
 use itertools::Itertools;
 use rustc_ast::token::{Delimiter, Lit, LitKind};
-use rustc_ast::{ForLoopKind, MatchKind, ast, ptr, token};
+use rustc_ast::{ForLoopKind, MatchKind, ast, token};
 use rustc_span::{BytePos, Span};
 use tracing::debug;
 
@@ -1368,7 +1368,7 @@ fn choose_separator_tactic(context: &RewriteContext<'_>, span: Span) -> Option<S
 pub(crate) fn rewrite_call(
     context: &RewriteContext<'_>,
     callee: &str,
-    args: &[ptr::P<ast::Expr>],
+    args: &[Box<ast::Expr>],
     span: Span,
     shape: Shape,
 ) -> RewriteResult {
@@ -1634,7 +1634,7 @@ fn struct_lit_can_be_aligned(fields: &[ast::ExprField], has_base: bool) -> bool
 fn rewrite_struct_lit<'a>(
     context: &RewriteContext<'_>,
     path: &ast::Path,
-    qself: &Option<ptr::P<ast::QSelf>>,
+    qself: &Option<Box<ast::QSelf>>,
     fields: &'a [ast::ExprField],
     struct_rest: &ast::StructRest,
     attrs: &[ast::Attribute],
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 7084639aca9..57d4142ebe4 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -4,8 +4,8 @@ use std::borrow::Cow;
 use std::cmp::{Ordering, max, min};
 
 use regex::Regex;
+use rustc_ast::ast;
 use rustc_ast::visit;
-use rustc_ast::{ast, ptr};
 use rustc_span::{BytePos, DUMMY_SP, Ident, Span, symbol};
 use tracing::debug;
 
@@ -725,9 +725,9 @@ impl<'a> FmtVisitor<'a> {
             .ok()
     }
 
-    fn visit_impl_items(&mut self, items: &[ptr::P<ast::AssocItem>]) {
+    fn visit_impl_items(&mut self, items: &[Box<ast::AssocItem>]) {
         if self.get_context().config.reorder_impl_items() {
-            type TyOpt = Option<ptr::P<ast::Ty>>;
+            type TyOpt = Option<Box<ast::Ty>>;
             use crate::ast::AssocItemKind::*;
             let is_type = |ty: &TyOpt| opaque_ty(ty).is_none();
             let is_opaque = |ty: &TyOpt| opaque_ty(ty).is_some();
@@ -934,7 +934,7 @@ pub(crate) fn format_impl(
 
 fn is_impl_single_line(
     context: &RewriteContext<'_>,
-    items: &[ptr::P<ast::AssocItem>],
+    items: &[Box<ast::AssocItem>],
     result: &str,
     where_clause_str: &str,
     item: &ast::Item,
@@ -2024,7 +2024,7 @@ pub(crate) struct StaticParts<'a> {
     generics: Option<&'a ast::Generics>,
     ty: &'a ast::Ty,
     mutability: ast::Mutability,
-    expr_opt: Option<&'a ptr::P<ast::Expr>>,
+    expr_opt: Option<&'a Box<ast::Expr>>,
     defaultness: Option<ast::Defaultness>,
     span: Span,
 }
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index 0ff0aad7a2d..2e7ac90f596 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -12,9 +12,9 @@
 use std::collections::HashMap;
 use std::panic::{AssertUnwindSafe, catch_unwind};
 
+use rustc_ast::ast;
 use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree};
-use rustc_ast::{ast, ptr};
 use rustc_ast_pretty::pprust;
 use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol};
 use tracing::debug;
@@ -53,10 +53,10 @@ pub(crate) enum MacroPosition {
 
 #[derive(Debug)]
 pub(crate) enum MacroArg {
-    Expr(ptr::P<ast::Expr>),
-    Ty(ptr::P<ast::Ty>),
-    Pat(ptr::P<ast::Pat>),
-    Item(ptr::P<ast::Item>),
+    Expr(Box<ast::Expr>),
+    Ty(Box<ast::Ty>),
+    Pat(Box<ast::Pat>),
+    Item(Box<ast::Item>),
     Keyword(Ident, Span),
 }
 
diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs
index 8f62648e576..209cb2f9287 100644
--- a/src/tools/rustfmt/src/matches.rs
+++ b/src/tools/rustfmt/src/matches.rs
@@ -2,7 +2,7 @@
 
 use std::iter::repeat;
 
-use rustc_ast::{MatchKind, ast, ptr};
+use rustc_ast::{MatchKind, ast};
 use rustc_span::{BytePos, Span};
 use tracing::debug;
 
@@ -394,7 +394,7 @@ fn flatten_arm_body<'a>(
 
 fn rewrite_match_body(
     context: &RewriteContext<'_>,
-    body: &ptr::P<ast::Expr>,
+    body: &Box<ast::Expr>,
     pats_str: &str,
     shape: Shape,
     has_guard: bool,
@@ -569,7 +569,7 @@ fn rewrite_match_body(
 // The `if ...` guard on a match arm.
 fn rewrite_guard(
     context: &RewriteContext<'_>,
-    guard: &Option<ptr::P<ast::Expr>>,
+    guard: &Option<Box<ast::Expr>>,
     shape: Shape,
     // The amount of space used up on this line for the pattern in
     // the arm (excludes offset).
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 44c8123517c..3bc656b64b3 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -26,7 +26,7 @@ type FileModMap<'ast> = BTreeMap<FileName, Module<'ast>>;
 #[derive(Debug, Clone)]
 pub(crate) struct Module<'a> {
     ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
-    pub(crate) items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
+    pub(crate) items: Cow<'a, ThinVec<Box<ast::Item>>>,
     inner_attr: ast::AttrVec,
     pub(crate) span: Span,
 }
@@ -35,7 +35,7 @@ impl<'a> Module<'a> {
     pub(crate) fn new(
         mod_span: Span,
         ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
-        mod_items: Cow<'a, ThinVec<rustc_ast::ptr::P<ast::Item>>>,
+        mod_items: Cow<'a, ThinVec<Box<ast::Item>>>,
         mod_attrs: Cow<'a, ast::AttrVec>,
     ) -> Self {
         let inner_attr = mod_attrs
@@ -170,7 +170,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
     /// Visit modules defined inside macro calls.
     fn visit_mod_outside_ast(
         &mut self,
-        items: ThinVec<rustc_ast::ptr::P<ast::Item>>,
+        items: ThinVec<Box<ast::Item>>,
     ) -> Result<(), ModuleResolutionError> {
         for item in items {
             if is_cfg_if(&item) {
@@ -197,7 +197,7 @@ impl<'ast, 'psess, 'c> ModResolver<'ast, 'psess> {
     /// Visit modules from AST.
     fn visit_mod_from_ast(
         &mut self,
-        items: &'ast [rustc_ast::ptr::P<ast::Item>],
+        items: &'ast [Box<ast::Item>],
     ) -> Result<(), ModuleResolutionError> {
         for item in items {
             if is_cfg_if(item) {
diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs
index 728adff2c7d..bb1ebc87f67 100644
--- a/src/tools/rustfmt/src/overflow.rs
+++ b/src/tools/rustfmt/src/overflow.rs
@@ -3,8 +3,8 @@
 use std::cmp::min;
 
 use itertools::Itertools;
+use rustc_ast::ast;
 use rustc_ast::token::Delimiter;
-use rustc_ast::{ast, ptr};
 use rustc_span::Span;
 use tracing::debug;
 
@@ -219,7 +219,7 @@ pub(crate) trait IntoOverflowableItem<'a>: Rewrite + Spanned {
     fn into_overflowable_item(&'a self) -> OverflowableItem<'a>;
 }
 
-impl<'a, T: 'a + IntoOverflowableItem<'a>> IntoOverflowableItem<'a> for ptr::P<T> {
+impl<'a, T: 'a + IntoOverflowableItem<'a>> IntoOverflowableItem<'a> for Box<T> {
     fn into_overflowable_item(&'a self) -> OverflowableItem<'a> {
         (**self).into_overflowable_item()
     }
diff --git a/src/tools/rustfmt/src/parse/macros/lazy_static.rs b/src/tools/rustfmt/src/parse/macros/lazy_static.rs
index cbe81004e22..8611615d123 100644
--- a/src/tools/rustfmt/src/parse/macros/lazy_static.rs
+++ b/src/tools/rustfmt/src/parse/macros/lazy_static.rs
@@ -1,5 +1,4 @@
 use rustc_ast::ast;
-use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_parse::exp;
@@ -10,7 +9,7 @@ use crate::rewrite::RewriteContext;
 pub(crate) fn parse_lazy_static(
     context: &RewriteContext<'_>,
     ts: TokenStream,
-) -> Option<Vec<(ast::Visibility, symbol::Ident, P<ast::Ty>, P<ast::Expr>)>> {
+) -> Option<Vec<(ast::Visibility, symbol::Ident, Box<ast::Ty>, Box<ast::Expr>)>> {
     let mut result = vec![];
     let mut parser = super::build_parser(context, ts);
     macro_rules! parse_or {
diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs
index d7964484b26..724d7a09e4a 100644
--- a/src/tools/rustfmt/src/parse/macros/mod.rs
+++ b/src/tools/rustfmt/src/parse/macros/mod.rs
@@ -1,6 +1,6 @@
+use rustc_ast::ast;
 use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::{ast, ptr};
 use rustc_parse::MACRO_ARGUMENTS;
 use rustc_parse::parser::{ForceCollect, Parser, Recovery};
 use rustc_session::parse::ParseSess;
@@ -49,26 +49,26 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
         Expr,
         NonterminalKind::Expr(Expr),
         |parser: &mut Parser<'b>| parser.parse_expr(),
-        |x: ptr::P<ast::Expr>| Some(x)
+        |x: Box<ast::Expr>| Some(x)
     );
     parse_macro_arg!(
         Ty,
         NonterminalKind::Ty,
         |parser: &mut Parser<'b>| parser.parse_ty(),
-        |x: ptr::P<ast::Ty>| Some(x)
+        |x: Box<ast::Ty>| Some(x)
     );
     parse_macro_arg!(
         Pat,
         NonterminalKind::Pat(PatParam { inferred: false }),
         |parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None),
-        |x: ptr::P<ast::Pat>| Some(x)
+        |x: Box<ast::Pat>| Some(x)
     );
-    // `parse_item` returns `Option<ptr::P<ast::Item>>`.
+    // `parse_item` returns `Option<Box<ast::Item>>`.
     parse_macro_arg!(
         Item,
         NonterminalKind::Item,
         |parser: &mut Parser<'b>| parser.parse_item(ForceCollect::No),
-        |x: Option<ptr::P<ast::Item>>| x
+        |x: Option<Box<ast::Item>>| x
     );
 
     None
@@ -164,7 +164,7 @@ pub(crate) fn parse_macro_args(
 pub(crate) fn parse_expr(
     context: &RewriteContext<'_>,
     tokens: TokenStream,
-) -> Option<ptr::P<ast::Expr>> {
+) -> Option<Box<ast::Expr>> {
     let mut parser = build_parser(context, tokens);
     parser.parse_expr().ok()
 }
diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index f357aed66c2..2ec8769c45f 100644
--- a/src/tools/rustfmt/src/parse/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -1,7 +1,7 @@
 use std::panic::{AssertUnwindSafe, catch_unwind};
 use std::path::{Path, PathBuf};
 
-use rustc_ast::{ast, attr, ptr};
+use rustc_ast::{ast, attr};
 use rustc_errors::Diag;
 use rustc_parse::parser::Parser as RawParser;
 use rustc_parse::{exp, new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
@@ -102,7 +102,7 @@ impl<'a> Parser<'a> {
         psess: &'a ParseSess,
         path: &Path,
         span: Span,
-    ) -> Result<(ast::AttrVec, ThinVec<ptr::P<ast::Item>>, Span), ParserError> {
+    ) -> Result<(ast::AttrVec, ThinVec<Box<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
             let mut parser =
                 unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span)));
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index cb3879f4be8..d212ecf392a 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -1,5 +1,4 @@
 use rustc_ast::ast::{self, BindingMode, ByRef, Pat, PatField, PatKind, RangeEnd, RangeSyntax};
-use rustc_ast::ptr;
 use rustc_span::{BytePos, Span};
 
 use crate::comment::{FindUncommented, combine_strs_with_missing_comments};
@@ -77,7 +76,7 @@ fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool
 }
 
 pub(crate) struct RangeOperand<'a, T> {
-    pub operand: &'a Option<ptr::P<T>>,
+    pub operand: &'a Option<Box<T>>,
     pub span: Span,
 }
 
@@ -329,8 +328,8 @@ impl Rewrite for Pat {
 pub fn rewrite_range_pat<T: Rewrite>(
     context: &RewriteContext<'_>,
     shape: Shape,
-    lhs: &Option<ptr::P<T>>,
-    rhs: &Option<ptr::P<T>>,
+    lhs: &Option<Box<T>>,
+    rhs: &Option<Box<T>>,
     end_kind: &rustc_span::source_map::Spanned<RangeEnd>,
     span: Span,
 ) -> RewriteResult {
@@ -371,7 +370,7 @@ pub fn rewrite_range_pat<T: Rewrite>(
 }
 
 fn rewrite_struct_pat(
-    qself: &Option<ptr::P<ast::QSelf>>,
+    qself: &Option<Box<ast::QSelf>>,
     path: &ast::Path,
     fields: &[ast::PatField],
     ellipsis: bool,
@@ -505,7 +504,7 @@ impl Rewrite for PatField {
 
 #[derive(Debug)]
 pub(crate) enum TuplePatField<'a> {
-    Pat(&'a ptr::P<ast::Pat>),
+    Pat(&'a Box<ast::Pat>),
     Dotdot(Span),
 }
 
@@ -562,7 +561,7 @@ pub(crate) fn can_be_overflowed_pat(
 }
 
 fn rewrite_tuple_pat(
-    pats: &[ptr::P<ast::Pat>],
+    pats: &[Box<ast::Pat>],
     path_str: Option<String>,
     span: Span,
     context: &RewriteContext<'_>,
diff --git a/src/tools/rustfmt/src/rewrite.rs b/src/tools/rustfmt/src/rewrite.rs
index 83020709797..f0accd62d1a 100644
--- a/src/tools/rustfmt/src/rewrite.rs
+++ b/src/tools/rustfmt/src/rewrite.rs
@@ -3,7 +3,6 @@
 use std::cell::{Cell, RefCell};
 use std::rc::Rc;
 
-use rustc_ast::ptr;
 use rustc_span::Span;
 use thiserror::Error;
 
@@ -24,7 +23,7 @@ pub(crate) trait Rewrite {
     }
 }
 
-impl<T: Rewrite> Rewrite for ptr::P<T> {
+impl<T: Rewrite> Rewrite for Box<T> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         (**self).rewrite(context, shape)
     }
diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs
index ac132999b62..020651e2daa 100644
--- a/src/tools/rustfmt/src/spanned.rs
+++ b/src/tools/rustfmt/src/spanned.rs
@@ -1,6 +1,6 @@
 use std::cmp::max;
 
-use rustc_ast::{ast, ptr};
+use rustc_ast::ast;
 use rustc_span::{Span, source_map};
 
 use crate::macros::MacroArg;
@@ -12,7 +12,7 @@ pub(crate) trait Spanned {
     fn span(&self) -> Span;
 }
 
-impl<T: Spanned> Spanned for ptr::P<T> {
+impl<T: Spanned> Spanned for Box<T> {
     fn span(&self) -> Span {
         (**self).span()
     }
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 9ee10d86270..5dce9a0c8d0 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -1,7 +1,6 @@
 use std::ops::Deref;
 
 use rustc_ast::ast::{self, FnRetTy, Mutability, Term};
-use rustc_ast::ptr;
 use rustc_span::{BytePos, Pos, Span, symbol::kw};
 use tracing::debug;
 
@@ -39,7 +38,7 @@ pub(crate) enum PathContext {
 pub(crate) fn rewrite_path(
     context: &RewriteContext<'_>,
     path_context: PathContext,
-    qself: &Option<ptr::P<ast::QSelf>>,
+    qself: &Option<Box<ast::QSelf>>,
     path: &ast::Path,
     shape: Shape,
 ) -> RewriteResult {
@@ -1340,7 +1339,7 @@ fn join_bounds_inner(
     }
 }
 
-pub(crate) fn opaque_ty(ty: &Option<ptr::P<ast::Ty>>) -> Option<&ast::GenericBounds> {
+pub(crate) fn opaque_ty(ty: &Option<Box<ast::Ty>>) -> Option<&ast::GenericBounds> {
     ty.as_ref().and_then(|t| match &t.kind {
         ast::TyKind::ImplTrait(_, bounds) => Some(bounds),
         _ => None,
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index fcd475b1784..b9950e94d0c 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -1,10 +1,10 @@
 use std::borrow::Cow;
 
+use rustc_ast::YieldKind;
 use rustc_ast::ast::{
     self, Attribute, MetaItem, MetaItemInner, MetaItemKind, NodeId, Path, Visibility,
     VisibilityKind,
 };
-use rustc_ast::{YieldKind, ptr};
 use rustc_ast_pretty::pprust;
 use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol};
 use unicode_width::UnicodeWidthStr;
@@ -149,8 +149,8 @@ pub(crate) fn format_extern(ext: ast::Extern, explicit_abi: bool) -> Cow<'static
 }
 
 #[inline]
-// Transform `Vec<rustc_ast::ptr::P<T>>` into `Vec<&T>`
-pub(crate) fn ptr_vec_to_ref_vec<T>(vec: &[ptr::P<T>]) -> Vec<&T> {
+// Transform `Vec<Box<T>>` into `Vec<&T>`
+pub(crate) fn ptr_vec_to_ref_vec<T>(vec: &[Box<T>]) -> Vec<&T> {
     vec.iter().map(|x| &**x).collect::<Vec<_>>()
 }
 
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index f6a9a3f2cd1..23d07c930d9 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -874,7 +874,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
         !is_skip_attr(segments)
     }
 
-    fn walk_mod_items(&mut self, items: &[rustc_ast::ptr::P<ast::Item>]) {
+    fn walk_mod_items(&mut self, items: &[Box<ast::Item>]) {
         self.visit_items_with_reordering(&ptr_vec_to_ref_vec(items));
     }
 
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index fb00b3a943f..6618ba24be6 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -9,6 +9,7 @@
 //! * All unstable lang features have tests to ensure they are actually unstable.
 //! * Language features in a group are sorted by feature name.
 
+use std::collections::BTreeSet;
 use std::collections::hash_map::{Entry, HashMap};
 use std::ffi::OsStr;
 use std::num::NonZeroU32;
@@ -21,6 +22,7 @@ use crate::walk::{filter_dirs, filter_not_rust, walk, walk_many};
 mod tests;
 
 mod version;
+use regex::Regex;
 use version::Version;
 
 const FEATURE_GROUP_START_PREFIX: &str = "// feature-group-start";
@@ -623,3 +625,36 @@ fn map_lib_features(
         },
     );
 }
+
+fn should_document(var: &str) -> bool {
+    if var.starts_with("RUSTC_") || var.starts_with("RUST_") || var.starts_with("UNSTABLE_RUSTDOC_")
+    {
+        return true;
+    }
+    ["SDKROOT", "QNX_TARGET", "COLORTERM", "TERM"].contains(&var)
+}
+
+pub fn collect_env_vars(compiler: &Path) -> BTreeSet<String> {
+    let env_var_regex: Regex = Regex::new(r#"env::var(_os)?\("([^"]+)"#).unwrap();
+
+    let mut vars = BTreeSet::new();
+    walk(
+        compiler,
+        // skip build scripts, tests, and non-rust files
+        |path, _is_dir| {
+            filter_dirs(path)
+                || filter_not_rust(path)
+                || path.ends_with("build.rs")
+                || path.ends_with("tests.rs")
+        },
+        &mut |_entry, contents| {
+            for env_var in env_var_regex.captures_iter(contents).map(|c| c.get(2).unwrap().as_str())
+            {
+                if should_document(env_var) {
+                    vars.insert(env_var.to_owned());
+                }
+            }
+        },
+    );
+    vars
+}
diff --git a/src/tools/tidy/src/unstable_book.rs b/src/tools/tidy/src/unstable_book.rs
index 9dc9d42d466..0ed954d48de 100644
--- a/src/tools/tidy/src/unstable_book.rs
+++ b/src/tools/tidy/src/unstable_book.rs
@@ -6,6 +6,8 @@ use crate::features::{CollectedFeatures, Features, Status};
 
 pub const PATH_STR: &str = "doc/unstable-book";
 
+pub const ENV_VARS_DIR: &str = "src/compiler-environment-variables";
+
 pub const COMPILER_FLAGS_DIR: &str = "src/compiler-flags";
 
 pub const LANG_FEATURES_DIR: &str = "src/language-features";
diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs
index 159a1d0fa17..a7c6173d88c 100644
--- a/src/tools/unstable-book-gen/src/main.rs
+++ b/src/tools/unstable-book-gen/src/main.rs
@@ -5,11 +5,11 @@ use std::env;
 use std::fs::{self, write};
 use std::path::Path;
 
-use tidy::features::{Features, collect_lang_features, collect_lib_features};
+use tidy::features::{Features, collect_env_vars, collect_lang_features, collect_lib_features};
 use tidy::t;
 use tidy::unstable_book::{
-    LANG_FEATURES_DIR, LIB_FEATURES_DIR, PATH_STR, collect_unstable_book_section_file_names,
-    collect_unstable_feature_names,
+    ENV_VARS_DIR, LANG_FEATURES_DIR, LIB_FEATURES_DIR, PATH_STR,
+    collect_unstable_book_section_file_names, collect_unstable_feature_names,
 };
 
 fn generate_stub_issue(path: &Path, name: &str, issue: u32, description: &str) {
@@ -27,6 +27,11 @@ fn generate_stub_no_issue(path: &Path, name: &str, description: &str) {
     t!(write(path, content), path);
 }
 
+fn generate_stub_env_var(path: &Path, name: &str) {
+    let content = format!(include_str!("stub-env-var.md"), name = name);
+    t!(write(path, content), path);
+}
+
 fn set_to_summary_str(set: &BTreeSet<String>, dir: &str) -> String {
     set.iter()
         .map(|ref n| format!("    - [{}]({}/{}.md)", n.replace('-', "_"), dir, n))
@@ -59,7 +64,7 @@ fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Featur
     t!(write(&summary_path, content), summary_path);
 }
 
-fn generate_unstable_book_files(src: &Path, out: &Path, features: &Features) {
+fn generate_feature_files(src: &Path, out: &Path, features: &Features) {
     let unstable_features = collect_unstable_feature_names(features);
     let unstable_section_file_names = collect_unstable_book_section_file_names(src);
     t!(fs::create_dir_all(&out));
@@ -83,6 +88,16 @@ fn generate_unstable_book_files(src: &Path, out: &Path, features: &Features) {
     }
 }
 
+fn generate_env_files(src: &Path, out: &Path, env_vars: &BTreeSet<String>) {
+    let env_var_file_names = collect_unstable_book_section_file_names(src);
+    t!(fs::create_dir_all(&out));
+    for env_var in env_vars - &env_var_file_names {
+        let file_name = format!("{env_var}.md");
+        let out_file_path = out.join(&file_name);
+        generate_stub_env_var(&out_file_path, &env_var);
+    }
+}
+
 fn copy_recursive(from: &Path, to: &Path) {
     for entry in t!(fs::read_dir(from)) {
         let e = t!(entry);
@@ -112,21 +127,23 @@ fn main() {
         .into_iter()
         .filter(|&(ref name, _)| !lang_features.contains_key(name))
         .collect();
+    let env_vars = collect_env_vars(compiler_path);
 
     let doc_src_path = src_path.join(PATH_STR);
 
     t!(fs::create_dir_all(&dest_path));
 
-    generate_unstable_book_files(
+    generate_feature_files(
         &doc_src_path.join(LANG_FEATURES_DIR),
         &dest_path.join(LANG_FEATURES_DIR),
         &lang_features,
     );
-    generate_unstable_book_files(
+    generate_feature_files(
         &doc_src_path.join(LIB_FEATURES_DIR),
         &dest_path.join(LIB_FEATURES_DIR),
         &lib_features,
     );
+    generate_env_files(&doc_src_path.join(ENV_VARS_DIR), &dest_path.join(ENV_VARS_DIR), &env_vars);
 
     copy_recursive(&doc_src_path, &dest_path);
 
diff --git a/src/tools/unstable-book-gen/src/stub-env-var.md b/src/tools/unstable-book-gen/src/stub-env-var.md
new file mode 100644
index 00000000000..e8a7ddb855a
--- /dev/null
+++ b/src/tools/unstable-book-gen/src/stub-env-var.md
@@ -0,0 +1,9 @@
+# `{name}`
+
+Environment variables have no tracking issue. This environment variable has no documentation, and therefore is likely internal to the compiler and not meant for general use.
+
+See [the code][github search] for more information.
+
+[github search]: https://github.com/search?q=repo%3Arust-lang%2Frust+%22{name}%22+path%3Acompiler&type=code
+
+------------------------
diff --git a/tests/assembly-llvm/asm/loongarch-type.rs b/tests/assembly-llvm/asm/loongarch-type.rs
index c782be19f1d..95d811a6bd0 100644
--- a/tests/assembly-llvm/asm/loongarch-type.rs
+++ b/tests/assembly-llvm/asm/loongarch-type.rs
@@ -1,8 +1,15 @@
 //@ add-core-stubs
+//@ revisions: loongarch32 loongarch64
+
 //@ assembly-output: emit-asm
-//@ compile-flags: --target loongarch64-unknown-linux-gnu
+
+//@[loongarch32] compile-flags: --target loongarch32-unknown-none
+//@[loongarch32] needs-llvm-components: loongarch
+
+//@[loongarch64] compile-flags: --target loongarch64-unknown-none
+//@[loongarch64] needs-llvm-components: loongarch
+
 //@ compile-flags: -Zmerge-functions=disabled
-//@ needs-llvm-components: loongarch
 
 #![feature(no_core, f16)]
 #![crate_type = "rlib"]
@@ -22,7 +29,7 @@ extern "C" {
 // CHECK-LABEL: sym_fn:
 // CHECK: #APP
 // CHECK: pcalau12i $t0, %got_pc_hi20(extern_func)
-// CHECK: ld.d $t0, $t0, %got_pc_lo12(extern_func)
+// CHECK: ld.{{[wd]}} $t0, $t0, %got_pc_lo12(extern_func)
 // CHECK: #NO_APP
 #[no_mangle]
 pub unsafe fn sym_fn() {
@@ -32,7 +39,7 @@ pub unsafe fn sym_fn() {
 // CHECK-LABEL: sym_static:
 // CHECK: #APP
 // CHECK: pcalau12i $t0, %got_pc_hi20(extern_static)
-// CHECK: ld.d $t0, $t0, %got_pc_lo12(extern_static)
+// CHECK: ld.{{[wd]}} $t0, $t0, %got_pc_lo12(extern_static)
 // CHECK: #NO_APP
 #[no_mangle]
 pub unsafe fn sym_static() {
@@ -87,16 +94,18 @@ check!(reg_i32, i32, reg, "move");
 // CHECK: #NO_APP
 check!(reg_f32, f32, reg, "move");
 
-// CHECK-LABEL: reg_i64:
-// CHECK: #APP
-// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
-// CHECK: #NO_APP
+// loongarch64-LABEL: reg_i64:
+// loongarch64: #APP
+// loongarch64: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// loongarch64: #NO_APP
+#[cfg(loongarch64)]
 check!(reg_i64, i64, reg, "move");
 
-// CHECK-LABEL: reg_f64:
-// CHECK: #APP
-// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
-// CHECK: #NO_APP
+// loongarch64-LABEL: reg_f64:
+// loongarch64: #APP
+// loongarch64: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// loongarch64: #NO_APP
+#[cfg(loongarch64)]
 check!(reg_f64, f64, reg, "move");
 
 // CHECK-LABEL: reg_ptr:
@@ -153,16 +162,18 @@ check_reg!(r4_i32, i32, "$r4", "move");
 // CHECK: #NO_APP
 check_reg!(r4_f32, f32, "$r4", "move");
 
-// CHECK-LABEL: r4_i64:
-// CHECK: #APP
-// CHECK: move $a0, $a0
-// CHECK: #NO_APP
+// loongarch64-LABEL: r4_i64:
+// loongarch64: #APP
+// loongarch64: move $a0, $a0
+// loongarch64: #NO_APP
+#[cfg(loongarch64)]
 check_reg!(r4_i64, i64, "$r4", "move");
 
-// CHECK-LABEL: r4_f64:
-// CHECK: #APP
-// CHECK: move $a0, $a0
-// CHECK: #NO_APP
+// loongarch64-LABEL: r4_f64:
+// loongarch64: #APP
+// loongarch64: move $a0, $a0
+// loongarch64: #NO_APP
+#[cfg(loongarch64)]
 check_reg!(r4_f64, f64, "$r4", "move");
 
 // CHECK-LABEL: r4_ptr:
diff --git a/tests/codegen-llvm/atomicptr.rs b/tests/codegen-llvm/atomicptr.rs
index 4819af40ca2..ce6c4aa0d2b 100644
--- a/tests/codegen-llvm/atomicptr.rs
+++ b/tests/codegen-llvm/atomicptr.rs
@@ -1,5 +1,5 @@
 // LLVM does not support some atomic RMW operations on pointers, so inside codegen we lower those
-// to integer atomics, surrounded by casts to and from integer type.
+// to integer atomics, followed by an inttoptr cast.
 // This test ensures that we do the round-trip correctly for AtomicPtr::fetch_byte_add, and also
 // ensures that we do not have such a round-trip for AtomicPtr::swap, because LLVM supports pointer
 // arguments to `atomicrmw xchg`.
@@ -20,8 +20,8 @@ pub fn helper(_: usize) {}
 // CHECK-LABEL: @atomicptr_fetch_byte_add
 #[no_mangle]
 pub fn atomicptr_fetch_byte_add(a: &AtomicPtr<u8>, v: usize) -> *mut u8 {
-    // CHECK: %[[INTPTR:.*]] = ptrtoint ptr %{{.*}} to [[USIZE]]
-    // CHECK-NEXT: %[[RET:.*]] = atomicrmw add ptr %{{.*}}, [[USIZE]] %[[INTPTR]]
+    // CHECK: llvm.lifetime.start
+    // CHECK-NEXT: %[[RET:.*]] = atomicrmw add ptr %{{.*}}, [[USIZE]] %v
     // CHECK-NEXT: inttoptr [[USIZE]] %[[RET]] to ptr
     a.fetch_byte_add(v, Relaxed)
 }
diff --git a/tests/crashes/135528.rs b/tests/crashes/135528.rs
deleted file mode 100644
index 171550e209e..00000000000
--- a/tests/crashes/135528.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ known-bug: #135528
-//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
-#![feature(type_alias_impl_trait)]
-type Tait = impl Copy;
-
-fn set(x: &isize) -> isize {
-    *x
-}
-
-#[define_opaque(Tait)]
-fn d(x: Tait) {
-    set(x);
-}
-
-#[define_opaque(Tait)]
-fn other_define() -> Tait {
-    ()
-}
-
-fn main() {}
diff --git a/tests/crashes/135646.rs b/tests/crashes/135646.rs
deleted file mode 100644
index 841ea5b81b4..00000000000
--- a/tests/crashes/135646.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ known-bug: #135646
-//@ compile-flags: -Zpolonius=next
-//@ edition: 2024
-
-fn main() {
-    &{ [1, 2, 3][4] };
-}
diff --git a/tests/mir-opt/remove_unneeded_drop_in_place.rs b/tests/mir-opt/remove_unneeded_drop_in_place.rs
new file mode 100644
index 00000000000..470c6499d16
--- /dev/null
+++ b/tests/mir-opt/remove_unneeded_drop_in_place.rs
@@ -0,0 +1,17 @@
+//@ test-mir-pass: RemoveUnneededDrops
+//@ needs-unwind
+//@ compile-flags: -Z mir-opt-level=1
+
+// EMIT_MIR remove_unneeded_drop_in_place.slice_in_place.RemoveUnneededDrops.diff
+unsafe fn slice_in_place(ptr: *mut [char]) {
+    // CHECK-LABEL: fn slice_in_place(_1: *mut [char])
+    // CHECK: bb0: {
+    // CHECK-NEXT: return;
+    // CHECK-NEXT: }
+    std::ptr::drop_in_place(ptr)
+}
+
+fn main() {
+    let mut a = ['o', 'k'];
+    unsafe { slice_in_place(&raw mut a) };
+}
diff --git a/tests/mir-opt/remove_unneeded_drop_in_place.slice_in_place.RemoveUnneededDrops.diff b/tests/mir-opt/remove_unneeded_drop_in_place.slice_in_place.RemoveUnneededDrops.diff
new file mode 100644
index 00000000000..4d70e7151c3
--- /dev/null
+++ b/tests/mir-opt/remove_unneeded_drop_in_place.slice_in_place.RemoveUnneededDrops.diff
@@ -0,0 +1,20 @@
+- // MIR for `slice_in_place` before RemoveUnneededDrops
++ // MIR for `slice_in_place` after RemoveUnneededDrops
+  
+  fn slice_in_place(_1: *mut [char]) -> () {
+      debug ptr => _1;
+      let mut _0: ();
+      let mut _2: *mut [char];
+  
+      bb0: {
+          StorageLive(_2);
+          _2 = copy _1;
+-         _0 = drop_in_place::<[char]>(move _2) -> [return: bb1, unwind continue];
+-     }
+- 
+-     bb1: {
+          StorageDead(_2);
+          return;
+      }
+  }
+  
diff --git a/tests/run-make/atomic-lock-free/atomic_lock_free.rs b/tests/run-make/atomic-lock-free/atomic_lock_free.rs
index f5c3b360ee8..92ffd111ce8 100644
--- a/tests/run-make/atomic-lock-free/atomic_lock_free.rs
+++ b/tests/run-make/atomic-lock-free/atomic_lock_free.rs
@@ -14,7 +14,7 @@ pub enum AtomicOrdering {
 }
 
 #[rustc_intrinsic]
-unsafe fn atomic_xadd<T, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+unsafe fn atomic_xadd<T, U, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 #[lang = "pointee_sized"]
 pub trait PointeeSized {}
@@ -35,51 +35,62 @@ impl<T: ?Sized> Copy for *mut T {}
 impl ConstParamTy for AtomicOrdering {}
 
 #[cfg(target_has_atomic = "8")]
+#[unsafe(no_mangle)] // let's make sure we actually generate a symbol to check
 pub unsafe fn atomic_u8(x: *mut u8) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u8);
 }
 #[cfg(target_has_atomic = "8")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i8(x: *mut i8) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i8);
 }
 #[cfg(target_has_atomic = "16")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_u16(x: *mut u16) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u16);
 }
 #[cfg(target_has_atomic = "16")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i16(x: *mut i16) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i16);
 }
 #[cfg(target_has_atomic = "32")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_u32(x: *mut u32) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u32);
 }
 #[cfg(target_has_atomic = "32")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i32(x: *mut i32) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i32);
 }
 #[cfg(target_has_atomic = "64")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_u64(x: *mut u64) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u64);
 }
 #[cfg(target_has_atomic = "64")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i64(x: *mut i64) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i64);
 }
 #[cfg(target_has_atomic = "128")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_u128(x: *mut u128) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u128);
 }
 #[cfg(target_has_atomic = "128")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i128(x: *mut i128) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i128);
 }
 #[cfg(target_has_atomic = "ptr")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_usize(x: *mut usize) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1usize);
 }
 #[cfg(target_has_atomic = "ptr")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_isize(x: *mut isize) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1isize);
 }
diff --git a/tests/rustdoc-js-std/core-transmute.js b/tests/rustdoc-js-std/core-transmute.js
index 8c9910a32d7..b15f398902c 100644
--- a/tests/rustdoc-js-std/core-transmute.js
+++ b/tests/rustdoc-js-std/core-transmute.js
@@ -3,9 +3,9 @@ const EXPECTED = [
     {
         'query': 'generic:T -> generic:U',
         'others': [
+            { 'path': 'core::mem', 'name': 'transmute' },
             { 'path': 'core::intrinsics::simd', 'name': 'simd_as' },
             { 'path': 'core::intrinsics::simd', 'name': 'simd_cast' },
-            { 'path': 'core::mem', 'name': 'transmute' },
         ],
     },
 ];
diff --git a/tests/rustdoc-js-std/transmute-fail.js b/tests/rustdoc-js-std/transmute-fail.js
index ddfb2761948..459e8dc3f00 100644
--- a/tests/rustdoc-js-std/transmute-fail.js
+++ b/tests/rustdoc-js-std/transmute-fail.js
@@ -6,9 +6,9 @@ const EXPECTED = [
         // should-fail tag and the search query below:
         'query': 'generic:T -> generic:T',
         'others': [
+            { 'path': 'std::mem', 'name': 'transmute' },
             { 'path': 'std::intrinsics::simd', 'name': 'simd_as' },
             { 'path': 'std::intrinsics::simd', 'name': 'simd_cast' },
-            { 'path': 'std::mem', 'name': 'transmute' },
         ],
     },
 ];
diff --git a/tests/rustdoc-js-std/transmute.js b/tests/rustdoc-js-std/transmute.js
index f52e0ab1436..a85b02e2994 100644
--- a/tests/rustdoc-js-std/transmute.js
+++ b/tests/rustdoc-js-std/transmute.js
@@ -5,9 +5,9 @@ const EXPECTED = [
         // should-fail tag and the search query below:
         'query': 'generic:T -> generic:U',
         'others': [
+            { 'path': 'std::mem', 'name': 'transmute' },
             { 'path': 'std::intrinsics::simd', 'name': 'simd_as' },
             { 'path': 'std::intrinsics::simd', 'name': 'simd_cast' },
-            { 'path': 'std::mem', 'name': 'transmute' },
         ],
     },
 ];
diff --git a/tests/rustdoc-js/doc-alias-after-other-items.js b/tests/rustdoc-js/doc-alias-after-other-items.js
new file mode 100644
index 00000000000..5b22ef67698
--- /dev/null
+++ b/tests/rustdoc-js/doc-alias-after-other-items.js
@@ -0,0 +1,38 @@
+// exact-check
+
+// Checking that doc aliases are always listed after items with equivalent matching.
+
+const EXPECTED = [
+    {
+        'query': 'coo',
+        'others': [
+            {
+                'path': 'doc_alias_after_other_items',
+                'name': 'Foo',
+                'href': '../doc_alias_after_other_items/struct.Foo.html',
+            },
+            {
+                'path': 'doc_alias_after_other_items',
+                'name': 'bar',
+                'alias': 'Boo',
+                'is_alias': true
+            },
+        ],
+    },
+    {
+        'query': '"confiture"',
+        'others': [
+            {
+                'path': 'doc_alias_after_other_items',
+                'name': 'Confiture',
+                'href': '../doc_alias_after_other_items/struct.Confiture.html',
+            },
+            {
+                'path': 'doc_alias_after_other_items',
+                'name': 'this_is_a_long_name',
+                'alias': 'Confiture',
+                'is_alias': true
+            },
+        ],
+    },
+];
diff --git a/tests/rustdoc-js/doc-alias-after-other-items.rs b/tests/rustdoc-js/doc-alias-after-other-items.rs
new file mode 100644
index 00000000000..2ed555c8e2f
--- /dev/null
+++ b/tests/rustdoc-js/doc-alias-after-other-items.rs
@@ -0,0 +1,9 @@
+pub struct Foo;
+
+#[doc(alias = "Boo")]
+pub fn bar() {}
+
+pub struct Confiture;
+
+#[doc(alias = "Confiture")]
+pub fn this_is_a_long_name() {}
diff --git a/tests/rustdoc-js/sort-stability.js b/tests/rustdoc-js/sort-stability.js
new file mode 100644
index 00000000000..8c095619a08
--- /dev/null
+++ b/tests/rustdoc-js/sort-stability.js
@@ -0,0 +1,9 @@
+const EXPECTED = [
+    {
+        'query': 'foo',
+        'others': [
+            {"path": "sort_stability::old", "name": "foo"},
+            {"path": "sort_stability::new", "name": "foo"},
+        ],
+    },
+];
diff --git a/tests/rustdoc-js/sort-stability.rs b/tests/rustdoc-js/sort-stability.rs
new file mode 100644
index 00000000000..68662bb3aab
--- /dev/null
+++ b/tests/rustdoc-js/sort-stability.rs
@@ -0,0 +1,16 @@
+#![feature(staged_api)]
+#![stable(feature = "foo_lib", since = "1.0.0")]
+
+#[stable(feature = "old_foo", since = "1.0.1")]
+pub mod old {
+    /// Old, stable foo
+    #[stable(feature = "old_foo", since = "1.0.1")]
+    pub fn foo() {}
+}
+
+#[unstable(feature = "new_foo", issue = "none")]
+pub mod new {
+    /// New, unstable foo
+    #[unstable(feature = "new_foo", issue = "none")]
+    pub fn foo() {}
+}
diff --git a/tests/ui-fulldeps/auxiliary/parser.rs b/tests/ui-fulldeps/auxiliary/parser.rs
index 8a370512460..6726969350d 100644
--- a/tests/ui-fulldeps/auxiliary/parser.rs
+++ b/tests/ui-fulldeps/auxiliary/parser.rs
@@ -10,7 +10,6 @@ extern crate rustc_span;
 use rustc_ast::ast::{AttrKind, Attribute, DUMMY_NODE_ID, Expr};
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::node_id::NodeId;
-use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Token};
 use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, LazyAttrTokenStream};
 use rustc_errors::Diag;
@@ -19,7 +18,7 @@ use rustc_session::parse::ParseSess;
 use rustc_span::{AttrId, DUMMY_SP, FileName, Span};
 use std::sync::Arc;
 
-pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<P<Expr>> {
+pub fn parse_expr(psess: &ParseSess, source_code: &str) -> Option<Box<Expr>> {
     let parser = rustc_parse::unwrap_or_emit_fatal(rustc_parse::new_parser_from_source_str(
         psess,
         FileName::anon_source_code(source_code),
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index 8bca20852ad..08ded2aee53 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -35,7 +35,6 @@ extern crate rustc_driver;
 
 use parser::parse_expr;
 use rustc_ast::mut_visit::MutVisitor;
-use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust;
 use rustc_session::parse::ParseSess;
@@ -45,11 +44,11 @@ use rustc_span::DUMMY_SP;
 use thin_vec::{thin_vec, ThinVec};
 
 // Helper functions for building exprs
-fn expr(kind: ExprKind) -> P<Expr> {
-    P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: AttrVec::new(), tokens: None })
+fn expr(kind: ExprKind) -> Box<Expr> {
+    Box::new(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: AttrVec::new(), tokens: None })
 }
 
-fn make_x() -> P<Expr> {
+fn make_x() -> Box<Expr> {
     let seg = PathSegment::from_ident(Ident::from_str("x"));
     let path = Path { segments: thin_vec![seg], span: DUMMY_SP, tokens: None };
     expr(ExprKind::Path(None, path))
@@ -58,7 +57,7 @@ fn make_x() -> P<Expr> {
 /// Iterate over exprs of depth up to `depth`. The goal is to explore all "interesting"
 /// combinations of expression nesting. For example, we explore combinations using `if`, but not
 /// `while` or `match`, since those should print and parse in much the same way as `if`.
-fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
+fn iter_exprs(depth: usize, f: &mut dyn FnMut(Box<Expr>)) {
     if depth == 0 {
         f(make_x());
         return;
@@ -108,7 +107,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::Unary(UnOp::Deref, e)));
             }
             9 => {
-                let block = P(Block {
+                let block = Box::new(Block {
                     stmts: ThinVec::new(),
                     id: DUMMY_NODE_ID,
                     rules: BlockCheckMode::Default,
@@ -118,7 +117,10 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::If(e, block.clone(), None)));
             }
             10 => {
-                let decl = P(FnDecl { inputs: thin_vec![], output: FnRetTy::Default(DUMMY_SP) });
+                let decl = Box::new(FnDecl {
+                    inputs: thin_vec![],
+                    output: FnRetTy::Default(DUMMY_SP),
+                });
                 iter_exprs(depth - 1, &mut |e| {
                     g(ExprKind::Closure(Box::new(Closure {
                         binder: ClosureBinder::NotPresent,
@@ -159,7 +161,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
             }
             16 => {
                 let path = Path::from_ident(Ident::from_str("S"));
-                g(ExprKind::Struct(P(StructExpr {
+                g(ExprKind::Struct(Box::new(StructExpr {
                     qself: None,
                     path,
                     fields: thin_vec![],
@@ -170,8 +172,12 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
                 iter_exprs(depth - 1, &mut |e| g(ExprKind::Try(e)));
             }
             18 => {
-                let pat =
-                    P(Pat { id: DUMMY_NODE_ID, kind: PatKind::Wild, span: DUMMY_SP, tokens: None });
+                let pat = Box::new(Pat {
+                    id: DUMMY_NODE_ID,
+                    kind: PatKind::Wild,
+                    span: DUMMY_SP,
+                    tokens: None,
+                });
                 iter_exprs(depth - 1, &mut |e| {
                     g(ExprKind::Let(pat.clone(), e, DUMMY_SP, Recovered::No))
                 })
@@ -204,7 +210,7 @@ impl MutVisitor for AddParens {
         mut_visit::walk_expr(self, e);
         let expr = std::mem::replace(e, Expr::dummy());
 
-        e.kind = ExprKind::Paren(P(expr));
+        e.kind = ExprKind::Paren(Box::new(expr));
     }
 }
 
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
index 15314fac37b..aad45c422e2 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1
    |
 LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
+   |    ---------------------- in this attribute macro expansion
 LL | // fn oom(
 LL | ||     info: &Layout,
 LL | || ) -> ()
@@ -23,7 +23,7 @@ error[E0308]: mismatched types
   --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1
    |
 LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
+   |    ---------------------- in this attribute macro expansion
 LL | // fn oom(
 LL | ||     info: &Layout,
 LL | || ) -> ()
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
index 2ab42638411..581d1947419 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1
    |
 LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
+   |    ---------------------- in this attribute macro expansion
 LL | // fn oom(
 LL | ||     info: Layout,
 LL | || ) {
@@ -31,7 +31,7 @@ error[E0308]: mismatched types
   --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1
    |
 LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
+   |    ---------------------- in this attribute macro expansion
 LL | // fn oom(
 LL | ||     info: Layout,
 LL | || ) {
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
index 3a410174f54..91147df71eb 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/alloc-error-handler-bad-signature-3.rs:10:1
    |
 LL |   #[alloc_error_handler]
-   |   ---------------------- in this procedural macro expansion
+   |   ---------------------- in this attribute macro expansion
 LL |   fn oom() -> ! {
    |  _-^^^^^^^^^^^^
 LL | |     loop {}
diff --git a/tests/ui/allocator/not-an-allocator.stderr b/tests/ui/allocator/not-an-allocator.stderr
index 079bf9334eb..f33a698ed78 100644
--- a/tests/ui/allocator/not-an-allocator.stderr
+++ b/tests/ui/allocator/not-an-allocator.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
@@ -12,7 +12,7 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
@@ -23,7 +23,7 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
@@ -34,7 +34,7 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
diff --git a/tests/ui/allocator/two-allocators.stderr b/tests/ui/allocator/two-allocators.stderr
index 5308232a20b..1a9a5910eec 100644
--- a/tests/ui/allocator/two-allocators.stderr
+++ b/tests/ui/allocator/two-allocators.stderr
@@ -4,7 +4,7 @@ error: cannot define multiple global allocators
 LL | static A: System = System;
    | -------------------------- previous global allocator defined here
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static B: System = System;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator
 
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr
new file mode 100644
index 00000000000..8742d4bd82c
--- /dev/null
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32d.stderr
@@ -0,0 +1,38 @@
+error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:27:18
+   |
+LL |         asm!("", out("$r0") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$tp`: reserved for TLS
+  --> $DIR/bad-reg.rs:29:18
+   |
+LL |         asm!("", out("$tp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:31:18
+   |
+LL |         asm!("", out("$sp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$r21`: reserved by the ABI
+  --> $DIR/bad-reg.rs:33:18
+   |
+LL |         asm!("", out("$r21") _);
+   |                  ^^^^^^^^^^^^^
+
+error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:35:18
+   |
+LL |         asm!("", out("$fp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:37:18
+   |
+LL |         asm!("", out("$r31") _);
+   |                  ^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr
new file mode 100644
index 00000000000..e6cb6e40c70
--- /dev/null
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch32_ilp32s.stderr
@@ -0,0 +1,62 @@
+error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:27:18
+   |
+LL |         asm!("", out("$r0") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$tp`: reserved for TLS
+  --> $DIR/bad-reg.rs:29:18
+   |
+LL |         asm!("", out("$tp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:31:18
+   |
+LL |         asm!("", out("$sp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$r21`: reserved by the ABI
+  --> $DIR/bad-reg.rs:33:18
+   |
+LL |         asm!("", out("$r21") _);
+   |                  ^^^^^^^^^^^^^
+
+error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:35:18
+   |
+LL |         asm!("", out("$fp") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:37:18
+   |
+LL |         asm!("", out("$r31") _);
+   |                  ^^^^^^^^^^^^^
+
+error: register class `freg` requires at least one of the following target features: d, f
+  --> $DIR/bad-reg.rs:41:26
+   |
+LL |         asm!("/* {} */", in(freg) f);
+   |                          ^^^^^^^^^^
+
+error: register class `freg` requires at least one of the following target features: d, f
+  --> $DIR/bad-reg.rs:43:26
+   |
+LL |         asm!("/* {} */", out(freg) _);
+   |                          ^^^^^^^^^^^
+
+error: register class `freg` requires at least one of the following target features: d, f
+  --> $DIR/bad-reg.rs:45:26
+   |
+LL |         asm!("/* {} */", in(freg) d);
+   |                          ^^^^^^^^^^
+
+error: register class `freg` requires at least one of the following target features: d, f
+  --> $DIR/bad-reg.rs:47:26
+   |
+LL |         asm!("/* {} */", out(freg) d);
+   |                          ^^^^^^^^^^^
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
index 0e544119650..8742d4bd82c 100644
--- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64d.stderr
@@ -1,35 +1,35 @@
 error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:22:18
+  --> $DIR/bad-reg.rs:27:18
    |
 LL |         asm!("", out("$r0") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$tp`: reserved for TLS
-  --> $DIR/bad-reg.rs:24:18
+  --> $DIR/bad-reg.rs:29:18
    |
 LL |         asm!("", out("$tp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:26:18
+  --> $DIR/bad-reg.rs:31:18
    |
 LL |         asm!("", out("$sp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r21`: reserved by the ABI
-  --> $DIR/bad-reg.rs:28:18
+  --> $DIR/bad-reg.rs:33:18
    |
 LL |         asm!("", out("$r21") _);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:30:18
+  --> $DIR/bad-reg.rs:35:18
    |
 LL |         asm!("", out("$fp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
+  --> $DIR/bad-reg.rs:37:18
    |
 LL |         asm!("", out("$r31") _);
    |                  ^^^^^^^^^^^^^
diff --git a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
index 6d0410dc6a1..e6cb6e40c70 100644
--- a/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
+++ b/tests/ui/asm/loongarch/bad-reg.loongarch64_lp64s.stderr
@@ -1,59 +1,59 @@
 error: invalid register `$r0`: constant zero cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:22:18
+  --> $DIR/bad-reg.rs:27:18
    |
 LL |         asm!("", out("$r0") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$tp`: reserved for TLS
-  --> $DIR/bad-reg.rs:24:18
+  --> $DIR/bad-reg.rs:29:18
    |
 LL |         asm!("", out("$tp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$sp`: the stack pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:26:18
+  --> $DIR/bad-reg.rs:31:18
    |
 LL |         asm!("", out("$sp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r21`: reserved by the ABI
-  --> $DIR/bad-reg.rs:28:18
+  --> $DIR/bad-reg.rs:33:18
    |
 LL |         asm!("", out("$r21") _);
    |                  ^^^^^^^^^^^^^
 
 error: invalid register `$fp`: the frame pointer cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:30:18
+  --> $DIR/bad-reg.rs:35:18
    |
 LL |         asm!("", out("$fp") _);
    |                  ^^^^^^^^^^^^
 
 error: invalid register `$r31`: $r31 is used internally by LLVM and cannot be used as an operand for inline asm
-  --> $DIR/bad-reg.rs:32:18
+  --> $DIR/bad-reg.rs:37:18
    |
 LL |         asm!("", out("$r31") _);
    |                  ^^^^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:36:26
+  --> $DIR/bad-reg.rs:41:26
    |
 LL |         asm!("/* {} */", in(freg) f);
    |                          ^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:38:26
+  --> $DIR/bad-reg.rs:43:26
    |
 LL |         asm!("/* {} */", out(freg) _);
    |                          ^^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:40:26
+  --> $DIR/bad-reg.rs:45:26
    |
 LL |         asm!("/* {} */", in(freg) d);
    |                          ^^^^^^^^^^
 
 error: register class `freg` requires at least one of the following target features: d, f
-  --> $DIR/bad-reg.rs:42:26
+  --> $DIR/bad-reg.rs:47:26
    |
 LL |         asm!("/* {} */", out(freg) d);
    |                          ^^^^^^^^^^^
diff --git a/tests/ui/asm/loongarch/bad-reg.rs b/tests/ui/asm/loongarch/bad-reg.rs
index 685b460bc92..0d3eba07f14 100644
--- a/tests/ui/asm/loongarch/bad-reg.rs
+++ b/tests/ui/asm/loongarch/bad-reg.rs
@@ -1,6 +1,11 @@
 //@ add-core-stubs
 //@ needs-asm-support
-//@ revisions: loongarch64_lp64d loongarch64_lp64s
+//@ revisions: loongarch32_ilp32d loongarch32_ilp32s loongarch64_lp64d loongarch64_lp64s
+//@ min-llvm-version: 20
+//@[loongarch32_ilp32d] compile-flags: --target loongarch32-unknown-none
+//@[loongarch32_ilp32d] needs-llvm-components: loongarch
+//@[loongarch32_ilp32s] compile-flags: --target loongarch32-unknown-none-softfloat
+//@[loongarch32_ilp32s] needs-llvm-components: loongarch
 //@[loongarch64_lp64d] compile-flags: --target loongarch64-unknown-linux-gnu
 //@[loongarch64_lp64d] needs-llvm-components: loongarch
 //@[loongarch64_lp64s] compile-flags: --target loongarch64-unknown-none-softfloat
@@ -34,12 +39,12 @@ fn f() {
 
         asm!("", out("$f0") _); // ok
         asm!("/* {} */", in(freg) f);
-        //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
+        //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
         asm!("/* {} */", out(freg) _);
-        //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
+        //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
         asm!("/* {} */", in(freg) d);
-        //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
+        //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
         asm!("/* {} */", out(freg) d);
-        //[loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
+        //[loongarch32_ilp32s,loongarch64_lp64s]~^ ERROR register class `freg` requires at least one of the following target features: d, f
     }
 }
diff --git a/tests/ui/asm/s390x/bad-reg.rs b/tests/ui/asm/s390x/bad-reg.rs
index 56b2d709372..eb9138755e7 100644
--- a/tests/ui/asm/s390x/bad-reg.rs
+++ b/tests/ui/asm/s390x/bad-reg.rs
@@ -1,7 +1,7 @@
 //@ add-core-stubs
 //@ needs-asm-support
 //@ revisions: s390x s390x_vector s390x_vector_stable
-//@[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//@[s390x] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=-vector
 //@[s390x] needs-llvm-components: systemz
 //@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector
 //@[s390x_vector] needs-llvm-components: systemz
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr
index 7fc28ed4664..e8ae4715398 100644
--- a/tests/ui/attributes/malformed-attrs.stderr
+++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -145,6 +145,12 @@ LL - #[macro_export = 18]
 LL + #[macro_export]
    |
 
+error: malformed `allow_internal_unsafe` attribute input
+  --> $DIR/malformed-attrs.rs:213:1
+   |
+LL | #[allow_internal_unsafe = 1]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[allow_internal_unsafe]`
+
 error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
   --> $DIR/malformed-attrs.rs:96:1
    |
@@ -555,15 +561,6 @@ error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `
 LL | #[macro_use = 1]
    | ^^^^^^^^^^^^^^^^
 
-error[E0565]: malformed `allow_internal_unsafe` attribute input
-  --> $DIR/malformed-attrs.rs:213:1
-   |
-LL | #[allow_internal_unsafe = 1]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^---^
-   | |                       |
-   | |                       didn't expect any arguments here
-   | help: must be of the form: `#[allow_internal_unsafe]`
-
 error[E0565]: malformed `type_const` attribute input
   --> $DIR/malformed-attrs.rs:140:5
    |
diff --git a/tests/ui/attributes/rustc_confusables_std_cases.stderr b/tests/ui/attributes/rustc_confusables_std_cases.stderr
index f2d9ebe2c0e..771c0c6dfe9 100644
--- a/tests/ui/attributes/rustc_confusables_std_cases.stderr
+++ b/tests/ui/attributes/rustc_confusables_std_cases.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `push` found for struct `BTreeSet` in the current scope
+error[E0599]: no method named `push` found for struct `BTreeSet<T, A>` in the current scope
   --> $DIR/rustc_confusables_std_cases.rs:6:7
    |
 LL |     x.push(1);
@@ -22,7 +22,7 @@ LL -     x.push_back(1);
 LL +     x.push(1);
    |
 
-error[E0599]: no method named `push` found for struct `VecDeque` in the current scope
+error[E0599]: no method named `push` found for struct `VecDeque<T, A>` in the current scope
   --> $DIR/rustc_confusables_std_cases.rs:12:7
    |
 LL |     x.push(1);
@@ -35,7 +35,7 @@ LL |     let mut x = Vec::new();
    |         ^^^^^ `x` of type `Vec<_>` that has method `push` defined earlier here
 ...
 LL |     let mut x = VecDeque::new();
-   |         ----- earlier `x` shadowed here with type `VecDeque`
+   |         ----- earlier `x` shadowed here with type `VecDeque<_>`
 help: you might have meant to use `push_back`
    |
 LL |     x.push_back(1);
diff --git a/tests/ui/issues/issue-15783.rs b/tests/ui/borrowck/array-slice-coercion-mismatch-15783.rs
index ef948a1a88c..3322ed71c60 100644
--- a/tests/ui/issues/issue-15783.rs
+++ b/tests/ui/borrowck/array-slice-coercion-mismatch-15783.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15783
+
 //@ dont-require-annotations: NOTE
 
 pub fn foo(params: Option<&[&str]>) -> usize {
diff --git a/tests/ui/issues/issue-15783.stderr b/tests/ui/borrowck/array-slice-coercion-mismatch-15783.stderr
index c9c9a723a86..050eb4baa41 100644
--- a/tests/ui/issues/issue-15783.stderr
+++ b/tests/ui/borrowck/array-slice-coercion-mismatch-15783.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-15783.rs:10:19
+  --> $DIR/array-slice-coercion-mismatch-15783.rs:12:19
    |
 LL |     let msg = foo(x);
    |               --- ^ expected `Option<&[&str]>`, found `Option<&[&str; 1]>`
@@ -9,7 +9,7 @@ LL |     let msg = foo(x);
    = note: expected enum `Option<&[&str]>`
               found enum `Option<&[&str; 1]>`
 note: function defined here
-  --> $DIR/issue-15783.rs:3:8
+  --> $DIR/array-slice-coercion-mismatch-15783.rs:5:8
    |
 LL | pub fn foo(params: Option<&[&str]>) -> usize {
    |        ^^^ -----------------------
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index b2186f85b8a..18e038a442e 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -156,7 +156,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `nto71_iosock`, `nto80`, `ohos`, `p1`, `p2`, `relibc`, `sgx`, `uclibc`, and `v5`
+   = note: expected values for `target_env` are: ``, `gnu`, `macabi`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `nto71_iosock`, `nto80`, `ohos`, `p1`, `p2`, `relibc`, `sgx`, `sim`, `uclibc`, and `v5`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
diff --git a/tests/ui/issues/issue-16256.rs b/tests/ui/closures/unused-closure-ice-16256.rs
index 1024e4511d6..fd569dd8a0a 100644
--- a/tests/ui/issues/issue-16256.rs
+++ b/tests/ui/closures/unused-closure-ice-16256.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16256
+
 //@ run-pass
 
 fn main() {
diff --git a/tests/ui/issues/issue-16256.stderr b/tests/ui/closures/unused-closure-ice-16256.stderr
index 75c3ec1bd1c..9df433add5d 100644
--- a/tests/ui/issues/issue-16256.stderr
+++ b/tests/ui/closures/unused-closure-ice-16256.stderr
@@ -1,5 +1,5 @@
 warning: unused closure that must be used
-  --> $DIR/issue-16256.rs:5:5
+  --> $DIR/unused-closure-ice-16256.rs:7:5
    |
 LL |     |c: u8| buf.push(c);
    |     ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/issues/issue-15793.rs b/tests/ui/codegen/nested-enum-match-optimization-15793.rs
index af92e9dfa4c..420e3ad82b2 100644
--- a/tests/ui/issues/issue-15793.rs
+++ b/tests/ui/codegen/nested-enum-match-optimization-15793.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15793
+
 //@ run-pass
 #![allow(dead_code)]
 
diff --git a/tests/ui/codegen/overflow-during-mono.rs b/tests/ui/codegen/overflow-during-mono.rs
index a9045840173..3aafe05ba05 100644
--- a/tests/ui/codegen/overflow-during-mono.rs
+++ b/tests/ui/codegen/overflow-during-mono.rs
@@ -1,5 +1,6 @@
-//~ ERROR overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: FnMut(&'a _)`
+//~ ERROR overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:14:41: 14:44}: FnMut(&'a _)`
 //@ build-fail
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 
 #![recursion_limit = "32"]
 
diff --git a/tests/ui/codegen/overflow-during-mono.stderr b/tests/ui/codegen/overflow-during-mono.stderr
index 74d98fde285..1559de757e7 100644
--- a/tests/ui/codegen/overflow-during-mono.stderr
+++ b/tests/ui/codegen/overflow-during-mono.stderr
@@ -1,10 +1,12 @@
-error[E0275]: overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: FnMut(&'a _)`
+error[E0275]: overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:14:41: 14:44}: FnMut(&'a _)`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "64"]` attribute to your crate (`overflow_during_mono`)
-   = note: required for `Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
+   = note: required for `Filter<IntoIter<i32, 11>, {closure@overflow-during-mono.rs:14:41}>` to implement `Iterator`
    = note: 31 redundant requirements hidden
-   = note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
-   = note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `IntoIterator`
+   = note: required for `Filter<Filter<Filter<Filter<Filter<..., ...>, ...>, ...>, ...>, ...>` to implement `Iterator`
+   = note: required for `Filter<Filter<Filter<Filter<Filter<..., ...>, ...>, ...>, ...>, ...>` to implement `IntoIterator`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/overflow-during-mono.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/coherence-tuple-conflict.stderr b/tests/ui/coherence/coherence-tuple-conflict.stderr
index 95f9a1a8841..8ce65f79aca 100644
--- a/tests/ui/coherence/coherence-tuple-conflict.stderr
+++ b/tests/ui/coherence/coherence-tuple-conflict.stderr
@@ -12,6 +12,8 @@ error[E0609]: no field `dummy` on type `&(A, B)`
    |
 LL |     fn get(&self) -> usize { self.dummy }
    |                                   ^^^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/confuse-field-and-method/issue-18343.stderr b/tests/ui/confuse-field-and-method/issue-18343.stderr
index e50c971d837..9517617fe34 100644
--- a/tests/ui/confuse-field-and-method/issue-18343.stderr
+++ b/tests/ui/confuse-field-and-method/issue-18343.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-18343.rs:7:7
    |
 LL | struct Obj<F> where F: FnMut() -> u32 {
diff --git a/tests/ui/confuse-field-and-method/issue-2392.stderr b/tests/ui/confuse-field-and-method/issue-2392.stderr
index 77930de44a7..e1ad24df80f 100644
--- a/tests/ui/confuse-field-and-method/issue-2392.stderr
+++ b/tests/ui/confuse-field-and-method/issue-2392.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:36:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -12,7 +12,7 @@ help: to call the closure stored in `closure`, surround the field access with pa
 LL |     (o_closure.closure)();
    |     +                 +
 
-error[E0599]: no method named `not_closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:38:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -23,7 +23,7 @@ LL |     o_closure.not_closure();
    |               |
    |               field, not a method
 
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:42:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -65,7 +65,7 @@ help: to call the trait object stored in `boxed_closure`, surround the field acc
 LL |     (boxed_closure.boxed_closure)();
    |     +                           +
 
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:53:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -79,7 +79,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (w.wrap.closure)();
    |     +              +
 
-error[E0599]: no method named `not_closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:55:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -90,7 +90,7 @@ LL |     w.wrap.not_closure();
    |            |
    |            field, not a method
 
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:58:24
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
diff --git a/tests/ui/consts/issue-19244-1.stderr b/tests/ui/consts/issue-19244-1.stderr
index 9c1336402e6..98a33817b4c 100644
--- a/tests/ui/consts/issue-19244-1.stderr
+++ b/tests/ui/consts/issue-19244-1.stderr
@@ -3,6 +3,8 @@ error[E0609]: no field `1` on type `(usize,)`
    |
 LL |     let a: [isize; TUP.1];
    |                        ^ unknown field
+   |
+   = note: available field is: `0`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/custom_test_frameworks/mismatch.stderr b/tests/ui/custom_test_frameworks/mismatch.stderr
index c7798635fbf..7cdfaa9e804 100644
--- a/tests/ui/custom_test_frameworks/mismatch.stderr
+++ b/tests/ui/custom_test_frameworks/mismatch.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `TestDescAndFn: Testable` is not satisfied
   --> $DIR/mismatch.rs:9:1
    |
 LL | #[test]
-   | ------- in this procedural macro expansion
+   | ------- in this attribute macro expansion
 LL | fn wrong_kind(){}
    | ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn`
    |
diff --git a/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr
index 61e2a8f64dd..b0bfc720658 100644
--- a/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr
+++ b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr
@@ -43,7 +43,7 @@ help: consider introducing lifetime `'a` here
 LL | impl<'a> Trait for Z {
    |     ++++
 
-error[E0599]: no function or associated item named `new` found for struct `InvariantRef` in the current scope
+error[E0599]: no function or associated item named `new` found for struct `InvariantRef<'a, T>` in the current scope
   --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:9:41
    |
 LL | pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
diff --git a/tests/ui/issues/issue-15523-big.rs b/tests/ui/derives/derive-partial-ord-discriminant-64bit.rs
index 7214a4fb1d5..5b6bf6fbf1f 100644
--- a/tests/ui/issues/issue-15523-big.rs
+++ b/tests/ui/derives/derive-partial-ord-discriminant-64bit.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15523
+
 //@ run-pass
 // Issue 15523: derive(PartialOrd) should use the provided
 // discriminant values for the derived ordering.
@@ -28,7 +30,6 @@ fn main() {
     assert!(Eu64::Pos2 < Eu64::PosMax);
     assert!(Eu64::Pos1 < Eu64::PosMax);
 
-
     assert!(Ei64::Pos2 > Ei64::Pos1);
     assert!(Ei64::Pos2 > Ei64::Neg1);
     assert!(Ei64::Pos1 > Ei64::Neg1);
diff --git a/tests/ui/issues/issue-15523.rs b/tests/ui/derives/derive-partial-ord-discriminant.rs
index 9fc2e51c6ab..28f325ec966 100644
--- a/tests/ui/issues/issue-15523.rs
+++ b/tests/ui/derives/derive-partial-ord-discriminant.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15523
+
 //@ run-pass
 // Issue 15523: derive(PartialOrd) should use the provided
 // discriminant values for the derived ordering.
diff --git a/tests/ui/diagnostic-width/long-E0609.stderr b/tests/ui/diagnostic-width/long-E0609.stderr
index 36ef8545746..70092ea34bc 100644
--- a/tests/ui/diagnostic-width/long-E0609.stderr
+++ b/tests/ui/diagnostic-width/long-E0609.stderr
@@ -4,6 +4,7 @@ error[E0609]: no field `field` on type `(..., ..., ..., ...)`
 LL |     x.field;
    |       ^^^^^ unknown field
    |
+   = note: available fields are: `0`, `1`, `2`, `3`
    = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0609.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
diff --git a/tests/ui/drop/dropck-normalize-errors.stderr b/tests/ui/drop/dropck-normalize-errors.nll.stderr
index 2bb5909c6b2..b008daa51a3 100644
--- a/tests/ui/drop/dropck-normalize-errors.stderr
+++ b/tests/ui/drop/dropck-normalize-errors.nll.stderr
@@ -1,44 +1,44 @@
 error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `ADecoder<'a>`
-  --> $DIR/dropck-normalize-errors.rs:15:28
+  --> $DIR/dropck-normalize-errors.rs:19:28
    |
 LL | fn make_a_decoder<'a>() -> ADecoder<'a> {
    |                            ^^^^^^^^^^^^ within `ADecoder<'a>`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dropck-normalize-errors.rs:7:1
+  --> $DIR/dropck-normalize-errors.rs:11:1
    |
 LL | trait NonImplementedTrait {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required because it appears within the type `BDecoder`
-  --> $DIR/dropck-normalize-errors.rs:26:12
+  --> $DIR/dropck-normalize-errors.rs:30:12
    |
 LL | pub struct BDecoder {
    |            ^^^^^^^^
 note: required because it appears within the type `ADecoder<'a>`
-  --> $DIR/dropck-normalize-errors.rs:12:12
+  --> $DIR/dropck-normalize-errors.rs:16:12
    |
 LL | pub struct ADecoder<'a> {
    |            ^^^^^^^^
    = note: the return type of a function must have a statically known size
 
 error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `BDecoder`
-  --> $DIR/dropck-normalize-errors.rs:23:20
+  --> $DIR/dropck-normalize-errors.rs:27:20
    |
 LL |     type Decoder = BDecoder;
    |                    ^^^^^^^^ within `BDecoder`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dropck-normalize-errors.rs:7:1
+  --> $DIR/dropck-normalize-errors.rs:11:1
    |
 LL | trait NonImplementedTrait {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: required because it appears within the type `BDecoder`
-  --> $DIR/dropck-normalize-errors.rs:26:12
+  --> $DIR/dropck-normalize-errors.rs:30:12
    |
 LL | pub struct BDecoder {
    |            ^^^^^^^^
 note: required by a bound in `Decode::Decoder`
-  --> $DIR/dropck-normalize-errors.rs:4:5
+  --> $DIR/dropck-normalize-errors.rs:8:5
    |
 LL |     type Decoder;
    |     ^^^^^^^^^^^^^ required by this bound in `Decode::Decoder`
@@ -48,25 +48,25 @@ LL |     type Decoder: ?Sized;
    |                 ++++++++
 
 error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied
-  --> $DIR/dropck-normalize-errors.rs:27:22
+  --> $DIR/dropck-normalize-errors.rs:31:22
    |
 LL |     non_implemented: <NonImplementedStruct as NonImplementedTrait>::Assoc,
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dropck-normalize-errors.rs:7:1
+  --> $DIR/dropck-normalize-errors.rs:11:1
    |
 LL | trait NonImplementedTrait {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied
-  --> $DIR/dropck-normalize-errors.rs:15:28
+  --> $DIR/dropck-normalize-errors.rs:19:28
    |
 LL | fn make_a_decoder<'a>() -> ADecoder<'a> {
    |                            ^^^^^^^^^^^^ the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/dropck-normalize-errors.rs:7:1
+  --> $DIR/dropck-normalize-errors.rs:11:1
    |
 LL | trait NonImplementedTrait {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/drop/dropck-normalize-errors.polonius.stderr b/tests/ui/drop/dropck-normalize-errors.polonius.stderr
new file mode 100644
index 00000000000..f8674b8e34a
--- /dev/null
+++ b/tests/ui/drop/dropck-normalize-errors.polonius.stderr
@@ -0,0 +1,64 @@
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `ADecoder<'a>`
+  --> $DIR/dropck-normalize-errors.rs:19:28
+   |
+LL | fn make_a_decoder<'a>() -> ADecoder<'a> {
+   |                            ^^^^^^^^^^^^ within `ADecoder<'a>`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:11:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `BDecoder`
+  --> $DIR/dropck-normalize-errors.rs:30:12
+   |
+LL | pub struct BDecoder {
+   |            ^^^^^^^^
+note: required because it appears within the type `ADecoder<'a>`
+  --> $DIR/dropck-normalize-errors.rs:16:12
+   |
+LL | pub struct ADecoder<'a> {
+   |            ^^^^^^^^
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied in `BDecoder`
+  --> $DIR/dropck-normalize-errors.rs:27:20
+   |
+LL |     type Decoder = BDecoder;
+   |                    ^^^^^^^^ within `BDecoder`, the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:11:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required because it appears within the type `BDecoder`
+  --> $DIR/dropck-normalize-errors.rs:30:12
+   |
+LL | pub struct BDecoder {
+   |            ^^^^^^^^
+note: required by a bound in `Decode::Decoder`
+  --> $DIR/dropck-normalize-errors.rs:8:5
+   |
+LL |     type Decoder;
+   |     ^^^^^^^^^^^^^ required by this bound in `Decode::Decoder`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL |     type Decoder: ?Sized;
+   |                 ++++++++
+
+error[E0277]: the trait bound `NonImplementedStruct: NonImplementedTrait` is not satisfied
+  --> $DIR/dropck-normalize-errors.rs:31:22
+   |
+LL |     non_implemented: <NonImplementedStruct as NonImplementedTrait>::Assoc,
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonImplementedTrait` is not implemented for `NonImplementedStruct`
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/dropck-normalize-errors.rs:11:1
+   |
+LL | trait NonImplementedTrait {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/drop/dropck-normalize-errors.rs b/tests/ui/drop/dropck-normalize-errors.rs
index 793122bd33d..2ade63f27c5 100644
--- a/tests/ui/drop/dropck-normalize-errors.rs
+++ b/tests/ui/drop/dropck-normalize-errors.rs
@@ -1,5 +1,9 @@
 // Test that we don't ICE when computing the drop types for
 
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius
+//@ [polonius] compile-flags: -Zpolonius=next
+
 trait Decode<'a> {
     type Decoder;
 }
@@ -14,7 +18,7 @@ pub struct ADecoder<'a> {
 }
 fn make_a_decoder<'a>() -> ADecoder<'a> {
     //~^ ERROR the trait bound
-    //~| ERROR the trait bound
+    //[nll]~| ERROR the trait bound
     panic!()
 }
 
diff --git a/tests/ui/issues/issue-15063.rs b/tests/ui/drop/enum-drop-impl-15063.rs
index 969dbe5fad2..a8198abafa0 100644
--- a/tests/ui/issues/issue-15063.rs
+++ b/tests/ui/drop/enum-drop-impl-15063.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15063
+
 //@ run-pass
 #![allow(dead_code)]
 #![allow(unused_variables)]
diff --git a/tests/ui/issues/issue-15858.rs b/tests/ui/drop/generic-drop-trait-bound-15858.rs
index 27887d49e3e..682604d17d8 100644
--- a/tests/ui/issues/issue-15858.rs
+++ b/tests/ui/drop/generic-drop-trait-bound-15858.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15858
+
 //@ run-pass
 // FIXME(static_mut_refs): this could use an atomic
 #![allow(static_mut_refs)]
diff --git a/tests/ui/issues/issue-15858.stderr b/tests/ui/drop/generic-drop-trait-bound-15858.stderr
index 0c082cc0862..86cd6cb6026 100644
--- a/tests/ui/issues/issue-15858.stderr
+++ b/tests/ui/drop/generic-drop-trait-bound-15858.stderr
@@ -1,5 +1,5 @@
 warning: method `do_something` is never used
-  --> $DIR/issue-15858.rs:7:8
+  --> $DIR/generic-drop-trait-bound-15858.rs:9:8
    |
 LL | trait Bar {
    |       --- method in this trait
diff --git a/tests/ui/drop/if-let-guards.rs b/tests/ui/drop/if-let-guards.rs
new file mode 100644
index 00000000000..bd353112c09
--- /dev/null
+++ b/tests/ui/drop/if-let-guards.rs
@@ -0,0 +1,88 @@
+//! Tests drop order for `if let` guard bindings and temporaries. This is for behavior specific to
+//! `match` expressions, whereas `tests/ui/drop/drop-order-comparisons.rs` compares `let` chains in
+//! guards to `let` chains in `if` expressions. Drop order for `let` chains in guards shouldn't
+//! differ between Editions, so we test on both 2021 and 2024, expecting the same results.
+//@ revisions: e2021 e2024
+//@ [e2021] edition: 2021
+//@ [e2024] edition: 2024
+//@ run-pass
+
+#![feature(if_let_guard)]
+#![deny(rust_2024_compatibility)]
+
+use core::{cell::RefCell, ops::Drop};
+
+fn main() {
+    // Test that `let` guard bindings and temps are dropped before the arm's pattern's bindings.
+    assert_drop_order(1..=6, |o| {
+        // We move out of the scrutinee, so the drop order of the array's elements are based on
+        // binding declaration order, and they're dropped in the arm's scope.
+        match [o.log(6), o.log(5)] {
+            // Partially move from the guard temporary to test drops both for temps and the binding.
+            [_x, _y] if let [_, _z, _] = [o.log(4), o.log(2), o.log(3)]
+                && true => { let _a = o.log(1); }
+            _ => unreachable!(),
+        }
+    });
+
+    // Sanity check: we don't move out of the match scrutinee when the guard fails.
+    assert_drop_order(1..=4, |o| {
+        // The scrutinee uses the drop order for arrays since its elements aren't moved.
+        match [o.log(3), o.log(4)] {
+            [_x, _y] if let _z = o.log(1)
+                && false => unreachable!(),
+            _ => { let _a = o.log(2); }
+        }
+    });
+
+    // Test `let` guards' temporaries are dropped immediately when a guard fails, even if the guard
+    // is lowered and run multiple times on the same arm due to or-patterns.
+    assert_drop_order(1..=8, |o| {
+        let mut _x = 1;
+        // The match's scrutinee isn't bound by-move, so it outlives the match.
+        match o.log(8) {
+            // Failing a guard breaks out of the arm's scope, dropping the `let` guard's scrutinee.
+            _ | _ | _ if let _ = o.log(_x)
+                && { _x += 1; false } => unreachable!(),
+            // The temporaries from a failed guard are dropped before testing the next guard.
+            _ if let _ = o.log(5)
+                && { o.push(4); false } => unreachable!(),
+            // If the guard succeeds, we stay in the arm's scope to execute its body.
+            _ if let _ = o.log(7)
+                && true => { o.log(6); }
+            _ => unreachable!(),
+        }
+    });
+}
+
+// # Test scaffolding...
+
+struct DropOrder(RefCell<Vec<u64>>);
+struct LogDrop<'o>(&'o DropOrder, u64);
+
+impl DropOrder {
+    fn log(&self, n: u64) -> LogDrop<'_> {
+        LogDrop(self, n)
+    }
+    fn push(&self, n: u64) {
+        self.0.borrow_mut().push(n);
+    }
+}
+
+impl<'o> Drop for LogDrop<'o> {
+    fn drop(&mut self) {
+        self.0.push(self.1);
+    }
+}
+
+#[track_caller]
+fn assert_drop_order(
+    ex: impl IntoIterator<Item = u64>,
+    f: impl Fn(&DropOrder),
+) {
+    let order = DropOrder(RefCell::new(Vec::new()));
+    f(&order);
+    let order = order.0.into_inner();
+    let expected: Vec<u64> = ex.into_iter().collect();
+    assert_eq!(order, expected);
+}
diff --git a/tests/ui/issues/issue-15763.rs b/tests/ui/drop/nested-return-drop-order.rs
index 0ebadd80541..67ab52e6250 100644
--- a/tests/ui/issues/issue-15763.rs
+++ b/tests/ui/drop/nested-return-drop-order.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15763
+
 //@ run-pass
 #![allow(unreachable_code)]
 
diff --git a/tests/ui/drop/same-alloca-reassigned-match-binding-16151.rs b/tests/ui/drop/same-alloca-reassigned-match-binding-16151.rs
new file mode 100644
index 00000000000..ecc862ec7be
--- /dev/null
+++ b/tests/ui/drop/same-alloca-reassigned-match-binding-16151.rs
@@ -0,0 +1,34 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16151
+
+//@ run-pass
+
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
+use std::mem;
+
+static mut DROP_COUNT: usize = 0;
+
+struct Fragment;
+
+impl Drop for Fragment {
+    fn drop(&mut self) {
+        unsafe {
+            DROP_COUNT += 1;
+        }
+    }
+}
+
+fn main() {
+    {
+        let mut fragments = vec![Fragment, Fragment, Fragment];
+        let _new_fragments: Vec<Fragment> = mem::replace(&mut fragments, vec![])
+            .into_iter()
+            .skip_while(|_fragment| {
+                true
+            }).collect();
+    }
+    unsafe {
+        assert_eq!(DROP_COUNT, 3);
+    }
+}
diff --git a/tests/ui/issues/issue-16492.rs b/tests/ui/drop/struct-field-drop-order.rs
index cfdba5fda35..80e3ea616a5 100644
--- a/tests/ui/issues/issue-16492.rs
+++ b/tests/ui/drop/struct-field-drop-order.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16492
+
 //@ run-pass
 #![allow(non_snake_case)]
 
diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
index 17b76b6c832..2bb82a2ebf2 100644
--- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
+++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
@@ -1,5 +1,6 @@
 // Issue 22443: Reject code using non-regular types that would
 // otherwise cause dropck to loop infinitely.
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 
 use std::marker::PhantomData;
 
diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
index 9360f4a98e9..330a40d925b 100644
--- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
+++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
@@ -1,10 +1,12 @@
 error[E0320]: overflow while adding drop-check rules for `FingerTree<i32>`
-  --> $DIR/dropck_no_diverge_on_nonregular_1.rs:24:9
+  --> $DIR/dropck_no_diverge_on_nonregular_1.rs:25:9
    |
 LL |     let ft =
    |         ^^
    |
-   = note: overflowed on `FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: overflowed on `FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<...>>>>>>>>>>`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/dropck_no_diverge_on_nonregular_1.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
index 2daf00f7804..f0d4de364fb 100644
--- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
+++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
@@ -5,7 +5,7 @@ LL |         true => Default::default(),
    |                 ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
    |
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 
 error[E0277]: the trait bound `!: Default` is not satisfied
   --> $DIR/never-type-fallback-breaking.rs:37:5
@@ -14,7 +14,7 @@ LL |     deserialize()?;
    |     ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
    |
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 note: required by a bound in `deserialize`
   --> $DIR/never-type-fallback-breaking.rs:33:23
    |
@@ -51,7 +51,7 @@ LL |     takes_apit(|| Default::default())?;
    |                   ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
    |
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 
 error[E0277]: the trait bound `!: Default` is not satisfied
   --> $DIR/never-type-fallback-breaking.rs:76:17
@@ -62,7 +62,7 @@ LL |     takes_apit2(mk()?);
    |     required by a bound introduced by this call
    |
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 note: required by a bound in `takes_apit2`
   --> $DIR/never-type-fallback-breaking.rs:71:25
    |
diff --git a/tests/ui/error-codes/E0275.rs b/tests/ui/error-codes/E0275.rs
index 28a9676f03e..98d4a3c01b9 100644
--- a/tests/ui/error-codes/E0275.rs
+++ b/tests/ui/error-codes/E0275.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 trait Foo {}
 
 struct Bar<T>(T);
diff --git a/tests/ui/error-codes/E0275.stderr b/tests/ui/error-codes/E0275.stderr
index 3b31c87320a..755404c1e16 100644
--- a/tests/ui/error-codes/E0275.stderr
+++ b/tests/ui/error-codes/E0275.stderr
@@ -1,17 +1,19 @@
 error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>: Foo`
-  --> $DIR/E0275.rs:5:33
+  --> $DIR/E0275.rs:6:33
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
    |                                 ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
-note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
-  --> $DIR/E0275.rs:5:9
+note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>>>>>>>` to implement `Foo`
+  --> $DIR/E0275.rs:6:9
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
    |         ^^^     ^               --- unsatisfied trait bound introduced here
    = note: 126 redundant requirements hidden
    = note: required for `Bar<T>` to implement `Foo`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/E0275.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/ex-E0612.stderr b/tests/ui/error-codes/ex-E0612.stderr
index 54451d3d452..e6062f6061d 100644
--- a/tests/ui/error-codes/ex-E0612.stderr
+++ b/tests/ui/error-codes/ex-E0612.stderr
@@ -4,11 +4,7 @@ error[E0609]: no field `1` on type `Foo`
 LL |    y.1;
    |      ^ unknown field
    |
-help: a field with a similar name exists
-   |
-LL -    y.1;
-LL +    y.0;
-   |
+   = note: available field is: `0`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-16441.rs b/tests/ui/extern/empty-struct-extern-fn-16441.rs
index 58cfb389297..82f2eee611d 100644
--- a/tests/ui/issues/issue-16441.rs
+++ b/tests/ui/extern/empty-struct-extern-fn-16441.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16441
+
 //@ run-pass
 #![allow(dead_code)]
 
diff --git a/tests/ui/feature-gates/feature-gate-macro-attr.rs b/tests/ui/feature-gates/feature-gate-macro-attr.rs
new file mode 100644
index 00000000000..8419d851147
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-macro-attr.rs
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+macro_rules! myattr { attr() {} => {} }
+//~^ ERROR `macro_rules!` attributes are unstable
diff --git a/tests/ui/feature-gates/feature-gate-macro-attr.stderr b/tests/ui/feature-gates/feature-gate-macro-attr.stderr
new file mode 100644
index 00000000000..b58418527c5
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-macro-attr.stderr
@@ -0,0 +1,13 @@
+error[E0658]: `macro_rules!` attributes are unstable
+  --> $DIR/feature-gate-macro-attr.rs:3:1
+   |
+LL | macro_rules! myattr { attr() {} => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_attr)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/issues/issue-15094.rs b/tests/ui/fn/fn-traits-call-once-signature-15094.rs
index 408ab82eb8c..f550bafe43d 100644
--- a/tests/ui/issues/issue-15094.rs
+++ b/tests/ui/fn/fn-traits-call-once-signature-15094.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15094
+
 #![feature(fn_traits, unboxed_closures)]
 
 use std::{fmt, ops};
diff --git a/tests/ui/issues/issue-15094.stderr b/tests/ui/fn/fn-traits-call-once-signature-15094.stderr
index 8e0fc8f1770..bb1d336e848 100644
--- a/tests/ui/issues/issue-15094.stderr
+++ b/tests/ui/fn/fn-traits-call-once-signature-15094.stderr
@@ -1,5 +1,5 @@
 error[E0053]: method `call_once` has an incompatible type for trait
-  --> $DIR/issue-15094.rs:11:5
+  --> $DIR/fn-traits-call-once-signature-15094.rs:13:5
    |
 LL |     fn call_once(self, _args: ()) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "Rust" fn
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
index d8a1f3fa69e..d2793afdd06 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
@@ -6,6 +6,8 @@
 // This tests double-checks that we do not allow such behavior to leak
 // through again.
 
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
+
 pub trait Stream {
     type Item;
     fn next(self) -> Option<Self::Item>;
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
index 23b979e2ef0..91e65b2b073 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
@@ -1,5 +1,5 @@
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>`, but its trait bounds were not satisfied
-  --> $DIR/hrtb-doesnt-borrow-self-2.rs:110:24
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, {closure@...}>`, but its trait bounds were not satisfied
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:112:24
    |
 LL | pub struct Filter<S, F> {
    | ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt`
@@ -8,19 +8,21 @@ LL |     let count = filter.countx();
    |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
-      `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>: Stream`
-      `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>: Stream`
-      `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>: Stream`
-  --> $DIR/hrtb-doesnt-borrow-self-2.rs:96:50
+      `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
+      `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
+      `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:98:50
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `StreamExt` defines an item `countx`, perhaps you need to implement it
-  --> $DIR/hrtb-doesnt-borrow-self-2.rs:64:1
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:66:1
    |
 LL | pub trait StreamExt
    | ^^^^^^^^^^^^^^^^^^^
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/hrtb-doesnt-borrow-self-2.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs
index 09450089ada..ead81bf3374 100644
--- a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs
+++ b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 use std::cell::Cell;
 use std::rc::Rc;
 
diff --git a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr
index 52fa28145d6..ba76d9ba2b8 100644
--- a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr
+++ b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak2.rs:20:10
+  --> $DIR/auto-trait-leak2.rs:21:10
    |
 LL | fn before() -> impl Fn(i32) {
    |                ------------ within this `impl Fn(i32)`
@@ -11,23 +11,23 @@ LL |     send(before());
    |
    = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
 note: required because it's used within this closure
-  --> $DIR/auto-trait-leak2.rs:10:5
+  --> $DIR/auto-trait-leak2.rs:11:5
    |
 LL |     move |x| p.set(x)
    |     ^^^^^^^^
 note: required because it appears within the type `impl Fn(i32)`
-  --> $DIR/auto-trait-leak2.rs:5:16
+  --> $DIR/auto-trait-leak2.rs:6:16
    |
 LL | fn before() -> impl Fn(i32) {
    |                ^^^^^^^^^^^^
 note: required by a bound in `send`
-  --> $DIR/auto-trait-leak2.rs:13:12
+  --> $DIR/auto-trait-leak2.rs:14:12
    |
 LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
 
 error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak2.rs:25:10
+  --> $DIR/auto-trait-leak2.rs:26:10
    |
 LL |     send(after());
    |     ---- ^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
@@ -39,17 +39,17 @@ LL | fn after() -> impl Fn(i32) {
    |
    = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
 note: required because it's used within this closure
-  --> $DIR/auto-trait-leak2.rs:38:5
+  --> $DIR/auto-trait-leak2.rs:39:5
    |
 LL |     move |x| p.set(x)
    |     ^^^^^^^^
 note: required because it appears within the type `impl Fn(i32)`
-  --> $DIR/auto-trait-leak2.rs:33:15
+  --> $DIR/auto-trait-leak2.rs:34:15
    |
 LL | fn after() -> impl Fn(i32) {
    |               ^^^^^^^^^^^^
 note: required by a bound in `send`
-  --> $DIR/auto-trait-leak2.rs:13:12
+  --> $DIR/auto-trait-leak2.rs:14:12
    |
 LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
diff --git a/tests/ui/impl-trait/issues/type-error-post-normalization-test.rs b/tests/ui/impl-trait/issues/type-error-post-normalization-test.rs
new file mode 100644
index 00000000000..0108bb23611
--- /dev/null
+++ b/tests/ui/impl-trait/issues/type-error-post-normalization-test.rs
@@ -0,0 +1,24 @@
+//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
+
+// This previously introduced a `{type_error}`` in the MIR body
+// during the `PostAnalysisNormalize` pass. While the underlying issue
+// #135528 did not get fixed, this reproducer no longer ICEs.
+
+#![feature(type_alias_impl_trait)]
+type Tait = impl Copy;
+
+fn set(x: &isize) -> isize {
+    *x
+}
+
+#[define_opaque(Tait)]
+fn d(x: Tait) {
+    set(x);
+}
+
+#[define_opaque(Tait)]
+fn other_define() -> Tait {
+    () //~^ ERROR concrete type differs from previous defining opaque type use
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/issues/type-error-post-normalization-test.stderr b/tests/ui/impl-trait/issues/type-error-post-normalization-test.stderr
new file mode 100644
index 00000000000..7d63c1cfbd6
--- /dev/null
+++ b/tests/ui/impl-trait/issues/type-error-post-normalization-test.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/type-error-post-normalization-test.rs:20:22
+   |
+LL | fn other_define() -> Tait {
+   |                      ^^^^ expected `&isize`, got `()`
+   |
+note: previous use here
+  --> $DIR/type-error-post-normalization-test.rs:16:9
+   |
+LL |     set(x);
+   |         ^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/impl-trait/member-constraints/apply_member_constraint-no-req-eq.rs b/tests/ui/impl-trait/member-constraints/apply_member_constraint-no-req-eq.rs
new file mode 100644
index 00000000000..3aa52fe2644
--- /dev/null
+++ b/tests/ui/impl-trait/member-constraints/apply_member_constraint-no-req-eq.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+// FIXME(-Znext-solver): enable this test
+
+trait Id {
+    type This;
+}
+impl<T> Id for T {
+    type This = T;
+}
+
+// We have two member constraints here:
+//
+// - 'unconstrained member ['a, 'static]
+// - 'unconstrained member ['static]
+//
+// Applying the first constraint results in `'unconstrained: 'a`
+// while the second then adds `'unconstrained: 'static`. If applying
+// member constraints were to require the member region equal to the
+// choice region, applying the first constraint first and then the
+// second would result in a `'a: 'static` requirement.
+fn test<'a>() -> impl Id<This = impl Sized + use<>> + use<'a> {
+    &()
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/member-constraints/incomplete-constraint.rs b/tests/ui/impl-trait/member-constraints/incomplete-constraint.rs
new file mode 100644
index 00000000000..4c085cc1eed
--- /dev/null
+++ b/tests/ui/impl-trait/member-constraints/incomplete-constraint.rs
@@ -0,0 +1,21 @@
+//@ check-pass
+// FIXME(-Znext-solver): enable this test
+
+// These functions currently do not normalize the opaque type but will do
+// so in the future. At this point we've got a new use of the opaque with fully
+// universal arguments but for which lifetimes in the hidden type are unconstrained.
+//
+// Applying the member constraints would then incompletely infer `'unconstrained` to `'static`.
+fn new_defining_use<F: FnOnce(T) -> R, T, R>(_: F) {}
+
+fn rpit1<'a,  'b: 'b>(x: &'b ()) -> impl Sized + use<'a, 'b> {
+    new_defining_use(rpit1::<'a, 'b>);
+    x
+}
+
+struct Inv<'a, 'b>(*mut (&'a (), &'b ()));
+fn rpit2<'a>(_: ()) -> impl Sized + use<'a> {
+    new_defining_use(rpit2::<'a>);
+    Inv::<'a, 'static>(std::ptr::null_mut())
+}
+fn main() {}
diff --git a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.rs b/tests/ui/impl-trait/member-constraints/min-choice-reject-ambiguous.rs
index 09138095523..09138095523 100644
--- a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.rs
+++ b/tests/ui/impl-trait/member-constraints/min-choice-reject-ambiguous.rs
diff --git a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr b/tests/ui/impl-trait/member-constraints/min-choice-reject-ambiguous.stderr
index 911ddd3dc80..911ddd3dc80 100644
--- a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr
+++ b/tests/ui/impl-trait/member-constraints/min-choice-reject-ambiguous.stderr
diff --git a/tests/ui/nll/member-constraints/min-choice.rs b/tests/ui/impl-trait/member-constraints/min-choice.rs
index 4fbffeb4b2a..4fbffeb4b2a 100644
--- a/tests/ui/nll/member-constraints/min-choice.rs
+++ b/tests/ui/impl-trait/member-constraints/min-choice.rs
diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs b/tests/ui/impl-trait/member-constraints/nested-impl-trait-fail.rs
index 0bf32a2624f..0bf32a2624f 100644
--- a/tests/ui/nll/member-constraints/nested-impl-trait-fail.rs
+++ b/tests/ui/impl-trait/member-constraints/nested-impl-trait-fail.rs
diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr b/tests/ui/impl-trait/member-constraints/nested-impl-trait-fail.stderr
index 1a0611e715e..1a0611e715e 100644
--- a/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr
+++ b/tests/ui/impl-trait/member-constraints/nested-impl-trait-fail.stderr
diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-pass.rs b/tests/ui/impl-trait/member-constraints/nested-impl-trait-pass.rs
index 4633ad68230..6860fc5e6a5 100644
--- a/tests/ui/nll/member-constraints/nested-impl-trait-pass.rs
+++ b/tests/ui/impl-trait/member-constraints/nested-impl-trait-pass.rs
@@ -1,6 +1,7 @@
 // Nested impl-traits can impose different member constraints on the same region variable.
 
 //@ check-pass
+// FIXME(-Znext-solver): enable this test
 
 trait Cap<'a> {}
 impl<T> Cap<'_> for T {}
@@ -8,7 +9,9 @@ impl<T> Cap<'_> for T {}
 // Assuming the hidden type is `[&'?15 u8; 1]`, we have two distinct member constraints:
 // - '?15 member ['static, 'a, 'b] // from outer impl-trait
 // - '?15 member ['static, 'a]     // from inner impl-trait
-// To satisfy both we can only choose 'a.
+// To satisfy both we can only choose 'a. Concretely, first member constraint requires ?15
+// to outlive at least 'b while the second requires ?15 to outlive 'a. As 'a outlives 'b we
+// end up with 'a as the final member region.
 fn pass_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a>> + Cap<'b>
 where
     's: 'a,
diff --git a/tests/ui/impl-trait/member-constraints/reject-choice-due-to-prev-constraint.rs b/tests/ui/impl-trait/member-constraints/reject-choice-due-to-prev-constraint.rs
new file mode 100644
index 00000000000..33f2d277fe5
--- /dev/null
+++ b/tests/ui/impl-trait/member-constraints/reject-choice-due-to-prev-constraint.rs
@@ -0,0 +1,34 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ check-pass
+
+// We've got `'0 member ['a, 'b, 'static]` and `'1 member ['a, 'b, 'static]`.
+//
+// As '0 gets outlived by 'a - its "upper bound" -  the only applicable choice
+// region is 'a.
+//
+// '1 has to outlive 'b so the only applicable choice regions are 'b and 'static.
+// Considering this member constraint by itself would choose 'b as it is the
+// smaller of the two regions.
+//
+// However, this is only the case when ignoring the member constraint on '0.
+// After applying this constraint and requiring '0 to outlive 'a. As '1 outlives
+// '0, the region 'b is no longer an applicable choice region for '1 as 'b does
+// does not outlive 'a. We would therefore choose 'static.
+//
+// This means applying member constraints is order dependent. We handle this by
+// first applying member constraints for regions 'x and then consider the resulting
+// constraints when applying member constraints for regions 'y with 'y: 'x.
+fn with_constraints<'r0, 'r1, 'a, 'b>() -> *mut (&'r0 (), &'r1 ())
+where
+    'r1: 'r0,
+    'a: 'r0,
+    'r1: 'b,
+{
+    loop {}
+}
+fn foo<'a, 'b>() -> impl Sized + use<'a, 'b> {
+    with_constraints::<'_, '_, 'a, 'b>()
+}
+fn main() {}
diff --git a/tests/ui/impl-trait/no-anonymize-regions.rs b/tests/ui/impl-trait/no-anonymize-regions.rs
new file mode 100644
index 00000000000..4f7f7c0641c
--- /dev/null
+++ b/tests/ui/impl-trait/no-anonymize-regions.rs
@@ -0,0 +1,18 @@
+//@ check-pass
+// FIXME(-Znext-solver): enable this test
+
+// A regression test for an error in `redis` while working on #139587.
+//
+// We check for structural equality when adding defining uses of opaques.
+// In this test one defining use had anonymized regions while the other
+// one did not, causing an error.
+struct W<T>(T);
+fn constrain<F: FnOnce(T) -> R, T, R>(f: F) -> R {
+    loop {}
+}
+fn foo<'a>(x: for<'b> fn(&'b ())) -> impl Sized + use<'a> {
+    let mut r = constrain(foo::<'_>);
+    r = W(x);
+    r
+}
+fn main() {}
diff --git a/tests/ui/issues/issue-15774.rs b/tests/ui/imports/enum-variant-import-path-15774.rs
index dadd59cc077..583fe4da179 100644
--- a/tests/ui/issues/issue-15774.rs
+++ b/tests/ui/imports/enum-variant-import-path-15774.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15774
+
 //@ edition: 2015
 //@ run-pass
 
diff --git a/tests/ui/inference/iterator-sum-array-15673.rs b/tests/ui/inference/iterator-sum-array-15673.rs
new file mode 100644
index 00000000000..c3d94415aff
--- /dev/null
+++ b/tests/ui/inference/iterator-sum-array-15673.rs
@@ -0,0 +1,11 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15673
+
+//@ run-pass
+#![allow(stable_features)]
+
+#![feature(iter_arith)]
+
+fn main() {
+    let x: [u64; 3] = [1, 2, 3];
+    assert_eq!(6, (0..3).map(|i| x[i]).sum::<u64>());
+}
diff --git a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs
index 4fd15eea9e0..f1353f1805d 100644
--- a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs
+++ b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr
index 65fe2ffcb7f..5c4a1a75829 100644
--- a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr
+++ b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr
@@ -1,9 +1,11 @@
-error[E0282]: type annotations needed for `Result<_, ((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))>`
-  --> $DIR/really-long-type-in-let-binding-without-sufficient-type-info.rs:7:9
+error[E0282]: type annotations needed for `Result<_, (((..., ..., ..., ...), ..., ..., ...), ..., ..., ...)>`
+  --> $DIR/really-long-type-in-let-binding-without-sufficient-type-info.rs:8:9
    |
 LL |     let y = Err(x);
    |         ^   ------ type must be known at this point
    |
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/really-long-type-in-let-binding-without-sufficient-type-info.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
    |
 LL |     let y: Result<T, _> = Err(x);
diff --git a/tests/ui/issues/issue-15965.rs b/tests/ui/inference/return-block-type-inference-15965.rs
index eef4900d432..50753e309e8 100644
--- a/tests/ui/issues/issue-15965.rs
+++ b/tests/ui/inference/return-block-type-inference-15965.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15965
+
 fn main() {
     return
         { return () }
diff --git a/tests/ui/issues/issue-15965.stderr b/tests/ui/inference/return-block-type-inference-15965.stderr
index 14727e74334..fc4f2defe7f 100644
--- a/tests/ui/issues/issue-15965.stderr
+++ b/tests/ui/inference/return-block-type-inference-15965.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/issue-15965.rs:3:9
+  --> $DIR/return-block-type-inference-15965.rs:5:9
    |
 LL | /         { return () }
 LL | |
diff --git a/tests/ui/interior-mutability/interior-mutability.rs b/tests/ui/interior-mutability/interior-mutability.rs
index c704acc22af..7e4fe76852d 100644
--- a/tests/ui/interior-mutability/interior-mutability.rs
+++ b/tests/ui/interior-mutability/interior-mutability.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 use std::cell::Cell;
 use std::panic::catch_unwind;
 fn main() {
diff --git a/tests/ui/interior-mutability/interior-mutability.stderr b/tests/ui/interior-mutability/interior-mutability.stderr
index cfc64445bf3..5a959d14c8a 100644
--- a/tests/ui/interior-mutability/interior-mutability.stderr
+++ b/tests/ui/interior-mutability/interior-mutability.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/interior-mutability.rs:5:18
+  --> $DIR/interior-mutability.rs:6:18
    |
 LL |     catch_unwind(|| { x.set(23); });
    |     ------------ ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
@@ -11,7 +11,7 @@ note: required because it appears within the type `Cell<i32>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
    = note: required for `&Cell<i32>` to implement `UnwindSafe`
 note: required because it's used within this closure
-  --> $DIR/interior-mutability.rs:5:18
+  --> $DIR/interior-mutability.rs:6:18
    |
 LL |     catch_unwind(|| { x.set(23); });
    |                  ^^
diff --git a/tests/ui/intrinsics/intrinsic-atomics.rs b/tests/ui/intrinsics/intrinsic-atomics.rs
index 2275aafff83..c19948137db 100644
--- a/tests/ui/intrinsics/intrinsic-atomics.rs
+++ b/tests/ui/intrinsics/intrinsic-atomics.rs
@@ -33,14 +33,14 @@ pub fn main() {
         assert_eq!(rusti::atomic_xchg::<_, { Release }>(&mut *x, 0), 1);
         assert_eq!(*x, 0);
 
-        assert_eq!(rusti::atomic_xadd::<_, { SeqCst }>(&mut *x, 1), 0);
-        assert_eq!(rusti::atomic_xadd::<_, { Acquire }>(&mut *x, 1), 1);
-        assert_eq!(rusti::atomic_xadd::<_, { Release }>(&mut *x, 1), 2);
+        assert_eq!(rusti::atomic_xadd::<_, _, { SeqCst }>(&mut *x, 1), 0);
+        assert_eq!(rusti::atomic_xadd::<_, _, { Acquire }>(&mut *x, 1), 1);
+        assert_eq!(rusti::atomic_xadd::<_, _, { Release }>(&mut *x, 1), 2);
         assert_eq!(*x, 3);
 
-        assert_eq!(rusti::atomic_xsub::<_, { SeqCst }>(&mut *x, 1), 3);
-        assert_eq!(rusti::atomic_xsub::<_, { Acquire }>(&mut *x, 1), 2);
-        assert_eq!(rusti::atomic_xsub::<_, { Release }>(&mut *x, 1), 1);
+        assert_eq!(rusti::atomic_xsub::<_, _, { SeqCst }>(&mut *x, 1), 3);
+        assert_eq!(rusti::atomic_xsub::<_, _, { Acquire }>(&mut *x, 1), 2);
+        assert_eq!(rusti::atomic_xsub::<_, _, { Release }>(&mut *x, 1), 1);
         assert_eq!(*x, 0);
 
         loop {
diff --git a/tests/ui/intrinsics/non-integer-atomic.rs b/tests/ui/intrinsics/non-integer-atomic.rs
index 853c163710f..30f713f1241 100644
--- a/tests/ui/intrinsics/non-integer-atomic.rs
+++ b/tests/ui/intrinsics/non-integer-atomic.rs
@@ -13,80 +13,80 @@ pub type Quux = [u8; 100];
 
 pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
     intrinsics::atomic_load::<_, { SeqCst }>(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer or pointer type, found `bool`
 }
 
 pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer or pointer type, found `bool`
 }
 
 pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer or pointer type, found `bool`
 }
 
 pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `bool`
 }
 
 pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
     intrinsics::atomic_load::<_, { SeqCst }>(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer or pointer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer or pointer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer or pointer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `Foo`
 }
 
 pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
     intrinsics::atomic_load::<_, { SeqCst }>(p);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+    //~^ ERROR expected basic integer or pointer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+    //~^ ERROR expected basic integer or pointer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+    //~^ ERROR expected basic integer or pointer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+    //~^ ERROR expected basic integer or pointer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
     intrinsics::atomic_load::<_, { SeqCst }>(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
 }
diff --git a/tests/ui/intrinsics/non-integer-atomic.stderr b/tests/ui/intrinsics/non-integer-atomic.stderr
index e539d99b8ae..b96ee7ba846 100644
--- a/tests/ui/intrinsics/non-integer-atomic.stderr
+++ b/tests/ui/intrinsics/non-integer-atomic.stderr
@@ -1,94 +1,94 @@
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `bool`
   --> $DIR/non-integer-atomic.rs:15:5
    |
 LL |     intrinsics::atomic_load::<_, { SeqCst }>(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `bool`
   --> $DIR/non-integer-atomic.rs:20:5
    |
 LL |     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `bool`
   --> $DIR/non-integer-atomic.rs:25:5
    |
 LL |     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `bool`
   --> $DIR/non-integer-atomic.rs:30:5
    |
 LL |     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:35:5
    |
 LL |     intrinsics::atomic_load::<_, { SeqCst }>(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:40:5
    |
 LL |     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:45:5
    |
 LL |     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:50:5
    |
 LL |     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:55:5
    |
 LL |     intrinsics::atomic_load::<_, { SeqCst }>(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:60:5
    |
 LL |     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:65:5
    |
 LL |     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:70:5
    |
 LL |     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:75:5
    |
 LL |     intrinsics::atomic_load::<_, { SeqCst }>(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:80:5
    |
 LL |     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:85:5
    |
 LL |     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:90:5
    |
 LL |     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
diff --git a/tests/ui/issues/issue-41880.stderr b/tests/ui/issues/issue-41880.stderr
index 1936c0aebd4..2f1ebee7ca5 100644
--- a/tests/ui/issues/issue-41880.stderr
+++ b/tests/ui/issues/issue-41880.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `iter` found for struct `Iterate` in the current scope
+error[E0599]: no method named `iter` found for struct `Iterate<T, F>` in the current scope
   --> $DIR/issue-41880.rs:27:24
    |
 LL | pub struct Iterate<T, F> {
diff --git a/tests/ui/issues/issue-15756.rs b/tests/ui/iterators/explicit-deref-non-deref-type-15756.rs
index e0861dee61e..6d4a3bffcf7 100644
--- a/tests/ui/issues/issue-15756.rs
+++ b/tests/ui/iterators/explicit-deref-non-deref-type-15756.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15756
+
 use std::slice::Chunks;
 use std::slice::ChunksMut;
 
diff --git a/tests/ui/issues/issue-15756.stderr b/tests/ui/iterators/explicit-deref-non-deref-type-15756.stderr
index a487d360bef..b4f9aab8496 100644
--- a/tests/ui/issues/issue-15756.stderr
+++ b/tests/ui/iterators/explicit-deref-non-deref-type-15756.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[T]` cannot be known at compilation time
-  --> $DIR/issue-15756.rs:7:10
+  --> $DIR/explicit-deref-non-deref-type-15756.rs:9:10
    |
 LL |     &mut something
    |          ^^^^^^^^^ doesn't have a size known at compile-time
diff --git a/tests/ui/issues/issue-15034.rs b/tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.rs
index 9ea6ed89ca2..e7f9a94231f 100644
--- a/tests/ui/issues/issue-15034.rs
+++ b/tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15034
+
 pub struct Lexer<'a> {
     input: &'a str,
 }
diff --git a/tests/ui/issues/issue-15034.stderr b/tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.stderr
index 7db8ade2e48..0762714d259 100644
--- a/tests/ui/issues/issue-15034.stderr
+++ b/tests/ui/lifetimes/nondeterministic-lifetime-errors-15034.stderr
@@ -1,5 +1,5 @@
 error[E0621]: explicit lifetime required in the type of `lexer`
-  --> $DIR/issue-15034.rs:17:9
+  --> $DIR/nondeterministic-lifetime-errors-15034.rs:19:9
    |
 LL |         Parser { lexer: lexer }
    |         ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
diff --git a/tests/ui/lifetimes/struct-lifetime-inference-15735.rs b/tests/ui/lifetimes/struct-lifetime-inference-15735.rs
new file mode 100644
index 00000000000..39e619648eb
--- /dev/null
+++ b/tests/ui/lifetimes/struct-lifetime-inference-15735.rs
@@ -0,0 +1,19 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15735
+
+//@ check-pass
+#![allow(dead_code)]
+struct A<'a> {
+    a: &'a i32,
+    b: &'a i32,
+}
+
+impl <'a> A<'a> {
+    fn foo<'b>(&'b self) {
+        A {
+            a: self.a,
+            b: self.b,
+        };
+    }
+}
+
+fn main() { }
diff --git a/tests/ui/issues/issue-15189.rs b/tests/ui/macros/for-loop-macro-rules-hygiene.rs
index 4dbe2179dd9..fcebda1b9da 100644
--- a/tests/ui/issues/issue-15189.rs
+++ b/tests/ui/macros/for-loop-macro-rules-hygiene.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15189
+
 //@ run-pass
 macro_rules! third {
     ($e:expr) => ({let x = 2; $e[x]})
diff --git a/tests/ui/issues/issue-15167.rs b/tests/ui/macros/macro-hygiene-scope-15167.rs
index a2653c10ea4..6578f898a5f 100644
--- a/tests/ui/issues/issue-15167.rs
+++ b/tests/ui/macros/macro-hygiene-scope-15167.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15167
+
 // macro f should not be able to inject a reference to 'n'.
 
 macro_rules! f { () => (n) }
diff --git a/tests/ui/issues/issue-15167.stderr b/tests/ui/macros/macro-hygiene-scope-15167.stderr
index 53082ea0ec6..58112c52df1 100644
--- a/tests/ui/issues/issue-15167.stderr
+++ b/tests/ui/macros/macro-hygiene-scope-15167.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find value `n` in this scope
-  --> $DIR/issue-15167.rs:3:25
+  --> $DIR/macro-hygiene-scope-15167.rs:5:25
    |
 LL | macro_rules! f { () => (n) }
    |                         ^ not found in this scope
@@ -10,7 +10,7 @@ LL |         println!("{}", f!());
    = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find value `n` in this scope
-  --> $DIR/issue-15167.rs:3:25
+  --> $DIR/macro-hygiene-scope-15167.rs:5:25
    |
 LL | macro_rules! f { () => (n) }
    |                         ^ not found in this scope
@@ -21,7 +21,7 @@ LL |         println!("{}", f!());
    = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find value `n` in this scope
-  --> $DIR/issue-15167.rs:3:25
+  --> $DIR/macro-hygiene-scope-15167.rs:5:25
    |
 LL | macro_rules! f { () => (n) }
    |                         ^ not found in this scope
@@ -32,7 +32,7 @@ LL |         println!("{}", f!());
    = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0425]: cannot find value `n` in this scope
-  --> $DIR/issue-15167.rs:3:25
+  --> $DIR/macro-hygiene-scope-15167.rs:5:25
    |
 LL | macro_rules! f { () => (n) }
    |                         ^ not found in this scope
diff --git a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr
index e5b913b208d..77f8bef83a4 100644
--- a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr
+++ b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr
@@ -11,7 +11,7 @@ error: cannot find attribute `sample` in this scope
   --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:5:3
    |
 LL | macro_rules! sample { () => {} }
-   |              ------ `sample` exists, but a declarative macro cannot be used as an attribute macro
+   |              ------ `sample` exists, but has no `attr` rules
 LL |
 LL | #[sample]
    |   ^^^^^^
diff --git a/tests/ui/macros/macro-rules-attr-error.rs b/tests/ui/macros/macro-rules-attr-error.rs
new file mode 100644
index 00000000000..1c8bb251e20
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-error.rs
@@ -0,0 +1,15 @@
+#![feature(macro_attr)]
+
+macro_rules! local_attr {
+    attr() { $($body:tt)* } => {
+        compile_error!(concat!("local_attr: ", stringify!($($body)*)));
+    };
+    //~^^ ERROR: local_attr
+}
+
+fn main() {
+    #[local_attr]
+    struct S;
+
+    local_attr!(arg); //~ ERROR: macro has no rules for function-like invocation
+}
diff --git a/tests/ui/macros/macro-rules-attr-error.stderr b/tests/ui/macros/macro-rules-attr-error.stderr
new file mode 100644
index 00000000000..177b7009384
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-error.stderr
@@ -0,0 +1,22 @@
+error: local_attr: struct S;
+  --> $DIR/macro-rules-attr-error.rs:5:9
+   |
+LL |         compile_error!(concat!("local_attr: ", stringify!($($body)*)));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     #[local_attr]
+   |     ------------- in this attribute macro expansion
+   |
+   = note: this error originates in the attribute macro `local_attr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: macro has no rules for function-like invocation `local_attr!`
+  --> $DIR/macro-rules-attr-error.rs:14:5
+   |
+LL | macro_rules! local_attr {
+   | ----------------------- this macro has no rules for function-like invocation
+...
+LL |     local_attr!(arg);
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/macros/macro-rules-attr-infinite-recursion.rs b/tests/ui/macros/macro-rules-attr-infinite-recursion.rs
new file mode 100644
index 00000000000..dc54c32cad3
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-infinite-recursion.rs
@@ -0,0 +1,12 @@
+#![crate_type = "lib"]
+#![feature(macro_attr)]
+
+macro_rules! attr {
+    attr() { $($body:tt)* } => {
+        #[attr] $($body)*
+    };
+    //~^^ ERROR: recursion limit reached
+}
+
+#[attr]
+struct S;
diff --git a/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr b/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr
new file mode 100644
index 00000000000..7d9a94338f5
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr
@@ -0,0 +1,14 @@
+error: recursion limit reached while expanding `#[attr]`
+  --> $DIR/macro-rules-attr-infinite-recursion.rs:6:9
+   |
+LL |         #[attr] $($body)*
+   |         ^^^^^^^
+...
+LL | #[attr]
+   | ------- in this attribute macro expansion
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`macro_rules_attr_infinite_recursion`)
+   = note: this error originates in the attribute macro `attr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/macro-rules-attr-nested.rs b/tests/ui/macros/macro-rules-attr-nested.rs
new file mode 100644
index 00000000000..af5c30f00dd
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-nested.rs
@@ -0,0 +1,24 @@
+//@ run-pass
+//@ check-run-results
+#![feature(macro_attr)]
+
+macro_rules! nest {
+    attr() { struct $name:ident; } => {
+        println!("nest");
+        #[nest(1)]
+        struct $name;
+    };
+    attr(1) { struct $name:ident; } => {
+        println!("nest(1)");
+        #[nest(2)]
+        struct $name;
+    };
+    attr(2) { struct $name:ident; } => {
+        println!("nest(2)");
+    };
+}
+
+fn main() {
+    #[nest]
+    struct S;
+}
diff --git a/tests/ui/macros/macro-rules-attr-nested.run.stdout b/tests/ui/macros/macro-rules-attr-nested.run.stdout
new file mode 100644
index 00000000000..46017f9ae08
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-nested.run.stdout
@@ -0,0 +1,3 @@
+nest
+nest(1)
+nest(2)
diff --git a/tests/ui/macros/macro-rules-attr.rs b/tests/ui/macros/macro-rules-attr.rs
new file mode 100644
index 00000000000..1d6f09b53e1
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr.rs
@@ -0,0 +1,90 @@
+//@ run-pass
+//@ check-run-results
+#![feature(macro_attr)]
+#![warn(unused)]
+
+#[macro_export]
+macro_rules! exported_attr {
+    attr($($args:tt)*) { $($body:tt)* } => {
+        println!(
+            "exported_attr: args={:?}, body={:?}",
+            stringify!($($args)*),
+            stringify!($($body)*),
+        );
+    };
+    { $($args:tt)* } => {
+        println!("exported_attr!({:?})", stringify!($($args)*));
+    };
+    attr() {} => {
+        unused_rule();
+    };
+    attr() {} => {
+        compile_error!();
+    };
+    {} => {
+        unused_rule();
+    };
+    {} => {
+        compile_error!();
+    };
+}
+
+macro_rules! local_attr {
+    attr($($args:tt)*) { $($body:tt)* } => {
+        println!(
+            "local_attr: args={:?}, body={:?}",
+            stringify!($($args)*),
+            stringify!($($body)*),
+        );
+    };
+    { $($args:tt)* } => {
+        println!("local_attr!({:?})", stringify!($($args)*));
+    };
+    attr() {} => { //~ WARN: never used
+        unused_rule();
+    };
+    attr() {} => {
+        compile_error!();
+    };
+    {} => { //~ WARN: never used
+        unused_rule();
+    };
+    {} => {
+        compile_error!();
+    };
+}
+
+fn main() {
+    #[crate::exported_attr]
+    struct S;
+    #[::exported_attr(arguments, key = "value")]
+    fn func(_arg: u32) {}
+    #[self::exported_attr(1)]
+    #[self::exported_attr(2)]
+    struct Twice;
+
+    crate::exported_attr!();
+    crate::exported_attr!(invoked, arguments);
+
+    #[exported_attr]
+    struct S;
+    #[exported_attr(arguments, key = "value")]
+    fn func(_arg: u32) {}
+    #[exported_attr(1)]
+    #[exported_attr(2)]
+    struct Twice;
+
+    exported_attr!();
+    exported_attr!(invoked, arguments);
+
+    #[local_attr]
+    struct S;
+    #[local_attr(arguments, key = "value")]
+    fn func(_arg: u32) {}
+    #[local_attr(1)]
+    #[local_attr(2)]
+    struct Twice;
+
+    local_attr!();
+    local_attr!(invoked, arguments);
+}
diff --git a/tests/ui/macros/macro-rules-attr.run.stdout b/tests/ui/macros/macro-rules-attr.run.stdout
new file mode 100644
index 00000000000..77aa94d54f8
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr.run.stdout
@@ -0,0 +1,15 @@
+exported_attr: args="", body="struct S;"
+exported_attr: args="arguments, key = \"value\"", body="fn func(_arg: u32) {}"
+exported_attr: args="1", body="#[self::exported_attr(2)] struct Twice;"
+exported_attr!("")
+exported_attr!("invoked, arguments")
+exported_attr: args="", body="struct S;"
+exported_attr: args="arguments, key = \"value\"", body="fn func(_arg: u32) {}"
+exported_attr: args="1", body="#[exported_attr(2)] struct Twice;"
+exported_attr!("")
+exported_attr!("invoked, arguments")
+local_attr: args="", body="struct S;"
+local_attr: args="arguments, key = \"value\"", body="fn func(_arg: u32) {}"
+local_attr: args="1", body="#[local_attr(2)] struct Twice;"
+local_attr!("")
+local_attr!("invoked, arguments")
diff --git a/tests/ui/macros/macro-rules-attr.stderr b/tests/ui/macros/macro-rules-attr.stderr
new file mode 100644
index 00000000000..567664cd73d
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr.stderr
@@ -0,0 +1,21 @@
+warning: rule #3 of macro `local_attr` is never used
+  --> $DIR/macro-rules-attr.rs:43:9
+   |
+LL |     attr() {} => {
+   |         ^^ ^^
+   |
+note: the lint level is defined here
+  --> $DIR/macro-rules-attr.rs:4:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_macro_rules)]` implied by `#[warn(unused)]`
+
+warning: rule #5 of macro `local_attr` is never used
+  --> $DIR/macro-rules-attr.rs:49:5
+   |
+LL |     {} => {
+   |     ^^
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/methods/call_method_unknown_referent.rs b/tests/ui/methods/call_method_unknown_referent.rs
index b01e2d80f7f..b26ecc74175 100644
--- a/tests/ui/methods/call_method_unknown_referent.rs
+++ b/tests/ui/methods/call_method_unknown_referent.rs
@@ -44,5 +44,5 @@ fn main() {
     // our resolution logic needs to be able to call methods such as foo()
     // on the outer type even if the inner type is ambiguous.
     let _c = (ptr as SmartPtr<_>).read();
-    //~^ ERROR no method named `read` found for struct `SmartPtr`
+    //~^ ERROR no method named `read` found for struct `SmartPtr<T>`
 }
diff --git a/tests/ui/methods/call_method_unknown_referent.stderr b/tests/ui/methods/call_method_unknown_referent.stderr
index 748b02b52b5..5d6974a00c6 100644
--- a/tests/ui/methods/call_method_unknown_referent.stderr
+++ b/tests/ui/methods/call_method_unknown_referent.stderr
@@ -10,7 +10,7 @@ error[E0282]: type annotations needed
 LL |     let _b = (rc as std::rc::Rc<_>).read();
    |                                     ^^^^ cannot infer type
 
-error[E0599]: no method named `read` found for struct `SmartPtr` in the current scope
+error[E0599]: no method named `read` found for struct `SmartPtr<T>` in the current scope
   --> $DIR/call_method_unknown_referent.rs:46:35
    |
 LL | struct SmartPtr<T>(T);
diff --git a/tests/ui/methods/inherent-bound-in-probe.rs b/tests/ui/methods/inherent-bound-in-probe.rs
index 4add93e808d..39b4ba983e4 100644
--- a/tests/ui/methods/inherent-bound-in-probe.rs
+++ b/tests/ui/methods/inherent-bound-in-probe.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 // Fixes #110131
 //
 // The issue is that we were constructing an `ImplDerived` cause code for the
diff --git a/tests/ui/methods/inherent-bound-in-probe.stderr b/tests/ui/methods/inherent-bound-in-probe.stderr
index 77aed390c9a..b7751ca4714 100644
--- a/tests/ui/methods/inherent-bound-in-probe.stderr
+++ b/tests/ui/methods/inherent-bound-in-probe.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `Helper<'a, T>` is not an iterator
-  --> $DIR/inherent-bound-in-probe.rs:38:21
+  --> $DIR/inherent-bound-in-probe.rs:39:21
    |
 LL |     type IntoIter = Helper<'a, T>;
    |                     ^^^^^^^^^^^^^ `Helper<'a, T>` is not an iterator
@@ -9,14 +9,14 @@ note: required by a bound in `std::iter::IntoIterator::IntoIter`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
 
 error[E0275]: overflow evaluating the requirement `&_: IntoIterator`
-  --> $DIR/inherent-bound-in-probe.rs:42:9
+  --> $DIR/inherent-bound-in-probe.rs:43:9
    |
 LL |         Helper::new(&self.0)
    |         ^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_bound_in_probe`)
 note: required for `&BitReaderWrapper<_>` to implement `IntoIterator`
-  --> $DIR/inherent-bound-in-probe.rs:32:13
+  --> $DIR/inherent-bound-in-probe.rs:33:13
    |
 LL | impl<'a, T> IntoIterator for &'a BitReaderWrapper<T>
    |             ^^^^^^^^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,15 +24,17 @@ LL | where
 LL |     &'a T: IntoIterator<Item = &'a u8>,
    |                         ------------- unsatisfied trait bound introduced here
    = note: 126 redundant requirements hidden
-   = note: required for `&BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `IntoIterator`
+   = note: required for `&BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<...>>>` to implement `IntoIterator`
 note: required by a bound in `Helper`
-  --> $DIR/inherent-bound-in-probe.rs:16:12
+  --> $DIR/inherent-bound-in-probe.rs:17:12
    |
 LL | struct Helper<'a, T>
    |        ------ required by a bound in this struct
 LL | where
 LL |     &'a T: IntoIterator<Item = &'a u8>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Helper`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/inherent-bound-in-probe.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/methods/method-not-found-generic-arg-elision.stderr b/tests/ui/methods/method-not-found-generic-arg-elision.stderr
index 8429c3aebac..75fabc27b0f 100644
--- a/tests/ui/methods/method-not-found-generic-arg-elision.stderr
+++ b/tests/ui/methods/method-not-found-generic-arg-elision.stderr
@@ -10,7 +10,7 @@ LL |     let d = point_i32.distance();
    = note: the method was found for
            - `Point<f64>`
 
-error[E0599]: no method named `other` found for struct `Point` in the current scope
+error[E0599]: no method named `other` found for struct `Point<T>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:84:23
    |
 LL | struct Point<T> {
@@ -19,7 +19,7 @@ LL | struct Point<T> {
 LL |     let d = point_i32.other();
    |                       ^^^^^ method not found in `Point<i32>`
 
-error[E0599]: no method named `extend` found for struct `Map` in the current scope
+error[E0599]: no method named `extend` found for struct `Map<I, F>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:87:67
    |
 LL |     v.iter().map(Box::new(|x| x * x) as Box<dyn Fn(&i32) -> i32>).extend(std::iter::once(100));
@@ -41,7 +41,7 @@ LL |     wrapper.method();
            - `Wrapper<i8>`
            and 2 more types
 
-error[E0599]: no method named `other` found for struct `Wrapper` in the current scope
+error[E0599]: no method named `other` found for struct `Wrapper<T>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:92:13
    |
 LL | struct Wrapper<T>(T);
@@ -64,7 +64,7 @@ LL |     wrapper.method();
            - `Wrapper2<'a, i32, C>`
            - `Wrapper2<'a, i8, C>`
 
-error[E0599]: no method named `other` found for struct `Wrapper2` in the current scope
+error[E0599]: no method named `other` found for struct `Wrapper2<'a, T, C>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:98:13
    |
 LL | struct Wrapper2<'a, T, const C: usize> {
diff --git a/tests/ui/methods/probe-error-on-infinite-deref.rs b/tests/ui/methods/probe-error-on-infinite-deref.rs
index 85c1c0c09c1..196d026438b 100644
--- a/tests/ui/methods/probe-error-on-infinite-deref.rs
+++ b/tests/ui/methods/probe-error-on-infinite-deref.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 use std::ops::Deref;
 
 // Make sure that method probe error reporting doesn't get too tangled up
diff --git a/tests/ui/methods/probe-error-on-infinite-deref.stderr b/tests/ui/methods/probe-error-on-infinite-deref.stderr
index 57a9ca2eaa8..6148b001163 100644
--- a/tests/ui/methods/probe-error-on-infinite-deref.stderr
+++ b/tests/ui/methods/probe-error-on-infinite-deref.stderr
@@ -1,13 +1,15 @@
-error[E0055]: reached the recursion limit while auto-dereferencing `Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<{integer}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/probe-error-on-infinite-deref.rs:13:13
+error[E0055]: reached the recursion limit while auto-dereferencing `Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<...>>>>>>>>>>>`
+  --> $DIR/probe-error-on-infinite-deref.rs:14:13
    |
 LL |     Wrap(1).lmao();
    |             ^^^^ deref recursion limit reached
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`probe_error_on_infinite_deref`)
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/probe-error-on-infinite-deref.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error[E0599]: no method named `lmao` found for struct `Wrap<{integer}>` in the current scope
-  --> $DIR/probe-error-on-infinite-deref.rs:13:13
+  --> $DIR/probe-error-on-infinite-deref.rs:14:13
    |
 LL | struct Wrap<T>(T);
    | -------------- method `lmao` not found for this struct
diff --git a/tests/ui/methods/untrimmed-path-type.stderr b/tests/ui/methods/untrimmed-path-type.stderr
index 1f3101ff4e7..ee07e2daa1e 100644
--- a/tests/ui/methods/untrimmed-path-type.stderr
+++ b/tests/ui/methods/untrimmed-path-type.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `unknown` found for enum `Result` in the current scope
+error[E0599]: no method named `unknown` found for enum `Result<T, E>` in the current scope
   --> $DIR/untrimmed-path-type.rs:5:11
    |
 LL |    meow().unknown();
diff --git a/tests/ui/issues/issue-15571.rs b/tests/ui/moves/match-move-same-binding-15571.rs
index cf17113a282..f6d79c6d76c 100644
--- a/tests/ui/issues/issue-15571.rs
+++ b/tests/ui/moves/match-move-same-binding-15571.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15571
+
 //@ run-pass
 
 fn match_on_local() {
diff --git a/tests/ui/issues/issue-15207.rs b/tests/ui/never/never-type-method-call-15207.rs
index 356e55ac912..69cdeeabb7c 100644
--- a/tests/ui/issues/issue-15207.rs
+++ b/tests/ui/never/never-type-method-call-15207.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15207
+
 fn main() {
     loop {
         break.push(1) //~ ERROR no method named `push` found for type `!`
diff --git a/tests/ui/issues/issue-15207.stderr b/tests/ui/never/never-type-method-call-15207.stderr
index a1047e27ba2..265e7c8611d 100644
--- a/tests/ui/issues/issue-15207.stderr
+++ b/tests/ui/never/never-type-method-call-15207.stderr
@@ -1,5 +1,5 @@
 error[E0599]: no method named `push` found for type `!` in the current scope
-  --> $DIR/issue-15207.rs:3:15
+  --> $DIR/never-type-method-call-15207.rs:5:15
    |
 LL |         break.push(1)
    |               ^^^^ method not found in `!`
diff --git a/tests/ui/never_type/defaulted-never-note.fallback.stderr b/tests/ui/never_type/defaulted-never-note.fallback.stderr
index fe9a924f64a..7526a399bf1 100644
--- a/tests/ui/never_type/defaulted-never-note.fallback.stderr
+++ b/tests/ui/never_type/defaulted-never-note.fallback.stderr
@@ -8,7 +8,7 @@ LL |     foo(_x);
    |
    = help: the trait `ImplementedForUnitButNotNever` is implemented for `()`
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 note: required by a bound in `foo`
   --> $DIR/defaulted-never-note.rs:25:11
    |
diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/defaulted-never-note.rs
index badb5d4c51d..71f0d9fa5bb 100644
--- a/tests/ui/never_type/defaulted-never-note.rs
+++ b/tests/ui/never_type/defaulted-never-note.rs
@@ -35,7 +35,7 @@ fn smeg() {
     //[fallback]~| HELP trait `ImplementedForUnitButNotNever` is implemented for `()`
     //[fallback]~| NOTE this error might have been caused
     //[fallback]~| NOTE required by a bound introduced by this call
-    //[fallback]~| HELP did you intend
+    //[fallback]~| HELP you might have intended to use the type `()`
 }
 
 fn main() {
diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
index c5463814475..610c687194b 100644
--- a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
+++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
@@ -10,7 +10,7 @@ LL |     unconstrained_arg(return);
              ()
              i32
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 note: required by a bound in `unconstrained_arg`
   --> $DIR/diverging-fallback-no-leak.rs:12:25
    |
diff --git a/tests/ui/nll/issue-46589.nll.stderr b/tests/ui/nll/issue-46589.nll.stderr
index dc80c1d08de..f2d08d1f4c8 100644
--- a/tests/ui/nll/issue-46589.nll.stderr
+++ b/tests/ui/nll/issue-46589.nll.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `**other` as mutable more than once at a time
-  --> $DIR/issue-46589.rs:24:21
+  --> $DIR/issue-46589.rs:25:21
    |
 LL |         *other = match (*other).get_self() {
    |                        -------- first mutable borrow occurs here
diff --git a/tests/ui/nll/issue-46589.polonius.stderr b/tests/ui/nll/issue-46589.polonius.stderr
new file mode 100644
index 00000000000..f2d08d1f4c8
--- /dev/null
+++ b/tests/ui/nll/issue-46589.polonius.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `**other` as mutable more than once at a time
+  --> $DIR/issue-46589.rs:25:21
+   |
+LL |         *other = match (*other).get_self() {
+   |                        -------- first mutable borrow occurs here
+LL |             Some(s) => s,
+LL |             None => (*other).new_self()
+   |                     ^^^^^^^^
+   |                     |
+   |                     second mutable borrow occurs here
+   |                     first borrow later used here
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/issue-46589.rs b/tests/ui/nll/issue-46589.rs
index 10aff0d7b4e..9a23f61b8cb 100644
--- a/tests/ui/nll/issue-46589.rs
+++ b/tests/ui/nll/issue-46589.rs
@@ -1,9 +1,10 @@
 //@ ignore-compare-mode-polonius (explicit revisions)
-//@ revisions: nll polonius_next polonius
-//@ [polonius_next] check-pass
-//@ [polonius_next] compile-flags: -Zpolonius=next
-//@ [polonius] check-pass
-//@ [polonius] compile-flags: -Zpolonius
+//@ revisions: nll polonius legacy
+//@ [nll] known-bug: #46589
+//@ [polonius] known-bug: #46589
+//@ [polonius] compile-flags: -Zpolonius=next
+//@ [legacy] check-pass
+//@ [legacy] compile-flags: -Zpolonius=legacy
 
 struct Foo;
 
@@ -22,7 +23,6 @@ impl Foo {
         *other = match (*other).get_self() {
             Some(s) => s,
             None => (*other).new_self()
-            //[nll]~^ ERROR cannot borrow `**other` as mutable more than once at a time [E0499]
         };
 
         let c = other;
diff --git a/tests/ui/nll/polonius/array-literal-index-oob-2024.rs b/tests/ui/nll/polonius/array-literal-index-oob-2024.rs
new file mode 100644
index 00000000000..2054a32e535
--- /dev/null
+++ b/tests/ui/nll/polonius/array-literal-index-oob-2024.rs
@@ -0,0 +1,12 @@
+// This test used to ICE under `-Zpolonius=next` when computing loan liveness
+// and taking kills into account during reachability traversal of the localized
+// constraint graph. Originally from another test but on edition 2024, as
+// seen in issue #135646.
+
+//@ compile-flags: -Zpolonius=next
+//@ edition: 2024
+//@ check-pass
+
+fn main() {
+    &{ [1, 2, 3][4] };
+}
diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr b/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr
new file mode 100644
index 00000000000..5756148f4eb
--- /dev/null
+++ b/tests/ui/nll/polonius/flow-sensitive-invariance.nll.stderr
@@ -0,0 +1,36 @@
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:17
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                 ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:45
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                                             ^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr b/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr
new file mode 100644
index 00000000000..5756148f4eb
--- /dev/null
+++ b/tests/ui/nll/polonius/flow-sensitive-invariance.polonius.stderr
@@ -0,0 +1,36 @@
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:17
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                 ^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: lifetime may not live long enough
+  --> $DIR/flow-sensitive-invariance.rs:20:45
+   |
+LL | fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+   |           --  -- lifetime `'b` defined here
+   |           |
+   |           lifetime `'a` defined here
+LL |     let returned_value = create_invariant();
+LL |     if choice { Ok(returned_value) } else { Err(returned_value) }
+   |                                             ^^^^^^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+   = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Invariant<'l>` is invariant over the parameter `'l`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/nll/polonius/flow-sensitive-invariance.rs b/tests/ui/nll/polonius/flow-sensitive-invariance.rs
new file mode 100644
index 00000000000..c5571f131da
--- /dev/null
+++ b/tests/ui/nll/polonius/flow-sensitive-invariance.rs
@@ -0,0 +1,34 @@
+// An example (from @steffahn) of reachability as an approximation of liveness where the polonius
+// alpha analysis shows the same imprecision as NLLs, unlike the datalog implementation.
+
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius legacy
+//@ [polonius] compile-flags: -Z polonius=next
+//@ [legacy] check-pass
+//@ [legacy] compile-flags: -Z polonius=legacy
+
+use std::cell::Cell;
+
+struct Invariant<'l>(Cell<&'l ()>);
+
+fn create_invariant<'l>() -> Invariant<'l> {
+    Invariant(Cell::new(&()))
+}
+
+fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
+    let returned_value = create_invariant();
+    if choice { Ok(returned_value) } else { Err(returned_value) }
+    //[nll]~^ ERROR lifetime may not live long enough
+    //[nll]~| ERROR lifetime may not live long enough
+    //[polonius]~^^^ ERROR lifetime may not live long enough
+    //[polonius]~| ERROR lifetime may not live long enough
+}
+
+fn use_it_but_its_the_same_region<'a: 'b, 'b: 'a>(
+    choice: bool,
+) -> Result<Invariant<'a>, Invariant<'b>> {
+    let returned_value = create_invariant();
+    if choice { Ok(returned_value) } else { Err(returned_value) }
+}
+
+fn main() {}
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr
index 7ac4e5de283..b768f60590c 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.nll.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `*elements` as mutable more than once at a time
-  --> $DIR/iterating-updating-cursor-issue-108704.rs:40:26
+  --> $DIR/iterating-updating-cursor-issue-108704.rs:41:26
    |
 LL |         for (idx, el) in elements.iter_mut().enumerate() {
    |                          ^^^^^^^^
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.polonius.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.polonius.stderr
new file mode 100644
index 00000000000..b768f60590c
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.polonius.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `*elements` as mutable more than once at a time
+  --> $DIR/iterating-updating-cursor-issue-108704.rs:41:26
+   |
+LL |         for (idx, el) in elements.iter_mut().enumerate() {
+   |                          ^^^^^^^^
+   |                          |
+   |                          `*elements` was mutably borrowed here in the previous iteration of the loop
+   |                          first borrow used here, in later iteration of loop
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs
index 420cb73bed2..673efa8f225 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-108704.rs
@@ -1,11 +1,12 @@
 #![crate_type = "lib"]
 
-// An example from #108704 of the linked-list cursor-like pattern of #46859/#48001.
+// An example from #108704 of the linked-list cursor-like pattern of #46859/#48001, where the
+// polonius alpha analysis shows the same imprecision as NLLs, unlike the datalog implementation.
 
 //@ ignore-compare-mode-polonius (explicit revisions)
 //@ revisions: nll polonius legacy
 //@ [nll] known-bug: #108704
-//@ [polonius] check-pass
+//@ [polonius] known-bug: #108704
 //@ [polonius] compile-flags: -Z polonius=next
 //@ [legacy] check-pass
 //@ [legacy] compile-flags: -Z polonius=legacy
@@ -32,7 +33,7 @@ fn merge_tree_ok(root: &mut Root, path: Vec<String>) {
     }
 }
 
-// NLLs fail here
+// NLLs and polonius alpha fail here
 fn merge_tree_ko(root: &mut Root, path: Vec<String>) {
     let mut elements = &mut root.children;
 
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr
index 14e1726e158..34b04e707db 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.nll.stderr
@@ -1,5 +1,5 @@
 error[E0499]: cannot borrow `p.0` as mutable more than once at a time
-  --> $DIR/iterating-updating-cursor-issue-57165.rs:29:20
+  --> $DIR/iterating-updating-cursor-issue-57165.rs:30:20
    |
 LL |     while let Some(now) = p {
    |                    ^^^    - first borrow used here, in later iteration of loop
@@ -7,7 +7,7 @@ LL |     while let Some(now) = p {
    |                    `p.0` was mutably borrowed here in the previous iteration of the loop
 
 error[E0503]: cannot use `*p` because it was mutably borrowed
-  --> $DIR/iterating-updating-cursor-issue-57165.rs:29:27
+  --> $DIR/iterating-updating-cursor-issue-57165.rs:30:27
    |
 LL |     while let Some(now) = p {
    |                    ---    ^
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.polonius.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.polonius.stderr
new file mode 100644
index 00000000000..34b04e707db
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.polonius.stderr
@@ -0,0 +1,22 @@
+error[E0499]: cannot borrow `p.0` as mutable more than once at a time
+  --> $DIR/iterating-updating-cursor-issue-57165.rs:30:20
+   |
+LL |     while let Some(now) = p {
+   |                    ^^^    - first borrow used here, in later iteration of loop
+   |                    |
+   |                    `p.0` was mutably borrowed here in the previous iteration of the loop
+
+error[E0503]: cannot use `*p` because it was mutably borrowed
+  --> $DIR/iterating-updating-cursor-issue-57165.rs:30:27
+   |
+LL |     while let Some(now) = p {
+   |                    ---    ^
+   |                    |      |
+   |                    |      use of borrowed `p.0`
+   |                    |      borrow later used here
+   |                    `p.0` is borrowed here
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0499, E0503.
+For more information about an error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs
index 63ec89146d4..9670fc77e6f 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-57165.rs
@@ -1,11 +1,12 @@
 #![crate_type = "lib"]
 
-// An example from #57165 of the linked-list cursor-like pattern of #46859/#48001.
+// An example from #57165 of the linked-list cursor-like pattern of #46859/#48001, where the
+// polonius alpha analysis shows the same imprecision as NLLs, unlike the datalog implementation.
 
 //@ ignore-compare-mode-polonius (explicit revisions)
 //@ revisions: nll polonius legacy
 //@ [nll] known-bug: #57165
-//@ [polonius] check-pass
+//@ [polonius] known-bug: #57165
 //@ [polonius] compile-flags: -Z polonius=next
 //@ [legacy] check-pass
 //@ [legacy] compile-flags: -Z polonius=legacy
@@ -22,7 +23,7 @@ fn no_control_flow() {
     }
 }
 
-// NLLs fail here
+// NLLs and polonius alpha fail here
 fn conditional() {
     let mut b = Some(Box::new(X { next: None }));
     let mut p = &mut b;
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr
index bf38da566c6..b76e4ff6398 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.nll.stderr
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `*node_ref` because it is borrowed
-  --> $DIR/iterating-updating-cursor-issue-63908.rs:42:5
+  --> $DIR/iterating-updating-cursor-issue-63908.rs:43:5
    |
 LL | fn remove_last_node_iterative<T>(mut node_ref: &mut List<T>) {
    |                                                - let's call the lifetime of this reference `'1`
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.polonius.stderr b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.polonius.stderr
new file mode 100644
index 00000000000..b76e4ff6398
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.polonius.stderr
@@ -0,0 +1,18 @@
+error[E0506]: cannot assign to `*node_ref` because it is borrowed
+  --> $DIR/iterating-updating-cursor-issue-63908.rs:43:5
+   |
+LL | fn remove_last_node_iterative<T>(mut node_ref: &mut List<T>) {
+   |                                                - let's call the lifetime of this reference `'1`
+LL |     loop {
+LL |         let next_ref = &mut node_ref.as_mut().unwrap().next;
+   |                             -------- `*node_ref` is borrowed here
+...
+LL |             node_ref = next_ref;
+   |             ------------------- assignment requires that `*node_ref` is borrowed for `'1`
+...
+LL |     *node_ref = None;
+   |     ^^^^^^^^^ `*node_ref` is assigned to here but it was already borrowed
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs
index 00e48b65fed..6682926c523 100644
--- a/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs
+++ b/tests/ui/nll/polonius/iterating-updating-cursor-issue-63908.rs
@@ -1,11 +1,12 @@
 #![crate_type = "lib"]
 
-// An example from #63908 of the linked-list cursor-like pattern of #46859/#48001.
+// An example from #63908 of the linked-list cursor-like pattern of #46859/#48001, where the
+// polonius alpha analysis shows the same imprecision as NLLs, unlike the datalog implementation.
 
 //@ ignore-compare-mode-polonius (explicit revisions)
 //@ revisions: nll polonius legacy
 //@ [nll] known-bug: #63908
-//@ [polonius] check-pass
+//@ [polonius] known-bug: #63908
 //@ [polonius] compile-flags: -Z polonius=next
 //@ [legacy] check-pass
 //@ [legacy] compile-flags: -Z polonius=legacy
@@ -27,7 +28,7 @@ fn remove_last_node_recursive<T>(node_ref: &mut List<T>) {
     }
 }
 
-// NLLs fail here
+// NLLs and polonius alpha fail here
 fn remove_last_node_iterative<T>(mut node_ref: &mut List<T>) {
     loop {
         let next_ref = &mut node_ref.as_mut().unwrap().next;
diff --git a/tests/ui/nll/polonius/iterating-updating-mutref.nll.stderr b/tests/ui/nll/polonius/iterating-updating-mutref.nll.stderr
new file mode 100644
index 00000000000..941c736d8d2
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-mutref.nll.stderr
@@ -0,0 +1,15 @@
+error[E0499]: cannot borrow `self.buf_read` as mutable more than once at a time
+  --> $DIR/iterating-updating-mutref.rs:61:23
+   |
+LL |     pub fn next<'a>(&'a mut self) -> &'a str {
+   |                 -- lifetime `'a` defined here
+LL |         loop {
+LL |             let buf = self.buf_read.fill_buf();
+   |                       ^^^^^^^^^^^^^ `self.buf_read` was mutably borrowed here in the previous iteration of the loop
+LL |             if let Some(s) = decode(buf) {
+LL |                 return s;
+   |                        - returning this value requires that `self.buf_read` is borrowed for `'a`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/iterating-updating-mutref.rs b/tests/ui/nll/polonius/iterating-updating-mutref.rs
new file mode 100644
index 00000000000..a315bf66279
--- /dev/null
+++ b/tests/ui/nll/polonius/iterating-updating-mutref.rs
@@ -0,0 +1,87 @@
+// These are some examples of iterating through and updating a mutable ref, similar in spirit to the
+// linked-list-like pattern of #46859/#48001 where the polonius alpha analysis shows imprecision,
+// unlike the datalog implementation.
+//
+// They differ in that after the loans prior to the loop are either not live after the loop, or with
+// control flow and outlives relationships that are simple enough for the reachability
+// approximation. They're thus accepted by the alpha analysis, like NLLs did for the simplest cases
+// of flow-sensitivity.
+
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius legacy
+//@ [nll] known-bug: #46859
+//@ [polonius] check-pass
+//@ [polonius] compile-flags: -Z polonius=next
+//@ [legacy] check-pass
+//@ [legacy] compile-flags: -Z polonius=legacy
+
+// The #46859 OP
+struct List<T> {
+    value: T,
+    next: Option<Box<List<T>>>,
+}
+
+fn to_refs<T>(mut list: &mut List<T>) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            list = n;
+        } else {
+            return result;
+        }
+    }
+}
+
+// A similar construction, where paths in the constraint graph are also clearly terminating, so it's
+// fine even for NLLs.
+fn to_refs2<T>(mut list: &mut List<T>) -> Vec<&mut T> {
+    let mut result = vec![];
+    loop {
+        result.push(&mut list.value);
+        if let Some(n) = list.next.as_mut() {
+            list = n;
+        } else {
+            break;
+        }
+    }
+
+    result
+}
+
+// Another MCVE from the same issue, but was rejected by NLLs.
+pub struct Decoder {
+    buf_read: BufRead,
+}
+
+impl Decoder {
+    // NLLs fail here
+    pub fn next<'a>(&'a mut self) -> &'a str {
+        loop {
+            let buf = self.buf_read.fill_buf();
+            if let Some(s) = decode(buf) {
+                return s;
+            }
+            // loop to get more input data
+
+            // At this point `buf` is not used anymore.
+            // With NLL I would expect the borrow to end here,
+            // such that `self.buf_read` is not borrowed anymore
+            // by the time we start the next loop iteration.
+        }
+    }
+}
+
+struct BufRead;
+
+impl BufRead {
+    fn fill_buf(&mut self) -> &[u8] {
+        unimplemented!()
+    }
+}
+
+fn decode(_: &[u8]) -> Option<&str> {
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr
new file mode 100644
index 00000000000..fa201b89048
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.legacy.stderr
@@ -0,0 +1,28 @@
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:19:19
+   |
+LL | fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
+   |                                    - let's call the lifetime of this reference `'1`
+LL |     let Some(i) = t.next() else { return None };
+   |                   - first mutable borrow occurs here
+LL |     let Some(j) = t.next() else { return None };
+   |                   ^ second mutable borrow occurs here
+...
+LL |     Some((i, j))
+   |     ------------ returning this value requires that `*t` is borrowed for `'1`
+
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:31:13
+   |
+LL |     let i = t.next();
+   |             - first mutable borrow occurs here
+...
+LL |     let j = t.next();
+   |             ^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `Option<<T as LendingIterator>::Item<'_>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr
new file mode 100644
index 00000000000..fa201b89048
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.nll.stderr
@@ -0,0 +1,28 @@
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:19:19
+   |
+LL | fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
+   |                                    - let's call the lifetime of this reference `'1`
+LL |     let Some(i) = t.next() else { return None };
+   |                   - first mutable borrow occurs here
+LL |     let Some(j) = t.next() else { return None };
+   |                   ^ second mutable borrow occurs here
+...
+LL |     Some((i, j))
+   |     ------------ returning this value requires that `*t` is borrowed for `'1`
+
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:31:13
+   |
+LL |     let i = t.next();
+   |             - first mutable borrow occurs here
+...
+LL |     let j = t.next();
+   |             ^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `Option<<T as LendingIterator>::Item<'_>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr b/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr
new file mode 100644
index 00000000000..bf8546b63bf
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.polonius.stderr
@@ -0,0 +1,26 @@
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:19:19
+   |
+LL |     let Some(i) = t.next() else { return None };
+   |                   - first mutable borrow occurs here
+LL |     let Some(j) = t.next() else { return None };
+   |                   ^ second mutable borrow occurs here
+...
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `<T as LendingIterator>::Item<'_>`
+
+error[E0499]: cannot borrow `*t` as mutable more than once at a time
+  --> $DIR/lending-iterator-sanity-checks.rs:31:13
+   |
+LL |     let i = t.next();
+   |             - first mutable borrow occurs here
+...
+LL |     let j = t.next();
+   |             ^ second mutable borrow occurs here
+LL |
+LL | }
+   | - first borrow might be used here, when `i` is dropped and runs the destructor for type `Option<<T as LendingIterator>::Item<'_>>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/nll/polonius/lending-iterator-sanity-checks.rs b/tests/ui/nll/polonius/lending-iterator-sanity-checks.rs
new file mode 100644
index 00000000000..ae8cc78957f
--- /dev/null
+++ b/tests/ui/nll/polonius/lending-iterator-sanity-checks.rs
@@ -0,0 +1,71 @@
+// Some sanity checks for lending iterators with GATs. This is just some non-regression tests
+// ensuring the polonius alpha analysis, the datalog implementation, and NLLs agree in these common
+// cases of overlapping yielded items.
+
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius legacy
+//@ [polonius] compile-flags: -Z polonius=next
+//@ [legacy] compile-flags: -Z polonius=legacy
+
+trait LendingIterator {
+    type Item<'a>
+    where
+        Self: 'a;
+    fn next(&mut self) -> Option<Self::Item<'_>>;
+}
+
+fn use_live<T: LendingIterator>(t: &mut T) -> Option<(T::Item<'_>, T::Item<'_>)> {
+    let Some(i) = t.next() else { return None };
+    let Some(j) = t.next() else { return None };
+    //~^ ERROR cannot borrow `*t` as mutable more than once at a time
+
+    // `i` is obviously still (use-)live here, but we called `next` again to get `j`.
+    Some((i, j))
+}
+
+fn drop_live<T: LendingIterator>(t: &mut T) {
+    let i = t.next();
+
+    // Now `i` is use-dead here, but we don't know if the iterator items have a `Drop` impl, so it's
+    // still drop-live.
+    let j = t.next();
+    //~^ ERROR cannot borrow `*t` as mutable more than once at a time
+}
+
+// But we can still manually serialize the lifetimes with scopes (or preventing the destructor from
+// being called), so they're not overlapping.
+fn manually_non_overlapping<T: LendingIterator>(t: &mut T) {
+    {
+        let i = t.next();
+    }
+
+    let j = t.next(); // i is dead
+
+    drop(j);
+    let k = t.next(); // j is dead
+
+    let k = std::mem::ManuallyDrop::new(k);
+    let l = t.next(); // we told the compiler that k is not drop-live
+}
+
+// The cfg below is because there's a diagnostic ICE trying to explain the source of the error when
+// using the datalog implementation. We're not fixing *that*, outside of removing the implementation
+// in the future.
+#[cfg(not(legacy))] // FIXME: remove this cfg when removing the datalog implementation
+fn items_have_no_borrows<T: LendingIterator>(t: &mut T)
+where
+    for<'a> T::Item<'a>: 'static,
+{
+    let i = t.next();
+    let j = t.next();
+}
+
+fn items_are_copy<T: LendingIterator>(t: &mut T)
+where
+    for<'a> T::Item<'a>: Copy,
+{
+    let i = t.next();
+    let j = t.next();
+}
+
+fn main() {}
diff --git a/tests/ui/offset-of/offset-of-tuple-field.stderr b/tests/ui/offset-of/offset-of-tuple-field.stderr
index 4da0d851650..01622c5fa2d 100644
--- a/tests/ui/offset-of/offset-of-tuple-field.stderr
+++ b/tests/ui/offset-of/offset-of-tuple-field.stderr
@@ -15,60 +15,96 @@ error[E0609]: no field `_0` on type `(u8, u8)`
    |
 LL |     offset_of!((u8, u8), _0);
    |                          ^^
+   |
+help: a field with a similar name exists
+   |
+LL -     offset_of!((u8, u8), _0);
+LL +     offset_of!((u8, u8), 0);
+   |
 
 error[E0609]: no field `01` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:7:26
    |
 LL |     offset_of!((u8, u8), 01);
    |                          ^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1e2` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:8:26
    |
 LL |     offset_of!((u8, u8), 1e2);
    |                          ^^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1_` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:9:26
    |
 LL |     offset_of!((u8, u8), 1_u8);
    |                          ^^^^
+   |
+help: a field with a similar name exists
+   |
+LL -     offset_of!((u8, u8), 1_u8);
+LL +     offset_of!((u8, u8), 1);
+   |
 
 error[E0609]: no field `1e2` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:12:35
    |
 LL |     builtin # offset_of((u8, u8), 1e2);
    |                                   ^^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `_0` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:13:35
    |
 LL |     builtin # offset_of((u8, u8), _0);
    |                                   ^^
+   |
+help: a field with a similar name exists
+   |
+LL -     builtin # offset_of((u8, u8), _0);
+LL +     builtin # offset_of((u8, u8), 0);
+   |
 
 error[E0609]: no field `01` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:14:35
    |
 LL |     builtin # offset_of((u8, u8), 01);
    |                                   ^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1_` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:15:35
    |
 LL |     builtin # offset_of((u8, u8), 1_u8);
    |                                   ^^^^
+   |
+help: a field with a similar name exists
+   |
+LL -     builtin # offset_of((u8, u8), 1_u8);
+LL +     builtin # offset_of((u8, u8), 1);
+   |
 
 error[E0609]: no field `2` on type `(u8, u16)`
   --> $DIR/offset-of-tuple-field.rs:18:47
    |
 LL |     offset_of!(((u8, u16), (u32, u16, u8)), 0.2);
    |                                               ^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1e2` on type `(u8, u16)`
   --> $DIR/offset-of-tuple-field.rs:19:47
    |
 LL |     offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2);
    |                                               ^^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `0` on type `u8`
   --> $DIR/offset-of-tuple-field.rs:21:49
diff --git a/tests/ui/parser/float-field.stderr b/tests/ui/parser/float-field.stderr
index 0cc1b0767dc..078d16a4117 100644
--- a/tests/ui/parser/float-field.stderr
+++ b/tests/ui/parser/float-field.stderr
@@ -305,6 +305,8 @@ error[E0609]: no field `1e1` on type `(u8, u8)`
    |
 LL |     { s.1.1e1; }
    |           ^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `0x1e1` on type `S`
   --> $DIR/float-field.rs:34:9
@@ -343,12 +345,16 @@ error[E0609]: no field `f32` on type `(u8, u8)`
    |
 LL |     { s.1.f32; }
    |           ^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1e1` on type `(u8, u8)`
   --> $DIR/float-field.rs:71:9
    |
 LL |     { s.1.1e1f32; }
    |         ^^^^^^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error: aborting due to 57 previous errors
 
diff --git a/tests/ui/issues/issue-15043.rs b/tests/ui/parser/generics-rangle-eq-15043.rs
index a9bb46b649b..1afc334dfd8 100644
--- a/tests/ui/issues/issue-15043.rs
+++ b/tests/ui/parser/generics-rangle-eq-15043.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15043
+
 //@ run-pass
 
 #![allow(warnings)]
diff --git a/tests/ui/parser/macro/macro-attr-bad.rs b/tests/ui/parser/macro/macro-attr-bad.rs
new file mode 100644
index 00000000000..4313a4d04ab
--- /dev/null
+++ b/tests/ui/parser/macro/macro-attr-bad.rs
@@ -0,0 +1,32 @@
+#![crate_type = "lib"]
+#![feature(macro_attr)]
+
+macro_rules! attr_incomplete_1 { attr }
+//~^ ERROR macro definition ended unexpectedly
+
+macro_rules! attr_incomplete_2 { attr() }
+//~^ ERROR macro definition ended unexpectedly
+
+macro_rules! attr_incomplete_3 { attr() {} }
+//~^ ERROR expected `=>`
+
+macro_rules! attr_incomplete_4 { attr() {} => }
+//~^ ERROR macro definition ended unexpectedly
+
+macro_rules! attr_noparens_1 { attr{} {} => {} }
+//~^ ERROR macro attribute argument matchers require parentheses
+
+macro_rules! attr_noparens_2 { attr[] {} => {} }
+//~^ ERROR macro attribute argument matchers require parentheses
+
+macro_rules! attr_noparens_3 { attr _ {} => {} }
+//~^ ERROR invalid macro matcher
+
+macro_rules! attr_dup_matcher_1 { attr() {$x:ident $x:ident} => {} }
+//~^ ERROR duplicate matcher binding
+
+macro_rules! attr_dup_matcher_2 { attr($x:ident $x:ident) {} => {} }
+//~^ ERROR duplicate matcher binding
+
+macro_rules! attr_dup_matcher_3 { attr($x:ident) {$x:ident} => {} }
+//~^ ERROR duplicate matcher binding
diff --git a/tests/ui/parser/macro/macro-attr-bad.stderr b/tests/ui/parser/macro/macro-attr-bad.stderr
new file mode 100644
index 00000000000..4d286b66649
--- /dev/null
+++ b/tests/ui/parser/macro/macro-attr-bad.stderr
@@ -0,0 +1,80 @@
+error: macro definition ended unexpectedly
+  --> $DIR/macro-attr-bad.rs:4:38
+   |
+LL | macro_rules! attr_incomplete_1 { attr }
+   |                                      ^ expected macro attr args
+
+error: macro definition ended unexpectedly
+  --> $DIR/macro-attr-bad.rs:7:40
+   |
+LL | macro_rules! attr_incomplete_2 { attr() }
+   |                                        ^ expected macro attr body
+
+error: expected `=>`, found end of macro arguments
+  --> $DIR/macro-attr-bad.rs:10:43
+   |
+LL | macro_rules! attr_incomplete_3 { attr() {} }
+   |                                           ^ expected `=>`
+
+error: macro definition ended unexpectedly
+  --> $DIR/macro-attr-bad.rs:13:46
+   |
+LL | macro_rules! attr_incomplete_4 { attr() {} => }
+   |                                              ^ expected right-hand side of macro rule
+
+error: macro attribute argument matchers require parentheses
+  --> $DIR/macro-attr-bad.rs:16:36
+   |
+LL | macro_rules! attr_noparens_1 { attr{} {} => {} }
+   |                                    ^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL - macro_rules! attr_noparens_1 { attr{} {} => {} }
+LL + macro_rules! attr_noparens_1 { attr() {} => {} }
+   |
+
+error: macro attribute argument matchers require parentheses
+  --> $DIR/macro-attr-bad.rs:19:36
+   |
+LL | macro_rules! attr_noparens_2 { attr[] {} => {} }
+   |                                    ^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL - macro_rules! attr_noparens_2 { attr[] {} => {} }
+LL + macro_rules! attr_noparens_2 { attr() {} => {} }
+   |
+
+error: invalid macro matcher; matchers must be contained in balanced delimiters
+  --> $DIR/macro-attr-bad.rs:22:37
+   |
+LL | macro_rules! attr_noparens_3 { attr _ {} => {} }
+   |                                     ^
+
+error: duplicate matcher binding
+  --> $DIR/macro-attr-bad.rs:25:52
+   |
+LL | macro_rules! attr_dup_matcher_1 { attr() {$x:ident $x:ident} => {} }
+   |                                           -------- ^^^^^^^^ duplicate binding
+   |                                           |
+   |                                           previous binding
+
+error: duplicate matcher binding
+  --> $DIR/macro-attr-bad.rs:28:49
+   |
+LL | macro_rules! attr_dup_matcher_2 { attr($x:ident $x:ident) {} => {} }
+   |                                        -------- ^^^^^^^^ duplicate binding
+   |                                        |
+   |                                        previous binding
+
+error: duplicate matcher binding
+  --> $DIR/macro-attr-bad.rs:31:51
+   |
+LL | macro_rules! attr_dup_matcher_3 { attr($x:ident) {$x:ident} => {} }
+   |                                        --------   ^^^^^^^^ duplicate binding
+   |                                        |
+   |                                        previous binding
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/parser/macro/macro-attr-recovery.rs b/tests/ui/parser/macro/macro-attr-recovery.rs
new file mode 100644
index 00000000000..dbb795f57aa
--- /dev/null
+++ b/tests/ui/parser/macro/macro-attr-recovery.rs
@@ -0,0 +1,19 @@
+#![crate_type = "lib"]
+#![feature(macro_attr)]
+
+macro_rules! attr {
+    attr[$($args:tt)*] { $($body:tt)* } => {
+        //~^ ERROR: macro attribute argument matchers require parentheses
+        //~v ERROR: attr:
+        compile_error!(concat!(
+            "attr: args=\"",
+            stringify!($($args)*),
+            "\" body=\"",
+            stringify!($($body)*),
+            "\"",
+        ));
+    };
+}
+
+#[attr]
+struct S;
diff --git a/tests/ui/parser/macro/macro-attr-recovery.stderr b/tests/ui/parser/macro/macro-attr-recovery.stderr
new file mode 100644
index 00000000000..ab3a0b7c607
--- /dev/null
+++ b/tests/ui/parser/macro/macro-attr-recovery.stderr
@@ -0,0 +1,31 @@
+error: macro attribute argument matchers require parentheses
+  --> $DIR/macro-attr-recovery.rs:5:9
+   |
+LL |     attr[$($args:tt)*] { $($body:tt)* } => {
+   |         ^^^^^^^^^^^^^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL -     attr[$($args:tt)*] { $($body:tt)* } => {
+LL +     attr($($args:tt)*) { $($body:tt)* } => {
+   |
+
+error: attr: args="" body="struct S;"
+  --> $DIR/macro-attr-recovery.rs:8:9
+   |
+LL | /         compile_error!(concat!(
+LL | |             "attr: args=\"",
+LL | |             stringify!($($args)*),
+LL | |             "\" body=\"",
+LL | |             stringify!($($body)*),
+LL | |             "\"",
+LL | |         ));
+   | |__________^
+...
+LL |   #[attr]
+   |   ------- in this attribute macro expansion
+   |
+   = note: this error originates in the attribute macro `attr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs
index 704cae8bdbc..bab6308223e 100644
--- a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs
+++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs
@@ -15,7 +15,7 @@ fn main() {
     }
 
     match Box::new((true, Box::new(false))) {
-        //~^ ERROR non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered
+        //~^ ERROR non-exhaustive patterns: `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered
         (true, false) => {}
         (false, true) => {}
     }
diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr
index 55fa84bafde..a1abd5f0e3f 100644
--- a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr
+++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr
@@ -28,11 +28,11 @@ LL ~         true => {},
 LL +         deref!(deref!(false)) => todo!()
    |
 
-error[E0004]: non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered
+error[E0004]: non-exhaustive patterns: `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered
   --> $DIR/non-exhaustive.rs:17:11
    |
 LL |     match Box::new((true, Box::new(false))) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered
    |
 note: `Box<(bool, Box<bool>)>` defined here
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
@@ -40,7 +40,7 @@ note: `Box<(bool, Box<bool>)>` defined here
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
 LL ~         (false, true) => {},
-LL +         deref!((false, deref!(false))) | deref!((true, deref!(true))) => todo!()
+LL +         deref!((true, deref!(true))) | deref!((false, deref!(false))) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `deref!((deref!(T::C), _))` not covered
diff --git a/tests/ui/issues/issue-15896.rs b/tests/ui/pattern/enum-struct-pattern-mismatch-15896.rs
index d3153b516e6..9f7c5084c0e 100644
--- a/tests/ui/issues/issue-15896.rs
+++ b/tests/ui/pattern/enum-struct-pattern-mismatch-15896.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15896
+
 // Regression test for #15896. It used to ICE rustc.
 
 fn main() {
diff --git a/tests/ui/issues/issue-15896.stderr b/tests/ui/pattern/enum-struct-pattern-mismatch-15896.stderr
index 381f6dc2276..8dee4c37e2f 100644
--- a/tests/ui/issues/issue-15896.stderr
+++ b/tests/ui/pattern/enum-struct-pattern-mismatch-15896.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-15896.rs:11:11
+  --> $DIR/enum-struct-pattern-mismatch-15896.rs:13:11
    |
 LL |     let u = match e {
    |                   - this expression has type `E`
diff --git a/tests/ui/issues/issue-15381.rs b/tests/ui/pattern/refutable-pattern-for-loop-15381.rs
index bd5f62ddc67..3c19612c9cc 100644
--- a/tests/ui/issues/issue-15381.rs
+++ b/tests/ui/pattern/refutable-pattern-for-loop-15381.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15381
+
 fn main() {
     let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
 
diff --git a/tests/ui/issues/issue-15381.stderr b/tests/ui/pattern/refutable-pattern-for-loop-15381.stderr
index 03a0100f1bd..3c1d5fb454c 100644
--- a/tests/ui/issues/issue-15381.stderr
+++ b/tests/ui/pattern/refutable-pattern-for-loop-15381.stderr
@@ -1,5 +1,5 @@
 error[E0005]: refutable pattern in `for` loop binding
-  --> $DIR/issue-15381.rs:4:9
+  --> $DIR/refutable-pattern-for-loop-15381.rs:6:9
    |
 LL |     for &[x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
    |         ^^^^^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
diff --git a/tests/ui/issues/issue-15104.rs b/tests/ui/pattern/slice-pattern-recursion-15104.rs
index e68c94c370e..24e3fe78de0 100644
--- a/tests/ui/issues/issue-15104.rs
+++ b/tests/ui/pattern/slice-pattern-recursion-15104.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15104
+
 //@ run-pass
 
 fn main() {
diff --git a/tests/ui/issues/issue-16149.rs b/tests/ui/pattern/static-binding-shadow-16149.rs
index 51b60725c5a..a46f78214c7 100644
--- a/tests/ui/issues/issue-16149.rs
+++ b/tests/ui/pattern/static-binding-shadow-16149.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16149
+
 extern "C" {
     static externalValue: isize;
 }
diff --git a/tests/ui/issues/issue-16149.stderr b/tests/ui/pattern/static-binding-shadow-16149.stderr
index 9ffd0e7e645..6d8c7634acd 100644
--- a/tests/ui/issues/issue-16149.stderr
+++ b/tests/ui/pattern/static-binding-shadow-16149.stderr
@@ -1,5 +1,5 @@
 error[E0530]: match bindings cannot shadow statics
-  --> $DIR/issue-16149.rs:7:9
+  --> $DIR/static-binding-shadow-16149.rs:9:9
    |
 LL |     static externalValue: isize;
    |     ---------------------------- the static `externalValue` is defined here
diff --git a/tests/ui/issues/issue-15260.rs b/tests/ui/pattern/struct-field-duplicate-binding-15260.rs
index 64fc3df3d23..a3617798cdf 100644
--- a/tests/ui/issues/issue-15260.rs
+++ b/tests/ui/pattern/struct-field-duplicate-binding-15260.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15260
+
 struct Foo {
     a: usize,
 }
diff --git a/tests/ui/issues/issue-15260.stderr b/tests/ui/pattern/struct-field-duplicate-binding-15260.stderr
index 4a3041122b2..536904fbcb3 100644
--- a/tests/ui/issues/issue-15260.stderr
+++ b/tests/ui/pattern/struct-field-duplicate-binding-15260.stderr
@@ -1,5 +1,5 @@
 error[E0025]: field `a` bound multiple times in the pattern
-  --> $DIR/issue-15260.rs:8:9
+  --> $DIR/struct-field-duplicate-binding-15260.rs:10:9
    |
 LL |         a: _,
    |         ---- first use of `a`
@@ -7,7 +7,7 @@ LL |         a: _
    |         ^^^^ multiple uses of `a` in pattern
 
 error[E0025]: field `a` bound multiple times in the pattern
-  --> $DIR/issue-15260.rs:14:9
+  --> $DIR/struct-field-duplicate-binding-15260.rs:16:9
    |
 LL |         a,
    |         - first use of `a`
@@ -15,7 +15,7 @@ LL |         a: _
    |         ^^^^ multiple uses of `a` in pattern
 
 error[E0025]: field `a` bound multiple times in the pattern
-  --> $DIR/issue-15260.rs:20:9
+  --> $DIR/struct-field-duplicate-binding-15260.rs:22:9
    |
 LL |         a,
    |         - first use of `a`
@@ -23,7 +23,7 @@ LL |         a: _,
    |         ^^^^ multiple uses of `a` in pattern
 
 error[E0025]: field `a` bound multiple times in the pattern
-  --> $DIR/issue-15260.rs:22:9
+  --> $DIR/struct-field-duplicate-binding-15260.rs:24:9
    |
 LL |         a,
    |         - first use of `a`
diff --git a/tests/ui/issues/issue-15129-rpass.rs b/tests/ui/pattern/tuple-enum-match-15129.rs
index e2ddb989072..1d6192c4cb3 100644
--- a/tests/ui/issues/issue-15129-rpass.rs
+++ b/tests/ui/pattern/tuple-enum-match-15129.rs
@@ -1,24 +1,25 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15129
+
 //@ run-pass
 
 pub enum T {
     T1(()),
-    T2(())
+    T2(()),
 }
 
 pub enum V {
     V1(isize),
-    V2(bool)
+    V2(bool),
 }
 
 fn foo(x: (T, V)) -> String {
     match x {
-        (T::T1(()), V::V1(i))  => format!("T1(()), V1({})", i),
-        (T::T2(()), V::V2(b))  => format!("T2(()), V2({})", b),
-        _ => String::new()
+        (T::T1(()), V::V1(i)) => format!("T1(()), V1({})", i),
+        (T::T2(()), V::V2(b)) => format!("T2(()), V2({})", b),
+        _ => String::new(),
     }
 }
 
-
 fn main() {
     assert_eq!(foo((T::T1(()), V::V1(99))), "T1(()), V1(99)".to_string());
     assert_eq!(foo((T::T2(()), V::V2(true))), "T2(()), V2(true)".to_string());
diff --git a/tests/ui/issues/issue-16401.rs b/tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.rs
index 0985a6806d2..2eba33e177e 100644
--- a/tests/ui/issues/issue-16401.rs
+++ b/tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16401
+
 struct Slice<T> {
     data: *const T,
     len: usize,
diff --git a/tests/ui/issues/issue-16401.stderr b/tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.stderr
index 6af920ca439..22c04e439c4 100644
--- a/tests/ui/issues/issue-16401.stderr
+++ b/tests/ui/pattern/unit-type-struct-pattern-mismatch-16401.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-16401.rs:8:9
+  --> $DIR/unit-type-struct-pattern-mismatch-16401.rs:10:9
    |
 LL |     match () {
    |           -- this expression has type `()`
diff --git a/tests/ui/pattern/usefulness/unions.rs b/tests/ui/pattern/usefulness/unions.rs
index 80a7f36a09a..3de79c6f849 100644
--- a/tests/ui/pattern/usefulness/unions.rs
+++ b/tests/ui/pattern/usefulness/unions.rs
@@ -26,7 +26,7 @@ fn main() {
         }
         // Our approach can report duplicate witnesses sometimes.
         match (x, true) {
-            //~^ ERROR non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
+            //~^ ERROR non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: true }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
             (U8AsBool { b: true }, true) => {}
             (U8AsBool { b: false }, true) => {}
             (U8AsBool { n: 1.. }, true) => {}
diff --git a/tests/ui/pattern/usefulness/unions.stderr b/tests/ui/pattern/usefulness/unions.stderr
index 4b397dc25db..98fb6a33ae4 100644
--- a/tests/ui/pattern/usefulness/unions.stderr
+++ b/tests/ui/pattern/usefulness/unions.stderr
@@ -16,11 +16,11 @@ LL ~             U8AsBool { n: 1.. } => {},
 LL +             U8AsBool { n: 0_u8 } | U8AsBool { b: false } => todo!()
    |
 
-error[E0004]: non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
+error[E0004]: non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: true }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
   --> $DIR/unions.rs:28:15
    |
 LL |         match (x, true) {
-   |               ^^^^^^^^^ patterns `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
+   |               ^^^^^^^^^ patterns `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: true }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
    |
    = note: the matched value is of type `(U8AsBool, bool)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
diff --git a/tests/ui/proc-macro/span-from-proc-macro.stderr b/tests/ui/proc-macro/span-from-proc-macro.stderr
index 452c04df877..c79ab04eadf 100644
--- a/tests/ui/proc-macro/span-from-proc-macro.stderr
+++ b/tests/ui/proc-macro/span-from-proc-macro.stderr
@@ -10,7 +10,7 @@ LL |             field: MissingType
   ::: $DIR/span-from-proc-macro.rs:8:1
    |
 LL | #[error_from_attribute]
-   | ----------------------- in this procedural macro expansion
+   | ----------------------- in this attribute macro expansion
 
 error[E0412]: cannot find type `OtherMissingType` in this scope
   --> $DIR/auxiliary/span-from-proc-macro.rs:42:21
diff --git a/tests/ui/recursion/issue-23122-2.rs b/tests/ui/recursion/issue-23122-2.rs
index 95e1f60d8b0..d4f13e9fa55 100644
--- a/tests/ui/recursion/issue-23122-2.rs
+++ b/tests/ui/recursion/issue-23122-2.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 trait Next {
     type Next: Next;
 }
diff --git a/tests/ui/recursion/issue-23122-2.stderr b/tests/ui/recursion/issue-23122-2.stderr
index c5774cc1888..de402d65e6d 100644
--- a/tests/ui/recursion/issue-23122-2.stderr
+++ b/tests/ui/recursion/issue-23122-2.stderr
@@ -1,17 +1,19 @@
 error[E0275]: overflow evaluating the requirement `<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
-  --> $DIR/issue-23122-2.rs:10:17
+  --> $DIR/issue-23122-2.rs:11:17
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
-note: required for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
-  --> $DIR/issue-23122-2.rs:9:15
+note: required for `GetNext<<<<... as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
+  --> $DIR/issue-23122-2.rs:10:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
    |      -        ^^^^     ^^^^^^^^^^
    |      |
    |      unsatisfied trait bound introduced here
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-23122-2.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
index 7b7b1a9580b..c219a920bb4 100644
--- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
+++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 // `S` is infinitely recursing so it's not possible to generate a finite
 // drop impl.
 //
diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
index 409f63b91b6..cf3bc4578a7 100644
--- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
+++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
@@ -1,10 +1,12 @@
 error[E0320]: overflow while adding drop-check rules for `S<u32>`
-  --> $DIR/issue-38591-non-regular-dropck-recursion.rs:11:6
+  --> $DIR/issue-38591-non-regular-dropck-recursion.rs:12:6
    |
 LL | fn f(x: S<u32>) {}
    |      ^
    |
-   = note: overflowed on `S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>`
+   = note: overflowed on `S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(...))))))))))))))))>`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-38591-non-regular-dropck-recursion.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/recursion/issue-83150.rs b/tests/ui/recursion/issue-83150.rs
index b720c168187..9194ce1ab17 100644
--- a/tests/ui/recursion/issue-83150.rs
+++ b/tests/ui/recursion/issue-83150.rs
@@ -1,6 +1,6 @@
 //~ ERROR overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>: Iterator`
 //@ build-fail
-//@ compile-flags: -Copt-level=0
+//@ compile-flags: -Copt-level=0 -Zwrite-long-types-to-disk=yes
 
 fn main() {
     let mut iter = 0u8..1;
diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr
index 600922f1e57..a245b001bad 100644
--- a/tests/ui/recursion/issue-83150.stderr
+++ b/tests/ui/recursion/issue-83150.stderr
@@ -13,9 +13,11 @@ LL |     func(&mut iter.map(|x| x + 1))
 error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>: Iterator`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
-   = note: required for `&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>` to implement `Iterator`
+   = note: required for `&mut Map<&mut Range<u8>, {closure@issue-83150.rs:12:24}>` to implement `Iterator`
    = note: 65 redundant requirements hidden
-   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>` to implement `Iterator`
+   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut ..., ...>, ...>, ...>, ...>` to implement `Iterator`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-83150.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
index b89c5e8dda8..020c2e6f241 100644
--- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `f32: Termination` is not satisfied
   --> $DIR/termination-trait-test-wrong-type.rs:6:31
    |
 LL | #[test]
-   | ------- in this procedural macro expansion
+   | ------- in this attribute macro expansion
 LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32`
    |
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs
index 4cf2d1ac4a6..80a4ab35527 100644
--- a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs
@@ -41,6 +41,7 @@ mod capture_tait_complex_pass {
     #[define_opaque(Opq2)]
     fn test() -> Opq2 {}
     //~^ ERROR: expected generic lifetime parameter, found `'a`
+    //~| ERROR: expected generic lifetime parameter, found `'b`
 }
 
 // Same as the above, but make sure that different placeholder regions are not equal.
@@ -80,6 +81,7 @@ mod constrain_pass {
     #[define_opaque(Opq2)]
     fn test() -> Opq2 {}
     //~^ ERROR: expected generic lifetime parameter, found `'a`
+    //~| ERROR: expected generic lifetime parameter, found `'a`
 }
 
 fn main() {}
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr
index 3614fc8f45c..665b9a91696 100644
--- a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr
@@ -36,8 +36,17 @@ LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'b>>; // <- Note 'b
 LL |     fn test() -> Opq2 {}
    |                       ^^
 
+error[E0792]: expected generic lifetime parameter, found `'b`
+  --> $DIR/higher-ranked-regions-basic.rs:42:23
+   |
+LL |     type Opq0<'a> = impl Sized;
+   |               -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     fn test() -> Opq2 {}
+   |                       ^^
+
 error[E0700]: hidden type for `capture_tait_complex_fail::Opq0<'a>` captures lifetime that does not appear in bounds
-  --> $DIR/higher-ranked-regions-basic.rs:53:23
+  --> $DIR/higher-ranked-regions-basic.rs:54:23
    |
 LL |     type Opq0<'a> = impl Sized;
    |                     ---------- opaque type defined here
@@ -48,7 +57,7 @@ LL |     fn test() -> Opq2 {}
    |                       ^^
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/higher-ranked-regions-basic.rs:62:65
+  --> $DIR/higher-ranked-regions-basic.rs:63:65
    |
 LL |     type Opq0<'a, 'b> = impl Sized;
    |               -- this generic parameter must be used with a generic lifetime parameter
@@ -57,7 +66,7 @@ LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
    |                                                                 ^^
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/higher-ranked-regions-basic.rs:71:60
+  --> $DIR/higher-ranked-regions-basic.rs:72:60
    |
 LL |     type Opq0<'a, 'b> = impl Sized;
    |               -- this generic parameter must be used with a generic lifetime parameter
@@ -66,7 +75,7 @@ LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
    |                                                            ^^
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/higher-ranked-regions-basic.rs:81:23
+  --> $DIR/higher-ranked-regions-basic.rs:82:23
    |
 LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a, 'b>>;
    |               -- this generic parameter must be used with a generic lifetime parameter
@@ -74,7 +83,16 @@ LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a, 'b>>;
 LL |     fn test() -> Opq2 {}
    |                       ^^
 
-error: aborting due to 8 previous errors
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/higher-ranked-regions-basic.rs:82:23
+   |
+LL |     type Opq0<'a, 'b> = impl Sized;
+   |               -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     fn test() -> Opq2 {}
+   |                       ^^
+
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0700, E0792.
 For more information about an error, try `rustc --explain E0700`.
diff --git a/tests/ui/rustc_public-ir-print/async-closure.stdout b/tests/ui/rustc_public-ir-print/async-closure.stdout
index 4afb15af7a9..73e9b8fc097 100644
--- a/tests/ui/rustc_public-ir-print/async-closure.stdout
+++ b/tests/ui/rustc_public-ir-print/async-closure.stdout
@@ -63,7 +63,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo
         StorageDead(_3);
         _0 = std::task::Poll::Ready(move _5);
         _10 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        discriminant((*_10) = 1;
+        discriminant((*_10)) = 1;
         return;
     }
     bb2: {
@@ -101,7 +101,7 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c
         StorageDead(_3);
         _0 = std::task::Poll::Ready(move _5);
         _10 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
-        discriminant((*_10) = 1;
+        discriminant((*_10)) = 1;
         return;
     }
     bb2: {
diff --git a/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr b/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr
index 5e652efb364..2dadc5c2d33 100644
--- a/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr
+++ b/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr
@@ -32,7 +32,7 @@ LL |   p.method();
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`arbitrary_self_type_infinite_recursion`)
 
-error[E0599]: no method named `method` found for struct `MySmartPtr` in the current scope
+error[E0599]: no method named `method` found for struct `MySmartPtr<T>` in the current scope
   --> $DIR/arbitrary_self_type_infinite_recursion.rs:21:5
    |
 LL | struct MySmartPtr<T>(T);
diff --git a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
index a30cf605829..5d7f6142093 100644
--- a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
+++ b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `frobnicate_ref` found for struct `CppRef` in the current scope
+error[E0599]: no method named `frobnicate_ref` found for struct `CppRef<T>` in the current scope
   --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:29:17
    |
 LL | struct CppRef<T>(T);
@@ -16,7 +16,7 @@ help: there is a method `frobnicate_cpp_ref` with a similar name
 LL |     foo_cpp_ref.frobnicate_cpp_ref();
    |                            ++++
 
-error[E0599]: no method named `frobnicate_self` found for struct `CppRef` in the current scope
+error[E0599]: no method named `frobnicate_self` found for struct `CppRef<T>` in the current scope
   --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:32:17
    |
 LL | struct CppRef<T>(T);
diff --git a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs
index d877dbe6075..28845890278 100644
--- a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs
+++ b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs
@@ -9,5 +9,5 @@ impl S {
 fn main() {
     Pin::new(S).x();
     //~^ ERROR the trait bound `S: Deref` is not satisfied
-    //~| ERROR no method named `x` found for struct `Pin` in the current scope
+    //~| ERROR no method named `x` found for struct `Pin<Ptr>` in the current scope
 }
diff --git a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr
index 1811cd6753f..df226a9366a 100644
--- a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr
+++ b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr
@@ -15,7 +15,7 @@ LL |     Pin::new(&S).x();
 LL |     Pin::new(&mut S).x();
    |              ++++
 
-error[E0599]: no method named `x` found for struct `Pin` in the current scope
+error[E0599]: no method named `x` found for struct `Pin<Ptr>` in the current scope
   --> $DIR/arbitrary_self_types_pin_needing_borrow.rs:10:17
    |
 LL |     Pin::new(S).x();
diff --git a/tests/ui/simd/libm_no_std_cant_float.stderr b/tests/ui/simd/libm_no_std_cant_float.stderr
index 97e0b7efe2a..cc9aefaad5e 100644
--- a/tests/ui/simd/libm_no_std_cant_float.stderr
+++ b/tests/ui/simd/libm_no_std_cant_float.stderr
@@ -1,34 +1,34 @@
-error[E0599]: no method named `ceil` found for struct `Simd` in the current scope
+error[E0599]: no method named `ceil` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:15:17
    |
 LL |     let _xc = x.ceil();
    |                 ^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `floor` found for struct `Simd` in the current scope
+error[E0599]: no method named `floor` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:16:17
    |
 LL |     let _xf = x.floor();
    |                 ^^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `round` found for struct `Simd` in the current scope
+error[E0599]: no method named `round` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:17:17
    |
 LL |     let _xr = x.round();
    |                 ^^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `trunc` found for struct `Simd` in the current scope
+error[E0599]: no method named `trunc` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:18:17
    |
 LL |     let _xt = x.trunc();
    |                 ^^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `mul_add` found for struct `Simd` in the current scope
+error[E0599]: no method named `mul_add` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:19:19
    |
 LL |     let _xfma = x.mul_add(x, x);
    |                   ^^^^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `sqrt` found for struct `Simd` in the current scope
+error[E0599]: no method named `sqrt` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:20:20
    |
 LL |     let _xsqrt = x.sqrt();
diff --git a/tests/ui/issues/issue-16452.rs b/tests/ui/statics/conditional-static-declaration-16010.rs
index 4ab74f09059..0bc5b0ee86f 100644
--- a/tests/ui/issues/issue-16452.rs
+++ b/tests/ui/statics/conditional-static-declaration-16010.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16010
+
 //@ run-pass
 #![allow(dead_code)]
 
diff --git a/tests/ui/stats/macro-stats.rs b/tests/ui/stats/macro-stats.rs
index d986904ddd6..1b7d58bf058 100644
--- a/tests/ui/stats/macro-stats.rs
+++ b/tests/ui/stats/macro-stats.rs
@@ -49,10 +49,32 @@ fn opt(x: Option<u32>) {
     }
 }
 
-macro_rules! long_name_that_fits_on_a_single_line {
-    () => {}
-}
-long_name_that_fits_on_a_single_line!();
+macro_rules! long_name_that_fits_on_one_line { () => {} }
+long_name_that_fits_on_one_line!();
+long_name_that_fits_on_one_line!();
+long_name_that_fits_on_one_line!();
+long_name_that_fits_on_one_line!();
+long_name_that_fits_on_one_line!();
+long_name_that_fits_on_one_line!();
+long_name_that_fits_on_one_line!();
+long_name_that_fits_on_one_line!();
+long_name_that_fits_on_one_line!();
+long_name_that_fits_on_one_line!();
+
+macro_rules! long_name_that_fits_on_one_line_ { () => {} }
+long_name_that_fits_on_one_line_!();
+
+macro_rules! long_name_that_fits_on_one_line__ { () => {} }
+long_name_that_fits_on_one_line__!();
+
+macro_rules! long_name_that_fits_on_one_line___ { () => {} }
+long_name_that_fits_on_one_line___!();
+
+macro_rules! long_name_that_fits_on_one_line____ { () => {} }
+long_name_that_fits_on_one_line____!();
+
+macro_rules! long_name_that_fits_on_one_line_____ { () => {} }
+long_name_that_fits_on_one_line_____!();
 
 macro_rules! long_name_that_doesnt_fit_on_one_line {
     ($t:ty) => {
diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr
index 8d0fdb8958a..75b90df6466 100644
--- a/tests/ui/stats/macro-stats.stderr
+++ b/tests/ui/stats/macro-stats.stderr
@@ -22,6 +22,11 @@ macro-stats trait_tys!                            1          2        2.0
 macro-stats n99!                                  2          2        1.0          4        2.0
 macro-stats none!                                 1          1        1.0          4        4.0
 macro-stats u32!                                  1          1        1.0          3        3.0
-macro-stats long_name_that_fits_on_a_single_line! 1          1        1.0          0        0.0
+macro-stats long_name_that_fits_on_one_line!     10         10        1.0          0        0.0
+macro-stats long_name_that_fits_on_one_line_____! 1          1        1.0          0        0.0
+macro-stats long_name_that_fits_on_one_line____!  1          1        1.0          0        0.0
+macro-stats long_name_that_fits_on_one_line___!   1          1        1.0          0        0.0
+macro-stats long_name_that_fits_on_one_line__!    1          1        1.0          0        0.0
+macro-stats long_name_that_fits_on_one_line_!     1          1        1.0          0        0.0
 macro-stats #[test]                               1          1        1.0          0        0.0
 macro-stats ===================================================================================
diff --git a/tests/ui/structs/tuple-struct-field-naming-47073.stderr b/tests/ui/structs/tuple-struct-field-naming-47073.stderr
index efbdaeca4ea..09ba2fb406a 100644
--- a/tests/ui/structs/tuple-struct-field-naming-47073.stderr
+++ b/tests/ui/structs/tuple-struct-field-naming-47073.stderr
@@ -4,11 +4,7 @@ error[E0609]: no field `00` on type `Verdict`
 LL |     let _condemned = justice.00;
    |                              ^^ unknown field
    |
-help: a field with a similar name exists
-   |
-LL -     let _condemned = justice.00;
-LL +     let _condemned = justice.0;
-   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `001` on type `Verdict`
   --> $DIR/tuple-struct-field-naming-47073.rs:11:31
diff --git a/tests/ui/suggestions/enum-method-probe.fixed b/tests/ui/suggestions/enum-method-probe.fixed
index b7fd6f112d5..1ce6a943c5b 100644
--- a/tests/ui/suggestions/enum-method-probe.fixed
+++ b/tests/ui/suggestions/enum-method-probe.fixed
@@ -14,7 +14,7 @@ impl Foo {
 fn test_result_in_result() -> Result<(), ()> {
     let res: Result<_, ()> = Ok(Foo);
     res?.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP use the `?` operator
     Ok(())
 }
@@ -22,7 +22,7 @@ fn test_result_in_result() -> Result<(), ()> {
 async fn async_test_result_in_result() -> Result<(), ()> {
     let res: Result<_, ()> = Ok(Foo);
     res?.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP use the `?` operator
     Ok(())
 }
@@ -30,21 +30,21 @@ async fn async_test_result_in_result() -> Result<(), ()> {
 fn test_result_in_unit_return() {
     let res: Result<_, ()> = Ok(Foo);
     res.expect("REASON").get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
 }
 
 async fn async_test_result_in_unit_return() {
     let res: Result<_, ()> = Ok(Foo);
     res.expect("REASON").get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
 }
 
 fn test_option_in_option() -> Option<()> {
     let res: Option<_> = Some(Foo);
     res?.get();
-    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~^ ERROR no method named `get` found for enum `Option<T>` in the current scope
     //~| HELP use the `?` operator
     Some(())
 }
@@ -52,7 +52,7 @@ fn test_option_in_option() -> Option<()> {
 fn test_option_in_unit_return() {
     let res: Option<_> = Some(Foo);
     res.expect("REASON").get();
-    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~^ ERROR no method named `get` found for enum `Option<T>` in the current scope
     //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
 }
 
diff --git a/tests/ui/suggestions/enum-method-probe.rs b/tests/ui/suggestions/enum-method-probe.rs
index cbb819b7c8c..dd3addbd0a3 100644
--- a/tests/ui/suggestions/enum-method-probe.rs
+++ b/tests/ui/suggestions/enum-method-probe.rs
@@ -14,7 +14,7 @@ impl Foo {
 fn test_result_in_result() -> Result<(), ()> {
     let res: Result<_, ()> = Ok(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP use the `?` operator
     Ok(())
 }
@@ -22,7 +22,7 @@ fn test_result_in_result() -> Result<(), ()> {
 async fn async_test_result_in_result() -> Result<(), ()> {
     let res: Result<_, ()> = Ok(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP use the `?` operator
     Ok(())
 }
@@ -30,21 +30,21 @@ async fn async_test_result_in_result() -> Result<(), ()> {
 fn test_result_in_unit_return() {
     let res: Result<_, ()> = Ok(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
 }
 
 async fn async_test_result_in_unit_return() {
     let res: Result<_, ()> = Ok(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
 }
 
 fn test_option_in_option() -> Option<()> {
     let res: Option<_> = Some(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~^ ERROR no method named `get` found for enum `Option<T>` in the current scope
     //~| HELP use the `?` operator
     Some(())
 }
@@ -52,7 +52,7 @@ fn test_option_in_option() -> Option<()> {
 fn test_option_in_unit_return() {
     let res: Option<_> = Some(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~^ ERROR no method named `get` found for enum `Option<T>` in the current scope
     //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
 }
 
diff --git a/tests/ui/suggestions/enum-method-probe.stderr b/tests/ui/suggestions/enum-method-probe.stderr
index e66973d9d95..5aa0fc44c7b 100644
--- a/tests/ui/suggestions/enum-method-probe.stderr
+++ b/tests/ui/suggestions/enum-method-probe.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `get` found for enum `Result` in the current scope
+error[E0599]: no method named `get` found for enum `Result<T, E>` in the current scope
   --> $DIR/enum-method-probe.rs:24:9
    |
 LL |     res.get();
@@ -14,7 +14,7 @@ help: use the `?` operator to extract the `Foo` value, propagating a `Result::Er
 LL |     res?.get();
    |        +
 
-error[E0599]: no method named `get` found for enum `Result` in the current scope
+error[E0599]: no method named `get` found for enum `Result<T, E>` in the current scope
   --> $DIR/enum-method-probe.rs:39:9
    |
 LL |     res.get();
@@ -30,7 +30,7 @@ help: consider using `Result::expect` to unwrap the `Foo` value, panicking if th
 LL |     res.expect("REASON").get();
    |        +++++++++++++++++
 
-error[E0599]: no method named `get` found for enum `Result` in the current scope
+error[E0599]: no method named `get` found for enum `Result<T, E>` in the current scope
   --> $DIR/enum-method-probe.rs:16:9
    |
 LL |     res.get();
@@ -46,7 +46,7 @@ help: use the `?` operator to extract the `Foo` value, propagating a `Result::Er
 LL |     res?.get();
    |        +
 
-error[E0599]: no method named `get` found for enum `Result` in the current scope
+error[E0599]: no method named `get` found for enum `Result<T, E>` in the current scope
   --> $DIR/enum-method-probe.rs:32:9
    |
 LL |     res.get();
@@ -62,7 +62,7 @@ help: consider using `Result::expect` to unwrap the `Foo` value, panicking if th
 LL |     res.expect("REASON").get();
    |        +++++++++++++++++
 
-error[E0599]: no method named `get` found for enum `Option` in the current scope
+error[E0599]: no method named `get` found for enum `Option<T>` in the current scope
   --> $DIR/enum-method-probe.rs:46:9
    |
 LL |     res.get();
@@ -78,7 +78,7 @@ help: use the `?` operator to extract the `Foo` value, propagating an `Option::N
 LL |     res?.get();
    |        +
 
-error[E0599]: no method named `get` found for enum `Option` in the current scope
+error[E0599]: no method named `get` found for enum `Option<T>` in the current scope
   --> $DIR/enum-method-probe.rs:54:9
    |
 LL |     res.get();
diff --git a/tests/ui/suggestions/field-has-method.rs b/tests/ui/suggestions/field-has-method.rs
index d28b6ba546c..6e584d78338 100644
--- a/tests/ui/suggestions/field-has-method.rs
+++ b/tests/ui/suggestions/field-has-method.rs
@@ -17,7 +17,7 @@ struct InferOk<T> {
 
 fn foo(i: InferOk<Ty>) {
     let k = i.kind();
-    //~^ ERROR no method named `kind` found for struct `InferOk` in the current scope
+    //~^ ERROR no method named `kind` found for struct `InferOk<T>` in the current scope
 }
 
 fn main() {}
diff --git a/tests/ui/suggestions/field-has-method.stderr b/tests/ui/suggestions/field-has-method.stderr
index daff2db6418..adcb723e4f1 100644
--- a/tests/ui/suggestions/field-has-method.stderr
+++ b/tests/ui/suggestions/field-has-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `kind` found for struct `InferOk` in the current scope
+error[E0599]: no method named `kind` found for struct `InferOk<T>` in the current scope
   --> $DIR/field-has-method.rs:19:15
    |
 LL | struct InferOk<T> {
diff --git a/tests/ui/suggestions/for-loop-missing-in.fixed b/tests/ui/suggestions/for-loop-missing-in.fixed
index ff376b5a52c..396c3ff87ff 100644
--- a/tests/ui/suggestions/for-loop-missing-in.fixed
+++ b/tests/ui/suggestions/for-loop-missing-in.fixed
@@ -1,8 +1,7 @@
 //@ run-rustfix
 
 fn main() {
-    for _i in 0..2 { //~ ERROR missing `in`
-    }
-    for _i in 0..2 { //~ ERROR missing `in`
-    }
+    for _i in 0..2 {} //~ ERROR missing `in`
+    for _i in 0..2 {} //~ ERROR missing `in`
+    for _i in 0..2 {} //~ ERROR missing `in`
 }
diff --git a/tests/ui/suggestions/for-loop-missing-in.rs b/tests/ui/suggestions/for-loop-missing-in.rs
index 28c12aec665..6c2092106cb 100644
--- a/tests/ui/suggestions/for-loop-missing-in.rs
+++ b/tests/ui/suggestions/for-loop-missing-in.rs
@@ -1,8 +1,7 @@
 //@ run-rustfix
 
 fn main() {
-    for _i 0..2 { //~ ERROR missing `in`
-    }
-    for _i of 0..2 { //~ ERROR missing `in`
-    }
+    for _i 0..2 {} //~ ERROR missing `in`
+    for _i of 0..2 {} //~ ERROR missing `in`
+    for _i = 0..2 {} //~ ERROR missing `in`
 }
diff --git a/tests/ui/suggestions/for-loop-missing-in.stderr b/tests/ui/suggestions/for-loop-missing-in.stderr
index 4e0cb229d50..b9c8c393406 100644
--- a/tests/ui/suggestions/for-loop-missing-in.stderr
+++ b/tests/ui/suggestions/for-loop-missing-in.stderr
@@ -1,25 +1,37 @@
 error: missing `in` in `for` loop
   --> $DIR/for-loop-missing-in.rs:4:11
    |
-LL |     for _i 0..2 {
+LL |     for _i 0..2 {}
    |           ^
    |
 help: try adding `in` here
    |
-LL |     for _i in 0..2 {
+LL |     for _i in 0..2 {}
    |            ++
 
 error: missing `in` in `for` loop
-  --> $DIR/for-loop-missing-in.rs:6:12
+  --> $DIR/for-loop-missing-in.rs:5:12
    |
-LL |     for _i of 0..2 {
+LL |     for _i of 0..2 {}
    |            ^^
    |
 help: try using `in` here instead
    |
-LL -     for _i of 0..2 {
-LL +     for _i in 0..2 {
+LL -     for _i of 0..2 {}
+LL +     for _i in 0..2 {}
+   |
+
+error: missing `in` in `for` loop
+  --> $DIR/for-loop-missing-in.rs:6:12
+   |
+LL |     for _i = 0..2 {}
+   |            ^
+   |
+help: try using `in` here instead
+   |
+LL -     for _i = 0..2 {}
+LL +     for _i in 0..2 {}
    |
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/suggestions/inner_type.fixed b/tests/ui/suggestions/inner_type.fixed
index 175a2a02acd..8174f8e204e 100644
--- a/tests/ui/suggestions/inner_type.fixed
+++ b/tests/ui/suggestions/inner_type.fixed
@@ -15,26 +15,26 @@ fn main() {
     let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
 
     other_item.borrow().method();
-    //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `RefCell<T>` in the current scope [E0599]
     //~| HELP use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
 
     other_item.borrow_mut().some_mutable_method();
-    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell<T>` in the current scope [E0599]
     //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
 
     let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
 
     another_item.lock().unwrap().method();
-    //~^ ERROR no method named `method` found for struct `std::sync::Mutex` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `std::sync::Mutex<T>` in the current scope [E0599]
     //~| HELP use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 
     let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
 
     another_item.read().unwrap().method();
-    //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `RwLock<T>` in the current scope [E0599]
     //~| HELP  use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 
     another_item.write().unwrap().some_mutable_method();
-    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock<T>` in the current scope [E0599]
     //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 }
diff --git a/tests/ui/suggestions/inner_type.rs b/tests/ui/suggestions/inner_type.rs
index ab021414f56..e4eaf07ca8b 100644
--- a/tests/ui/suggestions/inner_type.rs
+++ b/tests/ui/suggestions/inner_type.rs
@@ -15,26 +15,26 @@ fn main() {
     let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
 
     other_item.method();
-    //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `RefCell<T>` in the current scope [E0599]
     //~| HELP use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
 
     other_item.some_mutable_method();
-    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell<T>` in the current scope [E0599]
     //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
 
     let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
 
     another_item.method();
-    //~^ ERROR no method named `method` found for struct `std::sync::Mutex` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `std::sync::Mutex<T>` in the current scope [E0599]
     //~| HELP use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 
     let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
 
     another_item.method();
-    //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `RwLock<T>` in the current scope [E0599]
     //~| HELP  use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 
     another_item.some_mutable_method();
-    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock<T>` in the current scope [E0599]
     //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 }
diff --git a/tests/ui/suggestions/inner_type.stderr b/tests/ui/suggestions/inner_type.stderr
index 67ebb5789b7..017ddb5ad6d 100644
--- a/tests/ui/suggestions/inner_type.stderr
+++ b/tests/ui/suggestions/inner_type.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `method` found for struct `RefCell` in the current scope
+error[E0599]: no method named `method` found for struct `RefCell<T>` in the current scope
   --> $DIR/inner_type.rs:17:16
    |
 LL |     other_item.method();
@@ -14,7 +14,7 @@ help: use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow
 LL |     other_item.borrow().method();
    |               +++++++++
 
-error[E0599]: no method named `some_mutable_method` found for struct `RefCell` in the current scope
+error[E0599]: no method named `some_mutable_method` found for struct `RefCell<T>` in the current scope
   --> $DIR/inner_type.rs:21:16
    |
 LL |     other_item.some_mutable_method();
@@ -30,7 +30,7 @@ help: use `.borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any
 LL |     other_item.borrow_mut().some_mutable_method();
    |               +++++++++++++
 
-error[E0599]: no method named `method` found for struct `std::sync::Mutex` in the current scope
+error[E0599]: no method named `method` found for struct `std::sync::Mutex<T>` in the current scope
   --> $DIR/inner_type.rs:27:18
    |
 LL |     another_item.method();
@@ -46,7 +46,7 @@ help: use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current t
 LL |     another_item.lock().unwrap().method();
    |                 ++++++++++++++++
 
-error[E0599]: no method named `method` found for struct `RwLock` in the current scope
+error[E0599]: no method named `method` found for struct `RwLock<T>` in the current scope
   --> $DIR/inner_type.rs:33:18
    |
 LL |     another_item.method();
@@ -62,7 +62,7 @@ help: use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current t
 LL |     another_item.read().unwrap().method();
    |                 ++++++++++++++++
 
-error[E0599]: no method named `some_mutable_method` found for struct `RwLock` in the current scope
+error[E0599]: no method named `some_mutable_method` found for struct `RwLock<T>` in the current scope
   --> $DIR/inner_type.rs:37:18
    |
 LL |     another_item.some_mutable_method();
diff --git a/tests/ui/suggestions/inner_type2.rs b/tests/ui/suggestions/inner_type2.rs
index fac68c053eb..7082862f409 100644
--- a/tests/ui/suggestions/inner_type2.rs
+++ b/tests/ui/suggestions/inner_type2.rs
@@ -16,11 +16,11 @@ thread_local! {
 
 fn main() {
     STRUCT.method();
-    //~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `LocalKey<T>` in the current scope [E0599]
     //~| HELP use `with` or `try_with` to access thread local storage
 
     let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 });
     item.method();
-    //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for union `MaybeUninit<T>` in the current scope [E0599]
     //~| HELP if this `MaybeUninit<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
 }
diff --git a/tests/ui/suggestions/inner_type2.stderr b/tests/ui/suggestions/inner_type2.stderr
index 984366123c8..e6cb2048522 100644
--- a/tests/ui/suggestions/inner_type2.stderr
+++ b/tests/ui/suggestions/inner_type2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `method` found for struct `LocalKey` in the current scope
+error[E0599]: no method named `method` found for struct `LocalKey<T>` in the current scope
   --> $DIR/inner_type2.rs:18:12
    |
 LL |     STRUCT.method();
@@ -11,7 +11,7 @@ note: the method `method` exists on the type `Struct<u32>`
 LL |     pub fn method(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `method` found for union `MaybeUninit` in the current scope
+error[E0599]: no method named `method` found for union `MaybeUninit<T>` in the current scope
   --> $DIR/inner_type2.rs:23:10
    |
 LL |     item.method();
diff --git a/tests/ui/test-attrs/issue-12997-2.stderr b/tests/ui/test-attrs/issue-12997-2.stderr
index 1123630a4a1..41d0074ad1a 100644
--- a/tests/ui/test-attrs/issue-12997-2.stderr
+++ b/tests/ui/test-attrs/issue-12997-2.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-12997-2.rs:8:1
    |
 LL | #[bench]
-   | -------- in this procedural macro expansion
+   | -------- in this attribute macro expansion
 LL | fn bar(x: isize) { }
    | ^^^^^^^^^^^^^^^^^^^^
    | |
diff --git a/tests/ui/test-attrs/test-function-signature.stderr b/tests/ui/test-attrs/test-function-signature.stderr
index c025163c0bd..55d09970b32 100644
--- a/tests/ui/test-attrs/test-function-signature.stderr
+++ b/tests/ui/test-attrs/test-function-signature.stderr
@@ -26,7 +26,7 @@ error[E0277]: the trait bound `i32: Termination` is not satisfied
   --> $DIR/test-function-signature.rs:9:13
    |
 LL | #[test]
-   | ------- in this procedural macro expansion
+   | ------- in this attribute macro expansion
 LL | fn bar() -> i32 {
    |             ^^^ the trait `Termination` is not implemented for `i32`
    |
diff --git a/tests/ui/issues/issue-15444.rs b/tests/ui/traits/fn-type-trait-impl-15444.rs
index 14708c7733c..ab91e88b9cd 100644
--- a/tests/ui/issues/issue-15444.rs
+++ b/tests/ui/traits/fn-type-trait-impl-15444.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15444
+
 //@ run-pass
 
 trait MyTrait {
diff --git a/tests/ui/issues/issue-15734.rs b/tests/ui/traits/index-trait-multiple-impls-15734.rs
index 26fb7061664..a2d5d7c87fc 100644
--- a/tests/ui/issues/issue-15734.rs
+++ b/tests/ui/traits/index-trait-multiple-impls-15734.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/15734
+
 //@ run-pass
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.rs b/tests/ui/traits/issue-91949-hangs-on-recursion.rs
index 7c9ae09349a..434cf00fc4b 100644
--- a/tests/ui/traits/issue-91949-hangs-on-recursion.rs
+++ b/tests/ui/traits/issue-91949-hangs-on-recursion.rs
@@ -1,6 +1,6 @@
 //~ ERROR overflow evaluating the requirement `<std::iter::Empty<()> as Iterator>::Item == ()`
 //@ build-fail
-//@ compile-flags: -Zinline-mir=no
+//@ compile-flags: -Zinline-mir=no -Zwrite-long-types-to-disk=yes
 
 // Regression test for #91949.
 // This hanged *forever* on 1.56, fixed by #90423.
diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
index c2f09371cf7..a179107885a 100644
--- a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
+++ b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
@@ -24,7 +24,9 @@ LL | impl<T, I: Iterator<Item = T>> Iterator for IteratorOfWrapped<T, I> {
    |                     |
    |                     unsatisfied trait bound introduced here
    = note: 256 redundant requirements hidden
-   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), std::iter::Empty<()>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>` to implement `Iterator`
+   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>` to implement `Iterator`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-91949-hangs-on-recursion.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/issues/issue-16048.rs b/tests/ui/traits/lifetime-mismatch-trait-impl-16048.rs
index eaf6acff26b..9c36b231403 100644
--- a/tests/ui/issues/issue-16048.rs
+++ b/tests/ui/traits/lifetime-mismatch-trait-impl-16048.rs
@@ -1,3 +1,5 @@
+//! Regression test for https://github.com/rust-lang/rust/issues/16048
+
 trait NoLifetime {
     fn get<'p, T : Test<'p>>(&self) -> T;
     //~^ NOTE lifetimes in impl do not match this method in trait
diff --git a/tests/ui/issues/issue-16048.stderr b/tests/ui/traits/lifetime-mismatch-trait-impl-16048.stderr
index f97f13152bc..08b69184b7f 100644
--- a/tests/ui/issues/issue-16048.stderr
+++ b/tests/ui/traits/lifetime-mismatch-trait-impl-16048.stderr
@@ -1,5 +1,5 @@
 error[E0195]: lifetime parameters or bounds on method `get` do not match the trait declaration
-  --> $DIR/issue-16048.rs:21:11
+  --> $DIR/lifetime-mismatch-trait-impl-16048.rs:23:11
    |
 LL |     fn get<'p, T : Test<'p>>(&self) -> T;
    |           ------------------ lifetimes in impl do not match this method in trait
@@ -8,7 +8,7 @@ LL |     fn get<'p, T: Test<'a> + From<Foo<'a>>>(&self) -> T {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
 
 error[E0605]: non-primitive cast: `Foo<'a>` as `T`
-  --> $DIR/issue-16048.rs:24:16
+  --> $DIR/lifetime-mismatch-trait-impl-16048.rs:26:16
    |
 LL |         return *self as T;
    |                ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/traits/well-formed-recursion-limit.stderr b/tests/ui/traits/well-formed-recursion-limit.stderr
index e0270ecabbd..a4c85c4fcbd 100644
--- a/tests/ui/traits/well-formed-recursion-limit.stderr
+++ b/tests/ui/traits/well-formed-recursion-limit.stderr
@@ -3,12 +3,16 @@ error[E0609]: no field `ab` on type `(Box<(dyn Fn(Option<A>) -> Option<B> + 'sta
    |
 LL |     let (ab, ba) = (i.ab, i.ba);
    |                       ^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `ba` on type `(Box<(dyn Fn(Option<A>) -> Option<B> + 'static)>, Box<(dyn Fn(Option<B>) -> Option<A> + 'static)>)`
   --> $DIR/well-formed-recursion-limit.rs:12:29
    |
 LL |     let (ab, ba) = (i.ab, i.ba);
    |                             ^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0275]: overflow assigning `_` to `Option<_>`
   --> $DIR/well-formed-recursion-limit.rs:15:33
diff --git a/tests/ui/tuple/index-invalid.stderr b/tests/ui/tuple/index-invalid.stderr
index ae2c275f52c..fee09b7947c 100644
--- a/tests/ui/tuple/index-invalid.stderr
+++ b/tests/ui/tuple/index-invalid.stderr
@@ -3,18 +3,24 @@ error[E0609]: no field `1` on type `(((),),)`
    |
 LL |     let _ = (((),),).1.0;
    |                      ^ unknown field
+   |
+   = note: available field is: `0`
 
 error[E0609]: no field `1` on type `((),)`
   --> $DIR/index-invalid.rs:4:24
    |
 LL |     let _ = (((),),).0.1;
    |                        ^ unknown field
+   |
+   = note: available field is: `0`
 
 error[E0609]: no field `000` on type `(((),),)`
   --> $DIR/index-invalid.rs:6:22
    |
 LL |     let _ = (((),),).000.000;
    |                      ^^^ unknown field
+   |
+   = note: available field is: `0`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/tuple/missing-field-access.rs b/tests/ui/tuple/missing-field-access.rs
new file mode 100644
index 00000000000..b94b7cf977c
--- /dev/null
+++ b/tests/ui/tuple/missing-field-access.rs
@@ -0,0 +1,16 @@
+// Ensure that suggestions to search for missing intermediary field accesses are available for both
+// tuple structs *and* regular tuples.
+// Ensure that we do not suggest pinning the expression just because `Pin::get_ref` exists.
+// https://github.com/rust-lang/rust/issues/144602
+use std::{fs::File, io::BufReader};
+
+struct F(BufReader<File>);
+
+fn main() {
+    let f = F(BufReader::new(File::open("x").unwrap()));
+    let x = f.get_ref(); //~ ERROR E0599
+    //~^ HELP one of the expressions' fields has a method of the same name
+    let f = (BufReader::new(File::open("x").unwrap()), );
+    let x = f.get_ref(); //~ ERROR E0599
+    //~^ HELP one of the expressions' fields has a method of the same name
+}
diff --git a/tests/ui/tuple/missing-field-access.stderr b/tests/ui/tuple/missing-field-access.stderr
new file mode 100644
index 00000000000..fd9f01f8ff6
--- /dev/null
+++ b/tests/ui/tuple/missing-field-access.stderr
@@ -0,0 +1,28 @@
+error[E0599]: no method named `get_ref` found for struct `F` in the current scope
+  --> $DIR/missing-field-access.rs:11:15
+   |
+LL | struct F(BufReader<File>);
+   | -------- method `get_ref` not found for this struct
+...
+LL |     let x = f.get_ref();
+   |               ^^^^^^^ method not found in `F`
+   |
+help: one of the expressions' fields has a method of the same name
+   |
+LL |     let x = f.0.get_ref();
+   |               ++
+
+error[E0599]: no method named `get_ref` found for tuple `(BufReader<File>,)` in the current scope
+  --> $DIR/missing-field-access.rs:14:15
+   |
+LL |     let x = f.get_ref();
+   |               ^^^^^^^ method not found in `(BufReader<File>,)`
+   |
+help: one of the expressions' fields has a method of the same name
+   |
+LL |     let x = f.0.get_ref();
+   |               ++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/tuple/tuple-index-out-of-bounds.stderr b/tests/ui/tuple/tuple-index-out-of-bounds.stderr
index 8b3c835c3e3..2be9d5631f7 100644
--- a/tests/ui/tuple/tuple-index-out-of-bounds.stderr
+++ b/tests/ui/tuple/tuple-index-out-of-bounds.stderr
@@ -4,17 +4,15 @@ error[E0609]: no field `2` on type `Point`
 LL |     origin.2;
    |            ^ unknown field
    |
-help: a field with a similar name exists
-   |
-LL -     origin.2;
-LL +     origin.0;
-   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `2` on type `({integer}, {integer})`
   --> $DIR/tuple-index-out-of-bounds.rs:12:11
    |
 LL |     tuple.2;
    |           ^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden.rs
index 994adc476e2..72da2af96b8 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden.rs
@@ -8,7 +8,9 @@ type Opaque<'a> = impl Sized + 'a;
 
 #[define_opaque(Opaque)]
 fn test(s: &str) -> (impl Fn(&str) -> Opaque<'_>, impl Fn(&str) -> Opaque<'_>) {
-    (id, id) //~ ERROR expected generic lifetime parameter, found `'_`
+    (id, id)
+    //~^ ERROR expected generic lifetime parameter, found `'_`
+    //~| ERROR expected generic lifetime parameter, found `'_`
 }
 
 fn id2<'a, 'b>(s: (&'a str, &'b str)) -> (&'a str, &'b str) {
@@ -19,7 +21,9 @@ type Opaque2<'a> = impl Sized + 'a;
 
 #[define_opaque(Opaque2)]
 fn test2() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque2<'a>, Opaque2<'b>) {
-    id2 //~ ERROR expected generic lifetime parameter, found `'a`
+    id2
+    //~^ ERROR expected generic lifetime parameter, found `'a`
+    //~| ERROR expected generic lifetime parameter, found `'b`
 }
 
 type Opaque3<'a> = impl Sized + 'a;
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
index d404d60f31e..315bdfb2272 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
@@ -7,8 +7,28 @@ LL | type Opaque<'a> = impl Sized + 'a;
 LL |     (id, id)
    |     ^^^^^^^^
 
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/hkl_forbidden.rs:11:5
+   |
+LL | type Opaque<'a> = impl Sized + 'a;
+   |             -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     (id, id)
+   |     ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/hkl_forbidden.rs:22:5
+  --> $DIR/hkl_forbidden.rs:24:5
+   |
+LL | type Opaque2<'a> = impl Sized + 'a;
+   |              -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     id2
+   |     ^^^
+
+error[E0792]: expected generic lifetime parameter, found `'b`
+  --> $DIR/hkl_forbidden.rs:24:5
    |
 LL | type Opaque2<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
@@ -17,7 +37,7 @@ LL |     id2
    |     ^^^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/hkl_forbidden.rs:29:5
+  --> $DIR/hkl_forbidden.rs:33:5
    |
 LL | type Opaque3<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
@@ -26,7 +46,7 @@ LL |     (id, s)
    |     ^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/hkl_forbidden.rs:35:5
+  --> $DIR/hkl_forbidden.rs:39:5
    |
 LL | type Opaque4<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
@@ -35,7 +55,7 @@ LL |     (s, id)
    |     ^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/hkl_forbidden.rs:41:5
+  --> $DIR/hkl_forbidden.rs:45:5
    |
 LL | type Inner<'a> = impl Sized;
    |            -- this generic parameter must be used with a generic lifetime parameter
@@ -43,6 +63,6 @@ LL | type Inner<'a> = impl Sized;
 LL |     |x| x
    |     ^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch2.rs b/tests/ui/type-alias-impl-trait/param_mismatch2.rs
index f6a99711411..94c495cb330 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch2.rs
+++ b/tests/ui/type-alias-impl-trait/param_mismatch2.rs
@@ -11,7 +11,9 @@ type Opaque<'a> = impl Sized + 'a;
 
 #[define_opaque(Opaque)]
 fn test(s: &str) -> (impl Fn(&str) -> Opaque<'_>, impl Fn(&str) -> Opaque<'_>) {
-    (id, id) //~ ERROR: expected generic lifetime parameter, found `'_`
+    (id, id)
+    //~^ ERROR: expected generic lifetime parameter, found `'_`
+    //~| ERROR: expected generic lifetime parameter, found `'_`
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch2.stderr b/tests/ui/type-alias-impl-trait/param_mismatch2.stderr
index f5ecade2f02..5c8a8af6501 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch2.stderr
+++ b/tests/ui/type-alias-impl-trait/param_mismatch2.stderr
@@ -7,6 +7,17 @@ LL | type Opaque<'a> = impl Sized + 'a;
 LL |     (id, id)
    |     ^^^^^^^^
 
-error: aborting due to 1 previous error
+error[E0792]: expected generic lifetime parameter, found `'_`
+  --> $DIR/param_mismatch2.rs:14:5
+   |
+LL | type Opaque<'a> = impl Sized + 'a;
+   |             -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     (id, id)
+   |     ^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch3.rs b/tests/ui/type-alias-impl-trait/param_mismatch3.rs
index 17b6f8bce2a..1514dd66db9 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch3.rs
+++ b/tests/ui/type-alias-impl-trait/param_mismatch3.rs
@@ -11,7 +11,9 @@ type Opaque<'a> = impl Sized + 'a;
 
 #[define_opaque(Opaque)]
 fn test() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque<'a>, Opaque<'b>) {
-    id2 //~ ERROR expected generic lifetime parameter, found `'a`
+    id2
+    //~^ ERROR expected generic lifetime parameter, found `'a`
+    //~| ERROR expected generic lifetime parameter, found `'b`
 }
 
 fn id(s: &str) -> &str {
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch3.stderr b/tests/ui/type-alias-impl-trait/param_mismatch3.stderr
index 7565bbfc6ff..76be07ce38f 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch3.stderr
+++ b/tests/ui/type-alias-impl-trait/param_mismatch3.stderr
@@ -7,8 +7,17 @@ LL | type Opaque<'a> = impl Sized + 'a;
 LL |     id2
    |     ^^^
 
+error[E0792]: expected generic lifetime parameter, found `'b`
+  --> $DIR/param_mismatch3.rs:14:5
+   |
+LL | type Opaque<'a> = impl Sized + 'a;
+   |             -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     id2
+   |     ^^^
+
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/param_mismatch3.rs:25:5
+  --> $DIR/param_mismatch3.rs:27:5
    |
 LL | type Opaque2<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
@@ -16,6 +25,6 @@ LL | type Opaque2<'a> = impl Sized + 'a;
 LL |     (id, s)
    |     ^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.stderr b/tests/ui/wf/hir-wf-check-erase-regions.nll.stderr
index 07304cd448e..dcade3aa367 100644
--- a/tests/ui/wf/hir-wf-check-erase-regions.stderr
+++ b/tests/ui/wf/hir-wf-check-erase-regions.nll.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `&'a T` is not an iterator
-  --> $DIR/hir-wf-check-erase-regions.rs:7:21
+  --> $DIR/hir-wf-check-erase-regions.rs:11:21
    |
 LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator
@@ -11,7 +11,7 @@ note: required by a bound in `std::iter::IntoIterator::IntoIter`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
 
 error[E0277]: `&'a T` is not an iterator
-  --> $DIR/hir-wf-check-erase-regions.rs:7:5
+  --> $DIR/hir-wf-check-erase-regions.rs:11:5
    |
 LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    |     ^^^^^^^^^^^^^ `&'a T` is not an iterator
@@ -23,7 +23,7 @@ note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
 
 error[E0277]: `&'a T` is not an iterator
-  --> $DIR/hir-wf-check-erase-regions.rs:11:27
+  --> $DIR/hir-wf-check-erase-regions.rs:15:27
    |
 LL |     fn into_iter(self) -> Self::IntoIter {
    |                           ^^^^^^^^^^^^^^ `&'a T` is not an iterator
@@ -35,7 +35,7 @@ note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
 
 error[E0277]: `&T` is not an iterator
-  --> $DIR/hir-wf-check-erase-regions.rs:11:27
+  --> $DIR/hir-wf-check-erase-regions.rs:15:27
    |
 LL |     fn into_iter(self) -> Self::IntoIter {
    |                           ^^^^^^^^^^^^^^ `&T` is not an iterator
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.polonius.stderr b/tests/ui/wf/hir-wf-check-erase-regions.polonius.stderr
new file mode 100644
index 00000000000..55728aa642b
--- /dev/null
+++ b/tests/ui/wf/hir-wf-check-erase-regions.polonius.stderr
@@ -0,0 +1,39 @@
+error[E0277]: `&'a T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:11:21
+   |
+LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'a T` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&'a T`
+   = help: the trait `Iterator` is implemented for `&mut I`
+   = note: required for `Flatten<std::slice::Iter<'a, T>>` to implement `Iterator`
+note: required by a bound in `std::iter::IntoIterator::IntoIter`
+  --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+
+error[E0277]: `&'a T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:11:5
+   |
+LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
+   |     ^^^^^^^^^^^^^ `&'a T` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&'a T`
+   = help: the trait `Iterator` is implemented for `&mut I`
+   = note: required for `&'a T` to implement `IntoIterator`
+note: required by a bound in `Flatten`
+  --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
+
+error[E0277]: `&'a T` is not an iterator
+  --> $DIR/hir-wf-check-erase-regions.rs:15:27
+   |
+LL |     fn into_iter(self) -> Self::IntoIter {
+   |                           ^^^^^^^^^^^^^^ `&'a T` is not an iterator
+   |
+   = help: the trait `Iterator` is not implemented for `&'a T`
+   = help: the trait `Iterator` is implemented for `&mut I`
+   = note: required for `&'a T` to implement `IntoIterator`
+note: required by a bound in `Flatten`
+  --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/wf/hir-wf-check-erase-regions.rs b/tests/ui/wf/hir-wf-check-erase-regions.rs
index 20cc1cfe730..ef9132697ef 100644
--- a/tests/ui/wf/hir-wf-check-erase-regions.rs
+++ b/tests/ui/wf/hir-wf-check-erase-regions.rs
@@ -1,6 +1,10 @@
 // Regression test for #87549.
 //@ incremental
 
+//@ ignore-compare-mode-polonius (explicit revisions)
+//@ revisions: nll polonius
+//@ [polonius] compile-flags: -Zpolonius=next
+
 pub struct Table<T, const N: usize>([Option<T>; N]);
 
 impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
@@ -10,7 +14,7 @@ impl<'a, T, const N: usize> IntoIterator for &'a Table<T, N> {
 
     fn into_iter(self) -> Self::IntoIter {
         //~^ ERROR `&'a T` is not an iterator
-        //~| ERROR `&T` is not an iterator
+        //[nll]~| ERROR `&T` is not an iterator
         unimplemented!()
     }
 }