summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml6
-rw-r--r--Cargo.lock12
-rw-r--r--Cargo.toml3
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs46
-rw-r--r--compiler/rustc_attr/src/builtin.rs10
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs26
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs51
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs47
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs20
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs17
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs9
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs14
-rw-r--r--compiler/rustc_borrowck/src/lib.rs81
-rw-r--r--compiler/rustc_borrowck/src/prefixes.rs3
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs22
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs6
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs13
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs62
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/polonius.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs29
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs198
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs43
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs21
-rw-r--r--compiler/rustc_codegen_gcc/messages.ftl11
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs13
-rw-r--r--compiler/rustc_codegen_gcc/src/gcc_util.rs65
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs3
-rw-r--r--compiler/rustc_codegen_llvm/messages.ftl5
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs29
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs122
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl5
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs29
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs54
-rw-r--r--compiler/rustc_const_eval/messages.ftl5
-rw-r--r--compiler/rustc_const_eval/src/check_consts/check.rs21
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs12
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs88
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_hir/src/lang_items.rs3
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/check/errs.rs88
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs21
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs22
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs34
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs36
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs19
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs38
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs2
-rw-r--r--compiler/rustc_interface/src/tests.rs2
-rw-r--r--compiler/rustc_lint/src/impl_trait_overcaptures.rs14
-rw-r--r--compiler/rustc_lint/src/late.rs3
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp46
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs4
-rw-r--r--compiler/rustc_middle/messages.ftl4
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs4
-rw-r--r--compiler/rustc_middle/src/mir/query.rs5
-rw-r--r--compiler/rustc_middle/src/query/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs12
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs12
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs17
-rw-r--r--compiler/rustc_middle/src/ty/context.rs9
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs2
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs2
-rw-r--r--compiler/rustc_middle/src/ty/intrinsic.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs12
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs19
-rw-r--r--compiler/rustc_middle/src/ty/region.rs28
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs6
-rw-r--r--compiler/rustc_middle/src/ty/util.rs8
-rw-r--r--compiler/rustc_middle/src/util/call_kind.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs18
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs28
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs156
-rw-r--r--compiler/rustc_passes/src/stability.rs15
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs55
-rw-r--r--compiler/rustc_session/src/config.rs18
-rw-r--r--compiler/rustc_session/src/config/cfg.rs5
-rw-r--r--compiler/rustc_session/src/options.rs20
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs6
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs38
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs4
-rw-r--r--compiler/rustc_target/src/asm/mod.rs30
-rw-r--r--compiler/rustc_target/src/asm/powerpc.rs78
-rw-r--r--compiler/rustc_target/src/spec/mod.rs14
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasi.rs11
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs2
-rw-r--r--compiler/rustc_target/src/target_features.rs143
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs14
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs8
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/region.rs10
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs35
-rw-r--r--compiler/rustc_trait_selection/src/errors/note_and_explain.rs4
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs42
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs22
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs8
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs2
-rw-r--r--library/alloc/src/str.rs1
-rw-r--r--library/core/src/cell.rs5
-rw-r--r--library/core/src/char/methods.rs14
-rw-r--r--library/core/src/ffi/c_str.rs99
-rw-r--r--library/core/src/fmt/num.rs5
-rw-r--r--library/core/src/intrinsics.rs2255
-rw-r--r--library/core/src/lib.rs6
-rw-r--r--library/core/src/macros/mod.rs61
-rw-r--r--library/core/src/num/f128.rs2
-rw-r--r--library/core/src/num/f16.rs2
-rw-r--r--library/core/src/num/f32.rs2
-rw-r--r--library/core/src/num/f64.rs2
-rw-r--r--library/core/src/num/mod.rs2
-rw-r--r--library/core/src/panic.rs56
-rw-r--r--library/core/src/panicking.rs62
-rw-r--r--library/core/src/ptr/const_ptr.rs320
-rw-r--r--library/core/src/ptr/mod.rs10
-rw-r--r--library/core/src/ptr/mut_ptr.rs265
-rw-r--r--library/core/src/ptr/non_null.rs170
-rw-r--r--library/core/src/slice/ascii.rs183
-rw-r--r--library/core/src/slice/index.rs2
-rw-r--r--library/core/src/slice/memchr.rs101
-rw-r--r--library/core/src/str/converts.rs1
-rw-r--r--library/core/src/str/mod.rs3
-rw-r--r--library/core/src/str/pattern.rs4
-rw-r--r--library/core/src/str/validations.rs23
-rw-r--r--library/core/src/ub_checks.rs73
-rw-r--r--library/core/src/unicode/unicode_data.rs2
-rw-r--r--library/core/tests/lib.rs4
-rw-r--r--library/core/tests/ptr.rs257
-rw-r--r--library/rustc-std-workspace-core/README.md3
-rw-r--r--library/std/src/lib.rs10
-rw-r--r--library/std/src/os/unix/process.rs2
-rw-r--r--library/std/src/sys/alloc/windows.rs69
-rw-r--r--rustfmt.toml3
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs11
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs14
-rw-r--r--src/bootstrap/src/core/builder/mod.rs5
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile1
-rw-r--r--src/ci/github-actions/jobs.yml16
m---------src/doc/edition-guide0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/platform-support.md5
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-wasip1.md4
-rw-r--r--src/doc/unstable-book/src/compiler-flags/branch-protection.md3
-rw-r--r--src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md2
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md22
-rw-r--r--src/librustdoc/clean/mod.rs36
-rw-r--r--src/librustdoc/clean/types.rs4
-rw-r--r--src/librustdoc/clean/utils.rs2
-rw-r--r--src/librustdoc/core.rs7
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs1
-rw-r--r--src/librustdoc/passes/strip_hidden.rs2
-rw-r--r--src/librustdoc/passes/strip_priv_imports.rs2
-rw-r--r--src/librustdoc/passes/strip_private.rs2
-rw-r--r--src/librustdoc/scrape_examples.rs10
-rw-r--r--src/librustdoc/visit_ast.rs2
-rw-r--r--src/rustc-std-workspace/README.md4
-rw-r--r--src/rustc-std-workspace/rustc-std-workspace-alloc/Cargo.toml11
-rw-r--r--src/rustc-std-workspace/rustc-std-workspace-alloc/src/lib.rs3
-rw-r--r--src/rustc-std-workspace/rustc-std-workspace-core/Cargo.toml11
-rw-r--r--src/rustc-std-workspace/rustc-std-workspace-core/src/lib.rs3
-rw-r--r--src/rustc-std-workspace/rustc-std-workspace-std/Cargo.toml11
-rw-r--r--src/rustc-std-workspace/rustc-std-workspace-std/src/lib.rs1
-rw-r--r--src/tools/build-manifest/src/main.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/mod.rs128
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/ctfe.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs5
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs2
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes.stderr10
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr11
-rw-r--r--src/tools/clippy/tests/ui/attrs.stderr18
-rw-r--r--src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr14
-rw-r--r--src/tools/compiletest/src/header/tests.rs4
-rw-r--r--src/tools/rust-analyzer/.github/workflows/autopublish.yaml1
-rw-r--r--src/tools/rust-analyzer/Cargo.lock24
-rw-r--r--src/tools/rust-analyzer/Cargo.toml10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs74
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs72
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expander.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs78
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lower.rs100
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs54
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs29
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs407
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs28
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs87
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs (renamed from src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs)4
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs430
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs30
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs24
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs51
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs155
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs483
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/interpret.rs64
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/interpret_function.rs47
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs1
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar.rs7
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/items.rs13
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs24
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs8
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rast54
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rast30
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rs1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs23
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs9
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs6
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs42
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/docs/dev/setup.md57
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json2
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--src/tools/rust-analyzer/xtask/src/tidy.rs1
-rw-r--r--src/tools/tidy/src/walk.rs1
-rw-r--r--src/tools/unicode-table-generator/src/cascading_map.rs2
-rw-r--r--tests/assembly/aarch64-pointer-auth.rs17
-rw-r--r--tests/assembly/targets/targets-elf.rs3
-rw-r--r--tests/codegen/asm/powerpc-clobbers.rs26
-rw-r--r--tests/codegen/branch-protection.rs42
-rw-r--r--tests/codegen/repr/transparent-opaque-ptr.rs6
-rw-r--r--tests/crashes/132127.rs9
-rw-r--r--tests/crashes/132142.rs3
-rw-r--r--tests/crashes/132320.rs15
-rw-r--r--tests/crashes/132330.rs28
-rw-r--r--tests/crashes/132335.rs13
-rw-r--r--tests/crashes/132391.rs8
-rw-r--r--tests/crashes/132430.rs9
-rw-r--r--tests/crashes/132530.rs9
-rw-r--r--tests/crashes/README.md4
-rw-r--r--tests/run-make/pointer-auth-link-with-c/rmake.rs14
-rw-r--r--tests/run-make/target-specs/definitely-not-builtin-target.json7
-rw-r--r--tests/run-make/target-specs/rmake.rs5
-rw-r--r--tests/rustdoc-ui/show-coverage-json.rs13
-rw-r--r--tests/rustdoc-ui/show-coverage-json.stdout1
-rw-r--r--tests/rustdoc-ui/show-coverage.rs13
-rw-r--r--tests/rustdoc-ui/show-coverage.stdout7
-rw-r--r--tests/rustdoc/const-intrinsic.rs28
-rw-r--r--tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs1
-rw-r--r--tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs5
-rw-r--r--tests/ui-fulldeps/hash-stable-is-unstable.rs11
-rw-r--r--tests/ui-fulldeps/hash-stable-is-unstable.stderr20
-rw-r--r--tests/ui-fulldeps/pathless-extern-unstable.rs3
-rw-r--r--tests/ui-fulldeps/pathless-extern-unstable.stderr4
-rw-r--r--tests/ui/asm/powerpc/bad-reg.aix64.stderr264
-rw-r--r--tests/ui/asm/powerpc/bad-reg.powerpc.stderr264
-rw-r--r--tests/ui/asm/powerpc/bad-reg.powerpc64.stderr264
-rw-r--r--tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr264
-rw-r--r--tests/ui/asm/powerpc/bad-reg.rs124
-rw-r--r--tests/ui/associated-inherent-types/assoc-inherent-unstable.rs2
-rw-r--r--tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr2
-rw-r--r--tests/ui/async-await/async-fn/edition-2015.rs4
-rw-r--r--tests/ui/async-await/async-fn/edition-2015.stderr4
-rw-r--r--tests/ui/box/alloc-unstable-fail.rs2
-rw-r--r--tests/ui/box/alloc-unstable-fail.stderr2
-rw-r--r--tests/ui/check-cfg/mix.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs6
-rw-r--r--tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr6
-rw-r--r--tests/ui/closures/2229_closure_analysis/by_value.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/by_value.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs12
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr12
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr2
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-enums.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/capture-enums.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs10
-rw-r--r--tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr10
-rw-r--r--tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs10
-rw-r--r--tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr10
-rw-r--r--tests/ui/closures/2229_closure_analysis/destructure_patterns.rs12
-rw-r--r--tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr12
-rw-r--r--tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/issue-87378.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/issue-87378.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/issue-88476.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/issue-88476.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs26
-rw-r--r--tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr26
-rw-r--r--tests/ui/closures/2229_closure_analysis/move_closure.rs20
-rw-r--r--tests/ui/closures/2229_closure_analysis/move_closure.stderr20
-rw-r--r--tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/nested-closure.rs18
-rw-r--r--tests/ui/closures/2229_closure_analysis/nested-closure.stderr18
-rw-r--r--tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/path-with-array-access.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr4
-rw-r--r--tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs24
-rw-r--r--tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr48
-rw-r--r--tests/ui/closures/2229_closure_analysis/repr_packed.rs14
-rw-r--r--tests/ui/closures/2229_closure_analysis/repr_packed.stderr14
-rw-r--r--tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs10
-rw-r--r--tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr8
-rw-r--r--tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs8
-rw-r--r--tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr8
-rw-r--r--tests/ui/closures/2229_closure_analysis/wild_patterns.rs4
-rw-r--r--tests/ui/closures/2229_closure_analysis/wild_patterns.stderr4
-rw-r--r--tests/ui/closures/coerce-unsafe-to-closure.stderr4
-rw-r--r--tests/ui/conditional-compilation/cfg_accessible-unstable.rs2
-rw-r--r--tests/ui/conditional-compilation/cfg_accessible-unstable.stderr2
-rw-r--r--tests/ui/consts/auxiliary/unstable_intrinsic.rs33
-rw-r--r--tests/ui/consts/const-compare-bytes-ub.rs1
-rw-r--r--tests/ui/consts/const-compare-bytes-ub.stderr16
-rw-r--r--tests/ui/consts/const-compare-bytes.rs1
-rw-r--r--tests/ui/consts/const-eval/simd/insert_extract.rs20
-rw-r--r--tests/ui/consts/const-ptr-is-null.stderr4
-rw-r--r--tests/ui/consts/const-unstable-intrinsic.rs70
-rw-r--r--tests/ui/consts/const-unstable-intrinsic.stderr111
-rw-r--r--tests/ui/consts/copy-intrinsic.rs20
-rw-r--r--tests/ui/consts/copy-intrinsic.stderr8
-rw-r--r--tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs11
-rw-r--r--tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr23
-rw-r--r--tests/ui/derives/rustc-decodable-issue-123156.stderr2
-rw-r--r--tests/ui/destructuring-assignment/struct_destructure_fail.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr4
-rw-r--r--tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr4
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs2
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr4
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs2
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr4
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs4
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr8
-rw-r--r--tests/ui/enum/assoc-fn-call-on-variant.rs15
-rw-r--r--tests/ui/enum/assoc-fn-call-on-variant.stderr14
-rw-r--r--tests/ui/error-codes/E0027.stderr16
-rw-r--r--tests/ui/error-festival.stderr11
-rw-r--r--tests/ui/explore-issue-38412.rs2
-rw-r--r--tests/ui/explore-issue-38412.stderr14
-rw-r--r--tests/ui/feature-gates/bench.rs4
-rw-r--r--tests/ui/feature-gates/bench.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-alloc-error-handler.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-autodiff-use.rs8
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_bytes.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_bytes.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_idents.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_idents2.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-concat_idents3.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-custom_mir.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-derive-coerce-pointee.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr4
-rw-r--r--tests/ui/feature-gates/feature-gate-format_args_nl.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-log_syntax.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-log_syntax2.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-naked_functions.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-naked_functions.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-trace_macros.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-type_ascription.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-type_ascription.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr6
-rw-r--r--tests/ui/feature-gates/issue-49983-see-issue-0.stderr2
-rw-r--r--tests/ui/feature-gates/rustc-private.rs2
-rw-r--r--tests/ui/feature-gates/rustc-private.stderr2
-rw-r--r--tests/ui/feature-gates/trace_macros-gate.stderr8
-rw-r--r--tests/ui/imports/issue-37887.stderr2
-rw-r--r--tests/ui/imports/resolve-other-libc.rs2
-rw-r--r--tests/ui/inference/inference_unstable_forced.stderr2
-rw-r--r--tests/ui/internal/internal-unstable-noallow.rs8
-rw-r--r--tests/ui/internal/internal-unstable-noallow.stderr8
-rw-r--r--tests/ui/internal/internal-unstable-thread-local.stderr2
-rw-r--r--tests/ui/internal/internal-unstable.stderr10
-rw-r--r--tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs1
-rw-r--r--tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr6
-rw-r--r--tests/ui/intrinsics/intrinsic-raw_eq-const.rs1
-rw-r--r--tests/ui/intrinsics/reify-intrinsic.stderr4
-rw-r--r--tests/ui/intrinsics/unchecked_math_unstable.stderr6
-rw-r--r--tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr2
-rw-r--r--tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr2
-rw-r--r--tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs9
-rw-r--r--tests/ui/issues/issue-52489.rs2
-rw-r--r--tests/ui/issues/issue-52489.stderr2
-rw-r--r--tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr4
-rw-r--r--tests/ui/layout/thaw-transmute-invalid-enum.rs6
-rw-r--r--tests/ui/layout/thaw-transmute-invalid-enum.stderr6
-rw-r--r--tests/ui/lint/expansion-time.rs2
-rw-r--r--tests/ui/lint/expansion-time.stderr4
-rw-r--r--tests/ui/lint/lint-output-format.stderr8
-rw-r--r--tests/ui/lint/lint-stability-2.rs16
-rw-r--r--tests/ui/lint/lint-stability-2.stderr64
-rw-r--r--tests/ui/lint/lint-stability-fields.stderr86
-rw-r--r--tests/ui/lint/lint-stability.rs10
-rw-r--r--tests/ui/lint/lint-stability.stderr86
-rw-r--r--tests/ui/macros/macro-stability.rs8
-rw-r--r--tests/ui/macros/macro-stability.stderr6
-rw-r--r--tests/ui/offset-of/offset-of-unstable.stderr16
-rw-r--r--tests/ui/on-unimplemented/suggest_tuple_wrap.rs19
-rw-r--r--tests/ui/on-unimplemented/suggest_tuple_wrap.stderr25
-rw-r--r--tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs26
-rw-r--r--tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr26
-rw-r--r--tests/ui/overloaded/overloaded-calls-nontuple.stderr4
-rw-r--r--tests/ui/pattern/usefulness/doc-hidden-fields.stderr12
-rw-r--r--tests/ui/pattern/usefulness/stable-gated-fields.stderr4
-rw-r--r--tests/ui/pattern/usefulness/unstable-gated-fields.stderr8
-rw-r--r--tests/ui/pin-macro/cant_access_internals.rs2
-rw-r--r--tests/ui/pin-macro/cant_access_internals.stderr2
-rw-r--r--tests/ui/proc-macro/expand-to-unstable.stderr2
-rw-r--r--tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs2
-rw-r--r--tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr4
-rw-r--r--tests/ui/repr/16-bit-repr-c-enum.rs11
-rw-r--r--tests/ui/resolve/resolve-variant-assoc-item.stderr6
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr2
-rw-r--r--tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs2
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs6
-rw-r--r--tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs5
-rw-r--r--tests/ui/stability-attribute/accidental-stable-in-unstable.rs2
-rw-r--r--tests/ui/stability-attribute/accidental-stable-in-unstable.stderr2
-rw-r--r--tests/ui/stability-attribute/allow-unstable-reexport.rs6
-rw-r--r--tests/ui/stability-attribute/allow-unstable-reexport.stderr6
-rw-r--r--tests/ui/stability-attribute/allowed-through-unstable.rs2
-rw-r--r--tests/ui/stability-attribute/allowed-through-unstable.stderr2
-rw-r--r--tests/ui/stability-attribute/default-body-stability-err.stderr8
-rw-r--r--tests/ui/stability-attribute/generics-default-stability-trait.rs6
-rw-r--r--tests/ui/stability-attribute/generics-default-stability-trait.stderr6
-rw-r--r--tests/ui/stability-attribute/generics-default-stability-where.rs2
-rw-r--r--tests/ui/stability-attribute/generics-default-stability-where.stderr2
-rw-r--r--tests/ui/stability-attribute/generics-default-stability.rs56
-rw-r--r--tests/ui/stability-attribute/generics-default-stability.stderr56
-rw-r--r--tests/ui/stability-attribute/issue-28075.rs2
-rw-r--r--tests/ui/stability-attribute/issue-28075.stderr2
-rw-r--r--tests/ui/stability-attribute/issue-28388-3.rs2
-rw-r--r--tests/ui/stability-attribute/issue-28388-3.stderr2
-rw-r--r--tests/ui/stability-attribute/missing-const-stability.rs6
-rw-r--r--tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs4
-rw-r--r--tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr4
-rw-r--r--tests/ui/stability-attribute/stability-attribute-issue.rs4
-rw-r--r--tests/ui/stability-attribute/stability-attribute-issue.stderr4
-rw-r--r--tests/ui/stability-attribute/stable-in-unstable.rs12
-rw-r--r--tests/ui/stability-attribute/stable-in-unstable.stderr12
-rw-r--r--tests/ui/stability-attribute/suggest-vec-allocator-api.rs8
-rw-r--r--tests/ui/stability-attribute/suggest-vec-allocator-api.stderr8
-rw-r--r--tests/ui/structs/struct-field-cfg.stderr4
-rw-r--r--tests/ui/structs/struct-pat-derived-error.stderr4
-rw-r--r--tests/ui/structs/struct-tuple-field-names.stderr4
-rw-r--r--tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr16
-rw-r--r--tests/ui/suggestions/partialeq_suggest_swap.rs11
-rw-r--r--tests/ui/suggestions/partialeq_suggest_swap.stderr17
-rw-r--r--tests/ui/suggestions/suggest-let-and-typo-issue-132483.rs7
-rw-r--r--tests/ui/suggestions/suggest-let-and-typo-issue-132483.stderr29
-rw-r--r--tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs (renamed from tests/ui/auxiliary/using-target-feature-unstable.rs)0
-rw-r--r--tests/ui/target-feature/feature-hierarchy.rs10
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-attribute.rs12
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-attribute.stderr8
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-cfg.rs15
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-flag-disable.rs11
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr7
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-flag.rs11
-rw-r--r--tests/ui/target-feature/forbidden-target-feature-flag.stderr7
-rw-r--r--tests/ui/target-feature/no-llvm-leaks.rs10
-rw-r--r--tests/ui/target-feature/using-target-feature-unstable.rs (renamed from tests/ui/using-target-feature-unstable.rs)0
-rw-r--r--tests/ui/traits/bound/unknown-assoc-with-const-arg.rs20
-rw-r--r--tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr38
-rw-r--r--tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr2
-rw-r--r--tests/ui/traits/const-traits/effects/auxiliary/minicore.rs (renamed from tests/ui/traits/const-traits/effects/minicore.rs)162
-rw-r--r--tests/ui/traits/const-traits/effects/minicore-deref-fail.rs20
-rw-r--r--tests/ui/traits/const-traits/effects/minicore-deref-fail.stderr9
-rw-r--r--tests/ui/traits/const-traits/effects/minicore-works.rs22
-rw-r--r--tests/ui/traits/const-traits/effects/minicore.stderr13
-rw-r--r--tests/ui/traits/issue-78372.rs4
-rw-r--r--tests/ui/traits/issue-78372.stderr4
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs4
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr4
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types.rs10
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types.stderr10
-rw-r--r--tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr4
-rw-r--r--triagebot.toml8
575 files changed, 8264 insertions, 5712 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2fca71716c1..703f6e5281d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -110,11 +110,7 @@ jobs:
       # less disk space.
       - name: free up disk space
         uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
-        if: contains(matrix.os, 'ubuntu')
-        with:
-          # Removing packages with APT saves ~5 GiB, but takes several
-          # minutes (and potentially removes important packages).
-          large-packages: false
+        if: matrix.free_disk
 
       # Rust Log Analyzer can't currently detect the PR number of a GitHub
       # Actions build on its own, so a hint in the log message is needed to
diff --git a/Cargo.lock b/Cargo.lock
index cc36dd82f97..f78db30b286 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3197,6 +3197,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5c9f15eec8235d7cb775ee6f81891db79b98fd54ba1ad8fae565b88ef1ae4e2"
 
 [[package]]
+name = "rustc-std-workspace-alloc"
+version = "1.0.1"
+
+[[package]]
+name = "rustc-std-workspace-core"
+version = "1.0.1"
+
+[[package]]
+name = "rustc-std-workspace-std"
+version = "1.0.1"
+
+[[package]]
 name = "rustc_abi"
 version = "0.0.0"
 dependencies = [
diff --git a/Cargo.toml b/Cargo.toml
index d4b84250fc4..e1d667bf015 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,9 @@ resolver = "2"
 members = [
   "compiler/rustc",
   "src/etc/test-float-parse",
+  "src/rustc-std-workspace/rustc-std-workspace-core",
+  "src/rustc-std-workspace/rustc-std-workspace-alloc",
+  "src/rustc-std-workspace/rustc-std-workspace-std",
   "src/rustdoc-json-types",
   "src/tools/build_helper",
   "src/tools/cargotest",
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 9311af28f54..54e826585d2 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -136,6 +136,13 @@ impl Attribute {
         }
     }
 
+    /// Returns a list of meta items if the attribute is delimited with parenthesis:
+    ///
+    /// ```text
+    /// #[attr(a, b = "c")] // Returns `Some()`.
+    /// #[attr = ""] // Returns `None`.
+    /// #[attr] // Returns `None`.
+    /// ```
     pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
         match &self.kind {
             AttrKind::Normal(normal) => normal.item.meta_item_list(),
@@ -143,6 +150,21 @@ impl Attribute {
         }
     }
 
+    /// Returns the string value in:
+    ///
+    /// ```text
+    /// #[attribute = "value"]
+    ///               ^^^^^^^
+    /// ```
+    ///
+    /// It returns `None` in any other cases, including doc comments if they
+    /// are not under the form `#[doc = "..."]`.
+    ///
+    /// It also returns `None` for:
+    ///
+    /// ```text
+    /// #[attr("value")]
+    /// ```
     pub fn value_str(&self) -> Option<Symbol> {
         match &self.kind {
             AttrKind::Normal(normal) => normal.item.value_str(),
@@ -232,6 +254,18 @@ impl AttrItem {
         }
     }
 
+    /// Returns the string value in:
+    ///
+    /// ```text
+    /// #[attribute = "value"]
+    ///               ^^^^^^^
+    /// ```
+    ///
+    /// It returns `None` in any other cases like:
+    ///
+    /// ```text
+    /// #[attr("value")]
+    /// ```
     fn value_str(&self) -> Option<Symbol> {
         match &self.args {
             AttrArgs::Eq(_, args) => args.value_str(),
@@ -315,6 +349,18 @@ impl MetaItem {
         Some(self.name_value_literal()?.span)
     }
 
+    /// Returns the string value in:
+    ///
+    /// ```text
+    /// #[attribute = "value"]
+    ///               ^^^^^^^
+    /// ```
+    ///
+    /// It returns `None` in any other cases like:
+    ///
+    /// ```text
+    /// #[attr("value")]
+    /// ```
     pub fn value_str(&self) -> Option<Symbol> {
         match &self.kind {
             MetaItemKind::NameValue(v) => v.kind.str(),
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 6af75bc94bb..2753ac529d1 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -273,8 +273,7 @@ pub fn find_stability(
 /// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
 /// attributes in `attrs`. Returns `None` if no stability attributes are found.
 ///
-/// `is_const_fn` indicates whether this is a function marked as `const`. It will always
-/// be false for intrinsics in an `extern` block!
+/// `is_const_fn` indicates whether this is a function marked as `const`.
 pub fn find_const_stability(
     sess: &Session,
     attrs: &[Attribute],
@@ -330,7 +329,7 @@ pub fn find_const_stability(
         }
     }
 
-    // Merge promotable and not_exposed_on_stable into stability info
+    // Merge promotable and const_stable_indirect into stability info
     if promotable {
         match &mut const_stab {
             Some((stab, _)) => stab.promotable = promotable,
@@ -352,10 +351,7 @@ pub fn find_const_stability(
                     })
                 }
             }
-            _ => {
-                // We ignore the `#[rustc_const_stable_indirect]` here, it should be picked up by
-                // the `default_const_unstable` logic.
-            }
+            _ => {}
         }
     }
     // Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index a8ade54732f..16b3d901956 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -20,18 +20,18 @@ pub struct BorrowSet<'tcx> {
     /// by the `Location` of the assignment statement in which it
     /// appears on the right hand side. Thus the location is the map
     /// key, and its position in the map corresponds to `BorrowIndex`.
-    pub location_map: FxIndexMap<Location, BorrowData<'tcx>>,
+    pub(crate) location_map: FxIndexMap<Location, BorrowData<'tcx>>,
 
     /// Locations which activate borrows.
     /// NOTE: a given location may activate more than one borrow in the future
     /// when more general two-phase borrow support is introduced, but for now we
     /// only need to store one borrow index.
-    pub activation_map: FxIndexMap<Location, Vec<BorrowIndex>>,
+    pub(crate) activation_map: FxIndexMap<Location, Vec<BorrowIndex>>,
 
     /// Map from local to all the borrows on that local.
-    pub local_map: FxIndexMap<mir::Local, FxIndexSet<BorrowIndex>>,
+    pub(crate) local_map: FxIndexMap<mir::Local, FxIndexSet<BorrowIndex>>,
 
-    pub locals_state_at_exit: LocalsStateAtExit,
+    pub(crate) locals_state_at_exit: LocalsStateAtExit,
 }
 
 impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
@@ -45,7 +45,7 @@ impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
 /// Location where a two-phase borrow is activated, if a borrow
 /// is in fact a two-phase borrow.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum TwoPhaseActivation {
+pub(crate) enum TwoPhaseActivation {
     NotTwoPhase,
     NotActivated,
     ActivatedAt(Location),
@@ -55,17 +55,17 @@ pub enum TwoPhaseActivation {
 pub struct BorrowData<'tcx> {
     /// Location where the borrow reservation starts.
     /// In many cases, this will be equal to the activation location but not always.
-    pub reserve_location: Location,
+    pub(crate) reserve_location: Location,
     /// Location where the borrow is activated.
-    pub activation_location: TwoPhaseActivation,
+    pub(crate) activation_location: TwoPhaseActivation,
     /// What kind of borrow this is
-    pub kind: mir::BorrowKind,
+    pub(crate) kind: mir::BorrowKind,
     /// The region for which this borrow is live
-    pub region: RegionVid,
+    pub(crate) region: RegionVid,
     /// Place from which we are borrowing
-    pub borrowed_place: mir::Place<'tcx>,
+    pub(crate) borrowed_place: mir::Place<'tcx>,
     /// Place to which the borrow was stored
-    pub assigned_place: mir::Place<'tcx>,
+    pub(crate) assigned_place: mir::Place<'tcx>,
 }
 
 impl<'tcx> fmt::Display for BorrowData<'tcx> {
@@ -120,7 +120,7 @@ impl LocalsStateAtExit {
 }
 
 impl<'tcx> BorrowSet<'tcx> {
-    pub fn build(
+    pub(crate) fn build(
         tcx: TyCtxt<'tcx>,
         body: &Body<'tcx>,
         locals_are_invalidated_at_exit: bool,
@@ -156,7 +156,7 @@ impl<'tcx> BorrowSet<'tcx> {
         self.activation_map.get(&location).map_or(&[], |activations| &activations[..])
     }
 
-    pub fn len(&self) -> usize {
+    pub(crate) fn len(&self) -> usize {
         self.location_map.len()
     }
 
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index ca435ee0865..a52269df682 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -210,7 +210,7 @@ impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
 
 rustc_index::newtype_index! {
     #[debug_format = "OutlivesConstraintIndex({})"]
-    pub struct OutlivesConstraintIndex {}
+    pub(crate) struct OutlivesConstraintIndex {}
 }
 
 rustc_index::newtype_index! {
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 89ff12c1479..d832decc170 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -254,8 +254,8 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
         let sccs = self.regioncx.constraint_sccs();
         let universal_regions = self.regioncx.universal_regions();
 
-        // We first handle the cases where the loan doesn't go out of scope, depending on the issuing
-        // region's successors.
+        // We first handle the cases where the loan doesn't go out of scope, depending on the
+        // issuing region's successors.
         for successor in graph::depth_first_search(&self.regioncx.region_graph(), issuing_region) {
             // 1. Via applied member constraints
             //
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 2fa752384a1..0897d140d60 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -3,7 +3,6 @@ use std::rc::Rc;
 
 use rustc_errors::Diag;
 use rustc_hir::def_id::LocalDefId;
-use rustc_infer::infer::canonical::CanonicalQueryInput;
 use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc_infer::infer::{
     InferCtxt, RegionResolutionError, RegionVariableOrigin, SubregionOrigin, TyCtxtInferExt as _,
@@ -21,7 +20,6 @@ use rustc_span::Span;
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::error_reporting::infer::nice_region_error::NiceRegionError;
 use rustc_trait_selection::traits::ObligationCtxt;
-use rustc_trait_selection::traits::query::type_op;
 use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
 use tracing::{debug, instrument};
 
@@ -31,12 +29,9 @@ use crate::session_diagnostics::{
     HigherRankedErrorCause, HigherRankedLifetimeError, HigherRankedSubtypeError,
 };
 
-#[derive(Clone)]
-pub(crate) struct UniverseInfo<'tcx>(UniverseInfoInner<'tcx>);
-
 /// What operation a universe was created for.
 #[derive(Clone)]
-enum UniverseInfoInner<'tcx> {
+pub(crate) enum UniverseInfo<'tcx> {
     /// Relating two types which have binders.
     RelateTys { expected: Ty<'tcx>, found: Ty<'tcx> },
     /// Created from performing a `TypeOp`.
@@ -47,11 +42,11 @@ enum UniverseInfoInner<'tcx> {
 
 impl<'tcx> UniverseInfo<'tcx> {
     pub(crate) fn other() -> UniverseInfo<'tcx> {
-        UniverseInfo(UniverseInfoInner::Other)
+        UniverseInfo::Other
     }
 
     pub(crate) fn relate(expected: Ty<'tcx>, found: Ty<'tcx>) -> UniverseInfo<'tcx> {
-        UniverseInfo(UniverseInfoInner::RelateTys { expected, found })
+        UniverseInfo::RelateTys { expected, found }
     }
 
     pub(crate) fn report_error(
@@ -61,8 +56,8 @@ impl<'tcx> UniverseInfo<'tcx> {
         error_element: RegionElement,
         cause: ObligationCause<'tcx>,
     ) {
-        match self.0 {
-            UniverseInfoInner::RelateTys { expected, found } => {
+        match *self {
+            UniverseInfo::RelateTys { expected, found } => {
                 let err = mbcx.infcx.err_ctxt().report_mismatched_types(
                     &cause,
                     mbcx.param_env,
@@ -72,10 +67,10 @@ impl<'tcx> UniverseInfo<'tcx> {
                 );
                 mbcx.buffer_error(err);
             }
-            UniverseInfoInner::TypeOp(ref type_op_info) => {
+            UniverseInfo::TypeOp(ref type_op_info) => {
                 type_op_info.report_error(mbcx, placeholder, error_element, cause);
             }
-            UniverseInfoInner::Other => {
+            UniverseInfo::Other => {
                 // FIXME: This error message isn't great, but it doesn't show
                 // up in the existing UI tests. Consider investigating this
                 // some more.
@@ -93,19 +88,16 @@ pub(crate) trait ToUniverseInfo<'tcx> {
 
 impl<'tcx> ToUniverseInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
     fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
-        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(crate::type_check::InstantiateOpaqueType {
+        UniverseInfo::TypeOp(Rc::new(crate::type_check::InstantiateOpaqueType {
             base_universe: Some(base_universe),
             ..self
-        })))
+        }))
     }
 }
 
 impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpProvePredicateGoal<'tcx> {
     fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
-        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(PredicateQuery {
-            canonical_query: self,
-            base_universe,
-        })))
+        UniverseInfo::TypeOp(Rc::new(PredicateQuery { canonical_query: self, base_universe }))
     }
 }
 
@@ -113,26 +105,13 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUnivers
     for CanonicalTypeOpNormalizeGoal<'tcx, T>
 {
     fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
-        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(NormalizeQuery {
-            canonical_query: self,
-            base_universe,
-        })))
+        UniverseInfo::TypeOp(Rc::new(NormalizeQuery { canonical_query: self, base_universe }))
     }
 }
 
 impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> {
     fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
-        UniverseInfo(UniverseInfoInner::TypeOp(Rc::new(AscribeUserTypeQuery {
-            canonical_query: self,
-            base_universe,
-        })))
-    }
-}
-
-impl<'tcx, F> ToUniverseInfo<'tcx> for CanonicalQueryInput<'tcx, type_op::custom::CustomTypeOp<F>> {
-    fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
-        // We can't rerun custom type ops.
-        UniverseInfo::other()
+        UniverseInfo::TypeOp(Rc::new(AscribeUserTypeQuery { canonical_query: self, base_universe }))
     }
 }
 
@@ -143,7 +122,7 @@ impl<'tcx> ToUniverseInfo<'tcx> for ! {
 }
 
 #[allow(unused_lifetimes)]
-trait TypeOpInfo<'tcx> {
+pub(crate) trait TypeOpInfo<'tcx> {
     /// Returns an error to be reported if rerunning the type op fails to
     /// recover the error's cause.
     fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx>;
@@ -289,8 +268,8 @@ where
         // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
         // `ObligationCause`. The normalization results are currently different between
         // `QueryNormalizeExt::query_normalize` used in the query and `normalize` called below:
-        // the former fails to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test.
-        // Check after #85499 lands to see if its fixes have erased this difference.
+        // the former fails to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs`
+        // test. Check after #85499 lands to see if its fixes have erased this difference.
         let (param_env, value) = key.into_parts();
         let _ = ocx.normalize(&cause, param_env, value.value);
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 511313cca6f..e5b28289faa 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1345,11 +1345,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             // See `tests/ui/moves/needs-clone-through-deref.rs`
             return false;
         }
-        // We don't want to suggest `.clone()` in a move closure, since the value has already been captured.
+        // We don't want to suggest `.clone()` in a move closure, since the value has already been
+        // captured.
         if self.in_move_closure(expr) {
             return false;
         }
-        // We also don't want to suggest cloning a closure itself, since the value has already been captured.
+        // We also don't want to suggest cloning a closure itself, since the value has already been
+        // captured.
         if let hir::ExprKind::Closure(_) = expr.kind {
             return false;
         }
@@ -1381,7 +1383,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 }
             }
         }
-        // Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch error. (see #126863)
+        // Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch
+        // error. (see #126863)
         if inner_expr.span.lo() != expr.span.lo() && !is_raw_ptr {
             // Remove "(*" or "(&"
             sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new()));
@@ -1553,8 +1556,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let use_spans = self.move_spans(place.as_ref(), location);
         let span = use_spans.var_or_use();
 
-        // If the attempted use is in a closure then we do not care about the path span of the place we are currently trying to use
-        // we call `var_span_label` on `borrow_spans` to annotate if the existing borrow was in a closure
+        // If the attempted use is in a closure then we do not care about the path span of the
+        // place we are currently trying to use we call `var_span_label` on `borrow_spans` to
+        // annotate if the existing borrow was in a closure.
         let mut err = self.cannot_use_when_mutably_borrowed(
             span,
             &self.describe_any_place(place.as_ref()),
@@ -2480,7 +2484,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 if let hir::ExprKind::Closure(closure) = ex.kind
                     && ex.span.contains(self.borrow_span)
                     // To support cases like `|| { v.call(|this| v.get()) }`
-                    // FIXME: actually support such cases (need to figure out how to move from the capture place to original local)
+                    // FIXME: actually support such cases (need to figure out how to move from the
+                    // capture place to original local).
                     && self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span))
                 {
                     self.res = Some((ex, closure));
@@ -2733,7 +2738,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     /// cannot borrow `a.u` (via `a.u.z.c`) as immutable because it is also borrowed as
     /// mutable (via `a.u.s.b`) [E0502]
     /// ```
-    pub(crate) fn describe_place_for_conflicting_borrow(
+    fn describe_place_for_conflicting_borrow(
         &self,
         first_borrowed_place: Place<'tcx>,
         second_borrowed_place: Place<'tcx>,
@@ -3188,8 +3193,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 /// misleading users in cases like `tests/ui/nll/borrowed-temporary-error.rs`.
                 /// We could expand the analysis to suggest hoising all of the relevant parts of
                 /// the users' code to make the code compile, but that could be too much.
-                /// We found the `prop_expr` by the way to check whether the expression is a `FormatArguments`,
-                /// which is a special case since it's generated by the compiler.
+                /// We found the `prop_expr` by the way to check whether the expression is a
+                /// `FormatArguments`, which is a special case since it's generated by the
+                /// compiler.
                 struct NestedStatementVisitor<'tcx> {
                     span: Span,
                     current: usize,
@@ -3420,7 +3426,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         let (sugg_span, suggestion) = match tcx.sess.source_map().span_to_snippet(args_span) {
             Ok(string) => {
                 let coro_prefix = if string.starts_with("async") {
-                    // `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize` to `u32`
+                    // `async` is 5 chars long. Not using `.len()` to avoid the cast from `usize`
+                    // to `u32`.
                     Some(5)
                 } else if string.starts_with("gen") {
                     // `gen` is 3 chars long
@@ -3618,10 +3625,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             let stmt_kind =
                 self.body[location.block].statements.get(location.statement_index).map(|s| &s.kind);
             if let Some(StatementKind::StorageDead(..)) = stmt_kind {
-                // this analysis only tries to find moves explicitly
-                // written by the user, so we ignore the move-outs
-                // created by `StorageDead` and at the beginning
-                // of a function.
+                // This analysis only tries to find moves explicitly written by the user, so we
+                // ignore the move-outs created by `StorageDead` and at the beginning of a
+                // function.
             } else {
                 // If we are found a use of a.b.c which was in error, then we want to look for
                 // moves not only of a.b.c but also a.b and a.
@@ -3706,13 +3712,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             }
         }
         if (is_argument || !reached_start) && result.is_empty() {
-            /* Process back edges (moves in future loop iterations) only if
-               the move path is definitely initialized upon loop entry,
-               to avoid spurious "in previous iteration" errors.
-               During DFS, if there's a path from the error back to the start
-               of the function with no intervening init or move, then the
-               move path may be uninitialized at loop entry.
-            */
+            // Process back edges (moves in future loop iterations) only if
+            // the move path is definitely initialized upon loop entry,
+            // to avoid spurious "in previous iteration" errors.
+            // During DFS, if there's a path from the error back to the start
+            // of the function with no intervening init or move, then the
+            // move path may be uninitialized at loop entry.
             while let Some(location) = back_edge_stack.pop() {
                 if dfs_iter(&mut result, location, true) {
                     continue;
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 31a5d451ff6..45a8ef0adb6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -130,7 +130,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
                 {
                     suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err);
                 } else if path_span.map_or(true, |path_span| path_span == var_or_use_span) {
-                    // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same
+                    // We can use `var_or_use_span` if either `path_span` is not present, or both
+                    // spans are the same.
                     if borrow_span.map_or(true, |sp| !sp.overlaps(var_or_use_span)) {
                         err.span_label(
                             var_or_use_span,
@@ -165,7 +166,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
                     LaterUseKind::FakeLetRead => "borrow later stored here",
                     LaterUseKind::Other => "borrow used here, in later iteration of loop",
                 };
-                // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same
+                // We can use `var_or_use_span` if either `path_span` is not present, or both spans
+                // are the same.
                 if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) {
                     err.span_label(var_or_use_span, format!("{borrow_desc}{message}"));
                 } else {
@@ -285,7 +287,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
                                 span: _,
                                 pat,
                                 init,
-                                // FIXME(#101728): enable rewrite when type ascription is stabilized again
+                                // FIXME(#101728): enable rewrite when type ascription is
+                                // stabilized again.
                                 ty: None,
                                 recovered: _,
                             }) = cond.kind
@@ -353,8 +356,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
         unsize_ty: Ty<'tcx>,
     ) {
         if let ty::Adt(def, args) = unsize_ty.kind() {
-            // We try to elaborate the object lifetime defaults and present those to the user. This should
-            // make it clear where the region constraint is coming from.
+            // We try to elaborate the object lifetime defaults and present those to the user. This
+            // should make it clear where the region constraint is coming from.
             let generics = tcx.generics_of(def.did());
 
             let mut has_dyn = false;
@@ -531,9 +534,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
         let mut use_in_later_iteration_of_loop = false;
 
         if region_sub == borrow_region_vid {
-            // When `region_sub` is the same as `borrow_region_vid` (the location where the borrow is
-            // issued is the same location that invalidates the reference), this is likely a loop iteration
-            // - in this case, try using the loop terminator location in `find_sub_region_live_at`.
+            // When `region_sub` is the same as `borrow_region_vid` (the location where the borrow
+            // is issued is the same location that invalidates the reference), this is likely a
+            // loop iteration. In this case, try using the loop terminator location in
+            // `find_sub_region_live_at`.
             if let Some(loop_terminator_location) =
                 regioncx.find_loop_terminator_location(borrow.region, body)
             {
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 07b3c295eaa..0797bb49bf9 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -763,7 +763,7 @@ impl<'tcx> BorrowedContentSource<'tcx> {
     }
 }
 
-///helper struct for explain_captures()
+/// Helper struct for `explain_captures`.
 struct CapturedMessageOpt {
     is_partial_move: bool,
     is_loop_message: bool,
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 3871816777c..15cc9c20ab7 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -10,6 +10,7 @@ use rustc_middle::ty::{self, Ty};
 use rustc_mir_dataflow::move_paths::{LookupResult, MovePathIndex};
 use rustc_span::{BytePos, ExpnKind, MacroKind, Span};
 use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
+use rustc_trait_selection::infer::InferCtxtExt;
 use tracing::debug;
 
 use crate::MirBorrowckCtxt;
@@ -267,6 +268,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                 kind,
                 self.is_upvar_field_projection(original_path.as_ref())
             );
+            if self.has_ambiguous_copy(original_path.ty(self.body, self.infcx.tcx).ty) {
+                // If the type may implement Copy, skip the error.
+                // It's an error with the Copy implementation (e.g. duplicate Copy) rather than borrow check
+                self.dcx().span_delayed_bug(
+                    span,
+                    "Type may implement copy, but there is no other error.",
+                );
+                return;
+            }
             (
                 match kind {
                     &IllegalMoveOriginKind::BorrowedContent { target_place } => self
@@ -291,6 +301,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
         self.buffer_error(err);
     }
 
+    fn has_ambiguous_copy(&mut self, ty: Ty<'tcx>) -> bool {
+        let Some(copy_trait_def) = self.infcx.tcx.lang_items().copy_trait() else { return false };
+        // This is only going to be ambiguous if there are incoherent impls, because otherwise
+        // ambiguity should never happen in MIR.
+        self.infcx.type_implements_trait(copy_trait_def, [ty], self.param_env).may_apply()
+    }
+
     fn report_cannot_move_from_static(&mut self, place: Place<'tcx>, span: Span) -> Diag<'infcx> {
         let description = if place.projection.len() == 1 {
             format!("static item {}", self.describe_any_place(place.as_ref()))
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 33bd4f37b7f..d064bf098e4 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -793,7 +793,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             let reason = if let PlaceBase::Upvar(upvar_id) = closure_kind_origin.base {
                 let upvar = ty::place_to_string_for_capture(tcx, closure_kind_origin);
                 let root_hir_id = upvar_id.var_path.hir_id;
-                // we have an origin for this closure kind starting at this root variable so it's safe to unwrap here
+                // We have an origin for this closure kind starting at this root variable so it's
+                // safe to unwrap here.
                 let captured_places =
                     tables.closure_min_captures[&closure_local_def_id].get(&root_hir_id).unwrap();
 
@@ -816,7 +817,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     ) {
                         match captured_place.info.capture_kind {
                             ty::UpvarCapture::ByRef(
-                                ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
+                                ty::BorrowKind::Mutable | ty::BorrowKind::UniqueImmutable,
                             ) => {
                                 capture_reason = format!("mutable borrow of `{upvar}`");
                             }
@@ -966,8 +967,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
             }
         };
 
-        // If we can detect the expression to be an function or method call where the closure was an argument,
-        // we point at the function or method definition argument...
+        // If we can detect the expression to be an function or method call where the closure was
+        // an argument, we point at the function or method definition argument...
         if let Some((callee_def_id, call_span, call_args)) = get_call_details() {
             let arg_pos = call_args
                 .iter()
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 49e999a3caa..807b5576976 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -189,7 +189,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     /// Returns `true` if a closure is inferred to be an `FnMut` closure.
     fn is_closure_fn_mut(&self, fr: RegionVid) -> bool {
         if let Some(ty::ReLateParam(late_param)) = self.to_error_region(fr).as_deref()
-            && let ty::BoundRegionKind::BrEnv = late_param.bound_region
+            && let ty::BoundRegionKind::ClosureEnv = late_param.bound_region
             && let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty
         {
             return args.as_closure().kind() == ty::ClosureKind::FnMut;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 6ca7251295d..d49dee85144 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -30,8 +30,8 @@ pub(crate) struct RegionName {
 }
 
 /// Denotes the source of a region that is named by a `RegionName`. For example, a free region that
-/// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get `Static`.
-/// This helps to print the right kinds of diagnostics.
+/// was named by the user would get `NamedLateParamRegion` and `'static` lifetime would get
+/// `Static`. This helps to print the right kinds of diagnostics.
 #[derive(Debug, Clone, Copy)]
 pub(crate) enum RegionNameSource {
     /// A bound (not free) region that was instantiated at the def site (not an HRTB).
@@ -301,7 +301,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
             }
 
             ty::ReLateParam(late_param) => match late_param.bound_region {
-                ty::BoundRegionKind::BrNamed(region_def_id, name) => {
+                ty::BoundRegionKind::Named(region_def_id, name) => {
                     // Get the span to point to, even if we don't use the name.
                     let span = tcx.hir().span_if_local(region_def_id).unwrap_or(DUMMY_SP);
                     debug!(
@@ -332,7 +332,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
                     }
                 }
 
-                ty::BoundRegionKind::BrEnv => {
+                ty::BoundRegionKind::ClosureEnv => {
                     let def_ty = self.regioncx.universal_regions().defining_ty;
 
                     let closure_kind = match def_ty {
@@ -369,7 +369,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
                     })
                 }
 
-                ty::BoundRegionKind::BrAnon => None,
+                ty::BoundRegionKind::Anon => None,
             },
 
             ty::ReBound(..)
@@ -825,8 +825,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
     /// async fn foo() -> i32 { 2 }
     /// ```
     ///
-    /// this function, given the lowered return type of `foo`, an [`OpaqueDef`] that implements `Future<Output=i32>`,
-    /// returns the `i32`.
+    /// this function, given the lowered return type of `foo`, an [`OpaqueDef`] that implements
+    /// `Future<Output=i32>`, returns the `i32`.
     ///
     /// [`OpaqueDef`]: hir::TyKind::OpaqueDef
     fn get_future_inner_return_ty(&self, hir_ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index ae23f004593..657e6e0907c 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -20,7 +20,6 @@ use std::collections::BTreeMap;
 use std::marker::PhantomData;
 use std::ops::Deref;
 
-use consumers::{BodyWithBorrowckFacts, ConsumerOptions};
 use rustc_abi::FieldIdx;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::graph::dominators::Dominators;
@@ -49,13 +48,21 @@ use rustc_span::{Span, Symbol};
 use smallvec::SmallVec;
 use tracing::{debug, instrument};
 
-use self::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName};
-use self::location::LocationTable;
-use self::path_utils::*;
-use self::prefixes::PrefixSet;
+use crate::borrow_set::{BorrowData, BorrowSet};
+use crate::consumers::{BodyWithBorrowckFacts, ConsumerOptions};
+use crate::dataflow::{BorrowIndex, BorrowckDomain, BorrowckResults, Borrows};
+use crate::diagnostics::{AccessKind, IllegalMoveOriginKind, MoveError, RegionName};
+use crate::location::LocationTable;
+use crate::nll::PoloniusOutput;
+use crate::path_utils::*;
+use crate::place_ext::PlaceExt;
+use crate::places_conflict::{PlaceConflictBias, places_conflict};
+use crate::prefixes::PrefixSet;
+use crate::region_infer::RegionInferenceContext;
+use crate::renumber::RegionCtxt;
 use crate::session_diagnostics::VarNeedNotMut;
 
-pub mod borrow_set;
+mod borrow_set;
 mod borrowck_errors;
 mod constraints;
 mod dataflow;
@@ -81,18 +88,11 @@ mod util;
 /// A public API provided for the Rust compiler consumers.
 pub mod consumers;
 
-use borrow_set::{BorrowData, BorrowSet};
-use dataflow::{BorrowIndex, BorrowckDomain, BorrowckResults, Borrows};
-use nll::PoloniusOutput;
-use place_ext::PlaceExt;
-use places_conflict::{PlaceConflictBias, places_conflict};
-use region_infer::RegionInferenceContext;
-use renumber::RegionCtxt;
-
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 /// Associate some local constants with the `'tcx` lifetime
 struct TyCtxtConsts<'tcx>(PhantomData<&'tcx ()>);
+
 impl<'tcx> TyCtxtConsts<'tcx> {
     const DEREF_PROJECTION: &'tcx [PlaceElem<'tcx>; 1] = &[ProjectionElem::Deref];
 }
@@ -162,7 +162,7 @@ fn do_mir_borrowck<'tcx>(
         }
     }
 
-    let mut diags = diags::BorrowckDiags::new();
+    let diags = &mut diags::BorrowckDiags::new();
 
     // Gather the upvars of a closure, if any.
     if let Some(e) = input_body.tainted_by_errors {
@@ -227,14 +227,7 @@ fn do_mir_borrowck<'tcx>(
 
     // We also have a `#[rustc_regions]` annotation that causes us to dump
     // information.
-    nll::dump_annotation(
-        &infcx,
-        body,
-        &regioncx,
-        &opt_closure_req,
-        &opaque_type_values,
-        &mut diags,
-    );
+    nll::dump_annotation(&infcx, body, &regioncx, &opt_closure_req, &opaque_type_values, diags);
 
     // The various `flow_*` structures can be large. We drop `flow_inits` here
     // so it doesn't overlap with the others below. This reduces peak memory
@@ -299,7 +292,6 @@ fn do_mir_borrowck<'tcx>(
         };
         MoveVisitor { ctxt: &mut promoted_mbcx }.visit_body(promoted_body);
         promoted_mbcx.report_move_errors();
-        diags = promoted_mbcx.diags;
 
         struct MoveVisitor<'a, 'b, 'infcx, 'tcx> {
             ctxt: &'a mut MirBorrowckCtxt<'b, 'infcx, 'tcx>,
@@ -434,7 +426,7 @@ fn do_mir_borrowck<'tcx>(
     (result, body_with_facts)
 }
 
-pub struct BorrowckInferCtxt<'tcx> {
+pub(crate) struct BorrowckInferCtxt<'tcx> {
     pub(crate) infcx: InferCtxt<'tcx>,
     pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
 }
@@ -587,7 +579,7 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
     /// Results of Polonius analysis.
     polonius_output: Option<Box<PoloniusOutput>>,
 
-    diags: diags::BorrowckDiags<'infcx, 'tcx>,
+    diags: &'a mut diags::BorrowckDiags<'infcx, 'tcx>,
     move_errors: Vec<MoveError<'tcx>>,
 }
 
@@ -638,7 +630,9 @@ impl<'a, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'a, 'tcx, R>
                 );
             }
             StatementKind::Intrinsic(box kind) => match kind {
-                NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), state),
+                NonDivergingIntrinsic::Assume(op) => {
+                    self.consume_operand(location, (op, span), state);
+                }
                 NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
                     span,
                     "Unexpected CopyNonOverlapping, should only appear after lower_intrinsics",
@@ -2105,7 +2099,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
             | Write(WriteKind::MutableBorrow(BorrowKind::Mut { kind: mut_borrow_kind })) => {
                 let is_local_mutation_allowed = match mut_borrow_kind {
                     // `ClosureCapture` is used for mutable variable with an immutable binding.
-                    // This is only behaviour difference between `ClosureCapture` and mutable borrows.
+                    // This is only behaviour difference between `ClosureCapture` and mutable
+                    // borrows.
                     MutBorrowKind::ClosureCapture => LocalMutationIsAllowed::Yes,
                     MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow => {
                         is_local_mutation_allowed
@@ -2350,23 +2345,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
                                 ) => Err(place),
                                 (Mutability::Not, LocalMutationIsAllowed::Yes)
                                 | (Mutability::Mut, _) => {
-                                    // Subtle: this is an upvar
-                                    // reference, so it looks like
-                                    // `self.foo` -- we want to double
-                                    // check that the location `*self`
-                                    // is mutable (i.e., this is not a
-                                    // `Fn` closure). But if that
-                                    // check succeeds, we want to
-                                    // *blame* the mutability on
-                                    // `place` (that is,
-                                    // `self.foo`). This is used to
-                                    // propagate the info about
-                                    // whether mutability declarations
-                                    // are used outwards, so that we register
-                                    // the outer variable as mutable. Otherwise a
-                                    // test like this fails to record the `mut`
-                                    // as needed:
-                                    //
+                                    // Subtle: this is an upvar reference, so it looks like
+                                    // `self.foo` -- we want to double check that the location
+                                    // `*self` is mutable (i.e., this is not a `Fn` closure). But
+                                    // if that check succeeds, we want to *blame* the mutability on
+                                    // `place` (that is, `self.foo`). This is used to propagate the
+                                    // info about whether mutability declarations are used
+                                    // outwards, so that we register the outer variable as mutable.
+                                    // Otherwise a test like this fails to record the `mut` as
+                                    // needed:
                                     // ```
                                     // fn foo<F: FnOnce()>(_f: F) { }
                                     // fn main() {
@@ -2511,7 +2498,7 @@ mod diags {
             // Buffer any move errors that we collected and de-duplicated.
             for (_, (_, diag)) in std::mem::take(&mut self.diags.buffered_move_errors) {
                 // We have already set tainted for this error, so just buffer it.
-                self.diags.buffered_diags.push(BufferedDiag::Error(diag));
+                self.diags.buffer_error(diag);
             }
             for (_, (mut diag, count)) in std::mem::take(&mut self.diags.buffered_mut_errors) {
                 if count > 10 {
@@ -2519,7 +2506,7 @@ mod diags {
                     #[allow(rustc::untranslatable_diagnostic)]
                     diag.note(format!("...and {} other attempted mutable borrows", count - 10));
                 }
-                self.diags.buffered_diags.push(BufferedDiag::Error(diag));
+                self.diags.buffer_error(diag);
             }
 
             if !self.diags.buffered_diags.is_empty() {
diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index aeb8a6c014a..fc7e6e58641 100644
--- a/compiler/rustc_borrowck/src/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
@@ -53,7 +53,7 @@ impl<'tcx> Iterator for Prefixes<'tcx> {
         // may hold one further down (e.g., we never return
         // downcasts here, but may return a base of a downcast).
 
-        'cursor: loop {
+        loop {
             match cursor.last_projection() {
                 None => {
                     self.next = None;
@@ -72,7 +72,6 @@ impl<'tcx> Iterator for Prefixes<'tcx> {
                         | ProjectionElem::ConstantIndex { .. }
                         | ProjectionElem::Index(_) => {
                             cursor = cursor_base;
-                            continue 'cursor;
                         }
                         ProjectionElem::Subtype(..) => {
                             panic!("Subtype projection is not allowed before borrow check")
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index d5c2796932e..7e317ea6554 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -99,9 +99,9 @@ impl RegionTracker {
     pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
         let (representative_is_placeholder, representative_is_existential) = match definition.origin
         {
-            rustc_infer::infer::NllRegionVariableOrigin::FreeRegion => (false, false),
-            rustc_infer::infer::NllRegionVariableOrigin::Placeholder(_) => (true, false),
-            rustc_infer::infer::NllRegionVariableOrigin::Existential { .. } => (false, true),
+            NllRegionVariableOrigin::FreeRegion => (false, false),
+            NllRegionVariableOrigin::Placeholder(_) => (true, false),
+            NllRegionVariableOrigin::Existential { .. } => (false, true),
         };
 
         let placeholder_universe =
@@ -553,7 +553,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     }
 
     /// Returns an iterator over all the region indices.
-    pub fn regions(&self) -> impl Iterator<Item = RegionVid> + 'tcx {
+    pub(crate) fn regions(&self) -> impl Iterator<Item = RegionVid> + 'tcx {
         self.definitions.indices()
     }
 
@@ -561,12 +561,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// corresponding index.
     ///
     /// (Panics if `r` is not a registered universal region.)
-    pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
+    pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
         self.universal_regions.to_region_vid(r)
     }
 
     /// Returns an iterator over all the outlives constraints.
-    pub fn outlives_constraints(&self) -> impl Iterator<Item = OutlivesConstraint<'tcx>> + '_ {
+    pub(crate) fn outlives_constraints(
+        &self,
+    ) -> impl Iterator<Item = OutlivesConstraint<'tcx>> + '_ {
         self.constraints.outlives().iter().copied()
     }
 
@@ -1495,6 +1497,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     fn scc_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex {
         self.constraint_sccs().annotation(scc).min_universe()
     }
+
     /// Checks the final value for the free region `fr` to see if it
     /// grew too large. In particular, examine what `end(X)` points
     /// wound up in `fr`'s final value; for each `end(X)` where `X !=
@@ -1667,7 +1670,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 placeholder,
             });
 
-            // Stop after the first error, it gets too noisy otherwise, and does not provide more information.
+            // Stop after the first error, it gets too noisy otherwise, and does not provide more
+            // information.
             break;
         }
         debug!("check_bound_universal_region: all bounds satisfied");
@@ -2000,8 +2004,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         // We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
         // Instead, we use it to produce an improved `ObligationCauseCode`.
-        // FIXME - determine what we should do if we encounter multiple `ConstraintCategory::Predicate`
-        // constraints. Currently, we just pick the first one.
+        // FIXME - determine what we should do if we encounter multiple
+        // `ConstraintCategory::Predicate` constraints. Currently, we just pick the first one.
         let cause_code = path
             .iter()
             .find_map(|constraint| {
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 3a2f5c35c72..f9dd649ab9f 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -145,9 +145,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 continue;
             }
             // Sometimes two opaque types are the same only after we remap the generic parameters
-            // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to `(X, Y)`
-            // and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we only know that
-            // once we convert the generic parameters to those of the opaque type.
+            // back to the opaque type definition. E.g. we may have `OpaqueType<X, Y>` mapped to
+            // `(X, Y)` and `OpaqueType<Y, X>` mapped to `(Y, X)`, and those are the same, but we
+            // only know that once we convert the generic parameters to those of the opaque type.
             if let Some(prev) = result.get_mut(&opaque_type_key.def_id) {
                 if prev.ty != ty {
                     let guar = ty.error_reported().err().unwrap_or_else(|| {
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index 662e6fa46b5..519edfafda5 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -15,7 +15,7 @@ use crate::BorrowIndex;
 rustc_index::newtype_index! {
     /// A single integer representing a `ty::Placeholder`.
     #[debug_format = "PlaceholderIndex({})"]
-    pub struct PlaceholderIndex {}
+    pub(crate) struct PlaceholderIndex {}
 }
 
 /// An individual element in a region value -- the value of a
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index fde68615cc0..aee13ca8cd7 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -62,7 +62,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         {
             let universe_info = error_info.to_universe_info(old_universe);
             for u in (old_universe + 1)..=universe {
-                self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
+                self.constraints.universe_causes.insert(u, universe_info.clone());
             }
         }
 
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 141f251244b..7effd5c5a68 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -48,9 +48,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // FIXME(async_closures): It's kind of wacky that we must apply this
         // transformation here, since we do the same thing in HIR typeck.
         // Maybe we could just fix up the canonicalized signature during HIR typeck?
-        if let DefiningTy::CoroutineClosure(_, args) =
-            self.borrowck_context.universal_regions.defining_ty
-        {
+        if let DefiningTy::CoroutineClosure(_, args) = self.universal_regions.defining_ty {
             assert_matches!(
                 self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)),
                 Some(hir::CoroutineKind::Desugared(
@@ -59,8 +57,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 )),
                 "this needs to be modified if we're lowering non-async closures"
             );
-            // Make sure to use the args from `DefiningTy` so the right NLL region vids are prepopulated
-            // into the type.
+            // Make sure to use the args from `DefiningTy` so the right NLL region vids are
+            // prepopulated into the type.
             let args = args.as_coroutine_closure();
             let tupled_upvars_ty = ty::CoroutineClosureSignature::tupled_upvars_by_closure_kind(
                 self.tcx(),
@@ -195,8 +193,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             // doing so ends up causing some other trouble.
             let b = self.normalize(b, Locations::All(span));
 
-            // Note: if we have to introduce new placeholders during normalization above, then we won't have
-            // added those universes to the universe info, which we would want in `relate_tys`.
+            // Note: if we have to introduce new placeholders during normalization above, then we
+            // won't have added those universes to the universe info, which we would want in
+            // `relate_tys`.
             if let Err(terr) =
                 self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
             {
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
index ccd9fb25739..695a1cdac0d 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs
@@ -137,56 +137,22 @@ struct LocalUseMapBuild<'me> {
     locals_with_use_data: IndexVec<Local, bool>,
 }
 
-impl LocalUseMapBuild<'_> {
-    fn insert_def(&mut self, local: Local, location: Location) {
-        Self::insert(
-            self.elements,
-            &mut self.local_use_map.first_def_at[local],
-            &mut self.local_use_map.appearances,
-            location,
-        );
-    }
-
-    fn insert_use(&mut self, local: Local, location: Location) {
-        Self::insert(
-            self.elements,
-            &mut self.local_use_map.first_use_at[local],
-            &mut self.local_use_map.appearances,
-            location,
-        );
-    }
-
-    fn insert_drop(&mut self, local: Local, location: Location) {
-        Self::insert(
-            self.elements,
-            &mut self.local_use_map.first_drop_at[local],
-            &mut self.local_use_map.appearances,
-            location,
-        );
-    }
-
-    fn insert(
-        elements: &DenseLocationMap,
-        first_appearance: &mut Option<AppearanceIndex>,
-        appearances: &mut Appearances,
-        location: Location,
-    ) {
-        let point_index = elements.point_from_location(location);
-        let appearance_index =
-            appearances.push(Appearance { point_index, next: *first_appearance });
-        *first_appearance = Some(appearance_index);
-    }
-}
-
 impl Visitor<'_> for LocalUseMapBuild<'_> {
     fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
-        if self.locals_with_use_data[local] {
-            match def_use::categorize(context) {
-                Some(DefUse::Def) => self.insert_def(local, location),
-                Some(DefUse::Use) => self.insert_use(local, location),
-                Some(DefUse::Drop) => self.insert_drop(local, location),
-                _ => (),
-            }
+        if self.locals_with_use_data[local]
+            && let Some(def_use) = def_use::categorize(context)
+        {
+            let first_appearance = match def_use {
+                DefUse::Def => &mut self.local_use_map.first_def_at[local],
+                DefUse::Use => &mut self.local_use_map.first_use_at[local],
+                DefUse::Drop => &mut self.local_use_map.first_drop_at[local],
+            };
+            let point_index = self.elements.point_from_location(location);
+            let appearance_index = self
+                .local_use_map
+                .appearances
+                .push(Appearance { point_index, next: *first_appearance });
+            *first_appearance = Some(appearance_index);
         }
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index b8e35f882ec..84fb36dd32a 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -39,8 +39,8 @@ pub(super) fn generate<'a, 'tcx>(
 
     let free_regions = regions_that_outlive_free_regions(
         typeck.infcx.num_region_vars(),
-        typeck.borrowck_context.universal_regions,
-        &typeck.borrowck_context.constraints.outlives_constraints,
+        typeck.universal_regions,
+        &typeck.constraints.outlives_constraints,
     );
     let (relevant_live_locals, boring_locals) =
         compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
@@ -59,11 +59,7 @@ pub(super) fn generate<'a, 'tcx>(
 
     // Mark regions that should be live where they appear within rvalues or within a call: like
     // args, regions, and types.
-    record_regular_live_regions(
-        typeck.tcx(),
-        &mut typeck.borrowck_context.constraints.liveness_constraints,
-        body,
-    );
+    record_regular_live_regions(typeck.tcx(), &mut typeck.constraints.liveness_constraints, body);
 }
 
 // The purpose of `compute_relevant_live_locals` is to define the subset of `Local`
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
index 3a458731f28..e8d8ae0850b 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
@@ -88,9 +88,9 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
     body: &Body<'tcx>,
     move_data: &MoveData<'tcx>,
 ) {
-    if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
+    if let Some(facts) = typeck.all_facts.as_mut() {
         debug!("populate_access_facts()");
-        let location_table = typeck.borrowck_context.location_table;
+        let location_table = typeck.location_table;
 
         let mut extractor = UseFactsExtractor {
             var_defined_at: &mut facts.var_defined_at,
@@ -108,7 +108,7 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
                 local, local_decl.ty
             );
             let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
-            let universal_regions = &typeck.borrowck_context.universal_regions;
+            let universal_regions = &typeck.universal_regions;
             typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
                 let region_vid = universal_regions.to_region_vid(region);
                 facts.use_of_var_derefs_origin.push((local, region_vid.into()));
@@ -125,9 +125,9 @@ pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
     kind: &GenericArg<'tcx>,
 ) {
     debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind);
-    if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
+    if let Some(facts) = typeck.all_facts.as_mut() {
         let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
-        let universal_regions = &typeck.borrowck_context.universal_regions;
+        let universal_regions = &typeck.universal_regions;
         typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
             let region_vid = universal_regions.to_region_vid(drop_live_region);
             facts.drop_of_var_derefs_origin.push((local, region_vid.into()));
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 35963228181..72f6a605279 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -47,13 +47,12 @@ pub(super) fn trace<'a, 'tcx>(
 
     // When using `-Zpolonius=next`, compute the set of loans that can reach a given region.
     if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() {
-        let borrowck_context = &mut typeck.borrowck_context;
-        let borrow_set = &borrowck_context.borrow_set;
+        let borrow_set = &typeck.borrow_set;
         let mut live_loans = LiveLoans::new(borrow_set.len());
-        let outlives_constraints = &borrowck_context.constraints.outlives_constraints;
+        let outlives_constraints = &typeck.constraints.outlives_constraints;
         let graph = outlives_constraints.graph(typeck.infcx.num_region_vars());
         let region_graph =
-            graph.region_graph(outlives_constraints, borrowck_context.universal_regions.fr_static);
+            graph.region_graph(outlives_constraints, typeck.universal_regions.fr_static);
 
         // Traverse each issuing region's constraints, and record the loan as flowing into the
         // outlived region.
@@ -73,7 +72,7 @@ pub(super) fn trace<'a, 'tcx>(
 
         // Store the inflowing loans in the liveness constraints: they will be used to compute live
         // loans when liveness data is recorded there.
-        borrowck_context.constraints.liveness_constraints.loans = Some(live_loans);
+        typeck.constraints.liveness_constraints.loans = Some(live_loans);
     };
 
     let cx = LivenessContext {
@@ -222,7 +221,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
         // It may be necessary to just pick out the parts of
         // `add_drop_live_facts_for()` that make sense.
         let facts_to_add: Vec<_> = {
-            let drop_used = &self.cx.typeck.borrowck_context.all_facts.as_ref()?.var_dropped_at;
+            let drop_used = &self.cx.typeck.all_facts.as_ref()?.var_dropped_at;
 
             let relevant_live_locals: FxIndexSet<_> =
                 relevant_live_locals.iter().copied().collect();
@@ -235,12 +234,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
                         return None;
                     }
 
-                    let location = match self
-                        .cx
-                        .typeck
-                        .borrowck_context
-                        .location_table
-                        .to_location(*location_index)
+                    let location = match self.cx.typeck.location_table.to_location(*location_index)
                     {
                         RichLocation::Start(l) => l,
                         RichLocation::Mid(l) => l,
@@ -251,7 +245,8 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
                 .collect()
         };
 
-        // FIXME: these locations seem to have a special meaning (e.g. everywhere, at the end, ...), but I don't know which one. Please help me rename it to something descriptive!
+        // FIXME: these locations seem to have a special meaning (e.g. everywhere, at the end,
+        // ...), but I don't know which one. Please help me rename it to something descriptive!
         // Also, if this IntervalSet is used in many places, it maybe should have a newtype'd
         // name with a description of what it means for future mortals passing by.
         let locations = IntervalSet::new(self.cx.elements.num_points());
@@ -615,13 +610,9 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
             tcx: typeck.tcx(),
             param_env: typeck.param_env,
             op: |r| {
-                let live_region_vid = typeck.borrowck_context.universal_regions.to_region_vid(r);
+                let live_region_vid = typeck.universal_regions.to_region_vid(r);
 
-                typeck
-                    .borrowck_context
-                    .constraints
-                    .liveness_constraints
-                    .add_points(live_region_vid, live_at);
+                typeck.constraints.liveness_constraints.add_points(live_region_vid, live_at);
             },
         });
     }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index dffdfb8ac1d..0fe6a4b5fce 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -156,25 +156,24 @@ pub(crate) fn type_check<'a, 'tcx>(
 
     debug!(?normalized_inputs_and_output);
 
-    let mut borrowck_context = BorrowCheckContext {
+    let mut checker = TypeChecker {
+        infcx,
+        param_env,
+        last_span: body.span,
+        body,
+        user_type_annotations: &body.user_type_annotations,
+        region_bound_pairs: &region_bound_pairs,
+        known_type_outlives_obligations,
+        implicit_region_bound,
+        reported_errors: Default::default(),
         universal_regions: &universal_regions,
         location_table,
-        borrow_set,
         all_facts,
+        borrow_set,
         constraints: &mut constraints,
         upvars,
     };
 
-    let mut checker = TypeChecker::new(
-        infcx,
-        body,
-        param_env,
-        &region_bound_pairs,
-        known_type_outlives_obligations,
-        implicit_region_bound,
-        &mut borrowck_context,
-    );
-
     checker.check_user_type_annotations();
 
     let mut verifier = TypeVerifier::new(&mut checker, promoted);
@@ -221,13 +220,12 @@ pub(crate) fn type_check<'a, 'tcx>(
                 infcx.tcx.fold_regions((opaque_type_key, hidden_type), |region, _| {
                     match region.kind() {
                         ty::ReVar(_) => region,
-                        ty::RePlaceholder(placeholder) => checker
-                            .borrowck_context
-                            .constraints
-                            .placeholder_region(infcx, placeholder),
+                        ty::RePlaceholder(placeholder) => {
+                            checker.constraints.placeholder_region(infcx, placeholder)
+                        }
                         _ => ty::Region::new_var(
                             infcx.tcx,
-                            checker.borrowck_context.universal_regions.to_region_vid(region),
+                            checker.universal_regions.to_region_vid(region),
                         ),
                     }
                 });
@@ -240,25 +238,26 @@ pub(crate) fn type_check<'a, 'tcx>(
 }
 
 fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
-    let cx = &mut typeck.borrowck_context;
-    if let Some(facts) = cx.all_facts {
+    if let Some(facts) = typeck.all_facts {
         let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
-        let location_table = cx.location_table;
-        facts.subset_base.extend(cx.constraints.outlives_constraints.outlives().iter().flat_map(
-            |constraint: &OutlivesConstraint<'_>| {
-                if let Some(from_location) = constraint.locations.from_location() {
-                    Either::Left(iter::once((
-                        constraint.sup.into(),
-                        constraint.sub.into(),
-                        location_table.mid_index(from_location),
-                    )))
-                } else {
-                    Either::Right(location_table.all_points().map(move |location| {
-                        (constraint.sup.into(), constraint.sub.into(), location)
-                    }))
-                }
-            },
-        ));
+        let location_table = typeck.location_table;
+        facts.subset_base.extend(
+            typeck.constraints.outlives_constraints.outlives().iter().flat_map(
+                |constraint: &OutlivesConstraint<'_>| {
+                    if let Some(from_location) = constraint.locations.from_location() {
+                        Either::Left(iter::once((
+                            constraint.sup.into(),
+                            constraint.sub.into(),
+                            location_table.mid_index(from_location),
+                        )))
+                    } else {
+                        Either::Right(location_table.all_points().map(move |location| {
+                            (constraint.sup.into(), constraint.sub.into(), location)
+                        }))
+                    }
+                },
+            ),
+        );
     }
 }
 
@@ -303,13 +302,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
         let ty = self.sanitize_type(constant, constant.const_.ty());
 
         self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
-            let live_region_vid =
-                self.cx.borrowck_context.universal_regions.to_region_vid(live_region);
-            self.cx
-                .borrowck_context
-                .constraints
-                .liveness_constraints
-                .add_location(live_region_vid, location);
+            let live_region_vid = self.cx.universal_regions.to_region_vid(live_region);
+            self.cx.constraints.liveness_constraints.add_location(live_region_vid, location);
         });
 
         // HACK(compiler-errors): Constants that are gathered into Body.required_consts
@@ -561,15 +555,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         // Don't try to add borrow_region facts for the promoted MIR
 
         let mut swap_constraints = |this: &mut Self| {
-            mem::swap(this.cx.borrowck_context.all_facts, all_facts);
-            mem::swap(
-                &mut this.cx.borrowck_context.constraints.outlives_constraints,
-                &mut constraints,
-            );
-            mem::swap(
-                &mut this.cx.borrowck_context.constraints.liveness_constraints,
-                &mut liveness_constraints,
-            );
+            mem::swap(this.cx.all_facts, all_facts);
+            mem::swap(&mut this.cx.constraints.outlives_constraints, &mut constraints);
+            mem::swap(&mut this.cx.constraints.liveness_constraints, &mut liveness_constraints);
         };
 
         swap_constraints(self);
@@ -594,7 +582,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 // temporary from the user's point of view.
                 constraint.category = ConstraintCategory::Boring;
             }
-            self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
+            self.cx.constraints.outlives_constraints.push(constraint)
         }
         // If the region is live at least one location in the promoted MIR,
         // then add a liveness constraint to the main MIR for this region
@@ -604,11 +592,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         // unordered.
         #[allow(rustc::potential_query_instability)]
         for region in liveness_constraints.live_regions_unordered() {
-            self.cx
-                .borrowck_context
-                .constraints
-                .liveness_constraints
-                .add_location(region, location);
+            self.cx.constraints.liveness_constraints.add_location(region, location);
         }
     }
 
@@ -863,15 +847,11 @@ struct TypeChecker<'a, 'tcx> {
     known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
     implicit_region_bound: ty::Region<'tcx>,
     reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
-    borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
-}
-
-struct BorrowCheckContext<'a, 'tcx> {
-    pub(crate) universal_regions: &'a UniversalRegions<'tcx>,
+    universal_regions: &'a UniversalRegions<'tcx>,
     location_table: &'a LocationTable,
     all_facts: &'a mut Option<AllFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
-    pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
+    constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
     upvars: &'a [&'a ty::CapturedPlace<'tcx>],
 }
 
@@ -1006,29 +986,6 @@ impl Locations {
 }
 
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
-    fn new(
-        infcx: &'a BorrowckInferCtxt<'tcx>,
-        body: &'a Body<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        region_bound_pairs: &'a RegionBoundPairs<'tcx>,
-        known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
-        implicit_region_bound: ty::Region<'tcx>,
-        borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
-    ) -> Self {
-        Self {
-            infcx,
-            last_span: body.span,
-            body,
-            user_type_annotations: &body.user_type_annotations,
-            param_env,
-            region_bound_pairs,
-            known_type_outlives_obligations,
-            implicit_region_bound,
-            borrowck_context,
-            reported_errors: Default::default(),
-        }
-    }
-
     fn body(&self) -> &Body<'tcx> {
         self.body
     }
@@ -1067,7 +1024,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         constraint_conversion::ConstraintConversion::new(
             self.infcx,
-            self.borrowck_context.universal_regions,
+            self.universal_regions,
             self.region_bound_pairs,
             self.implicit_region_bound,
             self.param_env,
@@ -1075,7 +1032,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             locations,
             locations.span(self.body),
             category,
-            self.borrowck_context.constraints,
+            self.constraints,
         )
         .convert_all(data);
     }
@@ -1191,7 +1148,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 // though.
                 let category = match place.as_local() {
                     Some(RETURN_PLACE) => {
-                        let defining_ty = &self.borrowck_context.universal_regions.defining_ty;
+                        let defining_ty = &self.universal_regions.defining_ty;
                         if defining_ty.is_const() {
                             if tcx.is_static(defining_ty.def_id()) {
                                 ConstraintCategory::UseAsStatic
@@ -1375,9 +1332,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                     let region_ctxt_fn = || {
                         let reg_info = match br.kind {
-                            ty::BoundRegionKind::BrAnon => sym::anon,
-                            ty::BoundRegionKind::BrNamed(_, name) => name,
-                            ty::BoundRegionKind::BrEnv => sym::env,
+                            ty::BoundRegionKind::Anon => sym::anon,
+                            ty::BoundRegionKind::Named(_, name) => name,
+                            ty::BoundRegionKind::ClosureEnv => sym::env,
                         };
 
                         RegionCtxt::LateBound(reg_info)
@@ -1439,12 +1396,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 // output) types in the signature must be live, since
                 // all the inputs that fed into it were live.
                 for &late_bound_region in map.values() {
-                    let region_vid =
-                        self.borrowck_context.universal_regions.to_region_vid(late_bound_region);
-                    self.borrowck_context
-                        .constraints
-                        .liveness_constraints
-                        .add_location(region_vid, term_location);
+                    let region_vid = self.universal_regions.to_region_vid(late_bound_region);
+                    self.constraints.liveness_constraints.add_location(region_vid, term_location);
                 }
 
                 self.check_call_inputs(body, term, func, &sig, args, term_location, call_source);
@@ -1532,18 +1485,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 let dest_ty = self.normalize(dest_ty, term_location);
                 let category = match destination.as_local() {
                     Some(RETURN_PLACE) => {
-                        if let BorrowCheckContext {
-                            universal_regions:
-                                UniversalRegions {
-                                    defining_ty:
-                                        DefiningTy::Const(def_id, _)
-                                        | DefiningTy::InlineConst(def_id, _),
-                                    ..
-                                },
-                            ..
-                        } = self.borrowck_context
+                        if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
+                            self.universal_regions.defining_ty
                         {
-                            if tcx.is_static(*def_id) {
+                            if tcx.is_static(def_id) {
                                 ConstraintCategory::UseAsStatic
                             } else {
                                 ConstraintCategory::UseAsConst
@@ -1606,9 +1551,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         let func_ty = func.ty(body, self.infcx.tcx);
         if let ty::FnDef(def_id, _) = *func_ty.kind() {
-            // Some of the SIMD intrinsics are special: they need a particular argument to be a constant.
-            // (Eventually this should use const-generics, but those are not up for the task yet:
-            // https://github.com/rust-lang/rust/issues/85229.)
+            // Some of the SIMD intrinsics are special: they need a particular argument to be a
+            // constant. (Eventually this should use const-generics, but those are not up for the
+            // task yet: https://github.com/rust-lang/rust/issues/85229.)
             if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
                 self.tcx().intrinsic(def_id).map(|i| i.name)
             {
@@ -1921,7 +1866,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 if len.try_to_target_usize(tcx).is_none_or(|len| len > 1) {
                     match operand {
                         Operand::Copy(..) | Operand::Constant(..) => {
-                            // These are always okay: direct use of a const, or a value that can evidently be copied.
+                            // These are always okay: direct use of a const, or a value that can
+                            // evidently be copied.
                         }
                         Operand::Move(place) => {
                             // Make sure that repeated elements implement `Copy`.
@@ -2402,9 +2348,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 let dst_tail = self.struct_tail(dst.ty, location);
 
                                 // This checks (lifetime part of) vtable validity for pointer casts,
-                                // which is irrelevant when there are aren't principal traits on both sides (aka only auto traits).
+                                // which is irrelevant when there are aren't principal traits on
+                                // both sides (aka only auto traits).
                                 //
-                                // Note that other checks (such as denying `dyn Send` -> `dyn Debug`) are in `rustc_hir_typeck`.
+                                // Note that other checks (such as denying `dyn Send` -> `dyn
+                                // Debug`) are in `rustc_hir_typeck`.
                                 if let ty::Dynamic(src_tty, ..) = src_tail.kind()
                                     && let ty::Dynamic(dst_tty, ..) = dst_tail.kind()
                                     && src_tty.principal().is_some()
@@ -2427,8 +2375,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                         ty::Dyn,
                                     ));
 
-                                    // Replace trait object lifetimes with fresh vars, to allow casts like
-                                    // `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static`,
+                                    // Replace trait object lifetimes with fresh vars, to allow
+                                    // casts like
+                                    // `*mut dyn FnOnce() + 'a` -> `*mut dyn FnOnce() + 'static`
                                     let src_obj =
                                         freshen_single_trait_object_lifetime(self.infcx, src_obj);
                                     let dst_obj =
@@ -2650,8 +2599,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         borrowed_place: &Place<'tcx>,
     ) {
         // These constraints are only meaningful during borrowck:
-        let BorrowCheckContext { borrow_set, location_table, all_facts, constraints, .. } =
-            self.borrowck_context;
+        let Self { borrow_set, location_table, all_facts, constraints, .. } = self;
 
         // In Polonius mode, we also push a `loan_issued_at` fact
         // linking the loan to the region (in some cases, though,
@@ -2681,12 +2629,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
 
         let tcx = self.infcx.tcx;
-        let field = path_utils::is_upvar_field_projection(
-            tcx,
-            self.borrowck_context.upvars,
-            borrowed_place.as_ref(),
-            body,
-        );
+        let field =
+            path_utils::is_upvar_field_projection(tcx, self.upvars, borrowed_place.as_ref(), body);
         let category = if let Some(field) = field {
             ConstraintCategory::ClosureUpvar(field)
         } else {
@@ -2840,7 +2784,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx,
-                self.borrowck_context.universal_regions,
+                self.universal_regions,
                 self.region_bound_pairs,
                 self.implicit_region_bound,
                 self.param_env,
@@ -2848,7 +2792,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 locations,
                 self.body.span,             // irrelevant; will be overridden.
                 ConstraintCategory::Boring, // same as above.
-                self.borrowck_context.constraints,
+                self.constraints,
             )
             .apply_closure_requirements(closure_requirements, def_id.to_def_id(), args);
         }
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index cfc14d146bd..e2f3e065bc0 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -240,11 +240,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
 
     fn create_next_universe(&mut self) -> ty::UniverseIndex {
         let universe = self.type_checker.infcx.create_next_universe();
-        self.type_checker
-            .borrowck_context
-            .constraints
-            .universe_causes
-            .insert(universe, self.universe_info.clone());
+        self.type_checker.constraints.universe_causes.insert(universe, self.universe_info.clone());
         universe
     }
 
@@ -264,16 +260,13 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
-        let reg = self
-            .type_checker
-            .borrowck_context
-            .constraints
-            .placeholder_region(self.type_checker.infcx, placeholder);
+        let reg =
+            self.type_checker.constraints.placeholder_region(self.type_checker.infcx, placeholder);
 
         let reg_info = match placeholder.bound.kind {
-            ty::BoundRegionKind::BrAnon => sym::anon,
-            ty::BoundRegionKind::BrNamed(_, name) => name,
-            ty::BoundRegionKind::BrEnv => sym::env,
+            ty::BoundRegionKind::Anon => sym::anon,
+            ty::BoundRegionKind::Named(_, name) => name,
+            ty::BoundRegionKind::ClosureEnv => sym::env,
         };
 
         if cfg!(debug_assertions) {
@@ -294,19 +287,17 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
         sub: ty::Region<'tcx>,
         info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
     ) {
-        let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub);
-        let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup);
-        self.type_checker.borrowck_context.constraints.outlives_constraints.push(
-            OutlivesConstraint {
-                sup,
-                sub,
-                locations: self.locations,
-                span: self.locations.span(self.type_checker.body),
-                category: self.category,
-                variance_info: info,
-                from_closure: false,
-            },
-        );
+        let sub = self.type_checker.universal_regions.to_region_vid(sub);
+        let sup = self.type_checker.universal_regions.to_region_vid(sup);
+        self.type_checker.constraints.outlives_constraints.push(OutlivesConstraint {
+            sup,
+            sub,
+            locations: self.locations,
+            span: self.locations.span(self.type_checker.body),
+            category: self.category,
+            variance_info: info,
+            from_closure: false,
+        });
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index fa44ffcd17d..b63144f560f 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -696,14 +696,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                 let closure_sig = args.as_closure().sig();
                 let inputs_and_output = closure_sig.inputs_and_output();
                 let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
-                    inputs_and_output
-                        .bound_vars()
-                        .iter()
-                        .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
+                    inputs_and_output.bound_vars().iter().chain(iter::once(
+                        ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
+                    )),
                 );
                 let br = ty::BoundRegion {
                     var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                    kind: ty::BrEnv,
+                    kind: ty::BoundRegionKind::ClosureEnv,
                 };
                 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
                 let closure_ty = tcx.closure_env_ty(
@@ -751,15 +750,13 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
             DefiningTy::CoroutineClosure(def_id, args) => {
                 assert_eq!(self.mir_def.to_def_id(), def_id);
                 let closure_sig = args.as_coroutine_closure().coroutine_closure_sig();
-                let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
-                    closure_sig
-                        .bound_vars()
-                        .iter()
-                        .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
-                );
+                let bound_vars =
+                    tcx.mk_bound_variable_kinds_from_iter(closure_sig.bound_vars().iter().chain(
+                        iter::once(ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv)),
+                    ));
                 let br = ty::BoundRegion {
                     var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                    kind: ty::BrEnv,
+                    kind: ty::BoundRegionKind::ClosureEnv,
                 };
                 let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
                 let closure_kind = args.as_coroutine_closure().kind();
diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl
index bbae59ea7a5..26ddc5732dd 100644
--- a/compiler/rustc_codegen_gcc/messages.ftl
+++ b/compiler/rustc_codegen_gcc/messages.ftl
@@ -8,6 +8,9 @@ codegen_gcc_invalid_minimum_alignment =
 codegen_gcc_lto_not_supported =
     LTO is not supported. You may get a linker error.
 
+codegen_gcc_forbidden_ctarget_feature =
+    target feature `{$feature}` cannot be toggled with `-Ctarget-feature`
+
 codegen_gcc_unwinding_inline_asm =
     GCC backend does not support unwinding from inline asm
 
@@ -24,11 +27,15 @@ codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdyl
 codegen_gcc_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$gcc_err})
 
 codegen_gcc_unknown_ctarget_feature =
-    unknown feature specified for `-Ctarget-feature`: `{$feature}`
-    .note = it is still passed through to the codegen backend
+    unknown and unstable feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future
     .possible_feature = you might have meant: `{$rust_feature}`
     .consider_filing_feature_request = consider filing a feature request
 
+codegen_gcc_unstable_ctarget_feature =
+    unstable feature specified for `-Ctarget-feature`: `{$feature}`
+    .note = this feature is not stably supported; its behavior can change in the future
+
 codegen_gcc_missing_features =
     add the missing features in a `target_feature` attribute
 
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index a04cd4735f4..b44d4aa8cc8 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -654,7 +654,8 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
-            | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
+            | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
+            | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
                 unreachable!("clobber-only")
             }
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
@@ -729,7 +730,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
-        | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
+        | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer)
+        | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vreg) => {
             unreachable!("clobber-only")
         }
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 660badb6a50..07c7a54de1c 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -146,7 +146,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
 
         // Wasm statics with custom link sections get special treatment as they
         // go into custom sections of the wasm executable.
-        if self.tcx.sess.opts.target_triple.tuple().starts_with("wasm32") {
+        if self.tcx.sess.target.is_like_wasm {
             if let Some(_section) = attrs.link_section {
                 unimplemented!();
             }
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index dc1895f437b..7a586b5b04c 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -17,6 +17,19 @@ pub(crate) struct UnknownCTargetFeature<'a> {
     pub rust_feature: PossibleFeature<'a>,
 }
 
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_unstable_ctarget_feature)]
+#[note]
+pub(crate) struct UnstableCTargetFeature<'a> {
+    pub feature: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_forbidden_ctarget_feature)]
+pub(crate) struct ForbiddenCTargetFeature<'a> {
+    pub feature: &'a str,
+}
+
 #[derive(Subdiagnostic)]
 pub(crate) enum PossibleFeature<'a> {
     #[help(codegen_gcc_possible_feature)]
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index 3104088e0d5..65279c9495a 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -5,10 +5,13 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::bug;
 use rustc_session::Session;
-use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
+use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability};
 use smallvec::{SmallVec, smallvec};
 
-use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix};
+use crate::errors::{
+    ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix,
+    UnstableCTargetFeature,
+};
 
 /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
 /// `--target` and similar).
@@ -43,7 +46,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
     );
 
     // -Ctarget-features
-    let supported_features = sess.target.supported_target_features();
+    let known_features = sess.target.rust_target_features();
     let mut featsmap = FxHashMap::default();
     let feats = sess
         .opts
@@ -62,37 +65,49 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
                 }
             };
 
+            // Get the backend feature name, if any.
+            // This excludes rustc-specific features, that do not get passed down to GCC.
             let feature = backend_feature_name(s)?;
             // Warn against use of GCC specific feature names on the CLI.
-            if diagnostics && !supported_features.iter().any(|&(v, _, _)| v == feature) {
-                let rust_feature = supported_features.iter().find_map(|&(rust_feature, _, _)| {
-                    let gcc_features = to_gcc_features(sess, rust_feature);
-                    if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) {
-                        Some(rust_feature)
-                    } else {
-                        None
+            if diagnostics {
+                let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature);
+                match feature_state {
+                    None => {
+                        let rust_feature =
+                            known_features.iter().find_map(|&(rust_feature, _, _)| {
+                                let gcc_features = to_gcc_features(sess, rust_feature);
+                                if gcc_features.contains(&feature)
+                                    && !gcc_features.contains(&rust_feature)
+                                {
+                                    Some(rust_feature)
+                                } else {
+                                    None
+                                }
+                            });
+                        let unknown_feature = if let Some(rust_feature) = rust_feature {
+                            UnknownCTargetFeature {
+                                feature,
+                                rust_feature: PossibleFeature::Some { rust_feature },
+                            }
+                        } else {
+                            UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
+                        };
+                        sess.dcx().emit_warn(unknown_feature);
                     }
-                });
-                let unknown_feature = if let Some(rust_feature) = rust_feature {
-                    UnknownCTargetFeature {
-                        feature,
-                        rust_feature: PossibleFeature::Some { rust_feature },
+                    Some((_, Stability::Stable, _)) => {}
+                    Some((_, Stability::Unstable(_), _)) => {
+                        // An unstable feature. Warn about using it.
+                        sess.dcx().emit_warn(UnstableCTargetFeature { feature });
                     }
-                } else {
-                    UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
-                };
-                sess.dcx().emit_warn(unknown_feature);
-            }
+                    Some((_, Stability::Forbidden { .. }, _)) => {
+                        sess.dcx().emit_err(ForbiddenCTargetFeature { feature });
+                    }
+                }
 
-            if diagnostics {
                 // FIXME(nagisa): figure out how to not allocate a full hashset here.
                 featsmap.insert(feature, enable_disable == '+');
             }
 
-            // rustc-specific features do not get passed down to GCC…
-            if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
-                return None;
-            }
             // ... otherwise though we run through `to_gcc_features` when
             // passing requests down to GCC. This means that all in-language
             // features also work on the command line instead of having two
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 7486eefeb85..f70dc94b267 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -491,8 +491,9 @@ pub fn target_features(
 ) -> Vec<Symbol> {
     // TODO(antoyo): use global_gcc_features.
     sess.target
-        .supported_target_features()
+        .rust_target_features()
         .iter()
+        .filter(|(_, gate, _)| gate.is_supported())
         .filter_map(|&(feature, gate, _)| {
             if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
                 Some(feature)
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index 0950e4bb26b..63c64269eb8 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -7,6 +7,11 @@ codegen_llvm_dynamic_linking_with_lto =
 
 codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
 
+codegen_llvm_forbidden_ctarget_feature =
+    target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason}
+    .note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+codegen_llvm_forbidden_ctarget_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
+
 codegen_llvm_from_llvm_diag = {$message}
 
 codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 21df60a4a7b..a1ccf0d1719 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -638,7 +638,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
             PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
             PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
             PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
-            PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
+            PowerPC(PowerPCInlineAsmRegClass::cr)
+            | PowerPC(PowerPCInlineAsmRegClass::xer)
+            | PowerPC(PowerPCInlineAsmRegClass::vreg) => {
                 unreachable!("clobber-only")
             }
             RiscV(RiscVInlineAsmRegClass::reg) => "r",
@@ -800,7 +802,9 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
         PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
         PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
         PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
-        PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
+        PowerPC(PowerPCInlineAsmRegClass::cr)
+        | PowerPC(PowerPCInlineAsmRegClass::xer)
+        | PowerPC(PowerPCInlineAsmRegClass::vreg) => {
             unreachable!("clobber-only")
         }
         RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 64bb22e8cb2..cb958c1d4d7 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -419,7 +419,10 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
                 if bti {
                     to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
                 }
-                if let Some(PacRet { leaf, key }) = pac_ret {
+                if let Some(PacRet { leaf, pc, key }) = pac_ret {
+                    if pc {
+                        to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr"));
+                    }
                     to_add.push(llvm::CreateAttrStringValue(
                         cx.llcx,
                         "sign-return-address",
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 647e9e13fbc..a65ae4df1e3 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -945,23 +945,10 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data:
     asm
 }
 
-fn target_is_apple(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
-    let triple = cgcx.opts.target_triple.tuple();
-    triple.contains("-ios")
-        || triple.contains("-darwin")
-        || triple.contains("-tvos")
-        || triple.contains("-watchos")
-        || triple.contains("-visionos")
-}
-
-fn target_is_aix(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
-    cgcx.opts.target_triple.tuple().contains("-aix")
-}
-
 pub(crate) fn bitcode_section_name(cgcx: &CodegenContext<LlvmCodegenBackend>) -> &'static CStr {
-    if target_is_apple(cgcx) {
+    if cgcx.target_is_like_osx {
         c"__LLVM,__bitcode"
-    } else if target_is_aix(cgcx) {
+    } else if cgcx.target_is_like_aix {
         c".ipa"
     } else {
         c".llvmbc"
@@ -1028,10 +1015,12 @@ unsafe fn embed_bitcode(
     // Unfortunately, LLVM provides no way to set custom section flags. For ELF
     // and COFF we emit the sections using module level inline assembly for that
     // reason (see issue #90326 for historical background).
-    let is_aix = target_is_aix(cgcx);
-    let is_apple = target_is_apple(cgcx);
     unsafe {
-        if is_apple || is_aix || cgcx.opts.target_triple.tuple().starts_with("wasm") {
+        if cgcx.target_is_like_osx
+            || cgcx.target_is_like_aix
+            || cgcx.target_arch == "wasm32"
+            || cgcx.target_arch == "wasm64"
+        {
             // We don't need custom section flags, create LLVM globals.
             let llconst = common::bytes_in_context(llcx, bitcode);
             let llglobal = llvm::LLVMAddGlobal(
@@ -1052,9 +1041,9 @@ unsafe fn embed_bitcode(
                 c"rustc.embedded.cmdline".as_ptr(),
             );
             llvm::LLVMSetInitializer(llglobal, llconst);
-            let section = if is_apple {
+            let section = if cgcx.target_is_like_osx {
                 c"__LLVM,__cmdline"
-            } else if is_aix {
+            } else if cgcx.target_is_like_aix {
                 c".info"
             } else {
                 c".llvmcmd"
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 6838a6f9779..b7ab5d6d5f0 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -308,7 +308,13 @@ pub(crate) unsafe fn create_module<'ll>(
                 "sign-return-address",
                 pac_ret.is_some().into(),
             );
-            let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
+            let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, pc: false, key: PAuthKey::A });
+            llvm::add_module_flag_u32(
+                llmod,
+                llvm::ModuleFlagMergeBehavior::Min,
+                "branch-protection-pauth-lr",
+                pac_opts.pc.into(),
+            );
             llvm::add_module_flag_u32(
                 llmod,
                 llvm::ModuleFlagMergeBehavior::Min,
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 0d436e1891e..3cdb5b971d9 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -31,6 +31,15 @@ pub(crate) struct UnstableCTargetFeature<'a> {
     pub feature: &'a str,
 }
 
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_forbidden_ctarget_feature)]
+#[note]
+#[note(codegen_llvm_forbidden_ctarget_feature_issue)]
+pub(crate) struct ForbiddenCTargetFeature<'a> {
+    pub feature: &'a str,
+    pub reason: &'a str,
+}
+
 #[derive(Subdiagnostic)]
 pub(crate) enum PossibleFeature<'a> {
     #[help(codegen_llvm_possible_feature)]
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 5b0a42d4532..6f2d86cc601 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -17,12 +17,12 @@ use rustc_session::Session;
 use rustc_session::config::{PrintKind, PrintRequest};
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
-use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
+use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES, Stability};
 
 use crate::back::write::create_informational_target_machine;
 use crate::errors::{
-    FixedX18InvalidArch, InvalidTargetFeaturePrefix, PossibleFeature, UnknownCTargetFeature,
-    UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
+    FixedX18InvalidArch, ForbiddenCTargetFeature, InvalidTargetFeaturePrefix, PossibleFeature,
+    UnknownCTargetFeature, UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
 };
 use crate::llvm;
 
@@ -277,23 +277,36 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         ("x86", s) if s.starts_with("avx512") => {
             Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")))
         }
+        // Support for `wide-arithmetic` will first land in LLVM 20 as part of
+        // llvm/llvm-project#111598
+        ("wasm32" | "wasm64", "wide-arithmetic") if get_version() < (20, 0, 0) => None,
         (_, s) => Some(LLVMFeature::new(s)),
     }
 }
 
-/// Used to generate cfg variables and apply features
-/// Must express features in the way Rust understands them
+/// Used to generate cfg variables and apply features.
+/// Must express features in the way Rust understands them.
+///
+/// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
 pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
-    let mut features = vec![];
-
-    // Add base features for the target
+    let mut features: FxHashSet<Symbol> = Default::default();
+
+    // Add base features for the target.
+    // We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below.
+    // The reason is that if LLVM considers a feature implied but we do not, we don't want that to
+    // show up in `cfg`. That way, `cfg` is entirely under our control -- except for the handling of
+    // the target CPU, that is still expanded to target features (with all their implied features) by
+    // LLVM.
     let target_machine = create_informational_target_machine(sess, true);
+    // Compute which of the known target features are enabled in the 'base' target machine.
+    // We only consider "supported" features; "forbidden" features are not reflected in `cfg` as of now.
     features.extend(
         sess.target
-            .supported_target_features()
+            .rust_target_features()
             .iter()
+            .filter(|(_, gate, _)| gate.is_supported())
             .filter(|(feature, _, _)| {
-                // skip checking special features, as LLVM may not understands them
+                // skip checking special features, as LLVM may not understand them
                 if RUSTC_SPECIAL_FEATURES.contains(feature) {
                     return true;
                 }
@@ -324,7 +337,12 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
         if enabled {
             features.extend(sess.target.implied_target_features(std::iter::once(feature)));
         } else {
+            // We don't care about the order in `features` since the only thing we use it for is the
+            // `features.contains` below.
+            #[allow(rustc::potential_query_instability)]
             features.retain(|f| {
+                // Keep a feature if it does not imply `feature`. Or, equivalently,
+                // remove the reverse-dependencies of `feature`.
                 !sess.target.implied_target_features(std::iter::once(*f)).contains(&feature)
             });
         }
@@ -332,8 +350,9 @@ pub fn target_features(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
 
     // Filter enabled features based on feature gates
     sess.target
-        .supported_target_features()
+        .rust_target_features()
         .iter()
+        .filter(|(_, gate, _)| gate.is_supported())
         .filter_map(|&(feature, gate, _)| {
             if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
                 Some(feature)
@@ -451,9 +470,13 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine, out: &mut Str
     let mut known_llvm_target_features = FxHashSet::<&'static str>::default();
     let mut rustc_target_features = sess
         .target
-        .supported_target_features()
+        .rust_target_features()
         .iter()
-        .filter_map(|(feature, _gate, _implied)| {
+        .filter_map(|(feature, gate, _implied)| {
+            if !gate.is_supported() {
+                // Only list (experimentally) supported features.
+                return None;
+            }
             // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these
             // strings.
             let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name;
@@ -605,7 +628,7 @@ pub(crate) fn global_llvm_features(
 
     // -Ctarget-features
     if !only_base_features {
-        let supported_features = sess.target.supported_target_features();
+        let known_features = sess.target.rust_target_features();
         let mut featsmap = FxHashMap::default();
 
         // insert implied features
@@ -639,50 +662,53 @@ pub(crate) fn global_llvm_features(
                     }
                 };
 
+                // Get the backend feature name, if any.
+                // This excludes rustc-specific features, which do not get passed to LLVM.
                 let feature = backend_feature_name(sess, s)?;
                 // Warn against use of LLVM specific feature names and unstable features on the CLI.
                 if diagnostics {
-                    let feature_state = supported_features.iter().find(|&&(v, _, _)| v == feature);
-                    if feature_state.is_none() {
-                        let rust_feature =
-                            supported_features.iter().find_map(|&(rust_feature, _, _)| {
-                                let llvm_features = to_llvm_features(sess, rust_feature)?;
-                                if llvm_features.contains(feature)
-                                    && !llvm_features.contains(rust_feature)
-                                {
-                                    Some(rust_feature)
-                                } else {
-                                    None
+                    let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature);
+                    match feature_state {
+                        None => {
+                            let rust_feature =
+                                known_features.iter().find_map(|&(rust_feature, _, _)| {
+                                    let llvm_features = to_llvm_features(sess, rust_feature)?;
+                                    if llvm_features.contains(feature)
+                                        && !llvm_features.contains(rust_feature)
+                                    {
+                                        Some(rust_feature)
+                                    } else {
+                                        None
+                                    }
+                                });
+                            let unknown_feature = if let Some(rust_feature) = rust_feature {
+                                UnknownCTargetFeature {
+                                    feature,
+                                    rust_feature: PossibleFeature::Some { rust_feature },
                                 }
-                            });
-                        let unknown_feature = if let Some(rust_feature) = rust_feature {
-                            UnknownCTargetFeature {
-                                feature,
-                                rust_feature: PossibleFeature::Some { rust_feature },
-                            }
-                        } else {
-                            UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
-                        };
-                        sess.dcx().emit_warn(unknown_feature);
-                    } else if feature_state
-                        .is_some_and(|(_name, feature_gate, _implied)| !feature_gate.is_stable())
-                    {
-                        // An unstable feature. Warn about using it.
-                        sess.dcx().emit_warn(UnstableCTargetFeature { feature });
+                            } else {
+                                UnknownCTargetFeature {
+                                    feature,
+                                    rust_feature: PossibleFeature::None,
+                                }
+                            };
+                            sess.dcx().emit_warn(unknown_feature);
+                        }
+                        Some((_, Stability::Stable, _)) => {}
+                        Some((_, Stability::Unstable(_), _)) => {
+                            // An unstable feature. Warn about using it.
+                            sess.dcx().emit_warn(UnstableCTargetFeature { feature });
+                        }
+                        Some((_, Stability::Forbidden { reason }, _)) => {
+                            sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason });
+                        }
                     }
-                }
 
-                if diagnostics {
                     // FIXME(nagisa): figure out how to not allocate a full hashset here.
                     featsmap.insert(feature, enable_disable == '+');
                 }
 
-                // rustc-specific features do not get passed down to LLVM…
-                if RUSTC_SPECIFIC_FEATURES.contains(&feature) {
-                    return None;
-                }
-
-                // ... otherwise though we run through `to_llvm_features` when
+                // We run through `to_llvm_features` when
                 // passing requests down to LLVM. This means that all in-language
                 // features also work on the command line instead of having two
                 // different names when the LLVM name and the Rust name differ.
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 3b34eb063ec..62db3d5a98c 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -2,6 +2,8 @@ codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not imp
 
 codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error}
 
+codegen_ssa_aix_strip_not_used = using host's `strip` binary to cross-compile to AIX which is not guaranteed to work
+
 codegen_ssa_apple_deployment_target_invalid =
     failed to parse deployment target specified in {$env_var}: {$error}
 
@@ -64,6 +66,9 @@ codegen_ssa_failed_to_write = failed to write {$path}: {$error}
 
 codegen_ssa_field_associated_value_expected = associated value expected for `{$name}`
 
+codegen_ssa_forbidden_target_feature_attr =
+    target feature `{$feature}` cannot be toggled with `#[target_feature]`: {$reason}
+
 codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced
 
 codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 20920d16f3c..44581cfa64b 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -85,11 +85,7 @@ pub fn link_binary(
         }
 
         if invalid_output_for_target(sess, crate_type) {
-            bug!(
-                "invalid output type `{:?}` for target os `{}`",
-                crate_type,
-                sess.opts.target_triple
-            );
+            bug!("invalid output type `{:?}` for target `{}`", crate_type, sess.opts.target_triple);
         }
 
         sess.time("link_binary_check_files_are_writeable", || {
@@ -996,6 +992,7 @@ fn link_natively(
                         && (code < 1000 || code > 9999)
                     {
                         let is_vs_installed = windows_registry::find_vs_version().is_ok();
+                        // FIXME(cc-rs#1265) pass only target arch to find_tool()
                         let has_linker = windows_registry::find_tool(
                             sess.opts.target_triple.tuple(),
                             "link.exe",
@@ -1088,9 +1085,7 @@ fn link_natively(
     let strip = sess.opts.cg.strip;
 
     if sess.target.is_like_osx {
-        // Use system `strip` when running on host macOS.
-        // <https://github.com/rust-lang/rust/pull/130781>
-        let stripcmd = if cfg!(target_os = "macos") { "/usr/bin/strip" } else { "strip" };
+        let stripcmd = "rust-objcopy";
         match (strip, crate_type) {
             (Strip::Debuginfo, _) => {
                 strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-S"))
@@ -1106,11 +1101,14 @@ fn link_natively(
         }
     }
 
-    if sess.target.os == "illumos" {
+    if sess.target.is_like_solaris {
         // Many illumos systems will have both the native 'strip' utility and
         // the GNU one. Use the native version explicitly and do not rely on
         // what's in the path.
-        let stripcmd = "/usr/bin/strip";
+        //
+        // If cross-compiling and there is not a native version, then use
+        // `llvm-strip` and hope.
+        let stripcmd = if !sess.host.is_like_solaris { "rust-objcopy" } else { "/usr/bin/strip" };
         match strip {
             // Always preserve the symbol table (-x).
             Strip::Debuginfo => {
@@ -1123,6 +1121,10 @@ fn link_natively(
     }
 
     if sess.target.is_like_aix {
+        // `llvm-strip` doesn't work for AIX - their strip must be used.
+        if !sess.host.is_like_aix {
+            sess.dcx().emit_warn(errors::AixStripNotUsed);
+        }
         let stripcmd = "/usr/bin/strip";
         match strip {
             Strip::Debuginfo => {
@@ -1150,6 +1152,13 @@ fn strip_symbols_with_external_utility(
     if let Some(option) = option {
         cmd.arg(option);
     }
+
+    let mut new_path = sess.get_tools_search_paths(false);
+    if let Some(path) = env::var_os("PATH") {
+        new_path.extend(env::split_paths(&path));
+    }
+    cmd.env("PATH", env::join_paths(new_path).unwrap());
+
     let prog = cmd.arg(out_filename).output();
     match prog {
         Ok(prog) => {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 3b4429535d4..4f3664a503d 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -47,6 +47,7 @@ pub(crate) fn get_linker<'a>(
     self_contained: bool,
     target_cpu: &'a str,
 ) -> Box<dyn Linker + 'a> {
+    // FIXME(cc-rs#1265) pass only target arch to find_tool()
     let msvc_tool = windows_registry::find_tool(sess.opts.target_triple.tuple(), "link.exe");
 
     // If our linker looks like a batch script on Windows then to execute this
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index dad21bb309f..3f3cb8b4073 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -211,7 +211,15 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         "powerpc64" => (Architecture::PowerPc64, None),
         "riscv32" => (Architecture::Riscv32, None),
         "riscv64" => (Architecture::Riscv64, None),
-        "sparc" => (Architecture::Sparc32Plus, None),
+        "sparc" => {
+            if sess.target.options.cpu == "v9" {
+                // Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode
+                (Architecture::Sparc32Plus, None)
+            } else {
+                // Target uses V7 or V8, aka EM_SPARC
+                (Architecture::Sparc, None)
+            }
+        }
         "sparc64" => (Architecture::Sparc64, None),
         "avr" => (Architecture::Avr, None),
         "msp430" => (Architecture::Msp430, None),
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index d977cca247e..a2285bf9204 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -345,6 +345,8 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub is_pe_coff: bool,
     pub target_can_use_split_dwarf: bool,
     pub target_arch: String,
+    pub target_is_like_osx: bool,
+    pub target_is_like_aix: bool,
     pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
     pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
 
@@ -1195,6 +1197,8 @@ fn start_executing_work<B: ExtraBackendMethods>(
         is_pe_coff: tcx.sess.target.is_like_windows,
         target_can_use_split_dwarf: tcx.sess.target_can_use_split_dwarf(),
         target_arch: tcx.sess.target.arch.to_string(),
+        target_is_like_osx: tcx.sess.target.is_like_osx,
+        target_is_like_aix: tcx.sess.target.is_like_aix,
         split_debuginfo: tcx.sess.split_debuginfo(),
         split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
         parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index a5bd3adbcdd..32e9422e005 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -20,8 +20,8 @@ use rustc_span::symbol::Ident;
 use rustc_span::{Span, sym};
 use rustc_target::spec::{SanitizerSet, abi};
 
-use crate::errors::{self, MissingFeatures, TargetFeatureDisableOrEnable};
-use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature};
+use crate::errors;
+use crate::target_features::{check_target_feature_trait_unsafe, from_target_feature_attr};
 
 fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
     use rustc_middle::mir::mono::Linkage::*;
@@ -73,7 +73,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS;
     }
 
-    let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
+    let rust_target_features = tcx.rust_target_features(LOCAL_CRATE);
 
     let mut inline_span = None;
     let mut link_ordinal_span = None;
@@ -281,10 +281,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                         check_target_feature_trait_unsafe(tcx, did, attr.span);
                     }
                 }
-                from_target_feature(
+                from_target_feature_attr(
                     tcx,
                     attr,
-                    supported_target_features,
+                    rust_target_features,
                     &mut codegen_fn_attrs.target_features,
                 );
             }
@@ -676,10 +676,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
             .next()
             .map_or_else(|| tcx.def_span(did), |a| a.span);
         tcx.dcx()
-            .create_err(TargetFeatureDisableOrEnable {
+            .create_err(errors::TargetFeatureDisableOrEnable {
                 features,
                 span: Some(span),
-                missing_features: Some(MissingFeatures),
+                missing_features: Some(errors::MissingFeatures),
             })
             .emit();
     }
@@ -710,7 +710,7 @@ pub fn check_tied_features(
 /// applied to the method prototype.
 fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     if let Some(impl_item) = tcx.opt_associated_item(def_id)
-        && let ty::AssocItemContainer::ImplContainer = impl_item.container
+        && let ty::AssocItemContainer::Impl = impl_item.container
         && let Some(trait_item) = impl_item.trait_item_def_id
     {
         return tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER);
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index cf8d1cfa0d1..f93cb52ea3e 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -1028,6 +1028,15 @@ pub(crate) struct TargetFeatureSafeTrait {
 }
 
 #[derive(Diagnostic)]
+#[diag(codegen_ssa_forbidden_target_feature_attr)]
+pub struct ForbiddenTargetFeatureAttr<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub feature: &'a str,
+    pub reason: &'a str,
+}
+
+#[derive(Diagnostic)]
 #[diag(codegen_ssa_failed_to_get_layout)]
 pub struct FailedToGetLayout<'tcx> {
     #[primary_span]
@@ -1101,3 +1110,7 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_
         diag
     }
 }
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_aix_strip_not_used)]
+pub(crate) struct AixStripNotUsed;
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 0845bcc5749..eee7cc75400 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -11,13 +11,16 @@ use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_span::Span;
 use rustc_span::symbol::{Symbol, sym};
+use rustc_target::target_features::{self, Stability};
 
 use crate::errors;
 
-pub(crate) fn from_target_feature(
+/// Compute the enabled target features from the `#[target_feature]` function attribute.
+/// Enabled target features are added to `target_features`.
+pub(crate) fn from_target_feature_attr(
     tcx: TyCtxt<'_>,
     attr: &ast::Attribute,
-    supported_target_features: &UnordMap<String, Option<Symbol>>,
+    rust_target_features: &UnordMap<String, target_features::Stability>,
     target_features: &mut Vec<TargetFeature>,
 ) {
     let Some(list) = attr.meta_item_list() else { return };
@@ -46,12 +49,12 @@ pub(crate) fn from_target_feature(
 
         // We allow comma separation to enable multiple features.
         added_target_features.extend(value.as_str().split(',').filter_map(|feature| {
-            let Some(feature_gate) = supported_target_features.get(feature) else {
+            let Some(stability) = rust_target_features.get(feature) else {
                 let msg = format!("the feature named `{feature}` is not valid for this target");
                 let mut err = tcx.dcx().struct_span_err(item.span(), msg);
                 err.span_label(item.span(), format!("`{feature}` is not valid for this target"));
                 if let Some(stripped) = feature.strip_prefix('+') {
-                    let valid = supported_target_features.contains_key(stripped);
+                    let valid = rust_target_features.contains_key(stripped);
                     if valid {
                         err.help("consider removing the leading `+` in the feature name");
                     }
@@ -61,18 +64,31 @@ pub(crate) fn from_target_feature(
             };
 
             // Only allow target features whose feature gates have been enabled.
-            let allowed = match feature_gate.as_ref().copied() {
-                Some(name) => rust_features.enabled(name),
-                None => true,
+            let allowed = match stability {
+                Stability::Forbidden { .. } => false,
+                Stability::Stable => true,
+                Stability::Unstable(name) => rust_features.enabled(*name),
             };
             if !allowed {
-                feature_err(
-                    &tcx.sess,
-                    feature_gate.unwrap(),
-                    item.span(),
-                    format!("the target feature `{feature}` is currently unstable"),
-                )
-                .emit();
+                match stability {
+                    Stability::Stable => unreachable!(),
+                    &Stability::Unstable(lang_feature_name) => {
+                        feature_err(
+                            &tcx.sess,
+                            lang_feature_name,
+                            item.span(),
+                            format!("the target feature `{feature}` is currently unstable"),
+                        )
+                        .emit();
+                    }
+                    Stability::Forbidden { reason } => {
+                        tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
+                            span: item.span(),
+                            feature,
+                            reason,
+                        });
+                    }
+                }
             }
             Some(Symbol::intern(feature))
         }));
@@ -138,20 +154,20 @@ pub(crate) fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId,
 
 pub(crate) fn provide(providers: &mut Providers) {
     *providers = Providers {
-        supported_target_features: |tcx, cnum| {
+        rust_target_features: |tcx, cnum| {
             assert_eq!(cnum, LOCAL_CRATE);
             if tcx.sess.opts.actually_rustdoc {
                 // rustdoc needs to be able to document functions that use all the features, so
                 // whitelist them all
-                rustc_target::target_features::all_known_features()
-                    .map(|(a, b)| (a.to_string(), b.as_feature_name()))
+                rustc_target::target_features::all_rust_features()
+                    .map(|(a, b)| (a.to_string(), b))
                     .collect()
             } else {
                 tcx.sess
                     .target
-                    .supported_target_features()
+                    .rust_target_features()
                     .iter()
-                    .map(|&(a, b, _)| (a.to_string(), b.as_feature_name()))
+                    .map(|&(a, b, _)| (a.to_string(), b))
                     .collect()
             }
         },
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 3e4f83c8242..826e34930ea 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -1,9 +1,6 @@
 const_eval_address_space_full =
     there are no more free addresses in the address space
 
-const_eval_align_offset_invalid_align =
-    `align_offset` called with non-power-of-two align: {$target_align}
-
 const_eval_alignment_check_failed =
     {$msg ->
      [AccessedPtr] accessing memory
@@ -402,7 +399,7 @@ const_eval_uninhabited_enum_variant_written =
 const_eval_unmarked_const_fn_exposed = `{$def_path}` cannot be (indirectly) exposed to stable
     .help = either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
 const_eval_unmarked_intrinsic_exposed = intrinsic `{$def_path}` cannot be (indirectly) exposed to stable
-    .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
+    .help = mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
 
 const_eval_unreachable = entering unreachable code
 const_eval_unreachable_unwind =
diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs
index 8cb7e02036f..aea3d5bd3e7 100644
--- a/compiler/rustc_const_eval/src/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/check_consts/check.rs
@@ -736,16 +736,25 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 // Intrinsics are language primitives, not regular calls, so treat them separately.
                 if let Some(intrinsic) = tcx.intrinsic(callee) {
+                    // We use `intrinsic.const_stable` to determine if this can be safely exposed to
+                    // stable code, rather than `const_stable_indirect`. This is to make
+                    // `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
+                    // We also ask is_safe_to_expose_on_stable_const_fn; this determines whether the intrinsic
+                    // fallback body is safe to expose on stable.
+                    let is_const_stable = intrinsic.const_stable
+                        || (!intrinsic.must_be_overridden
+                            && tcx.is_const_fn(callee)
+                            && is_safe_to_expose_on_stable_const_fn(tcx, callee));
                     match tcx.lookup_const_stability(callee) {
                         None => {
                             // Non-const intrinsic.
                             self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
                         }
-                        Some(ConstStability { feature: None, const_stable_indirect, .. }) => {
+                        Some(ConstStability { feature: None, .. }) => {
                             // Intrinsic does not need a separate feature gate (we rely on the
                             // regular stability checker). However, we have to worry about recursive
                             // const stability.
-                            if !const_stable_indirect && self.enforce_recursive_const_stability() {
+                            if !is_const_stable && self.enforce_recursive_const_stability() {
                                 self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
                                     span: self.span,
                                     def_path: self.tcx.def_path_str(callee),
@@ -755,17 +764,19 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                         Some(ConstStability {
                             feature: Some(feature),
                             level: StabilityLevel::Unstable { .. },
-                            const_stable_indirect,
                             ..
                         }) => {
                             self.check_op(ops::IntrinsicUnstable {
                                 name: intrinsic.name,
                                 feature,
-                                const_stable_indirect,
+                                const_stable: is_const_stable,
                             });
                         }
                         Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
-                            // All good.
+                            // All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it
+                            // can be *directly* invoked from stable const code) does not always
+                            // have the `#[rustc_const_stable_intrinsic]` attribute (which controls
+                            // exposing an intrinsic indirectly); we accept this call anyway.
                         }
                     }
                     // This completes the checks for intrinsics.
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index d264cab1511..2931159842f 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -354,14 +354,14 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicNonConst {
 pub(crate) struct IntrinsicUnstable {
     pub name: Symbol,
     pub feature: Symbol,
-    pub const_stable_indirect: bool,
+    pub const_stable: bool,
 }
 
 impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
     fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status {
         Status::Unstable {
             gate: self.feature,
-            safe_to_expose_on_stable: self.const_stable_indirect,
+            safe_to_expose_on_stable: self.const_stable,
             // We do *not* want to suggest to mark the intrinsic as `const_stable_indirect`,
             // that's not a trivial change!
             is_function_call: false,
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 037fdcbcf9b..beff0cd99fc 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -25,15 +25,9 @@ fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
             hir::Constness::Const
         }
         hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
-        hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
-            // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
-            // foreign items cannot be evaluated at compile-time.
-            let is_const = if tcx.intrinsic(def_id).is_some() {
-                tcx.lookup_const_stability(def_id).is_some()
-            } else {
-                false
-            };
-            if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
+        hir::Node::ForeignItem(_) => {
+            // Foreign items cannot be evaluated at compile-time.
+            hir::Constness::NotConst
         }
         hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
         _ => {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 851e6a587bc..62115aef4a7 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -1,7 +1,6 @@
 use std::borrow::{Borrow, Cow};
 use std::fmt;
 use std::hash::Hash;
-use std::ops::ControlFlow;
 
 use rustc_abi::{Align, ExternAbi, Size};
 use rustc_ast::Mutability;
@@ -10,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::{self as hir, CRATE_HIR_ID, LangItem};
 use rustc_middle::mir::AssertMessage;
 use rustc_middle::query::TyCtxtAt;
-use rustc_middle::ty::layout::{FnAbiOf, TyAndLayout};
+use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, mir};
 use rustc_span::Span;
@@ -22,9 +21,9 @@ use crate::errors::{LongRunning, LongRunningWarn};
 use crate::fluent_generated as fluent;
 use crate::interpret::{
     self, AllocId, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, GlobalAlloc, ImmTy,
-    InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, PointerArithmetic, RangeSet, Scalar,
-    StackPopCleanup, compile_time_machine, interp_ok, throw_exhaust, throw_inval, throw_ub,
-    throw_ub_custom, throw_unsup, throw_unsup_format,
+    InterpCx, InterpResult, MPlaceTy, OpTy, Pointer, RangeSet, Scalar, compile_time_machine,
+    interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_custom, throw_unsup,
+    throw_unsup_format,
 };
 
 /// When hitting this many interpreted terminators we emit a deny by default lint
@@ -226,8 +225,8 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
         &mut self,
         instance: ty::Instance<'tcx>,
         args: &[FnArg<'tcx>],
-        dest: &MPlaceTy<'tcx>,
-        ret: Option<mir::BasicBlock>,
+        _dest: &MPlaceTy<'tcx>,
+        _ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
         let def_id = instance.def_id();
 
@@ -259,85 +258,10 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
             );
 
             return interp_ok(Some(new_instance));
-        } else if self.tcx.is_lang_item(def_id, LangItem::AlignOffset) {
-            let args = self.copy_fn_args(args);
-            // For align_offset, we replace the function call if the pointer has no address.
-            match self.align_offset(instance, &args, dest, ret)? {
-                ControlFlow::Continue(()) => return interp_ok(Some(instance)),
-                ControlFlow::Break(()) => return interp_ok(None),
-            }
         }
         interp_ok(Some(instance))
     }
 
-    /// `align_offset(ptr, target_align)` needs special handling in const eval, because the pointer
-    /// may not have an address.
-    ///
-    /// If `ptr` does have a known address, then we return `Continue(())` and the function call should
-    /// proceed as normal.
-    ///
-    /// If `ptr` doesn't have an address, but its underlying allocation's alignment is at most
-    /// `target_align`, then we call the function again with an dummy address relative to the
-    /// allocation.
-    ///
-    /// If `ptr` doesn't have an address and `target_align` is stricter than the underlying
-    /// allocation's alignment, then we return `usize::MAX` immediately.
-    fn align_offset(
-        &mut self,
-        instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
-        dest: &MPlaceTy<'tcx>,
-        ret: Option<mir::BasicBlock>,
-    ) -> InterpResult<'tcx, ControlFlow<()>> {
-        assert_eq!(args.len(), 2);
-
-        let ptr = self.read_pointer(&args[0])?;
-        let target_align = self.read_scalar(&args[1])?.to_target_usize(self)?;
-
-        if !target_align.is_power_of_two() {
-            throw_ub_custom!(
-                fluent::const_eval_align_offset_invalid_align,
-                target_align = target_align,
-            );
-        }
-
-        match self.ptr_try_get_alloc_id(ptr, 0) {
-            Ok((alloc_id, offset, _extra)) => {
-                let (_size, alloc_align, _kind) = self.get_alloc_info(alloc_id);
-
-                if target_align <= alloc_align.bytes() {
-                    // Extract the address relative to the allocation base that is definitely
-                    // sufficiently aligned and call `align_offset` again.
-                    let addr = ImmTy::from_uint(offset.bytes(), args[0].layout).into();
-                    let align = ImmTy::from_uint(target_align, args[1].layout).into();
-                    let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty())?;
-
-                    // Push the stack frame with our own adjusted arguments.
-                    self.init_stack_frame(
-                        instance,
-                        self.load_mir(instance.def, None)?,
-                        fn_abi,
-                        &[FnArg::Copy(addr), FnArg::Copy(align)],
-                        /* with_caller_location = */ false,
-                        dest,
-                        StackPopCleanup::Goto { ret, unwind: mir::UnwindAction::Unreachable },
-                    )?;
-                    interp_ok(ControlFlow::Break(()))
-                } else {
-                    // Not alignable in const, return `usize::MAX`.
-                    let usize_max = Scalar::from_target_usize(self.target_usize_max(), self);
-                    self.write_scalar(usize_max, dest)?;
-                    self.return_to_block(ret)?;
-                    interp_ok(ControlFlow::Break(()))
-                }
-            }
-            Err(_addr) => {
-                // The pointer has an address, continue with function call.
-                interp_ok(ControlFlow::Continue(()))
-            }
-        }
-    }
-
     /// See documentation on the `ptr_guaranteed_cmp` intrinsic.
     fn guaranteed_cmp(&mut self, a: Scalar, b: Scalar) -> InterpResult<'tcx, u8> {
         interp_ok(match (a, b) {
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 0069b07ad62..cc0bdec7019 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -837,6 +837,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         rustc_const_stable_indirect, Normal,
         template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
     ),
+    rustc_attr!(
+        rustc_const_stable_intrinsic, Normal,
+        template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
+    ),
     gated!(
         rustc_allow_const_fn_unstable, Normal,
         template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No,
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 7d81f977c22..c952d5f6d77 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -348,9 +348,6 @@ language_item_table! {
 
     MaybeUninit,             sym::maybe_uninit,        maybe_uninit,               Target::Union,          GenericRequirement::None;
 
-    /// Align offset for stride != 1; must not panic.
-    AlignOffset,             sym::align_offset,        align_offset_fn,            Target::Fn,             GenericRequirement::None;
-
     Termination,             sym::termination,         termination,                Target::Trait,          GenericRequirement::None;
 
     Try,                     sym::Try,                 try_trait,                  Target::Trait,          GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 38b11aa4017..6e8ba51612e 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -311,8 +311,8 @@ hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snip
 
 hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
     .note = default implementation of `{$missing_item_name}` is unstable
-    .some_note = use of unstable library feature '{$feature}': {$reason}
-    .none_note = use of unstable library feature '{$feature}'
+    .some_note = use of unstable library feature `{$feature}`: {$reason}
+    .none_note = use of unstable library feature `{$feature}`
 
 hir_analysis_missing_type_params =
     the type {$parameterCount ->
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index dee76c66663..77c324183c3 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1189,8 +1189,8 @@ fn compare_self_type<'tcx>(
 
     let self_string = |method: ty::AssocItem| {
         let untransformed_self_ty = match method.container {
-            ty::ImplContainer => impl_trait_ref.self_ty(),
-            ty::TraitContainer => tcx.types.self_param,
+            ty::AssocItemContainer::Impl => impl_trait_ref.self_ty(),
+            ty::AssocItemContainer::Trait => tcx.types.self_param,
         };
         let self_arg_ty = tcx.fn_sig(method.def_id).instantiate_identity().input(0);
         let param_env = ty::ParamEnv::reveal_all();
@@ -2224,10 +2224,8 @@ fn param_env_with_gat_bounds<'tcx>(
 
     for impl_ty in impl_tys_to_install {
         let trait_ty = match impl_ty.container {
-            ty::AssocItemContainer::TraitContainer => impl_ty,
-            ty::AssocItemContainer::ImplContainer => {
-                tcx.associated_item(impl_ty.trait_item_def_id.unwrap())
-            }
+            ty::AssocItemContainer::Trait => impl_ty,
+            ty::AssocItemContainer::Impl => tcx.associated_item(impl_ty.trait_item_def_id.unwrap()),
         };
 
         let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
@@ -2246,7 +2244,7 @@ fn param_env_with_gat_bounds<'tcx>(
                     .into()
                 }
                 GenericParamDefKind::Lifetime => {
-                    let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
+                    let kind = ty::BoundRegionKind::Named(param.def_id, param.name);
                     let bound_var = ty::BoundVariableKind::Region(kind);
                     bound_vars.push(bound_var);
                     ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs
deleted file mode 100644
index 64307407b73..00000000000
--- a/compiler/rustc_hir_analysis/src/check/errs.rs
+++ /dev/null
@@ -1,88 +0,0 @@
-use rustc_hir as hir;
-use rustc_lint_defs::builtin::STATIC_MUT_REFS;
-use rustc_middle::ty::{Mutability, TyCtxt};
-use rustc_span::Span;
-
-use crate::errors;
-
-/// Check for shared or mutable references of `static mut` inside expression
-pub(crate) fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
-    let span = expr.span;
-    let hir_id = expr.hir_id;
-    if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind
-        && matches!(borrow_kind, hir::BorrowKind::Ref)
-        && path_if_static_mut(expr)
-    {
-        handle_static_mut_ref(
-            tcx,
-            span,
-            span.with_hi(expr.span.lo()),
-            span.shrink_to_hi(),
-            span.edition().at_least_rust_2024(),
-            m,
-            hir_id,
-        );
-    }
-}
-
-/// Check for shared or mutable references of `static mut` inside statement
-pub(crate) fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
-    if let hir::StmtKind::Let(loc) = stmt.kind
-        && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
-        && let hir::ByRef::Yes(rmutbl) = ba.0
-        && let Some(init) = loc.init
-        && path_if_static_mut(init)
-    {
-        handle_static_mut_ref(
-            tcx,
-            init.span,
-            init.span.shrink_to_lo(),
-            init.span.shrink_to_hi(),
-            loc.span.edition().at_least_rust_2024(),
-            rmutbl,
-            stmt.hir_id,
-        );
-    }
-}
-
-fn path_if_static_mut(expr: &hir::Expr<'_>) -> bool {
-    if let hir::ExprKind::Path(qpath) = expr.kind
-        && let hir::QPath::Resolved(_, path) = qpath
-        && let hir::def::Res::Def(def_kind, _) = path.res
-        && let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } =
-            def_kind
-    {
-        return true;
-    }
-    false
-}
-
-fn handle_static_mut_ref(
-    tcx: TyCtxt<'_>,
-    span: Span,
-    lo: Span,
-    hi: Span,
-    e2024: bool,
-    mutable: Mutability,
-    hir_id: hir::HirId,
-) {
-    if e2024 {
-        let (sugg, shared) = if mutable == Mutability::Mut {
-            (errors::MutRefSugg::Mut { lo, hi }, "mutable")
-        } else {
-            (errors::MutRefSugg::Shared { lo, hi }, "shared")
-        };
-        tcx.dcx().emit_err(errors::StaticMutRef { span, sugg, shared });
-    } else {
-        let (sugg, shared) = if mutable == Mutability::Mut {
-            (errors::MutRefSugg::Mut { lo, hi }, "mutable")
-        } else {
-            (errors::MutRefSugg::Shared { lo, hi }, "shared")
-        };
-        tcx.emit_node_span_lint(STATIC_MUT_REFS, hir_id, span, errors::RefOfMutStatic {
-            span,
-            sugg,
-            shared,
-        });
-    }
-}
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 680e12b02fc..1513ea7c9e8 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -178,19 +178,19 @@ pub fn check_intrinsic_type(
     let name_str = intrinsic_name.as_str();
 
     let bound_vars = tcx.mk_bound_variable_kinds(&[
-        ty::BoundVariableKind::Region(ty::BrAnon),
-        ty::BoundVariableKind::Region(ty::BrAnon),
-        ty::BoundVariableKind::Region(ty::BrEnv),
+        ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon),
+        ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon),
+        ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
     ]);
     let mk_va_list_ty = |mutbl| {
         tcx.lang_items().va_list().map(|did| {
             let region = ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
                 var: ty::BoundVar::ZERO,
-                kind: ty::BrAnon,
+                kind: ty::BoundRegionKind::Anon,
             });
             let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
                 var: ty::BoundVar::from_u32(2),
-                kind: ty::BrEnv,
+                kind: ty::BoundRegionKind::ClosureEnv,
             });
             let va_list_ty = tcx.type_of(did).instantiate(tcx, &[region.into()]);
             (Ty::new_ref(tcx, env_region, va_list_ty, mutbl), va_list_ty)
@@ -509,7 +509,8 @@ pub fn check_intrinsic_type(
                 );
                 let discriminant_def_id = assoc_items[0];
 
-                let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BrAnon };
+                let br =
+                    ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon };
                 (
                     1,
                     0,
@@ -573,10 +574,14 @@ pub fn check_intrinsic_type(
             }
 
             sym::raw_eq => {
-                let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BrAnon };
+                let br =
+                    ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon };
                 let param_ty_lhs =
                     Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
-                let br = ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrAnon };
+                let br = ty::BoundRegion {
+                    var: ty::BoundVar::from_u32(1),
+                    kind: ty::BoundRegionKind::Anon,
+                };
                 let param_ty_rhs =
                     Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0));
                 (1, 0, vec![param_ty_lhs, param_ty_rhs], tcx.types.bool)
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index bf7cc713841..3a6ea545741 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1048,8 +1048,10 @@ fn check_associated_item(
             .coherent_trait(tcx.parent(item.trait_item_def_id.unwrap_or(item_id.into())))?;
 
         let self_ty = match item.container {
-            ty::TraitContainer => tcx.types.self_param,
-            ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(),
+            ty::AssocItemContainer::Trait => tcx.types.self_param,
+            ty::AssocItemContainer::Impl => {
+                tcx.type_of(item.container_id(tcx)).instantiate_identity()
+            }
         };
 
         match item.kind {
@@ -1072,7 +1074,7 @@ fn check_associated_item(
                 check_method_receiver(wfcx, hir_sig, item, self_ty)
             }
             ty::AssocKind::Type => {
-                if let ty::AssocItemContainer::TraitContainer = item.container {
+                if let ty::AssocItemContainer::Trait = item.container {
                     check_associated_type_bounds(wfcx, item, span)
                 }
                 if item.defaultness(tcx).has_value() {
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index e89c7fc9cb7..63a0e7d31c3 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -634,7 +634,7 @@ fn get_new_lifetime_name<'tcx>(
         .collect_referenced_late_bound_regions(poly_trait_ref)
         .into_iter()
         .filter_map(|lt| {
-            if let ty::BoundRegionKind::BrNamed(_, name) = lt {
+            if let ty::BoundRegionKind::Named(_, name) = lt {
                 Some(name.as_str().to_string())
             } else {
                 None
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index dc3ef9952f0..cc55f57c46c 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -322,7 +322,7 @@ fn late_arg_as_bound_arg<'tcx>(
     let name = tcx.item_name(def_id);
     match param.kind {
         GenericParamKind::Lifetime { .. } => {
-            ty::BoundVariableKind::Region(ty::BrNamed(def_id, name))
+            ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name))
         }
         GenericParamKind::Type { .. } => {
             ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, name))
@@ -337,7 +337,7 @@ fn late_arg_as_bound_arg<'tcx>(
 fn generic_param_def_as_bound_arg(param: &ty::GenericParamDef) -> ty::BoundVariableKind {
     match param.kind {
         ty::GenericParamDefKind::Lifetime => {
-            ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(param.def_id, param.name))
+            ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(param.def_id, param.name))
         }
         ty::GenericParamDefKind::Type { .. } => {
             ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id, param.name))
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 84161ec7648..816761fd00f 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -175,19 +175,13 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
         // arm would handle this.
         //
         // I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
-        Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
+        Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(ty, segment)), .. }) => {
             // Find the Item containing the associated type so we can create an ItemCtxt.
             // Using the ItemCtxt lower the HIR for the unresolved assoc type into a
             // ty which is a fully resolved projection.
             // For the code example above, this would mean lowering `Self::Assoc<3>`
             // to a ty::Alias(ty::Projection, `<Self as Foo>::Assoc<3>`).
-            let item_def_id = tcx
-                .hir()
-                .parent_owner_iter(arg_hir_id)
-                .find(|(_, node)| matches!(node, OwnerNode::Item(_)))
-                .unwrap()
-                .0
-                .def_id;
+            let item_def_id = tcx.hir().get_parent_item(ty.hir_id).def_id;
             let ty = ItemCtxt::new(tcx, item_def_id).lower_ty(hir_ty);
 
             // Iterate through the generics of the projection to find the one that corresponds to
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 85ba88333f9..1cade402c54 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -644,7 +644,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 ty::GenericParamDefKind::Lifetime => {
                     ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
                         var: ty::BoundVar::from_usize(num_bound_vars),
-                        kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+                        kind: ty::BoundRegionKind::Named(param.def_id, param.name),
                     })
                     .into()
                 }
@@ -830,8 +830,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 't
             }
             ty::ReBound(db, br) if db >= self.depth => {
                 self.vars.insert(match br.kind {
-                    ty::BrNamed(def_id, name) => (def_id, name),
-                    ty::BrAnon | ty::BrEnv => {
+                    ty::BoundRegionKind::Named(def_id, name) => (def_id, name),
+                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
                         let guar = self
                             .cx
                             .dcx()
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 d6534dbc694..ed39708981b 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -314,7 +314,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let name = lifetime_name(def_id);
                 let br = ty::BoundRegion {
                     var: ty::BoundVar::from_u32(index),
-                    kind: ty::BrNamed(def_id.to_def_id(), name),
+                    kind: ty::BoundRegionKind::Named(def_id.to_def_id(), name),
                 };
                 ty::Region::new_bound(tcx, debruijn, br)
             }
@@ -332,7 +332,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 ty::Region::new_late_param(
                     tcx,
                     scope.to_def_id(),
-                    ty::BrNamed(id.to_def_id(), name),
+                    ty::BoundRegionKind::Named(id.to_def_id(), name),
                 )
 
                 // (*) -- not late-bound, won't change
@@ -2449,15 +2449,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
     ) {
         for br in referenced_regions.difference(&constrained_regions) {
             let br_name = match *br {
-                ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon | ty::BrEnv => {
-                    "an anonymous lifetime".to_string()
-                }
-                ty::BrNamed(_, name) => format!("lifetime `{name}`"),
+                ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime)
+                | ty::BoundRegionKind::Anon
+                | ty::BoundRegionKind::ClosureEnv => "an anonymous lifetime".to_string(),
+                ty::BoundRegionKind::Named(_, name) => format!("lifetime `{name}`"),
             };
 
             let mut err = generate_err(&br_name);
 
-            if let ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon = *br {
+            if let ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime)
+            | ty::BoundRegionKind::Anon = *br
+            {
                 // The only way for an anonymous lifetime to wind up
                 // in the return type but **also** be unconstrained is
                 // if it only appears in "associated types" in the
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index a49deaa2678..2026fd9a614 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -194,21 +194,21 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_>
     let panic_info_ty = tcx.type_of(panic_info_did).instantiate(tcx, &[ty::GenericArg::from(
         ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
             var: ty::BoundVar::from_u32(1),
-            kind: ty::BrAnon,
+            kind: ty::BoundRegionKind::Anon,
         }),
     )]);
     let panic_info_ref_ty = Ty::new_imm_ref(
         tcx,
         ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
             var: ty::BoundVar::ZERO,
-            kind: ty::BrAnon,
+            kind: ty::BoundRegionKind::Anon,
         }),
         panic_info_ty,
     );
 
     let bounds = tcx.mk_bound_variable_kinds(&[
-        ty::BoundVariableKind::Region(ty::BrAnon),
-        ty::BoundVariableKind::Region(ty::BrAnon),
+        ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon),
+        ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon),
     ]);
     let expected_sig = ty::Binder::bind_with_vars(
         tcx.mk_fn_sig([panic_info_ref_ty], tcx.types.never, false, fn_sig.safety, ExternAbi::Rust),
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 915dca614d6..b05731c6d52 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -103,9 +103,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) -> Ty<'tcx> {
+        self.check_expr_coercible_to_type_or_error(expr, expected, expected_ty_expr, |_, _| {})
+    }
+
+    pub(crate) fn check_expr_coercible_to_type_or_error(
+        &self,
+        expr: &'tcx hir::Expr<'tcx>,
+        expected: Ty<'tcx>,
+        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
+        extend_err: impl FnOnce(&mut Diag<'_>, Ty<'tcx>),
+    ) -> Ty<'tcx> {
         let ty = self.check_expr_with_hint(expr, expected);
         // checks don't need two phase
-        self.demand_coerce(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No)
+        match self.demand_coerce_diag(expr, ty, expected, expected_ty_expr, AllowTwoPhase::No) {
+            Ok(ty) => ty,
+            Err(mut err) => {
+                extend_err(&mut err, ty);
+                err.emit();
+                // Return the original type instead of an error type here, otherwise the type of `x` in
+                // `let x: u32 = ();` will be a type error, causing all subsequent usages of `x` to not
+                // report errors, even though `x` is definitely `u32`.
+                expected
+            }
+        }
     }
 
     pub(super) fn check_expr_with_hint(
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index 361fd55d5de..59bef8315d8 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -21,13 +21,12 @@ use rustc_middle::hir::place::ProjectionKind;
 pub use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection};
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{
-    self, AdtKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment,
+    self, AdtKind, BorrowKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, adjustment,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_span::{ErrorGuaranteed, Span};
 use rustc_trait_selection::infer::InferCtxtExt;
 use tracing::{debug, trace};
-use ty::BorrowKind::ImmBorrow;
 
 use crate::fn_ctxt::FnCtxt;
 
@@ -63,7 +62,7 @@ pub trait Delegate<'tcx> {
     fn copy(&mut self, place_with_id: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
         // In most cases, copying data from `x` is equivalent to doing `*&x`, so by default
         // we treat a copy of `x` as a borrow of `x`.
-        self.borrow(place_with_id, diag_expr_id, ty::BorrowKind::ImmBorrow)
+        self.borrow(place_with_id, diag_expr_id, ty::BorrowKind::Immutable)
     }
 
     /// The path at `assignee_place` is being assigned to.
@@ -387,7 +386,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
             }
 
             hir::ExprKind::Let(hir::LetExpr { pat, init, .. }) => {
-                self.walk_local(init, pat, None, || self.borrow_expr(init, ty::ImmBorrow))?;
+                self.walk_local(init, pat, None, || self.borrow_expr(init, BorrowKind::Immutable))?;
             }
 
             hir::ExprKind::Match(discr, arms, _) => {
@@ -626,7 +625,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
         }
 
         if needs_to_be_read {
-            self.borrow_expr(discr, ty::ImmBorrow)?;
+            self.borrow_expr(discr, BorrowKind::Immutable)?;
         } else {
             let closure_def_id = match discr_place.place.base {
                 PlaceBase::Upvar(upvar_id) => Some(upvar_id.closure_expr_id),
@@ -785,8 +784,8 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                     // Reborrowing a Pin is like a combinations of a deref and a borrow, so we do
                     // both.
                     let bk = match mutbl {
-                        ty::Mutability::Not => ty::BorrowKind::ImmBorrow,
-                        ty::Mutability::Mut => ty::BorrowKind::MutBorrow,
+                        ty::Mutability::Not => ty::BorrowKind::Immutable,
+                        ty::Mutability::Mut => ty::BorrowKind::Mutable,
                     };
                     self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
                 }
@@ -909,7 +908,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                     // binding when lowering pattern guards to ensure that the guard does not
                     // modify the scrutinee.
                     if has_guard {
-                        self.delegate.borrow_mut().borrow(place, discr_place.hir_id, ImmBorrow);
+                        self.delegate.borrow_mut().borrow(
+                            place,
+                            discr_place.hir_id,
+                            BorrowKind::Immutable,
+                        );
                     }
 
                     // It is also a borrow or copy/move of the value being matched.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 2753bee499b..ce0ab8a913b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -254,10 +254,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         for a in &adj {
-            if let Adjust::NeverToAny = a.kind {
-                if a.target.is_ty_var() {
-                    self.diverging_type_vars.borrow_mut().insert(a.target);
-                    debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
+            match a.kind {
+                Adjust::NeverToAny => {
+                    if a.target.is_ty_var() {
+                        self.diverging_type_vars.borrow_mut().insert(a.target);
+                        debug!("apply_adjustments: adding `{:?}` as diverging type var", a.target);
+                    }
+                }
+                Adjust::Deref(Some(overloaded_deref)) => {
+                    self.enforce_context_effects(
+                        expr.span,
+                        overloaded_deref.method_call(self.tcx),
+                        self.tcx.mk_args(&[a.target.into()]),
+                    );
+                }
+                Adjust::Deref(None) => {
+                    // FIXME(effects): We *could* enforce `&T: ~const Deref` here.
+                }
+                Adjust::Pointer(_pointer_coercion) => {
+                    // FIXME(effects): We should probably enforce these.
+                }
+                Adjust::ReborrowPin(_mutability) => {
+                    // FIXME(effects): We could enforce these; they correspond to
+                    // `&mut T: DerefMut` tho, so it's kinda moot.
+                }
+                Adjust::Borrow(_) => {
+                    // No effects to enforce here.
                 }
             }
         }
@@ -1025,7 +1047,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let container_id = assoc_item.container_id(tcx);
                 debug!(?def_id, ?container, ?container_id);
                 match container {
-                    ty::TraitContainer => {
+                    ty::AssocItemContainer::Trait => {
                         if let Err(e) = callee::check_legal_trait_for_method_call(
                             tcx,
                             path_span,
@@ -1037,7 +1059,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             self.set_tainted_by_errors(e);
                         }
                     }
-                    ty::ImplContainer => {
+                    ty::AssocItemContainer::Impl => {
                         if segments.len() == 1 {
                             // `<T>::assoc` will end up here, and so
                             // can `T::assoc`. If this came from an
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 3f703c2fcf6..919e83724d7 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1796,7 +1796,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 false,
                 |did| {
                     let assoc_item = self.tcx.associated_item(did);
-                    assoc_item.container == ty::AssocItemContainer::TraitContainer
+                    assoc_item.container == ty::AssocItemContainer::Trait
                         && assoc_item.container_id(self.tcx) == clone_trait_did
                 },
             )
@@ -3390,4 +3390,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.span_label(block.span, "this block is missing a tail expression");
         }
     }
+
+    pub(crate) fn suggest_swapping_lhs_and_rhs(
+        &self,
+        err: &mut Diag<'_>,
+        rhs_ty: Ty<'tcx>,
+        lhs_ty: Ty<'tcx>,
+        rhs_expr: &'tcx hir::Expr<'tcx>,
+        lhs_expr: &'tcx hir::Expr<'tcx>,
+        op: hir::BinOp,
+    ) {
+        match op.node {
+            hir::BinOpKind::Eq => {
+                if let Some(partial_eq_def_id) = self.infcx.tcx.lang_items().eq_trait()
+                    && self
+                        .infcx
+                        .type_implements_trait(partial_eq_def_id, [rhs_ty, lhs_ty], self.param_env)
+                        .must_apply_modulo_regions()
+                {
+                    let sm = self.tcx.sess.source_map();
+                    if let Ok(rhs_snippet) = sm.span_to_snippet(rhs_expr.span)
+                        && let Ok(lhs_snippet) = sm.span_to_snippet(lhs_expr.span)
+                    {
+                        err.note(format!("`{rhs_ty}` implements `PartialEq<{lhs_ty}>`"));
+                        err.multipart_suggestion(
+                            "consider swapping the equality",
+                            vec![(lhs_expr.span, rhs_snippet), (rhs_expr.span, lhs_snippet)],
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
 }
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index d8b63eef577..f5987a11fa5 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -239,7 +239,7 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
     let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = node.ty() {
         if let Some(item) = tcx.opt_associated_item(def_id.into())
             && let ty::AssocKind::Const = item.kind
-            && let ty::ImplContainer = item.container
+            && let ty::AssocItemContainer::Impl = item.container
             && let Some(trait_item_def_id) = item.trait_item_def_id
         {
             let impl_def_id = item.container_id(tcx);
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index eb5581f421b..640729576fc 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -480,7 +480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ProbeScope::Single(def_id) => {
                     let item = self.tcx.associated_item(def_id);
                     // FIXME(fn_delegation): Delegation to inherent methods is not yet supported.
-                    assert_eq!(item.container, AssocItemContainer::TraitContainer);
+                    assert_eq!(item.container, AssocItemContainer::Trait);
 
                     let trait_def_id = self.tcx.parent(def_id);
                     let trait_span = self.tcx.def_span(trait_def_id);
@@ -1406,7 +1406,7 @@ impl<'tcx> Pick<'tcx> {
                         tcx.def_path_str(self.item.def_id),
                     ));
                 }
-                (ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => {
+                (ty::AssocKind::Const, ty::AssocItemContainer::Trait) => {
                     let def_id = self.item.container_id(tcx);
                     lint.span_suggestion(
                         span,
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 9c1459ee188..9a3492abc9f 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -249,7 +249,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         );
 
         // see `NB` above
-        let rhs_ty = self.check_expr_coercible_to_type(rhs_expr, rhs_ty_var, Some(lhs_expr));
+        let rhs_ty = self.check_expr_coercible_to_type_or_error(
+            rhs_expr,
+            rhs_ty_var,
+            Some(lhs_expr),
+            |err, ty| {
+                self.suggest_swapping_lhs_and_rhs(err, ty, lhs_ty, rhs_expr, lhs_expr, op);
+            },
+        );
         let rhs_ty = self.resolve_vars_with_obligations(rhs_ty);
 
         let return_ty = match result {
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 03590b6a455..2a8ed26aa2b 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -2071,6 +2071,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 s = pluralize!(len),
                 them = if len == 1 { "it" } else { "them" },
             ),
+            format!(
+                "{}{}{}{}",
+                prefix,
+                unmentioned_fields
+                    .iter()
+                    .map(|(_, name)| {
+                        let field_name = name.to_string();
+                        format!("{field_name}: _")
+                    })
+                    .collect::<Vec<_>>()
+                    .join(", "),
+                if have_inaccessible_fields { ", .." } else { "" },
+                postfix,
+            ),
+            Applicability::MachineApplicable,
+        );
+        err.span_suggestion(
+            sp,
+            "or always ignore missing fields here",
             format!("{prefix}..{postfix}"),
             Applicability::MachineApplicable,
         );
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index d5c7fe5fff3..3d401cef76f 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -296,6 +296,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             );
                         };
                         *deref = OverloadedDeref { mutbl, span: deref.span };
+                        self.enforce_context_effects(expr.span, method.def_id, method.args);
                         // If this is a union field, also throw an error for `DerefMut` of `ManuallyDrop` (see RFC 2514).
                         // This helps avoid accidental drops.
                         if inside_union
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index fbb427da103..175fca327f3 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -44,8 +44,8 @@ use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, Pro
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::{
-    self, ClosureSizeProfileData, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, UpvarArgs,
-    UpvarCapture,
+    self, BorrowKind, ClosureSizeProfileData, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults,
+    UpvarArgs, UpvarCapture,
 };
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
@@ -381,7 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let closure_env_region: ty::Region<'_> =
                 ty::Region::new_bound(self.tcx, ty::INNERMOST, ty::BoundRegion {
                     var: ty::BoundVar::ZERO,
-                    kind: ty::BoundRegionKind::BrEnv,
+                    kind: ty::BoundRegionKind::ClosureEnv,
                 });
 
             let num_args = args
@@ -441,7 +441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         rustc_abi::ExternAbi::Rust,
                     ),
                     self.tcx.mk_bound_variable_kinds(&[ty::BoundVariableKind::Region(
-                        ty::BoundRegionKind::BrEnv,
+                        ty::BoundRegionKind::ClosureEnv,
                     )]),
                 ),
             );
@@ -646,7 +646,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     },
 
                     ty::UpvarCapture::ByRef(
-                        ty::BorrowKind::MutBorrow | ty::BorrowKind::UniqueImmBorrow,
+                        ty::BorrowKind::Mutable | ty::BorrowKind::UniqueImmutable,
                     ) => {
                         match closure_kind {
                             ty::ClosureKind::Fn => {
@@ -1681,7 +1681,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::UpvarCapture::ByValue
             }
             hir::CaptureBy::Value { .. } | hir::CaptureBy::Ref => {
-                ty::UpvarCapture::ByRef(ty::ImmBorrow)
+                ty::UpvarCapture::ByRef(BorrowKind::Immutable)
             }
         }
     }
@@ -1869,7 +1869,7 @@ fn should_reborrow_from_env_of_parent_coroutine_closure<'tcx>(
             Some(Projection { kind: ProjectionKind::Deref, .. })
         ))
         // (2.)
-        || matches!(child_capture.info.capture_kind, UpvarCapture::ByRef(ty::BorrowKind::MutBorrow))
+        || matches!(child_capture.info.capture_kind, UpvarCapture::ByRef(ty::BorrowKind::Mutable))
 }
 
 /// Truncate the capture so that the place being borrowed is in accordance with RFC 1240,
@@ -1984,7 +1984,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
 
         // We need to restrict Fake Read precision to avoid fake reading unsafe code,
         // such as deref of a raw pointer.
-        let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow);
+        let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::Immutable);
 
         let (place, _) = restrict_capture_precision(place.place.clone(), dummy_capture_kind);
 
@@ -2025,7 +2025,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
 
         // Raw pointers don't inherit mutability
         if place_with_id.place.deref_tys().any(Ty::is_unsafe_ptr) {
-            capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::ImmBorrow);
+            capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::Immutable);
         }
 
         self.capture_information.push((place, ty::CaptureInfo {
@@ -2037,7 +2037,7 @@ impl<'tcx> euv::Delegate<'tcx> for InferBorrowKind<'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     fn mutate(&mut self, assignee_place: &PlaceWithHirId<'tcx>, diag_expr_id: HirId) {
-        self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::MutBorrow);
+        self.borrow(assignee_place, diag_expr_id, ty::BorrowKind::Mutable);
     }
 }
 
@@ -2331,16 +2331,16 @@ fn determine_capture_info(
             (ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => {
                 match (ref_a, ref_b) {
                     // Take LHS:
-                    (ty::UniqueImmBorrow | ty::MutBorrow, ty::ImmBorrow)
-                    | (ty::MutBorrow, ty::UniqueImmBorrow) => capture_info_a,
+                    (BorrowKind::UniqueImmutable | BorrowKind::Mutable, BorrowKind::Immutable)
+                    | (BorrowKind::Mutable, BorrowKind::UniqueImmutable) => capture_info_a,
 
                     // Take RHS:
-                    (ty::ImmBorrow, ty::UniqueImmBorrow | ty::MutBorrow)
-                    | (ty::UniqueImmBorrow, ty::MutBorrow) => capture_info_b,
+                    (BorrowKind::Immutable, BorrowKind::UniqueImmutable | BorrowKind::Mutable)
+                    | (BorrowKind::UniqueImmutable, BorrowKind::Mutable) => capture_info_b,
 
-                    (ty::ImmBorrow, ty::ImmBorrow)
-                    | (ty::UniqueImmBorrow, ty::UniqueImmBorrow)
-                    | (ty::MutBorrow, ty::MutBorrow) => {
+                    (BorrowKind::Immutable, BorrowKind::Immutable)
+                    | (BorrowKind::UniqueImmutable, BorrowKind::UniqueImmutable)
+                    | (BorrowKind::Mutable, BorrowKind::Mutable) => {
                         bug!("Expected unequal capture kinds");
                     }
                 }
@@ -2367,12 +2367,12 @@ fn truncate_place_to_len_and_update_capture_kind<'tcx>(
     // Note that if the place contained Deref of a raw pointer it would've not been MutBorrow, so
     // we don't need to worry about that case here.
     match curr_mode {
-        ty::UpvarCapture::ByRef(ty::BorrowKind::MutBorrow) => {
+        ty::UpvarCapture::ByRef(ty::BorrowKind::Mutable) => {
             for i in len..place.projections.len() {
                 if place.projections[i].kind == ProjectionKind::Deref
                     && is_mut_ref(place.ty_before_projection(i))
                 {
-                    *curr_mode = ty::UpvarCapture::ByRef(ty::BorrowKind::UniqueImmBorrow);
+                    *curr_mode = ty::UpvarCapture::ByRef(ty::BorrowKind::UniqueImmutable);
                     break;
                 }
             }
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index c9d8ebecef0..f87c43a0ecd 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -753,7 +753,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
         let var = self.canonical_var(info, r.into());
-        let br = ty::BoundRegion { var, kind: ty::BrAnon };
+        let br = ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon };
         ty::Region::new_bound(self.cx(), self.binder_index, br)
     }
 
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 35bba149d0a..ce90ceeda56 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -764,7 +764,7 @@ fn test_unstable_options_tracking_hash() {
         branch_protection,
         Some(BranchProtection {
             bti: true,
-            pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B })
+            pac_ret: Some(PacRet { leaf: true, pc: true, key: PAuthKey::B })
         })
     );
     tracked!(codegen_backend, Some("abc".to_string()));
diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
index 026826021c8..002ab027982 100644
--- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs
+++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs
@@ -154,7 +154,7 @@ fn check_fn(tcx: TyCtxt<'_>, parent_def_id: LocalDefId) {
     }
 
     for bound_var in sig.bound_vars() {
-        let ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, name)) = bound_var
+        let ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name)) = bound_var
         else {
             span_bug!(tcx.def_span(parent_def_id), "unexpected non-lifetime binder on fn sig");
         };
@@ -215,7 +215,7 @@ where
         for arg in t.bound_vars() {
             let arg: ty::BoundVariableKind = arg;
             match arg {
-                ty::BoundVariableKind::Region(ty::BoundRegionKind::BrNamed(def_id, ..))
+                ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, ..))
                 | ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(def_id, _)) => {
                     added.push(def_id);
                     let unique = self.in_scope_parameters.insert(def_id, ParamKind::Late);
@@ -318,7 +318,7 @@ where
                         ParamKind::Free(def_id, name) => ty::Region::new_late_param(
                             self.tcx,
                             self.parent_def_id.to_def_id(),
-                            ty::BoundRegionKind::BrNamed(def_id, name),
+                            ty::BoundRegionKind::Named(def_id, name),
                         ),
                         // Totally ignore late bound args from binders.
                         ParamKind::Late => return true,
@@ -489,11 +489,11 @@ fn extract_def_id_from_arg<'tcx>(
             ty::ReEarlyParam(ebr) => generics.region_param(ebr, tcx).def_id,
             ty::ReBound(
                 _,
-                ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. },
+                ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id, ..), .. },
             )
             | ty::ReLateParam(ty::LateParamRegion {
                 scope: _,
-                bound_region: ty::BoundRegionKind::BrNamed(def_id, ..),
+                bound_region: ty::BoundRegionKind::Named(def_id, ..),
             }) => def_id,
             _ => unreachable!(),
         },
@@ -558,11 +558,11 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
             ty::ReEarlyParam(ebr) => self.generics.region_param(ebr, self.tcx).def_id,
             ty::ReBound(
                 _,
-                ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, ..), .. },
+                ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id, ..), .. },
             )
             | ty::ReLateParam(ty::LateParamRegion {
                 scope: _,
-                bound_region: ty::BoundRegionKind::BrNamed(def_id, ..),
+                bound_region: ty::BoundRegionKind::Named(def_id, ..),
             }) => def_id,
             _ => {
                 return Ok(a);
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 9d35ce19b57..a4d50c73104 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -422,6 +422,9 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
         .into_iter()
         .filter(|pass| {
             let lints = (**pass).get_lints();
+            // Lintless passes are always in
+            lints.is_empty() ||
+            // If the pass doesn't have a single needed lint, omit it
             !lints.iter().all(|lint| lints_that_dont_need_to_run.contains(&LintId::of(lint)))
         })
         .collect();
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index c5f0b94327f..4d8ebf2909e 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -26,8 +26,8 @@ pub(crate) enum MethodLateContext {
 pub(crate) fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext {
     let item = cx.tcx.associated_item(id);
     match item.container {
-        ty::TraitContainer => MethodLateContext::TraitAutoImpl,
-        ty::ImplContainer => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) {
+        ty::AssocItemContainer::Trait => MethodLateContext::TraitAutoImpl,
+        ty::AssocItemContainer::Impl => match cx.tcx.impl_trait_ref(item.container_id(cx.tcx)) {
             Some(_) => MethodLateContext::TraitImpl,
             None => MethodLateContext::PlainImpl,
         },
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 5d2df6ddfc9..eb99d560e57 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -784,8 +784,14 @@ extern "C" LLVMRustResult LLVMRustOptimize(
   // the PassBuilder does not create a pipeline.
   std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
       PipelineStartEPCallbacks;
+#if LLVM_VERSION_GE(20, 0)
+  std::vector<std::function<void(ModulePassManager &, OptimizationLevel,
+                                 ThinOrFullLTOPhase)>>
+      OptimizerLastEPCallbacks;
+#else
   std::vector<std::function<void(ModulePassManager &, OptimizationLevel)>>
       OptimizerLastEPCallbacks;
+#endif
 
   if (!IsLinkerPluginLTO && SanitizerOptions && SanitizerOptions->SanitizeCFI &&
       !NoPrepopulatePasses) {
@@ -832,7 +838,12 @@ extern "C" LLVMRustResult LLVMRustOptimize(
           SanitizerOptions->SanitizeDataFlowABIList +
               SanitizerOptions->SanitizeDataFlowABIListLen);
       OptimizerLastEPCallbacks.push_back(
+#if LLVM_VERSION_GE(20, 0)
+          [ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level,
+                         ThinOrFullLTOPhase phase) {
+#else
           [ABIListFiles](ModulePassManager &MPM, OptimizationLevel Level) {
+#endif
             MPM.addPass(DataFlowSanitizerPass(ABIListFiles));
           });
     }
@@ -844,23 +855,39 @@ extern "C" LLVMRustResult LLVMRustOptimize(
           /*CompileKernel=*/false,
           /*EagerChecks=*/true);
       OptimizerLastEPCallbacks.push_back(
+#if LLVM_VERSION_GE(20, 0)
+          [Options](ModulePassManager &MPM, OptimizationLevel Level,
+                    ThinOrFullLTOPhase phase) {
+#else
           [Options](ModulePassManager &MPM, OptimizationLevel Level) {
+#endif
             MPM.addPass(MemorySanitizerPass(Options));
           });
     }
 
     if (SanitizerOptions->SanitizeThread) {
-      OptimizerLastEPCallbacks.push_back([](ModulePassManager &MPM,
-                                            OptimizationLevel Level) {
-        MPM.addPass(ModuleThreadSanitizerPass());
-        MPM.addPass(createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
-      });
+      OptimizerLastEPCallbacks.push_back(
+#if LLVM_VERSION_GE(20, 0)
+          [](ModulePassManager &MPM, OptimizationLevel Level,
+             ThinOrFullLTOPhase phase) {
+#else
+          [](ModulePassManager &MPM, OptimizationLevel Level) {
+#endif
+            MPM.addPass(ModuleThreadSanitizerPass());
+            MPM.addPass(
+                createModuleToFunctionPassAdaptor(ThreadSanitizerPass()));
+          });
     }
 
     if (SanitizerOptions->SanitizeAddress ||
         SanitizerOptions->SanitizeKernelAddress) {
       OptimizerLastEPCallbacks.push_back(
+#if LLVM_VERSION_GE(20, 0)
+          [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level,
+                             ThinOrFullLTOPhase phase) {
+#else
           [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
+#endif
             auto CompileKernel = SanitizerOptions->SanitizeKernelAddress;
             AddressSanitizerOptions opts = AddressSanitizerOptions{
                 CompileKernel,
@@ -874,7 +901,12 @@ extern "C" LLVMRustResult LLVMRustOptimize(
     }
     if (SanitizerOptions->SanitizeHWAddress) {
       OptimizerLastEPCallbacks.push_back(
+#if LLVM_VERSION_GE(20, 0)
+          [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level,
+                             ThinOrFullLTOPhase phase) {
+#else
           [SanitizerOptions](ModulePassManager &MPM, OptimizationLevel Level) {
+#endif
             HWAddressSanitizerOptions opts(
                 /*CompileKernel=*/false,
                 SanitizerOptions->SanitizeHWAddressRecover,
@@ -935,7 +967,11 @@ extern "C" LLVMRustResult LLVMRustOptimize(
     for (const auto &C : PipelineStartEPCallbacks)
       C(MPM, OptLevel);
     for (const auto &C : OptimizerLastEPCallbacks)
+#if LLVM_VERSION_GE(20, 0)
+      C(MPM, OptLevel, ThinOrFullLTOPhase::None);
+#else
       C(MPM, OptLevel);
+#endif
   }
 
   if (ExtraPassesLen) {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 7277039bb7d..b5391247cea 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1203,8 +1203,8 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         DefKind::AssocTy => {
             let assoc_item = tcx.associated_item(def_id);
             match assoc_item.container {
-                ty::AssocItemContainer::ImplContainer => true,
-                ty::AssocItemContainer::TraitContainer => assoc_item.defaultness(tcx).has_value(),
+                ty::AssocItemContainer::Impl => true,
+                ty::AssocItemContainer::Trait => assoc_item.defaultness(tcx).has_value(),
             }
         }
         DefKind::TyParam => {
@@ -1336,7 +1336,7 @@ fn should_encode_const(def_kind: DefKind) -> bool {
 
 fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
     if let Some(assoc_item) = tcx.opt_associated_item(def_id)
-        && assoc_item.container == ty::AssocItemContainer::TraitContainer
+        && assoc_item.container == ty::AssocItemContainer::Trait
         && assoc_item.kind == ty::AssocKind::Fn
     {
         true
@@ -1649,7 +1649,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         self.tables.assoc_container.set_some(def_id.index, item.container);
 
         match item.container {
-            AssocItemContainer::TraitContainer => {
+            AssocItemContainer::Trait => {
                 if let ty::AssocKind::Type = item.kind {
                     self.encode_explicit_item_bounds(def_id);
                     self.encode_explicit_item_super_predicates(def_id);
@@ -1659,7 +1659,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     }
                 }
             }
-            AssocItemContainer::ImplContainer => {
+            AssocItemContainer::Impl => {
                 if let Some(trait_item_def_id) = item.trait_item_def_id {
                     self.tables.trait_item_def_id.set_some(def_id.index, trait_item_def_id.into());
                 }
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 3a6f3543317..63abd2be9a5 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -223,8 +223,8 @@ fixed_size_enum! {
 
 fixed_size_enum! {
     ty::AssocItemContainer {
-        ( TraitContainer )
-        ( ImplContainer  )
+        ( Trait )
+        ( Impl  )
     }
 }
 
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 39485a324f2..52c3212ab80 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -68,8 +68,8 @@ middle_deprecated_in_version = use of {$kind} `{$path}` that will be deprecated
 middle_deprecated_suggestion = replace the use of the deprecated {$kind}
 
 middle_drop_check_overflow =
-    overflow while adding drop-check rules for {$ty}
-    .note = overflowed on {$overflow_ty}
+    overflow while adding drop-check rules for `{$ty}`
+    .note = overflowed on `{$overflow_ty}`
 
 middle_erroneous_constant = erroneous constant encountered
 
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index c0688aff183..e6b36299d7f 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -112,8 +112,8 @@ pub fn report_unstable(
     soft_handler: impl FnOnce(&'static Lint, Span, String),
 ) {
     let msg = match reason {
-        Some(r) => format!("use of unstable library feature '{feature}': {r}"),
-        None => format!("use of unstable library feature '{feature}'"),
+        Some(r) => format!("use of unstable library feature `{feature}`: {r}"),
+        None => format!("use of unstable library feature `{feature}`"),
     };
 
     if is_soft {
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index c34bdf041af..86abeb50382 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -317,7 +317,10 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
     pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
         let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
             ty::ReVar(vid) => {
-                let br = ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon };
+                let br = ty::BoundRegion {
+                    var: ty::BoundVar::new(vid.index()),
+                    kind: ty::BoundRegionKind::Anon,
+                };
                 ty::Region::new_bound(tcx, depth, br)
             }
             _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 41d0b47388c..f58426601cd 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -2200,10 +2200,11 @@ rustc_queries! {
         desc { "computing autoderef types for `{}`", goal.canonical.value.value }
     }
 
-    query supported_target_features(_: CrateNum) -> &'tcx UnordMap<String, Option<Symbol>> {
+    /// Returns the Rust target features for the current target. These are not always the same as LLVM target features!
+    query rust_target_features(_: CrateNum) -> &'tcx UnordMap<String, rustc_target::target_features::Stability> {
         arena_cache
         eval_always
-        desc { "looking up supported target features" }
+        desc { "looking up Rust target features" }
     }
 
     query implied_target_features(feature: Symbol) -> &'tcx Vec<Symbol> {
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index ce27e81813c..f8ab555305f 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -1,5 +1,6 @@
 use rustc_abi::FieldIdx;
 use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 use rustc_span::Span;
@@ -123,19 +124,18 @@ pub struct OverloadedDeref {
 }
 
 impl OverloadedDeref {
-    /// Get the zst function item type for this method call.
-    pub fn method_call<'tcx>(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> {
+    /// Get the [`DefId`] of the method call for the given `Deref`/`DerefMut` trait
+    /// for this overloaded deref's mutability.
+    pub fn method_call<'tcx>(&self, tcx: TyCtxt<'tcx>) -> DefId {
         let trait_def_id = match self.mutbl {
             hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None),
             hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None),
         };
-        let method_def_id = tcx
-            .associated_items(trait_def_id)
+        tcx.associated_items(trait_def_id)
             .in_definition_order()
             .find(|m| m.kind == ty::AssocKind::Fn)
             .unwrap()
-            .def_id;
-        Ty::new_fn_def(tcx, method_def_id, [source])
+            .def_id
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index 3137fe9bd1d..62157d9bfe2 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -10,8 +10,8 @@ use crate::ty;
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash, Encodable, Decodable)]
 pub enum AssocItemContainer {
-    TraitContainer,
-    ImplContainer,
+    Trait,
+    Impl,
 }
 
 /// Information about an associated item
@@ -63,16 +63,16 @@ impl AssocItem {
     #[inline]
     pub fn trait_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
         match self.container {
-            AssocItemContainer::ImplContainer => None,
-            AssocItemContainer::TraitContainer => Some(tcx.parent(self.def_id)),
+            AssocItemContainer::Impl => None,
+            AssocItemContainer::Trait => Some(tcx.parent(self.def_id)),
         }
     }
 
     #[inline]
     pub fn impl_container(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
         match self.container {
-            AssocItemContainer::ImplContainer => Some(tcx.parent(self.def_id)),
-            AssocItemContainer::TraitContainer => None,
+            AssocItemContainer::Impl => Some(tcx.parent(self.def_id)),
+            AssocItemContainer::Trait => None,
         }
     }
 
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 9ee82942911..6ab4d76e545 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -10,7 +10,6 @@ use rustc_span::def_id::LocalDefIdMap;
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, Symbol};
 
-use self::BorrowKind::*;
 use super::TyCtxt;
 use crate::hir::place::{
     Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
@@ -334,7 +333,7 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc
 #[derive(TypeFoldable, TypeVisitable)]
 pub enum BorrowKind {
     /// Data must be immutable and is aliasable.
-    ImmBorrow,
+    Immutable,
 
     /// Data must be immutable but not aliasable. This kind of borrow
     /// cannot currently be expressed by the user and is used only in
@@ -382,17 +381,17 @@ pub enum BorrowKind {
     /// borrow, it's just used when translating closures.
     ///
     /// FIXME: Rename this to indicate the borrow is actually not immutable.
-    UniqueImmBorrow,
+    UniqueImmutable,
 
     /// Data is mutable and not aliasable.
-    MutBorrow,
+    Mutable,
 }
 
 impl BorrowKind {
     pub fn from_mutbl(m: hir::Mutability) -> BorrowKind {
         match m {
-            hir::Mutability::Mut => MutBorrow,
-            hir::Mutability::Not => ImmBorrow,
+            hir::Mutability::Mut => BorrowKind::Mutable,
+            hir::Mutability::Not => BorrowKind::Immutable,
         }
     }
 
@@ -402,13 +401,13 @@ impl BorrowKind {
     /// question.
     pub fn to_mutbl_lossy(self) -> hir::Mutability {
         match self {
-            MutBorrow => hir::Mutability::Mut,
-            ImmBorrow => hir::Mutability::Not,
+            BorrowKind::Mutable => hir::Mutability::Mut,
+            BorrowKind::Immutable => hir::Mutability::Not,
 
             // We have no type corresponding to a unique imm borrow, so
             // use `&mut`. It gives all the capabilities of a `&uniq`
             // and hence is a safe "over approximation".
-            UniqueImmBorrow => hir::Mutability::Mut,
+            BorrowKind::UniqueImmutable => hir::Mutability::Mut,
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 59c7b51ae68..c55733da7b3 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1059,7 +1059,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
                     .map(|v| {
                         mk(ty::ReBound(ty::DebruijnIndex::from(i), ty::BoundRegion {
                             var: ty::BoundVar::from(v),
-                            kind: ty::BrAnon,
+                            kind: ty::BoundRegionKind::Anon,
                         }))
                     })
                     .collect()
@@ -1982,7 +1982,10 @@ impl<'tcx> TyCtxt<'tcx> {
                 region = self.map_opaque_lifetime_to_parent_lifetime(def_id);
                 continue;
             }
-            break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into())));
+            break (
+                scope,
+                ty::BoundRegionKind::Named(def_id.into(), self.item_name(def_id.into())),
+            );
         };
 
         let is_impl_item = match self.hir_node_by_def_id(suitable_region_binding_scope) {
@@ -3091,7 +3094,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     return ty::Region::new_late_param(
                         self,
                         new_parent.to_def_id(),
-                        ty::BoundRegionKind::BrNamed(
+                        ty::BoundRegionKind::Named(
                             lbv.to_def_id(),
                             self.item_name(lbv.to_def_id()),
                         ),
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index b5a77b3c942..7adbd556141 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -399,7 +399,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 let index = entry.index();
                 let var = ty::BoundVar::from_usize(index);
                 let kind = entry
-                    .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon))
+                    .or_insert_with(|| ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon))
                     .expect_region();
                 let br = ty::BoundRegion { var, kind };
                 ty::Region::new_bound(self.tcx, ty::INNERMOST, br)
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index e237d382900..7ee13bc1725 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -690,7 +690,7 @@ impl<'tcx> Instance<'tcx> {
                         && !matches!(
                             tcx.opt_associated_item(def),
                             Some(ty::AssocItem {
-                                container: ty::AssocItemContainer::TraitContainer,
+                                container: ty::AssocItemContainer::Trait,
                                 ..
                             })
                         )
diff --git a/compiler/rustc_middle/src/ty/intrinsic.rs b/compiler/rustc_middle/src/ty/intrinsic.rs
index ed0fb37d3b8..6a3ddacb424 100644
--- a/compiler/rustc_middle/src/ty/intrinsic.rs
+++ b/compiler/rustc_middle/src/ty/intrinsic.rs
@@ -9,6 +9,8 @@ pub struct IntrinsicDef {
     pub name: Symbol,
     /// Whether the intrinsic has no meaningful body and all backends need to shim all calls to it.
     pub must_be_overridden: bool,
+    /// Whether the intrinsic can be invoked from stable const fn
+    pub const_stable: bool,
 }
 
 impl TyCtxt<'_> {
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 8a324be32e7..6d9ba3d60e3 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -49,19 +49,12 @@ pub use rustc_session::lint::RegisteredTools;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{Ident, Symbol, kw, sym};
 use rustc_span::{ExpnId, ExpnKind, Span};
-pub use rustc_type_ir::ConstKind::{
-    Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt,
-    Placeholder as PlaceholderCt, Unevaluated, Value,
-};
 pub use rustc_type_ir::relate::VarianceDiagInfo;
 pub use rustc_type_ir::*;
 use tracing::{debug, instrument};
 pub use vtable::*;
 use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
 
-pub use self::AssocItemContainer::*;
-pub use self::BorrowKind::*;
-pub use self::IntVarValue::*;
 pub use self::closure::{
     BorrowKind, CAPTURE_STRUCT_LOCAL, CaptureInfo, CapturedPlace, ClosureTypeInfo,
     MinCaptureInformationMap, MinCaptureList, RootVariableMinCaptureList, UpvarCapture, UpvarId,
@@ -91,7 +84,6 @@ pub use self::predicate::{
     RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, TraitPredicate, TraitRef,
     TypeOutlivesPredicate,
 };
-pub use self::region::BoundRegionKind::*;
 pub use self::region::{
     BoundRegion, BoundRegionKind, EarlyParamRegion, LateParamRegion, Region, RegionKind, RegionVid,
 };
@@ -902,7 +894,7 @@ impl rustc_type_ir::inherent::PlaceholderLike for PlaceholderRegion {
     }
 
     fn new(ui: UniverseIndex, var: BoundVar) -> Self {
-        Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::BrAnon } }
+        Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::Anon } }
     }
 }
 
@@ -2078,7 +2070,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let Some(item) = self.opt_associated_item(def_id) else {
             return false;
         };
-        if item.container != ty::AssocItemContainer::ImplContainer {
+        if item.container != ty::AssocItemContainer::Impl {
             return false;
         }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index d8725cb6ba0..039c988f5c9 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2483,7 +2483,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
             | ty::RePlaceholder(ty::Placeholder {
                 bound: ty::BoundRegion { kind: br, .. }, ..
             }) => {
-                if let ty::BrNamed(_, name) = br
+                if let ty::BoundRegionKind::Named(_, name) = br
                     && br.is_named()
                 {
                     p!(write("{}", name));
@@ -2569,7 +2569,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
                 // If this is an anonymous placeholder, don't rename. Otherwise, in some
                 // async fns, we get a `for<'r> Send` bound
                 match kind {
-                    ty::BrAnon | ty::BrEnv => r,
+                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => r,
                     _ => {
                         // Index doesn't matter, since this is just for naming and these never get bound
                         let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind };
@@ -2688,12 +2688,13 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                             binder_level_idx: ty::DebruijnIndex,
                             br: ty::BoundRegion| {
                 let (name, kind) = match br.kind {
-                    ty::BrAnon | ty::BrEnv => {
+                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
                         let name = next_name(self);
 
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
-                                let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name);
+                                let kind =
+                                    ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name);
                                 return ty::Region::new_bound(
                                     tcx,
                                     ty::INNERMOST,
@@ -2702,14 +2703,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                             }
                         }
 
-                        (name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name))
+                        (name, ty::BoundRegionKind::Named(CRATE_DEF_ID.to_def_id(), name))
                     }
-                    ty::BrNamed(def_id, kw::UnderscoreLifetime | kw::Empty) => {
+                    ty::BoundRegionKind::Named(def_id, kw::UnderscoreLifetime | kw::Empty) => {
                         let name = next_name(self);
 
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
-                                let kind = ty::BrNamed(def_id, name);
+                                let kind = ty::BoundRegionKind::Named(def_id, name);
                                 return ty::Region::new_bound(
                                     tcx,
                                     ty::INNERMOST,
@@ -2718,9 +2719,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
                             }
                         }
 
-                        (name, ty::BrNamed(def_id, name))
+                        (name, ty::BoundRegionKind::Named(def_id, name))
                     }
-                    ty::BrNamed(_, name) => {
+                    ty::BoundRegionKind::Named(_, name) => {
                         if let Some(lt_idx) = lifetime_idx {
                             if lt_idx > binder_level_idx {
                                 let kind = br.kind;
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index be4772e888f..60c2c322d4f 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -56,7 +56,7 @@ impl<'tcx> Region<'tcx> {
         bound_region: ty::BoundRegion,
     ) -> Region<'tcx> {
         // Use a pre-interned one when possible.
-        if let ty::BoundRegion { var, kind: ty::BrAnon } = bound_region
+        if let ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon } = bound_region
             && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize())
             && let Some(re) = inner.get(var.as_usize()).copied()
         {
@@ -147,7 +147,7 @@ impl<'tcx> rustc_type_ir::inherent::Region<TyCtxt<'tcx>> for Region<'tcx> {
     }
 
     fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self {
-        Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon })
+        Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon })
     }
 
     fn new_static(tcx: TyCtxt<'tcx>) -> Self {
@@ -311,7 +311,7 @@ impl<'tcx> Region<'tcx> {
                 Some(tcx.generics_of(binding_item).region_param(ebr, tcx).def_id)
             }
             ty::ReLateParam(ty::LateParamRegion {
-                bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
+                bound_region: ty::BoundRegionKind::Named(def_id, _),
                 ..
             }) => Some(def_id),
             _ => None,
@@ -355,7 +355,7 @@ impl std::fmt::Debug for EarlyParamRegion {
 /// Similar to a placeholder region as we create `LateParam` regions when entering a binder
 /// except they are always in the root universe and instead of using a boundvar to distinguish
 /// between others we use the `DefId` of the parameter. For this reason the `bound_region` field
-/// should basically always be `BoundRegionKind::BrNamed` as otherwise there is no way of telling
+/// should basically always be `BoundRegionKind::Named` as otherwise there is no way of telling
 /// different parameters apart.
 pub struct LateParamRegion {
     pub scope: DefId,
@@ -366,17 +366,17 @@ pub struct LateParamRegion {
 #[derive(HashStable)]
 pub enum BoundRegionKind {
     /// An anonymous region parameter for a given fn (&T)
-    BrAnon,
+    Anon,
 
     /// Named region parameters for functions (a in &'a T)
     ///
     /// The `DefId` is needed to distinguish free regions in
     /// the event of shadowing.
-    BrNamed(DefId, Symbol),
+    Named(DefId, Symbol),
 
     /// Anonymous region for the implicit env pointer parameter
     /// to a closure
-    BrEnv,
+    ClosureEnv,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
@@ -399,9 +399,9 @@ impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundRegion {
 impl core::fmt::Debug for BoundRegion {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self.kind {
-            BoundRegionKind::BrAnon => write!(f, "{:?}", self.var),
-            BoundRegionKind::BrEnv => write!(f, "{:?}.Env", self.var),
-            BoundRegionKind::BrNamed(def, symbol) => {
+            BoundRegionKind::Anon => write!(f, "{:?}", self.var),
+            BoundRegionKind::ClosureEnv => write!(f, "{:?}.Env", self.var),
+            BoundRegionKind::Named(def, symbol) => {
                 write!(f, "{:?}.Named({:?}, {:?})", self.var, def, symbol)
             }
         }
@@ -411,9 +411,7 @@ impl core::fmt::Debug for BoundRegion {
 impl BoundRegionKind {
     pub fn is_named(&self) -> bool {
         match *self {
-            BoundRegionKind::BrNamed(_, name) => {
-                name != kw::UnderscoreLifetime && name != kw::Empty
-            }
+            BoundRegionKind::Named(_, name) => name != kw::UnderscoreLifetime && name != kw::Empty,
             _ => false,
         }
     }
@@ -421,7 +419,7 @@ impl BoundRegionKind {
     pub fn get_name(&self) -> Option<Symbol> {
         if self.is_named() {
             match *self {
-                BoundRegionKind::BrNamed(_, name) => return Some(name),
+                BoundRegionKind::Named(_, name) => return Some(name),
                 _ => unreachable!(),
             }
         }
@@ -431,7 +429,7 @@ impl BoundRegionKind {
 
     pub fn get_id(&self) -> Option<DefId> {
         match *self {
-            BoundRegionKind::BrNamed(id, _) => Some(id),
+            BoundRegionKind::Named(id, _) => Some(id),
             _ => None,
         }
     }
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 3268dabd165..e48fac6c7e8 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -62,15 +62,15 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
 impl fmt::Debug for ty::BoundRegionKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            ty::BrAnon => write!(f, "BrAnon"),
-            ty::BrNamed(did, name) => {
+            ty::BoundRegionKind::Anon => write!(f, "BrAnon"),
+            ty::BoundRegionKind::Named(did, name) => {
                 if did.is_crate_root() {
                     write!(f, "BrNamed({name})")
                 } else {
                     write!(f, "BrNamed({did:?}, {name})")
                 }
             }
-            ty::BrEnv => write!(f, "BrEnv"),
+            ty::BoundRegionKind::ClosureEnv => write!(f, "BrEnv"),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 83276808a28..56e723ab517 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -735,8 +735,11 @@ impl<'tcx> TyCtxt<'tcx> {
                 let ty = self.fold_regions(decl.ty, |re, debruijn| {
                     assert_eq!(re, self.lifetimes.re_erased);
                     let var = ty::BoundVar::from_usize(vars.len());
-                    vars.push(ty::BoundVariableKind::Region(ty::BrAnon));
-                    ty::Region::new_bound(self, debruijn, ty::BoundRegion { var, kind: ty::BrAnon })
+                    vars.push(ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon));
+                    ty::Region::new_bound(self, debruijn, ty::BoundRegion {
+                        var,
+                        kind: ty::BoundRegionKind::Anon,
+                    })
                 });
                 ty::EarlyBinder::bind(ty::Binder::bind_with_vars(
                     ty,
@@ -1789,6 +1792,7 @@ pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Intrinsi
         Some(ty::IntrinsicDef {
             name: tcx.item_name(def_id.into()),
             must_be_overridden: tcx.has_attr(def_id, sym::rustc_intrinsic_must_be_overridden),
+            const_stable: tcx.has_attr(def_id, sym::rustc_const_stable_intrinsic),
         })
     } else {
         None
diff --git a/compiler/rustc_middle/src/util/call_kind.rs b/compiler/rustc_middle/src/util/call_kind.rs
index fe30cbfae4e..ed27a880562 100644
--- a/compiler/rustc_middle/src/util/call_kind.rs
+++ b/compiler/rustc_middle/src/util/call_kind.rs
@@ -72,8 +72,8 @@ pub fn call_kind<'tcx>(
     let parent = tcx.opt_associated_item(method_did).and_then(|assoc| {
         let container_id = assoc.container_id(tcx);
         match assoc.container {
-            AssocItemContainer::ImplContainer => tcx.trait_id_of_impl(container_id),
-            AssocItemContainer::TraitContainer => Some(container_id),
+            AssocItemContainer::Impl => tcx.trait_id_of_impl(container_id),
+            AssocItemContainer::Trait => Some(container_id),
         }
     });
 
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index 0481f715019..64457031997 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -136,7 +136,9 @@ impl<'tcx> Cx<'tcx> {
             Adjust::Deref(Some(deref)) => {
                 // We don't need to do call adjust_span here since
                 // deref coercions always start with a built-in deref.
-                let call = deref.method_call(self.tcx(), expr.ty);
+                let call_def_id = deref.method_call(self.tcx());
+                let overloaded_callee =
+                    Ty::new_fn_def(self.tcx(), call_def_id, self.tcx().mk_args(&[expr.ty.into()]));
 
                 expr = Expr {
                     temp_lifetime,
@@ -150,7 +152,13 @@ impl<'tcx> Cx<'tcx> {
 
                 let expr = Box::new([self.thir.exprs.push(expr)]);
 
-                self.overloaded_place(hir_expr, adjustment.target, Some(call), expr, deref.span)
+                self.overloaded_place(
+                    hir_expr,
+                    adjustment.target,
+                    Some(overloaded_callee),
+                    expr,
+                    deref.span,
+                )
             }
             Adjust::Borrow(AutoBorrow::Ref(m)) => ExprKind::Borrow {
                 borrow_kind: m.to_borrow_kind(),
@@ -1185,11 +1193,11 @@ impl<'tcx> Cx<'tcx> {
             ty::UpvarCapture::ByValue => captured_place_expr,
             ty::UpvarCapture::ByRef(upvar_borrow) => {
                 let borrow_kind = match upvar_borrow {
-                    ty::BorrowKind::ImmBorrow => BorrowKind::Shared,
-                    ty::BorrowKind::UniqueImmBorrow => {
+                    ty::BorrowKind::Immutable => BorrowKind::Shared,
+                    ty::BorrowKind::UniqueImmutable => {
                         BorrowKind::Mut { kind: mir::MutBorrowKind::ClosureCapture }
                     }
-                    ty::BorrowKind::MutBorrow => {
+                    ty::BorrowKind::Mutable => {
                         BorrowKind::Mut { kind: mir::MutBorrowKind::Default }
                     }
                 };
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 8bd615e6d79..c85d0bd05cb 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -136,8 +136,9 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
                 node_replacements.array_windows()
             {
                 assert!(
-                    node_range.0.end <= next_node_range.0.start,
-                    "Node ranges should be disjoint: ({:?}, {:?}) ({:?}, {:?})",
+                    node_range.0.end <= next_node_range.0.start
+                        || node_range.0.end >= next_node_range.0.end,
+                    "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
                     node_range,
                     tokens,
                     next_node_range,
@@ -145,8 +146,20 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
                 );
             }
 
-            // Process the replace ranges.
-            for (node_range, target) in node_replacements.into_iter() {
+            // Process the replace ranges, starting from the highest start
+            // position and working our way back. If have tokens like:
+            //
+            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
+            //
+            // Then we will generate replace ranges for both
+            // the `#[cfg(FALSE)] field: bool` and the entire
+            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
+            //
+            // By starting processing from the replace range with the greatest
+            // start position, we ensure that any (outer) replace range which
+            // encloses another (inner) replace range will fully overwrite the
+            // inner range's replacement.
+            for (node_range, target) in node_replacements.into_iter().rev() {
                 assert!(
                     !node_range.0.is_empty(),
                     "Cannot replace an empty node range: {:?}",
@@ -383,9 +396,10 @@ impl<'a> Parser<'a> {
             // from `ParserRange` form to `NodeRange` form. We will perform the actual
             // replacement only when we convert the `LazyAttrTokenStream` to an
             // `AttrTokenStream`.
-            self.capture_state
-                .parser_replacements
-                .drain(parser_replacements_start..parser_replacements_end)
+            self.capture_state.parser_replacements
+                [parser_replacements_start..parser_replacements_end]
+                .iter()
+                .cloned()
                 .chain(inner_attr_parser_replacements)
                 .map(|(parser_range, data)| {
                     (NodeRange::new(parser_range, collect_pos.start_pos), data)
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 27714a0fdcc..55fdbac8ad6 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -3,7 +3,7 @@
 // completely accurate (some things might be counted twice, others missed).
 
 use rustc_ast::visit::BoundKind;
-use rustc_ast::{self as ast, AttrId, NodeId, visit as ast_visit};
+use rustc_ast::{self as ast, NodeId, visit as ast_visit};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::{HirId, intravisit as hir_visit};
@@ -13,13 +13,6 @@ use rustc_middle::util::common::to_readable_str;
 use rustc_span::Span;
 use rustc_span::def_id::LocalDefId;
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-enum Id {
-    Node(HirId),
-    Attr(AttrId),
-    None,
-}
-
 struct NodeStats {
     count: usize,
     size: usize,
@@ -62,7 +55,7 @@ impl Node {
 struct StatCollector<'k> {
     krate: Option<Map<'k>>,
     nodes: FxHashMap<&'static str, Node>,
-    seen: FxHashSet<Id>,
+    seen: FxHashSet<HirId>,
 }
 
 pub fn print_hir_stats(tcx: TyCtxt<'_>) {
@@ -87,12 +80,18 @@ pub fn print_ast_stats(krate: &ast::Crate, title: &str, prefix: &str) {
 
 impl<'k> StatCollector<'k> {
     // Record a top-level node.
-    fn record<T>(&mut self, label: &'static str, id: Id, val: &T) {
+    fn record<T>(&mut self, label: &'static str, id: Option<HirId>, val: &T) {
         self.record_inner(label, None, id, val);
     }
 
     // Record a two-level entry, with a top-level enum type and a variant.
-    fn record_variant<T>(&mut self, label1: &'static str, label2: &'static str, id: Id, val: &T) {
+    fn record_variant<T>(
+        &mut self,
+        label1: &'static str,
+        label2: &'static str,
+        id: Option<HirId>,
+        val: &T,
+    ) {
         self.record_inner(label1, Some(label2), id, val);
     }
 
@@ -100,10 +99,10 @@ impl<'k> StatCollector<'k> {
         &mut self,
         label1: &'static str,
         label2: Option<&'static str>,
-        id: Id,
+        id: Option<HirId>,
         val: &T,
     ) {
-        if id != Id::None && !self.seen.insert(id) {
+        if id.is_some_and(|x| !self.seen.insert(x)) {
             return;
         }
 
@@ -191,7 +190,7 @@ macro_rules! record_variants {
 
 impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     fn visit_param(&mut self, param: &'v hir::Param<'v>) {
-        self.record("Param", Id::Node(param.hir_id), param);
+        self.record("Param", Some(param.hir_id), param);
         hir_visit::walk_param(self, param)
     }
 
@@ -221,7 +220,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_item(&mut self, i: &'v hir::Item<'v>) {
-        record_variants!((self, i, i.kind, Id::Node(i.hir_id()), hir, Item, ItemKind), [
+        record_variants!((self, i, i.kind, Some(i.hir_id()), hir, Item, ItemKind), [
             ExternCrate,
             Use,
             Static,
@@ -243,47 +242,46 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_body(&mut self, b: &hir::Body<'v>) {
-        self.record("Body", Id::None, b);
+        self.record("Body", None, b);
         hir_visit::walk_body(self, b);
     }
 
     fn visit_mod(&mut self, m: &'v hir::Mod<'v>, _s: Span, n: HirId) {
-        self.record("Mod", Id::None, m);
+        self.record("Mod", None, m);
         hir_visit::walk_mod(self, m, n)
     }
 
     fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) {
-        record_variants!(
-            (self, i, i.kind, Id::Node(i.hir_id()), hir, ForeignItem, ForeignItemKind),
-            [Fn, Static, Type]
-        );
+        record_variants!((self, i, i.kind, Some(i.hir_id()), hir, ForeignItem, ForeignItemKind), [
+            Fn, Static, Type
+        ]);
         hir_visit::walk_foreign_item(self, i)
     }
 
     fn visit_local(&mut self, l: &'v hir::LetStmt<'v>) {
-        self.record("Local", Id::Node(l.hir_id), l);
+        self.record("Local", Some(l.hir_id), l);
         hir_visit::walk_local(self, l)
     }
 
     fn visit_block(&mut self, b: &'v hir::Block<'v>) {
-        self.record("Block", Id::Node(b.hir_id), b);
+        self.record("Block", Some(b.hir_id), b);
         hir_visit::walk_block(self, b)
     }
 
     fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
-        record_variants!((self, s, s.kind, Id::Node(s.hir_id), hir, Stmt, StmtKind), [
+        record_variants!((self, s, s.kind, Some(s.hir_id), hir, Stmt, StmtKind), [
             Let, Item, Expr, Semi
         ]);
         hir_visit::walk_stmt(self, s)
     }
 
     fn visit_arm(&mut self, a: &'v hir::Arm<'v>) {
-        self.record("Arm", Id::Node(a.hir_id), a);
+        self.record("Arm", Some(a.hir_id), a);
         hir_visit::walk_arm(self, a)
     }
 
     fn visit_pat(&mut self, p: &'v hir::Pat<'v>) {
-        record_variants!((self, p, p.kind, Id::Node(p.hir_id), hir, Pat, PatKind), [
+        record_variants!((self, p, p.kind, Some(p.hir_id), hir, Pat, PatKind), [
             Wild,
             Binding,
             Struct,
@@ -304,12 +302,12 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_pat_field(&mut self, f: &'v hir::PatField<'v>) {
-        self.record("PatField", Id::Node(f.hir_id), f);
+        self.record("PatField", Some(f.hir_id), f);
         hir_visit::walk_pat_field(self, f)
     }
 
     fn visit_expr(&mut self, e: &'v hir::Expr<'v>) {
-        record_variants!((self, e, e.kind, Id::Node(e.hir_id), hir, Expr, ExprKind), [
+        record_variants!((self, e, e.kind, Some(e.hir_id), hir, Expr, ExprKind), [
             ConstBlock, Array, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, DropTemps,
             Let, If, Loop, Match, Closure, Block, Assign, AssignOp, Field, Index, Path, AddrOf,
             Break, Continue, Ret, Become, InlineAsm, OffsetOf, Struct, Repeat, Yield, Err
@@ -318,12 +316,12 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_expr_field(&mut self, f: &'v hir::ExprField<'v>) {
-        self.record("ExprField", Id::Node(f.hir_id), f);
+        self.record("ExprField", Some(f.hir_id), f);
         hir_visit::walk_expr_field(self, f)
     }
 
     fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
-        record_variants!((self, t, t.kind, Id::Node(t.hir_id), hir, Ty, TyKind), [
+        record_variants!((self, t, t.kind, Some(t.hir_id), hir, Ty, TyKind), [
             InferDelegation,
             Slice,
             Array,
@@ -345,17 +343,17 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
-        self.record("GenericParam", Id::Node(p.hir_id), p);
+        self.record("GenericParam", Some(p.hir_id), p);
         hir_visit::walk_generic_param(self, p)
     }
 
     fn visit_generics(&mut self, g: &'v hir::Generics<'v>) {
-        self.record("Generics", Id::None, g);
+        self.record("Generics", None, g);
         hir_visit::walk_generics(self, g)
     }
 
     fn visit_where_predicate(&mut self, p: &'v hir::WherePredicate<'v>) {
-        record_variants!((self, p, p, Id::None, hir, WherePredicate, WherePredicate), [
+        record_variants!((self, p, p, None, hir, WherePredicate, WherePredicate), [
             BoundPredicate,
             RegionPredicate,
             EqPredicate
@@ -371,66 +369,64 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
         _: Span,
         id: LocalDefId,
     ) {
-        self.record("FnDecl", Id::None, fd);
+        self.record("FnDecl", None, fd);
         hir_visit::walk_fn(self, fk, fd, b, id)
     }
 
     fn visit_use(&mut self, p: &'v hir::UsePath<'v>, hir_id: HirId) {
         // This is `visit_use`, but the type is `Path` so record it that way.
-        self.record("Path", Id::None, p);
+        self.record("Path", None, p);
         hir_visit::walk_use(self, p, hir_id)
     }
 
     fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) {
-        record_variants!(
-            (self, ti, ti.kind, Id::Node(ti.hir_id()), hir, TraitItem, TraitItemKind),
-            [Const, Fn, Type]
-        );
+        record_variants!((self, ti, ti.kind, Some(ti.hir_id()), hir, TraitItem, TraitItemKind), [
+            Const, Fn, Type
+        ]);
         hir_visit::walk_trait_item(self, ti)
     }
 
     fn visit_trait_item_ref(&mut self, ti: &'v hir::TraitItemRef) {
-        self.record("TraitItemRef", Id::Node(ti.id.hir_id()), ti);
+        self.record("TraitItemRef", Some(ti.id.hir_id()), ti);
         hir_visit::walk_trait_item_ref(self, ti)
     }
 
     fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
-        record_variants!(
-            (self, ii, ii.kind, Id::Node(ii.hir_id()), hir, ImplItem, ImplItemKind),
-            [Const, Fn, Type]
-        );
+        record_variants!((self, ii, ii.kind, Some(ii.hir_id()), hir, ImplItem, ImplItemKind), [
+            Const, Fn, Type
+        ]);
         hir_visit::walk_impl_item(self, ii)
     }
 
     fn visit_foreign_item_ref(&mut self, fi: &'v hir::ForeignItemRef) {
-        self.record("ForeignItemRef", Id::Node(fi.id.hir_id()), fi);
+        self.record("ForeignItemRef", Some(fi.id.hir_id()), fi);
         hir_visit::walk_foreign_item_ref(self, fi)
     }
 
     fn visit_impl_item_ref(&mut self, ii: &'v hir::ImplItemRef) {
-        self.record("ImplItemRef", Id::Node(ii.id.hir_id()), ii);
+        self.record("ImplItemRef", Some(ii.id.hir_id()), ii);
         hir_visit::walk_impl_item_ref(self, ii)
     }
 
     fn visit_param_bound(&mut self, b: &'v hir::GenericBound<'v>) {
-        record_variants!((self, b, b, Id::None, hir, GenericBound, GenericBound), [
+        record_variants!((self, b, b, None, hir, GenericBound, GenericBound), [
             Trait, Outlives, Use
         ]);
         hir_visit::walk_param_bound(self, b)
     }
 
     fn visit_field_def(&mut self, s: &'v hir::FieldDef<'v>) {
-        self.record("FieldDef", Id::Node(s.hir_id), s);
+        self.record("FieldDef", Some(s.hir_id), s);
         hir_visit::walk_field_def(self, s)
     }
 
     fn visit_variant(&mut self, v: &'v hir::Variant<'v>) {
-        self.record("Variant", Id::None, v);
+        self.record("Variant", None, v);
         hir_visit::walk_variant(self, v)
     }
 
     fn visit_generic_arg(&mut self, ga: &'v hir::GenericArg<'v>) {
-        record_variants!((self, ga, ga, Id::Node(ga.hir_id()), hir, GenericArg, GenericArg), [
+        record_variants!((self, ga, ga, Some(ga.hir_id()), hir, GenericArg, GenericArg), [
             Lifetime, Type, Const, Infer
         ]);
         match ga {
@@ -442,50 +438,50 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
-        self.record("Lifetime", Id::Node(lifetime.hir_id), lifetime);
+        self.record("Lifetime", Some(lifetime.hir_id), lifetime);
         hir_visit::walk_lifetime(self, lifetime)
     }
 
     fn visit_path(&mut self, path: &hir::Path<'v>, _id: HirId) {
-        self.record("Path", Id::None, path);
+        self.record("Path", None, path);
         hir_visit::walk_path(self, path)
     }
 
     fn visit_path_segment(&mut self, path_segment: &'v hir::PathSegment<'v>) {
-        self.record("PathSegment", Id::None, path_segment);
+        self.record("PathSegment", None, path_segment);
         hir_visit::walk_path_segment(self, path_segment)
     }
 
     fn visit_generic_args(&mut self, ga: &'v hir::GenericArgs<'v>) {
-        self.record("GenericArgs", Id::None, ga);
+        self.record("GenericArgs", None, ga);
         hir_visit::walk_generic_args(self, ga)
     }
 
     fn visit_assoc_item_constraint(&mut self, constraint: &'v hir::AssocItemConstraint<'v>) {
-        self.record("AssocItemConstraint", Id::Node(constraint.hir_id), constraint);
+        self.record("AssocItemConstraint", Some(constraint.hir_id), constraint);
         hir_visit::walk_assoc_item_constraint(self, constraint)
     }
 
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
-        self.record("Attribute", Id::Attr(attr.id), attr);
+        self.record("Attribute", None, attr);
     }
 
     fn visit_inline_asm(&mut self, asm: &'v hir::InlineAsm<'v>, id: HirId) {
-        self.record("InlineAsm", Id::None, asm);
+        self.record("InlineAsm", None, asm);
         hir_visit::walk_inline_asm(self, asm, id);
     }
 }
 
 impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) {
-        record_variants!((self, i, i.kind, Id::None, ast, ForeignItem, ForeignItemKind), [
+        record_variants!((self, i, i.kind, None, ast, ForeignItem, ForeignItemKind), [
             Static, Fn, TyAlias, MacCall
         ]);
         ast_visit::walk_item(self, i)
     }
 
     fn visit_item(&mut self, i: &'v ast::Item) {
-        record_variants!((self, i, i.kind, Id::None, ast, Item, ItemKind), [
+        record_variants!((self, i, i.kind, None, ast, Item, ItemKind), [
             ExternCrate,
             Use,
             Static,
@@ -510,34 +506,34 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_local(&mut self, l: &'v ast::Local) {
-        self.record("Local", Id::None, l);
+        self.record("Local", None, l);
         ast_visit::walk_local(self, l)
     }
 
     fn visit_block(&mut self, b: &'v ast::Block) {
-        self.record("Block", Id::None, b);
+        self.record("Block", None, b);
         ast_visit::walk_block(self, b)
     }
 
     fn visit_stmt(&mut self, s: &'v ast::Stmt) {
-        record_variants!((self, s, s.kind, Id::None, ast, Stmt, StmtKind), [
+        record_variants!((self, s, s.kind, None, ast, Stmt, StmtKind), [
             Let, Item, Expr, Semi, Empty, MacCall
         ]);
         ast_visit::walk_stmt(self, s)
     }
 
     fn visit_param(&mut self, p: &'v ast::Param) {
-        self.record("Param", Id::None, p);
+        self.record("Param", None, p);
         ast_visit::walk_param(self, p)
     }
 
     fn visit_arm(&mut self, a: &'v ast::Arm) {
-        self.record("Arm", Id::None, a);
+        self.record("Arm", None, a);
         ast_visit::walk_arm(self, a)
     }
 
     fn visit_pat(&mut self, p: &'v ast::Pat) {
-        record_variants!((self, p, p.kind, Id::None, ast, Pat, PatKind), [
+        record_variants!((self, p, p.kind, None, ast, Pat, PatKind), [
             Wild,
             Ident,
             Struct,
@@ -563,7 +559,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     fn visit_expr(&mut self, e: &'v ast::Expr) {
         #[rustfmt::skip]
         record_variants!(
-            (self, e, e.kind, Id::None, ast, Expr, ExprKind),
+            (self, e, e.kind, None, ast, Expr, ExprKind),
             [
                 Array, ConstBlock, Call, MethodCall, Tup, Binary, Unary, Lit, Cast, Type, Let,
                 If, While, ForLoop, Loop, Match, Closure, Block, Await, TryBlock, Assign,
@@ -576,7 +572,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_ty(&mut self, t: &'v ast::Ty) {
-        record_variants!((self, t, t.kind, Id::None, ast, Ty, TyKind), [
+        record_variants!((self, t, t.kind, None, ast, Ty, TyKind), [
             Slice,
             Array,
             Ptr,
@@ -603,12 +599,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_generic_param(&mut self, g: &'v ast::GenericParam) {
-        self.record("GenericParam", Id::None, g);
+        self.record("GenericParam", None, g);
         ast_visit::walk_generic_param(self, g)
     }
 
     fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) {
-        record_variants!((self, p, p, Id::None, ast, WherePredicate, WherePredicate), [
+        record_variants!((self, p, p, None, ast, WherePredicate, WherePredicate), [
             BoundPredicate,
             RegionPredicate,
             EqPredicate
@@ -617,12 +613,12 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, _: Span, _: NodeId) {
-        self.record("FnDecl", Id::None, fk.decl());
+        self.record("FnDecl", None, fk.decl());
         ast_visit::walk_fn(self, fk)
     }
 
     fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
-        record_variants!((self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind), [
+        record_variants!((self, i, i.kind, None, ast, AssocItem, AssocItemKind), [
             Const,
             Fn,
             Type,
@@ -634,19 +630,19 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_param_bound(&mut self, b: &'v ast::GenericBound, _ctxt: BoundKind) {
-        record_variants!((self, b, b, Id::None, ast, GenericBound, GenericBound), [
+        record_variants!((self, b, b, None, ast, GenericBound, GenericBound), [
             Trait, Outlives, Use
         ]);
         ast_visit::walk_param_bound(self, b)
     }
 
     fn visit_field_def(&mut self, s: &'v ast::FieldDef) {
-        self.record("FieldDef", Id::None, s);
+        self.record("FieldDef", None, s);
         ast_visit::walk_field_def(self, s)
     }
 
     fn visit_variant(&mut self, v: &'v ast::Variant) {
-        self.record("Variant", Id::None, v);
+        self.record("Variant", None, v);
         ast_visit::walk_variant(self, v)
     }
 
@@ -660,7 +656,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     // common than the former case, so we implement this visitor and tolerate
     // the double counting in the former case.
     fn visit_path_segment(&mut self, path_segment: &'v ast::PathSegment) {
-        self.record("PathSegment", Id::None, path_segment);
+        self.record("PathSegment", None, path_segment);
         ast_visit::walk_path_segment(self, path_segment)
     }
 
@@ -669,7 +665,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     // common, so we implement `visit_generic_args` and tolerate the double
     // counting in the former case.
     fn visit_generic_args(&mut self, g: &'v ast::GenericArgs) {
-        record_variants!((self, g, g, Id::None, ast, GenericArgs, GenericArgs), [
+        record_variants!((self, g, g, None, ast, GenericArgs, GenericArgs), [
             AngleBracketed,
             Parenthesized,
             ParenthesizedElided
@@ -678,24 +674,24 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
-        record_variants!((self, attr, attr.kind, Id::None, ast, Attribute, AttrKind), [
+        record_variants!((self, attr, attr.kind, None, ast, Attribute, AttrKind), [
             Normal, DocComment
         ]);
         ast_visit::walk_attribute(self, attr)
     }
 
     fn visit_expr_field(&mut self, f: &'v ast::ExprField) {
-        self.record("ExprField", Id::None, f);
+        self.record("ExprField", None, f);
         ast_visit::walk_expr_field(self, f)
     }
 
     fn visit_crate(&mut self, krate: &'v ast::Crate) {
-        self.record("Crate", Id::None, krate);
+        self.record("Crate", None, krate);
         ast_visit::walk_crate(self, krate)
     }
 
     fn visit_inline_asm(&mut self, asm: &'v ast::InlineAsm) {
-        self.record("InlineAsm", Id::None, asm);
+        self.record("InlineAsm", None, asm);
         ast_visit::walk_inline_asm(self, asm)
     }
 }
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 737e163efce..cd47c8ece60 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -106,7 +106,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         def_id: LocalDefId,
         item_sp: Span,
         fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
-        is_foreign_item: bool,
         kind: AnnotationKind,
         inherit_deprecation: InheritDeprecation,
         inherit_const_stability: InheritConstStability,
@@ -175,11 +174,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
         // implied), check if the function/method is const or the parent impl block is const.
         if let Some(fn_sig) = fn_sig
             && !fn_sig.header.is_const()
-            // We have to exclude foreign items as they might be intrinsics. Sadly we can't check
-            // their ABI; `fn_sig.abi` is *not* correct for foreign functions.
-            && !is_foreign_item
             && const_stab.is_some()
-            && (!self.in_trait_impl || !self.tcx.is_const_fn(def_id.to_def_id()))
         {
             self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
         }
@@ -398,7 +393,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
                         ctor_def_id,
                         i.span,
                         None,
-                        /* is_foreign_item */ false,
                         AnnotationKind::Required,
                         InheritDeprecation::Yes,
                         InheritConstStability::No,
@@ -417,7 +411,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
             i.owner_id.def_id,
             i.span,
             fn_sig,
-            /* is_foreign_item */ false,
             kind,
             InheritDeprecation::Yes,
             const_stab_inherit,
@@ -437,7 +430,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
             ti.owner_id.def_id,
             ti.span,
             fn_sig,
-            /* is_foreign_item */ false,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -461,7 +453,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
             ii.owner_id.def_id,
             ii.span,
             fn_sig,
-            /* is_foreign_item */ false,
             kind,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -477,7 +468,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
             var.def_id,
             var.span,
             None,
-            /* is_foreign_item */ false,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -488,7 +478,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
                         ctor_def_id,
                         var.span,
                         None,
-                        /* is_foreign_item */ false,
                         AnnotationKind::Required,
                         InheritDeprecation::Yes,
                         InheritConstStability::No,
@@ -507,7 +496,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
             s.def_id,
             s.span,
             None,
-            /* is_foreign_item */ false,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -527,7 +515,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
             i.owner_id.def_id,
             i.span,
             fn_sig,
-            /* is_foreign_item */ true,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
@@ -550,7 +537,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
             p.def_id,
             p.span,
             None,
-            /* is_foreign_item */ false,
             kind,
             InheritDeprecation::No,
             InheritConstStability::No,
@@ -712,7 +698,6 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
             CRATE_DEF_ID,
             tcx.hir().span(CRATE_HIR_ID),
             None,
-            /* is_foreign_item */ false,
             AnnotationKind::Required,
             InheritDeprecation::Yes,
             InheritConstStability::No,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index f0632a21091..42455983575 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -459,7 +459,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             return (err, Vec::new());
         }
 
-        let (found, mut candidates) = self.try_lookup_name_relaxed(
+        let (found, suggested_candidates, mut candidates) = self.try_lookup_name_relaxed(
             &mut err,
             source,
             path,
@@ -478,7 +478,15 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         }
 
         let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error);
-        fallback |= self.suggest_typo(&mut err, source, path, following_seg, span, &base_error);
+        fallback |= self.suggest_typo(
+            &mut err,
+            source,
+            path,
+            following_seg,
+            span,
+            &base_error,
+            suggested_candidates,
+        );
 
         if fallback {
             // Fallback label.
@@ -589,7 +597,16 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         span: Span,
         res: Option<Res>,
         base_error: &BaseError,
-    ) -> (bool, Vec<ImportSuggestion>) {
+    ) -> (bool, FxHashSet<String>, Vec<ImportSuggestion>) {
+        let span = match following_seg {
+            Some(_) if path[0].ident.span.eq_ctxt(path[path.len() - 1].ident.span) => {
+                // The path `span` that comes in includes any following segments, which we don't
+                // want to replace in the suggestions.
+                path[0].ident.span.to(path[path.len() - 1].ident.span)
+            }
+            _ => span,
+        };
+        let mut suggested_candidates = FxHashSet::default();
         // Try to lookup name in more relaxed fashion for better error reporting.
         let ident = path.last().unwrap().ident;
         let is_expected = &|res| source.is_expected(res);
@@ -646,6 +663,11 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 };
                 let msg = format!("{preamble}try using the variant's enum");
 
+                suggested_candidates.extend(
+                    enum_candidates
+                        .iter()
+                        .map(|(_variant_path, enum_ty_path)| enum_ty_path.clone()),
+                );
                 err.span_suggestions(
                     span,
                     msg,
@@ -658,7 +680,8 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         // Try finding a suitable replacement.
         let typo_sugg = self
             .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected)
-            .to_opt_suggestion();
+            .to_opt_suggestion()
+            .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str()));
         if let [segment] = path
             && !matches!(source, PathSource::Delegation)
             && self.self_type_is_available()
@@ -719,7 +742,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     }
                 }
                 self.r.add_typo_suggestion(err, typo_sugg, ident_span);
-                return (true, candidates);
+                return (true, suggested_candidates, candidates);
             }
 
             // If the first argument in call is `self` suggest calling a method.
@@ -737,7 +760,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     format!("self.{path_str}({args_snippet})"),
                     Applicability::MachineApplicable,
                 );
-                return (true, candidates);
+                return (true, suggested_candidates, candidates);
             }
         }
 
@@ -754,7 +777,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             ) {
                 // We do this to avoid losing a secondary span when we override the main error span.
                 self.r.add_typo_suggestion(err, typo_sugg, ident_span);
-                return (true, candidates);
+                return (true, suggested_candidates, candidates);
             }
         }
 
@@ -772,7 +795,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                         ident.span,
                         format!("the binding `{path_str}` is available in a different scope in the same function"),
                     );
-                    return (true, candidates);
+                    return (true, suggested_candidates, candidates);
                 }
             }
         }
@@ -781,7 +804,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg);
         }
 
-        (false, candidates)
+        (false, suggested_candidates, candidates)
     }
 
     fn suggest_trait_and_bounds(
@@ -869,13 +892,16 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         following_seg: Option<&Segment>,
         span: Span,
         base_error: &BaseError,
+        suggested_candidates: FxHashSet<String>,
     ) -> bool {
         let is_expected = &|res| source.is_expected(res);
         let ident_span = path.last().map_or(span, |ident| ident.ident.span);
         let typo_sugg =
             self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected);
         let mut fallback = false;
-        let typo_sugg = typo_sugg.to_opt_suggestion();
+        let typo_sugg = typo_sugg
+            .to_opt_suggestion()
+            .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str()));
         if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) {
             fallback = true;
             match self.diag_metadata.current_let_binding {
@@ -894,10 +920,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
 
             // If the trait has a single item (which wasn't matched by the algorithm), suggest it
             let suggestion = self.get_single_associated_item(path, &source, is_expected);
-            if !self.r.add_typo_suggestion(err, suggestion, ident_span) {
-                fallback = !self.let_binding_suggestion(err, ident_span);
-            }
+            self.r.add_typo_suggestion(err, suggestion, ident_span);
         }
+
+        if self.let_binding_suggestion(err, ident_span) {
+            fallback = false;
+        }
+
         fallback
     }
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index bb730592068..fe05605c1b9 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1320,6 +1320,7 @@ pub enum PAuthKey {
 #[derive(Clone, Copy, Hash, Debug, PartialEq)]
 pub struct PacRet {
     pub leaf: bool,
+    pub pc: bool,
     pub key: PAuthKey,
 }
 
@@ -1350,19 +1351,6 @@ pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: &
                 early_dcx.early_warn(warning)
             }
 
-            // The `wasm32-wasi` target is being renamed to `wasm32-wasip1` as
-            // part of rust-lang/compiler-team#607 and
-            // rust-lang/compiler-team#695. Warn unconditionally on usage to
-            // raise awareness of the renaming. This code will be deleted in
-            // October 2024.
-            if opts.target_triple.tuple() == "wasm32-wasi" {
-                early_dcx.early_warn(
-                    "the `wasm32-wasi` target is being renamed to \
-                    `wasm32-wasip1` and the `wasm32-wasi` target will be \
-                    removed from nightly in October 2024 and removed from \
-                    stable Rust in January 2025",
-                )
-            }
             if !matches!(target.pointer_width, 16 | 32 | 64) {
                 early_dcx.early_fatal(format!(
                     "target specification was invalid: unrecognized target-pointer-width {}",
@@ -2466,6 +2454,10 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
         early_dcx.early_fatal("value for threads must be a positive non-zero integer");
     }
 
+    if unstable_opts.threads == parse::MAX_THREADS_CAP {
+        early_dcx.early_warn(format!("number of threads was capped at {}", parse::MAX_THREADS_CAP));
+    }
+
     let fuel = unstable_opts.fuel.is_some() || unstable_opts.print_fuel.is_some();
     if fuel && unstable_opts.threads > 1 {
         early_dcx.early_fatal("optimization fuel is incompatible with multiple threads");
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index 347d298bacc..99d9d5b7665 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -370,8 +370,9 @@ impl CheckCfg {
         ins!(sym::sanitizer_cfi_normalize_integers, no_values);
 
         ins!(sym::target_feature, empty_values).extend(
-            rustc_target::target_features::all_known_features()
-                .map(|(f, _sb)| f)
+            rustc_target::target_features::all_rust_features()
+                .filter(|(_, s)| s.is_supported())
+                .map(|(f, _s)| f)
                 .chain(rustc_target::target_features::RUSTC_SPECIFIC_FEATURES.iter().cloned())
                 .map(Symbol::intern),
         );
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index ca67e0a68a9..087ba0522eb 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -442,8 +442,7 @@ mod desc {
     pub(crate) const parse_polonius: &str = "either no value or `legacy` (the default), or `next`";
     pub(crate) const parse_stack_protector: &str =
         "one of (`none` (default), `basic`, `strong`, or `all`)";
-    pub(crate) const parse_branch_protection: &str =
-        "a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf`";
+    pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf`";
     pub(crate) const parse_proc_macro_execution_strategy: &str =
         "one of supported execution strategies (`same-thread`, or `cross-thread`)";
     pub(crate) const parse_remap_path_scope: &str =
@@ -457,10 +456,11 @@ mod desc {
         "either a boolean (`yes`, `no`, `on`, `off`, etc), or `nll` (default: `nll`)";
 }
 
-mod parse {
+pub mod parse {
     use std::str::FromStr;
 
     pub(crate) use super::*;
+    pub(crate) const MAX_THREADS_CAP: usize = 256;
 
     /// This is for boolean options that don't take a value and start with
     /// `no-`. This style of option is deprecated.
@@ -657,7 +657,7 @@ mod parse {
     }
 
     pub(crate) fn parse_threads(slot: &mut usize, v: Option<&str>) -> bool {
-        match v.and_then(|s| s.parse().ok()) {
+        let ret = match v.and_then(|s| s.parse().ok()) {
             Some(0) => {
                 *slot = std::thread::available_parallelism().map_or(1, NonZero::<usize>::get);
                 true
@@ -667,7 +667,11 @@ mod parse {
                 true
             }
             None => false,
-        }
+        };
+        // We want to cap the number of threads here to avoid large numbers like 999999 and compiler panics.
+        // This solution was suggested here https://github.com/rust-lang/rust/issues/117638#issuecomment-1800925067
+        *slot = slot.clone().min(MAX_THREADS_CAP);
+        ret
     }
 
     /// Use this for any numeric option that has a static default.
@@ -1396,7 +1400,7 @@ mod parse {
                     match opt {
                         "bti" => slot.bti = true,
                         "pac-ret" if slot.pac_ret.is_none() => {
-                            slot.pac_ret = Some(PacRet { leaf: false, key: PAuthKey::A })
+                            slot.pac_ret = Some(PacRet { leaf: false, pc: false, key: PAuthKey::A })
                         }
                         "leaf" => match slot.pac_ret.as_mut() {
                             Some(pac) => pac.leaf = true,
@@ -1406,6 +1410,10 @@ mod parse {
                             Some(pac) => pac.key = PAuthKey::B,
                             _ => return false,
                         },
+                        "pc" => match slot.pac_ret.as_mut() {
+                            Some(pac) => pac.pc = true,
+                            _ => return false,
+                        },
                         _ => return false,
                     };
                 }
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index 655553de864..dec2a77619b 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -335,12 +335,12 @@ impl RustcInternal for BoundVariableKind {
                 ),
             }),
             BoundVariableKind::Region(kind) => rustc_ty::BoundVariableKind::Region(match kind {
-                BoundRegionKind::BrAnon => rustc_ty::BoundRegionKind::BrAnon,
-                BoundRegionKind::BrNamed(def, symbol) => rustc_ty::BoundRegionKind::BrNamed(
+                BoundRegionKind::BrAnon => rustc_ty::BoundRegionKind::Anon,
+                BoundRegionKind::BrNamed(def, symbol) => rustc_ty::BoundRegionKind::Named(
                     def.0.internal(tables, tcx),
                     Symbol::intern(symbol),
                 ),
-                BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::BrEnv,
+                BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::ClosureEnv,
             }),
             BoundVariableKind::Const => rustc_ty::BoundVariableKind::Const,
         }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index 8c510096764..a4f61313001 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -243,11 +243,11 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
         use stable_mir::ty::BoundRegionKind;
 
         match self {
-            ty::BoundRegionKind::BrAnon => BoundRegionKind::BrAnon,
-            ty::BoundRegionKind::BrNamed(def_id, symbol) => {
+            ty::BoundRegionKind::Anon => BoundRegionKind::BrAnon,
+            ty::BoundRegionKind::Named(def_id, symbol) => {
                 BoundRegionKind::BrNamed(tables.br_named_def(*def_id), symbol.to_string())
             }
-            ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv,
+            ty::BoundRegionKind::ClosureEnv => BoundRegionKind::BrEnv,
         }
     }
 }
@@ -418,7 +418,7 @@ pub(crate) fn mir_const_from_ty_const<'tcx>(
     ty: Ty<'tcx>,
 ) -> stable_mir::ty::MirConst {
     let kind = match ty_const.kind() {
-        ty::Value(ty, val) => {
+        ty::ConstKind::Value(ty, val) => {
             let val = match val {
                 ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
                 ty::ValTree::Branch(branch) => {
@@ -435,19 +435,19 @@ pub(crate) fn mir_const_from_ty_const<'tcx>(
                 ))
             }
         }
-        ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
-        ty::ErrorCt(_) => unreachable!(),
-        ty::InferCt(_) => unreachable!(),
-        ty::BoundCt(_, _) => unimplemented!(),
-        ty::PlaceholderCt(_) => unimplemented!(),
-        ty::Unevaluated(uv) => {
+        ty::ConstKind::Param(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
+        ty::ConstKind::Error(_) => unreachable!(),
+        ty::ConstKind::Infer(_) => unreachable!(),
+        ty::ConstKind::Bound(_, _) => unimplemented!(),
+        ty::ConstKind::Placeholder(_) => unimplemented!(),
+        ty::ConstKind::Unevaluated(uv) => {
             stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
                 def: tables.const_def(uv.def),
                 args: uv.args.stable(tables),
                 promoted: None,
             })
         }
-        ty::ExprCt(_) => unimplemented!(),
+        ty::ConstKind::Expr(_) => unimplemented!(),
     };
     let stable_ty = tables.intern_ty(ty);
     let id = tables.intern_mir_const(mir::Const::Ty(ty, ty_const));
@@ -459,7 +459,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         let kind = match self.kind() {
-            ty::Value(ty, val) => {
+            ty::ConstKind::Value(ty, val) => {
                 let val = match val {
                     ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
                     ty::ValTree::Branch(branch) => {
@@ -478,16 +478,16 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
                     )
                 }
             }
-            ty::ParamCt(param) => stable_mir::ty::TyConstKind::Param(param.stable(tables)),
-            ty::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated(
+            ty::ConstKind::Param(param) => stable_mir::ty::TyConstKind::Param(param.stable(tables)),
+            ty::ConstKind::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated(
                 tables.const_def(uv.def),
                 uv.args.stable(tables),
             ),
-            ty::ErrorCt(_) => unreachable!(),
-            ty::InferCt(_) => unreachable!(),
-            ty::BoundCt(_, _) => unimplemented!(),
-            ty::PlaceholderCt(_) => unimplemented!(),
-            ty::ExprCt(_) => unimplemented!(),
+            ty::ConstKind::Error(_) => unreachable!(),
+            ty::ConstKind::Infer(_) => unreachable!(),
+            ty::ConstKind::Bound(_, _) => unimplemented!(),
+            ty::ConstKind::Placeholder(_) => unimplemented!(),
+            ty::ConstKind::Expr(_) => unimplemented!(),
         };
         let id = tables.intern_ty_const(tables.tcx.lift(*self).unwrap());
         stable_mir::ty::TyConst::new(kind, id)
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 890c4fdafef..21a74bd4020 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -378,7 +378,6 @@ symbols! {
         aggregate_raw_ptr,
         alias,
         align,
-        align_offset,
         alignment,
         all,
         alloc,
@@ -1664,6 +1663,7 @@ symbols! {
         rustc_const_panic_str,
         rustc_const_stable,
         rustc_const_stable_indirect,
+        rustc_const_stable_intrinsic,
         rustc_const_unstable,
         rustc_conversion_suggestion,
         rustc_deallocator,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 334061bfdc1..05b4ff327a9 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -290,7 +290,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
 
             // Bound lifetimes use indices starting at 1,
             // see `BinderLevel` for more details.
-            ty::ReBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon }) => {
+            ty::ReBound(debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon }) => {
                 let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
                 let depth = binder.lifetime_depths.start + var.as_u32();
 
@@ -568,7 +568,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
 
             // We may still encounter unevaluated consts due to the printing
             // logic sometimes passing identity-substituted impl headers.
-            ty::Unevaluated(ty::UnevaluatedConst { def, args, .. }) => {
+            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args, .. }) => {
                 return self.print_def_path(def, args);
             }
 
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 4b539eb8e20..460b6e4b647 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -893,6 +893,7 @@ pub enum InlineAsmClobberAbi {
     Arm64EC,
     RiscV,
     LoongArch,
+    PowerPC,
     S390x,
     Msp430,
 }
@@ -944,6 +945,10 @@ impl InlineAsmClobberAbi {
                 "C" | "system" => Ok(InlineAsmClobberAbi::LoongArch),
                 _ => Err(&["C", "system"]),
             },
+            InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => match name {
+                "C" | "system" => Ok(InlineAsmClobberAbi::PowerPC),
+                _ => Err(&["C", "system"]),
+            },
             InlineAsmArch::S390x => match name {
                 "C" | "system" => Ok(InlineAsmClobberAbi::S390x),
                 _ => Err(&["C", "system"]),
@@ -1121,6 +1126,31 @@ impl InlineAsmClobberAbi {
                     f16, f17, f18, f19, f20, f21, f22, f23,
                 }
             },
+            InlineAsmClobberAbi::PowerPC => clobbered_regs! {
+                PowerPC PowerPCInlineAsmReg {
+                    // r0, r3-r12
+                    r0,
+                    r3, r4, r5, r6, r7,
+                    r8, r9, r10, r11, r12,
+
+                    // f0-f13
+                    f0, f1, f2, f3, f4, f5, f6, f7,
+                    f8, f9, f10, f11, f12, f13,
+
+                    // v0-v19
+                    // FIXME: PPC32 SysV ABI does not mention vector registers processing.
+                    // https://refspecs.linuxfoundation.org/elf/elfspec_ppc.pdf
+                    v0, v1, v2, v3, v4, v5, v6, v7,
+                    v8, v9, v10, v11, v12, v13, v14,
+                    v15, v16, v17, v18, v19,
+
+                    // cr0-cr1, cr5-cr7, xer
+                    cr0, cr1,
+                    cr5, cr6, cr7,
+                    xer,
+                    // lr and ctr are reserved
+                }
+            },
             InlineAsmClobberAbi::S390x => clobbered_regs! {
                 S390x S390xInlineAsmReg {
                     r0, r1, r2, r3, r4, r5,
diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs
index b2416466132..aa8b26170be 100644
--- a/compiler/rustc_target/src/asm/powerpc.rs
+++ b/compiler/rustc_target/src/asm/powerpc.rs
@@ -1,14 +1,17 @@
 use std::fmt;
 
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_span::Symbol;
 
 use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+use crate::spec::{RelocModel, Target};
 
 def_reg_class! {
     PowerPC PowerPCInlineAsmRegClass {
         reg,
         reg_nonzero,
         freg,
+        vreg,
         cr,
         xer,
     }
@@ -48,11 +51,44 @@ impl PowerPCInlineAsmRegClass {
                 }
             }
             Self::freg => types! { _: F32, F64; },
+            Self::vreg => &[],
             Self::cr | Self::xer => &[],
         }
     }
 }
 
+fn reserved_r13(
+    arch: InlineAsmArch,
+    _reloc_model: RelocModel,
+    _target_features: &FxIndexSet<Symbol>,
+    target: &Target,
+    _is_clobber: bool,
+) -> Result<(), &'static str> {
+    if target.is_like_aix && arch == InlineAsmArch::PowerPC {
+        Ok(())
+    } else {
+        Err("r13 is a reserved register on this target")
+    }
+}
+
+fn reserved_v20to31(
+    _arch: InlineAsmArch,
+    _reloc_model: RelocModel,
+    _target_features: &FxIndexSet<Symbol>,
+    target: &Target,
+    _is_clobber: bool,
+) -> Result<(), &'static str> {
+    if target.is_like_aix {
+        match &*target.options.abi {
+            "vec-default" => Err("v20-v31 are reserved on vec-default ABI"),
+            "vec-extabi" => Ok(()),
+            _ => unreachable!("unrecognized AIX ABI"),
+        }
+    } else {
+        Ok(())
+    }
+}
+
 def_regs! {
     PowerPC PowerPCInlineAsmReg PowerPCInlineAsmRegClass {
         r0: reg = ["r0", "0"],
@@ -66,6 +102,7 @@ def_regs! {
         r10: reg, reg_nonzero = ["r10", "10"],
         r11: reg, reg_nonzero = ["r11", "11"],
         r12: reg, reg_nonzero = ["r12", "12"],
+        r13: reg, reg_nonzero = ["r13", "13"] % reserved_r13,
         r14: reg, reg_nonzero = ["r14", "14"],
         r15: reg, reg_nonzero = ["r15", "15"],
         r16: reg, reg_nonzero = ["r16", "16"],
@@ -113,6 +150,38 @@ def_regs! {
         f29: freg = ["f29", "fr29"],
         f30: freg = ["f30", "fr30"],
         f31: freg = ["f31", "fr31"],
+        v0: vreg = ["v0"],
+        v1: vreg = ["v1"],
+        v2: vreg = ["v2"],
+        v3: vreg = ["v3"],
+        v4: vreg = ["v4"],
+        v5: vreg = ["v5"],
+        v6: vreg = ["v6"],
+        v7: vreg = ["v7"],
+        v8: vreg = ["v8"],
+        v9: vreg = ["v9"],
+        v10: vreg = ["v10"],
+        v11: vreg = ["v11"],
+        v12: vreg = ["v12"],
+        v13: vreg = ["v13"],
+        v14: vreg = ["v14"],
+        v15: vreg = ["v15"],
+        v16: vreg = ["v16"],
+        v17: vreg = ["v17"],
+        v18: vreg = ["v18"],
+        v19: vreg = ["v19"],
+        v20: vreg = ["v20"] % reserved_v20to31,
+        v21: vreg = ["v21"] % reserved_v20to31,
+        v22: vreg = ["v22"] % reserved_v20to31,
+        v23: vreg = ["v23"] % reserved_v20to31,
+        v24: vreg = ["v24"] % reserved_v20to31,
+        v25: vreg = ["v25"] % reserved_v20to31,
+        v26: vreg = ["v26"] % reserved_v20to31,
+        v27: vreg = ["v27"] % reserved_v20to31,
+        v28: vreg = ["v28"] % reserved_v20to31,
+        v29: vreg = ["v29"] % reserved_v20to31,
+        v30: vreg = ["v30"] % reserved_v20to31,
+        v31: vreg = ["v31"] % reserved_v20to31,
         cr: cr = ["cr"],
         cr0: cr = ["cr0"],
         cr1: cr = ["cr1"],
@@ -127,8 +196,6 @@ def_regs! {
             "the stack pointer cannot be used as an operand for inline asm",
         #error = ["r2", "2"] =>
             "r2 is a system reserved register and cannot be used as an operand for inline asm",
-        #error = ["r13", "13"] =>
-            "r13 is a system reserved register and cannot be used as an operand for inline asm",
         #error = ["r29", "29"] =>
             "r29 is used internally by LLVM and cannot be used as an operand for inline asm",
         #error = ["r30", "30"] =>
@@ -163,13 +230,17 @@ impl PowerPCInlineAsmReg {
         // Strip off the leading prefix.
         do_emit! {
             (r0, "0"), (r3, "3"), (r4, "4"), (r5, "5"), (r6, "6"), (r7, "7");
-            (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r14, "14"), (r15, "15");
+            (r8, "8"), (r9, "9"), (r10, "10"), (r11, "11"), (r12, "12"), (r13, "13"), (r14, "14"), (r15, "15");
             (r16, "16"), (r17, "17"), (r18, "18"), (r19, "19"), (r20, "20"), (r21, "21"), (r22, "22"), (r23, "23");
             (r24, "24"), (r25, "25"), (r26, "26"), (r27, "27"), (r28, "28");
             (f0, "0"), (f1, "1"), (f2, "2"), (f3, "3"), (f4, "4"), (f5, "5"), (f6, "6"), (f7, "7");
             (f8, "8"), (f9, "9"), (f10, "10"), (f11, "11"), (f12, "12"), (f13, "13"), (f14, "14"), (f15, "15");
             (f16, "16"), (f17, "17"), (f18, "18"), (f19, "19"), (f20, "20"), (f21, "21"), (f22, "22"), (f23, "23");
             (f24, "24"), (f25, "25"), (f26, "26"), (f27, "27"), (f28, "28"), (f29, "29"), (f30, "30"), (f31, "31");
+            (v0, "0"), (v1, "1"), (v2, "2"), (v3, "3"), (v4, "4"), (v5, "5"), (v6, "6"), (v7, "7");
+            (v8, "8"), (v9, "9"), (v10, "10"), (v11, "11"), (v12, "12"), (v13, "13"), (v14, "14"), (v15, "15");
+            (v16, "16"), (v17, "17"), (v18, "18"), (v19, "19"), (v20, "20"), (v21, "21"), (v22, "22"), (v23, "23");
+            (v24, "24"), (v25, "25"), (v26, "26"), (v27, "27"), (v28, "28"), (v29, "29"), (v30, "30"), (v31, "31");
             (cr, "cr");
             (cr0, "0"), (cr1, "1"), (cr2, "2"), (cr3, "3"), (cr4, "4"), (cr5, "5"), (cr6, "6"), (cr7, "7");
             (xer, "xer");
@@ -201,5 +272,6 @@ impl PowerPCInlineAsmReg {
         reg_conflicts! {
             cr : cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7;
         }
+        // f0-f31 (vsr0-vsr31) and v0-v31 (vsr32-vsr63) do not conflict.
     }
 }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 06408e0b210..321ab40403a 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1595,11 +1595,10 @@ macro_rules! supported_targets {
         pub const TARGETS: &[&str] = &[$($tuple),+];
 
         fn load_builtin(target: &str) -> Option<Target> {
-            let mut t = match target {
+            let t = match target {
                 $( $tuple => targets::$module::target(), )+
                 _ => return None,
             };
-            t.is_builtin = true;
             debug!("got builtin target: {:?}", t);
             Some(t)
         }
@@ -1806,7 +1805,6 @@ supported_targets! {
     ("wasm32-unknown-emscripten", wasm32_unknown_emscripten),
     ("wasm32-unknown-unknown", wasm32_unknown_unknown),
     ("wasm32v1-none", wasm32v1_none),
-    ("wasm32-wasi", wasm32_wasi),
     ("wasm32-wasip1", wasm32_wasip1),
     ("wasm32-wasip2", wasm32_wasip2),
     ("wasm32-wasip1-threads", wasm32_wasip1_threads),
@@ -2128,9 +2126,6 @@ type StaticCow<T> = Cow<'static, T>;
 /// through `Deref` impls.
 #[derive(PartialEq, Clone, Debug)]
 pub struct TargetOptions {
-    /// Whether the target is built-in or loaded from a custom target specification.
-    pub is_builtin: bool,
-
     /// Used as the `target_endian` `cfg` variable. Defaults to little endian.
     pub endian: Endian,
     /// Width of c_int type. Defaults to "32".
@@ -2606,7 +2601,6 @@ impl Default for TargetOptions {
     /// incomplete, and if used for compilation, will certainly not work.
     fn default() -> TargetOptions {
         TargetOptions {
-            is_builtin: false,
             endian: Endian::Little,
             c_int_width: "32".into(),
             os: "none".into(),
@@ -3349,7 +3343,6 @@ impl Target {
             }
         }
 
-        key!(is_builtin, bool);
         key!(c_int_width = "target-c-int-width");
         key!(c_enum_min_bits, Option<u64>); // if None, matches c_int_width
         key!(os);
@@ -3462,10 +3455,6 @@ impl Target {
         key!(entry_abi, Conv)?;
         key!(supports_xray, bool);
 
-        if base.is_builtin {
-            // This can cause unfortunate ICEs later down the line.
-            return Err("may not set is_builtin for targets not built-in".into());
-        }
         base.update_from_cli();
 
         // Each field should have been read using `Json::remove` so any keys remaining are unused.
@@ -3635,7 +3624,6 @@ impl ToJson for Target {
         target_val!(arch);
         target_val!(data_layout);
 
-        target_option_val!(is_builtin);
         target_option_val!(endian, "target-endian");
         target_option_val!(c_int_width, "target-c-int-width");
         target_option_val!(os);
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs
deleted file mode 100644
index c317ebd9592..00000000000
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasi.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//! NB: This target is in the process of being renamed to
-//! `wasm32-wasip1`. For more information see:
-//!
-//! * <https://github.com/rust-lang/compiler-team/issues/607>
-//! * <https://github.com/rust-lang/compiler-team/issues/695>
-
-use crate::spec::Target;
-
-pub(crate) fn target() -> Target {
-    super::wasm32_wasip1::target()
-}
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
index 89d0721bf35..1cd30f21bec 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
@@ -17,7 +17,7 @@ pub(crate) fn target() -> Target {
 
     options.os = "wasi".into();
     options.env = "p1".into();
-    options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]);
+    options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasip1"]);
 
     options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained();
     options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained();
@@ -47,7 +47,7 @@ pub(crate) fn target() -> Target {
     options.entry_name = "__main_void".into();
 
     Target {
-        llvm_target: "wasm32-wasi".into(),
+        llvm_target: "wasm32-wasip1".into(),
         metadata: crate::spec::TargetMetadata {
             description: Some("WebAssembly with WASI".into()),
             tier: Some(2),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
index bd6bba067ef..f06112160d1 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
@@ -1,5 +1,5 @@
 //! The `wasm32-wasip2` target is the next evolution of the
-//! wasm32-wasi target. While the wasi specification is still under
+//! wasm32-wasip1 target. While the wasi specification is still under
 //! active development, the preview 2 iteration is considered an "island
 //! of stability" that should allow users to rely on it indefinitely.
 //!
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 3df8f0590a3..96f1e257bb5 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -1,10 +1,17 @@
+//! Declares Rust's target feature names for each target.
+//! Note that these are similar to but not always identical to LLVM's feature names,
+//! and Rust adds some features that do not correspond to LLVM features at all.
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_span::symbol::{Symbol, sym};
 
 /// Features that control behaviour of rustc, rather than the codegen.
+/// These exist globally and are not in the target-specific lists below.
 pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
 
-/// Features that require special handling when passing to LLVM.
+/// Features that require special handling when passing to LLVM:
+/// these are target-specific (i.e., must also be listed in the target-specific list below)
+/// but do not correspond to an LLVM target feature.
 pub const RUSTC_SPECIAL_FEATURES: &[&str] = &["backchain"];
 
 /// Stability information for target features.
@@ -16,26 +23,47 @@ pub enum Stability {
     /// This target feature is unstable; using it in `#[target_feature]` or `#[cfg(target_feature)]`
     /// requires enabling the given nightly feature.
     Unstable(Symbol),
+    /// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set in the basic
+    /// target definition. Used in particular for features that change the floating-point ABI.
+    Forbidden { reason: &'static str },
 }
 use Stability::*;
 
-impl Stability {
-    pub fn as_feature_name(self) -> Option<Symbol> {
+impl<CTX> HashStable<CTX> for Stability {
+    #[inline]
+    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+        std::mem::discriminant(self).hash_stable(hcx, hasher);
         match self {
-            Stable => None,
-            Unstable(s) => Some(s),
+            Stable => {}
+            Unstable(sym) => {
+                sym.hash_stable(hcx, hasher);
+            }
+            Forbidden { .. } => {}
         }
     }
+}
 
+impl Stability {
     pub fn is_stable(self) -> bool {
         matches!(self, Stable)
     }
+
+    /// Forbidden features are not supported.
+    pub fn is_supported(self) -> bool {
+        !matches!(self, Forbidden { .. })
+    }
 }
 
 // Here we list target features that rustc "understands": they can be used in `#[target_feature]`
 // and `#[cfg(target_feature)]`. They also do not trigger any warnings when used with
 // `-Ctarget-feature`.
 //
+// Note that even unstable (and even entirely unlisted) features can be used with `-Ctarget-feature`
+// on stable. Using a feature not on the list of Rust target features only emits a warning.
+// Only `cfg(target_feature)` and `#[target_feature]` actually do any stability gating.
+// `cfg(target_feature)` for unstable features just works on nightly without any feature gate.
+// `#[target_feature]` requires a feature gate.
+//
 // When adding features to the below lists
 // check whether they're named already elsewhere in rust
 // e.g. in stdarch and whether the given name matches LLVM's
@@ -46,17 +74,27 @@ impl Stability {
 // per-function level, since we would then allow safe calls from functions with `+soft-float` to
 // functions without that feature!
 //
-// When adding a new feature, be particularly mindful of features that affect function ABIs. Those
-// need to be treated very carefully to avoid introducing unsoundness! This often affects features
-// that enable/disable hardfloat support (see https://github.com/rust-lang/rust/issues/116344 for an
-// example of this going wrong), but features enabling new SIMD registers are also a concern (see
-// https://github.com/rust-lang/rust/issues/116558 for an example of this going wrong).
+// It is important for soundness that features allowed here do *not* change the function call ABI.
+// For example, disabling the `x87` feature on x86 changes how scalar floats are passed as
+// arguments, so enabling toggling that feature would be unsound. In fact, since `-Ctarget-feature`
+// will just allow unknown features (with a warning), we have to explicitly list features that change
+// the ABI as `Forbidden` to ensure using them causes an error. Note that this is only effective if
+// such features can never be toggled via `-Ctarget-cpu`! If that is ever a possibility, we will need
+// extra checks ensuring that the LLVM-computed target features for a CPU did not (un)set a
+// `Forbidden` feature. See https://github.com/rust-lang/rust/issues/116344 for some more context.
+// FIXME: add such "forbidden" features for non-x86 targets.
+//
+// The one exception to features that change the ABI is features that enable larger vector
+// registers. Those are permitted to be listed here. This is currently unsound (see
+// https://github.com/rust-lang/rust/issues/116558); in the future we will have to ensure that
+// functions can only use such vectors as arguments/return types if the corresponding target feature
+// is enabled.
 //
 // Stabilizing a target feature requires t-lang approval.
 
 type ImpliedFeatures = &'static [&'static str];
 
-const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("aclass", Unstable(sym::arm_target_feature), &[]),
     ("aes", Unstable(sym::arm_target_feature), &["neon"]),
@@ -70,6 +108,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("neon", Unstable(sym::arm_target_feature), &["vfp3"]),
     ("rclass", Unstable(sym::arm_target_feature), &[]),
     ("sha2", Unstable(sym::arm_target_feature), &["neon"]),
+    ("soft-float", Forbidden { reason: "unsound because it changes float ABI" }, &[]),
     // This is needed for inline assembly, but shouldn't be stabilized as-is
     // since it should be enabled per-function using #[instruction_set], not
     // #[target_feature].
@@ -87,9 +126,10 @@ const ARM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("vfp4", Unstable(sym::arm_target_feature), &["vfp3"]),
     ("virtualization", Unstable(sym::arm_target_feature), &[]),
     // tidy-alphabetical-end
+    // FIXME: need to also forbid turning off `fpregs` on hardfloat targets
 ];
 
-const AARCH64_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     // FEAT_AES & FEAT_PMULL
     ("aes", Stable, &["neon"]),
@@ -277,7 +317,7 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[
     &["paca", "pacg"], // Together these represent `pauth` in LLVM
 ];
 
-const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("adx", Stable, &[]),
     ("aes", Stable, &["sse2"]),
@@ -328,6 +368,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("sha512", Unstable(sym::sha512_sm_x86), &["avx2"]),
     ("sm3", Unstable(sym::sha512_sm_x86), &["avx"]),
     ("sm4", Unstable(sym::sha512_sm_x86), &["avx2"]),
+    ("soft-float", Forbidden { reason: "unsound because it changes float ABI" }, &[]),
     ("sse", Stable, &[]),
     ("sse2", Stable, &["sse"]),
     ("sse3", Stable, &["sse2"]),
@@ -344,16 +385,17 @@ const X86_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("xsaveopt", Stable, &["xsave"]),
     ("xsaves", Stable, &["xsave"]),
     // tidy-alphabetical-end
+    // FIXME: need to also forbid turning off `x87` on hardfloat targets
 ];
 
-const HEXAGON_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("hvx", Unstable(sym::hexagon_target_feature), &[]),
     ("hvx-length128b", Unstable(sym::hexagon_target_feature), &["hvx"]),
     // tidy-alphabetical-end
 ];
 
-const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("altivec", Unstable(sym::powerpc_target_feature), &[]),
     ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]),
@@ -367,7 +409,7 @@ const POWERPC_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const MIPS_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("fp64", Unstable(sym::mips_target_feature), &[]),
     ("msa", Unstable(sym::mips_target_feature), &[]),
@@ -375,7 +417,7 @@ const MIPS_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("a", Stable, &["zaamo", "zalrsc"]),
     ("c", Stable, &[]),
@@ -415,7 +457,7 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("atomics", Unstable(sym::wasm_target_feature), &[]),
     ("bulk-memory", Stable, &[]),
@@ -428,13 +470,14 @@ const WASM_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("relaxed-simd", Stable, &["simd128"]),
     ("sign-ext", Stable, &[]),
     ("simd128", Stable, &[]),
+    ("wide-arithmetic", Unstable(sym::wasm_target_feature), &[]),
     // tidy-alphabetical-end
 ];
 
-const BPF_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] =
+const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] =
     &[("alu32", Unstable(sym::bpf_target_feature), &[])];
 
-const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("10e60", Unstable(sym::csky_target_feature), &["7e10"]),
     ("2e3", Unstable(sym::csky_target_feature), &["e2"]),
@@ -481,7 +524,7 @@ const CSKY_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("d", Unstable(sym::loongarch_target_feature), &["f"]),
     ("f", Unstable(sym::loongarch_target_feature), &[]),
@@ -495,7 +538,7 @@ const LOONGARCH_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("backchain", Unstable(sym::s390x_target_feature), &[]),
     ("vector", Unstable(sym::s390x_target_feature), &[]),
@@ -506,41 +549,39 @@ const IBMZ_ALLOWED_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
 /// primitives may be documented.
 ///
 /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
-pub fn all_known_features() -> impl Iterator<Item = (&'static str, Stability)> {
+pub fn all_rust_features() -> impl Iterator<Item = (&'static str, Stability)> {
     std::iter::empty()
-        .chain(ARM_ALLOWED_FEATURES.iter())
-        .chain(AARCH64_ALLOWED_FEATURES.iter())
-        .chain(X86_ALLOWED_FEATURES.iter())
-        .chain(HEXAGON_ALLOWED_FEATURES.iter())
-        .chain(POWERPC_ALLOWED_FEATURES.iter())
-        .chain(MIPS_ALLOWED_FEATURES.iter())
-        .chain(RISCV_ALLOWED_FEATURES.iter())
-        .chain(WASM_ALLOWED_FEATURES.iter())
-        .chain(BPF_ALLOWED_FEATURES.iter())
-        .chain(CSKY_ALLOWED_FEATURES)
-        .chain(LOONGARCH_ALLOWED_FEATURES)
-        .chain(IBMZ_ALLOWED_FEATURES)
+        .chain(ARM_FEATURES.iter())
+        .chain(AARCH64_FEATURES.iter())
+        .chain(X86_FEATURES.iter())
+        .chain(HEXAGON_FEATURES.iter())
+        .chain(POWERPC_FEATURES.iter())
+        .chain(MIPS_FEATURES.iter())
+        .chain(RISCV_FEATURES.iter())
+        .chain(WASM_FEATURES.iter())
+        .chain(BPF_FEATURES.iter())
+        .chain(CSKY_FEATURES)
+        .chain(LOONGARCH_FEATURES)
+        .chain(IBMZ_FEATURES)
         .cloned()
         .map(|(f, s, _)| (f, s))
 }
 
 impl super::spec::Target {
-    pub fn supported_target_features(
-        &self,
-    ) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
+    pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, ImpliedFeatures)] {
         match &*self.arch {
-            "arm" => ARM_ALLOWED_FEATURES,
-            "aarch64" | "arm64ec" => AARCH64_ALLOWED_FEATURES,
-            "x86" | "x86_64" => X86_ALLOWED_FEATURES,
-            "hexagon" => HEXAGON_ALLOWED_FEATURES,
-            "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_ALLOWED_FEATURES,
-            "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
-            "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
-            "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
-            "bpf" => BPF_ALLOWED_FEATURES,
-            "csky" => CSKY_ALLOWED_FEATURES,
-            "loongarch64" => LOONGARCH_ALLOWED_FEATURES,
-            "s390x" => IBMZ_ALLOWED_FEATURES,
+            "arm" => ARM_FEATURES,
+            "aarch64" | "arm64ec" => AARCH64_FEATURES,
+            "x86" | "x86_64" => X86_FEATURES,
+            "hexagon" => HEXAGON_FEATURES,
+            "mips" | "mips32r6" | "mips64" | "mips64r6" => MIPS_FEATURES,
+            "powerpc" | "powerpc64" => POWERPC_FEATURES,
+            "riscv32" | "riscv64" => RISCV_FEATURES,
+            "wasm32" | "wasm64" => WASM_FEATURES,
+            "bpf" => BPF_FEATURES,
+            "csky" => CSKY_FEATURES,
+            "loongarch64" => LOONGARCH_FEATURES,
+            "s390x" => IBMZ_FEATURES,
             _ => &[],
         }
     }
@@ -557,7 +598,7 @@ impl super::spec::Target {
         base_features: impl Iterator<Item = Symbol>,
     ) -> FxHashSet<Symbol> {
         let implied_features = self
-            .supported_target_features()
+            .rust_target_features()
             .iter()
             .map(|(f, _, i)| (Symbol::intern(f), i))
             .collect::<FxHashMap<_, _>>();
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
index 2ecd28f4868..cd621fd1a39 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs
@@ -100,7 +100,10 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
                     // Find the index of the named region that was part of the
                     // error. We will then search the function parameters for a bound
                     // region at the right depth with the same index
-                    (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+                    (
+                        Some(rbv::ResolvedArg::EarlyBound(id)),
+                        ty::BoundRegionKind::Named(def_id, _),
+                    ) => {
                         debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                         if id.to_def_id() == def_id {
                             return ControlFlow::Break(arg);
@@ -112,7 +115,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> {
                     // region at the right depth with the same index
                     (
                         Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)),
-                        ty::BrNamed(def_id, _),
+                        ty::BoundRegionKind::Named(def_id, _),
                     ) => {
                         debug!(
                             "FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
@@ -191,14 +194,17 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> {
     fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) -> Self::Result {
         match (self.tcx.named_bound_var(lifetime.hir_id), self.bound_region) {
             // the lifetime of the TyPath!
-            (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BrNamed(def_id, _)) => {
+            (Some(rbv::ResolvedArg::EarlyBound(id)), ty::BoundRegionKind::Named(def_id, _)) => {
                 debug!("EarlyBound id={:?} def_id={:?}", id, def_id);
                 if id.to_def_id() == def_id {
                     return ControlFlow::Break(());
                 }
             }
 
-            (Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)), ty::BrNamed(def_id, _)) => {
+            (
+                Some(rbv::ResolvedArg::LateBound(debruijn_index, _, id)),
+                ty::BoundRegionKind::Named(def_id, _),
+            ) => {
                 debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}", debruijn_index,);
                 debug!("id={:?}", id);
                 debug!("def_id={:?}", def_id);
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
index 7cf98183774..9fa5a8ac637 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs
@@ -60,7 +60,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let is_impl_item = region_info.is_impl_item;
 
         match br {
-            ty::BrNamed(_, kw::UnderscoreLifetime) | ty::BrAnon => {}
+            ty::BoundRegionKind::Named(_, kw::UnderscoreLifetime) | ty::BoundRegionKind::Anon => {}
             _ => {
                 /* not an anonymous region */
                 debug!("try_report_named_anon_conflict: not an anonymous region");
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
index f2a7da707b8..7fcd3c847e3 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_relation.rs
@@ -29,16 +29,16 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
             )) => {
                 let span = *span;
                 let (sub_span, sub_symbol) = match sub_name {
-                    ty::BrNamed(def_id, symbol) => {
+                    ty::BoundRegionKind::Named(def_id, symbol) => {
                         (Some(self.tcx().def_span(def_id)), Some(symbol))
                     }
-                    ty::BrAnon | ty::BrEnv => (None, None),
+                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None),
                 };
                 let (sup_span, sup_symbol) = match sup_name {
-                    ty::BrNamed(def_id, symbol) => {
+                    ty::BoundRegionKind::Named(def_id, symbol) => {
                         (Some(self.tcx().def_span(def_id)), Some(symbol))
                     }
-                    ty::BrAnon | ty::BrEnv => (None, None),
+                    ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => (None, None),
                 };
                 let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) {
                     (Some(sub_span), Some(sup_span), Some(&sub_symbol), Some(&sup_symbol)) => {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
index 2b19db2c14e..808e6a50d85 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs
@@ -59,11 +59,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                     let simple_ident = param.param.pat.simple_ident();
 
                     let (has_impl_path, impl_path) = match ctxt.assoc_item.container {
-                        AssocItemContainer::TraitContainer => {
+                        AssocItemContainer::Trait => {
                             let id = ctxt.assoc_item.container_id(tcx);
                             (true, tcx.def_path_str(id))
                         }
-                        AssocItemContainer::ImplContainer => (false, String::new()),
+                        AssocItemContainer::Impl => (false, String::new()),
                     };
 
                     let mut err = self.tcx().dcx().create_err(ButCallingIntroduces {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
index 90b354305ff..75054b22153 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs
@@ -46,7 +46,7 @@ pub fn find_param_with_region<'tcx>(
         ty::ReLateParam(late_param) => (late_param.scope, late_param.bound_region),
         ty::ReEarlyParam(ebr) => {
             let region_def = tcx.generics_of(generic_param_scope).region_param(ebr, tcx).def_id;
-            (tcx.parent(region_def), ty::BoundRegionKind::BrNamed(region_def, ebr.name))
+            (tcx.parent(region_def), ty::BoundRegionKind::Named(region_def, ebr.name))
         }
         _ => return None, // not a free region
     };
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
index 438639e72f9..9fd7dccc57c 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs
@@ -993,7 +993,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     fn report_inference_failure(&self, var_origin: RegionVariableOrigin) -> Diag<'_> {
         let br_string = |br: ty::BoundRegionKind| {
             let mut s = match br {
-                ty::BrNamed(_, name) => name.to_string(),
+                ty::BoundRegionKind::Named(_, name) => name.to_string(),
                 _ => String::new(),
             };
             if !s.is_empty() {
@@ -1103,7 +1103,7 @@ fn msg_span_from_named_region<'tcx>(
                 ("the anonymous lifetime defined here".to_string(), Some(ty.span))
             } else {
                 match fr.bound_region {
-                    ty::BoundRegionKind::BrNamed(param_def_id, name) => {
+                    ty::BoundRegionKind::Named(param_def_id, name) => {
                         let span = tcx.def_span(param_def_id);
                         let text = if name == kw::UnderscoreLifetime {
                             "the anonymous lifetime as defined here".to_string()
@@ -1112,7 +1112,7 @@ fn msg_span_from_named_region<'tcx>(
                         };
                         (text, Some(span))
                     }
-                    ty::BrAnon => (
+                    ty::BoundRegionKind::Anon => (
                         "the anonymous lifetime as defined here".to_string(),
                         Some(tcx.def_span(generic_param_scope)),
                     ),
@@ -1125,11 +1125,11 @@ fn msg_span_from_named_region<'tcx>(
         }
         ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, name), .. },
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::Named(def_id, name), .. },
             ..
         }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon, .. },
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::Anon, .. },
             ..
         }) => ("an anonymous lifetime".to_owned(), None),
         _ => bug!("{:?}", region),
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 f5cd99222e3..a1c97a38567 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
@@ -471,6 +471,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         }
 
                         self.try_to_add_help_message(
+                            &root_obligation,
                             &obligation,
                             leaf_trait_predicate,
                             &mut err,
@@ -2488,6 +2489,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
     fn try_to_add_help_message(
         &self,
+        root_obligation: &PredicateObligation<'tcx>,
         obligation: &PredicateObligation<'tcx>,
         trait_predicate: ty::PolyTraitPredicate<'tcx>,
         err: &mut Diag<'_>,
@@ -2575,6 +2577,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 impl_candidates.as_slice(),
                 span,
             );
+
+            self.suggest_tuple_wrapping(err, root_obligation, obligation);
         }
     }
 
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 e155effa1e3..86fd4c230f6 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -4452,6 +4452,41 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         }
     }
 
+    /// If the type failed selection but the trait is implemented for `(T,)`, suggest that the user
+    /// creates a unary tuple
+    ///
+    /// This is a common gotcha when using libraries that emulate variadic functions with traits for tuples.
+    pub(super) fn suggest_tuple_wrapping(
+        &self,
+        err: &mut Diag<'_>,
+        root_obligation: &PredicateObligation<'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) {
+        let ObligationCauseCode::FunctionArg { arg_hir_id, .. } = obligation.cause.code() else {
+            return;
+        };
+
+        let Some(root_pred) = root_obligation.predicate.as_trait_clause() else { return };
+
+        let trait_ref = root_pred.map_bound(|root_pred| {
+            root_pred
+                .trait_ref
+                .with_self_ty(self.tcx, Ty::new_tup(self.tcx, &[root_pred.trait_ref.self_ty()]))
+        });
+
+        let obligation =
+            Obligation::new(self.tcx, obligation.cause.clone(), obligation.param_env, trait_ref);
+
+        if self.predicate_must_hold_modulo_regions(&obligation) {
+            let arg_span = self.tcx.hir().span(*arg_hir_id);
+            err.multipart_suggestion_verbose(
+                format!("use a unary tuple instead"),
+                vec![(arg_span.shrink_to_lo(), "(".into()), (arg_span.shrink_to_hi(), ",)".into())],
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+
     pub(super) fn explain_hrtb_projection(
         &self,
         diag: &mut Diag<'_>,
diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
index 67463b9884c..cc0a637a78e 100644
--- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs
@@ -48,7 +48,7 @@ impl<'a> DescriptionCtx<'a> {
                 } else {
                     let scope = fr.scope.expect_local();
                     match fr.bound_region {
-                        ty::BoundRegionKind::BrNamed(_, name) => {
+                        ty::BoundRegionKind::Named(_, name) => {
                             let span = if let Some(param) = tcx
                                 .hir()
                                 .get_generics(scope)
@@ -64,7 +64,7 @@ impl<'a> DescriptionCtx<'a> {
                                 (Some(span), "as_defined", name.to_string())
                             }
                         }
-                        ty::BrAnon => {
+                        ty::BoundRegionKind::Anon => {
                             let span = Some(tcx.def_span(scope));
                             (span, "defined_here", String::new())
                         }
diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs
index bacb3b1b1b8..8f1c8a29663 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -60,6 +60,24 @@ impl<'tcx> InferCtxt<'tcx> {
     ///
     /// Invokes `evaluate_obligation`, so in the event that evaluating
     /// `Ty: Trait` causes overflow, EvaluatedToAmbigStackDependent will be returned.
+    ///
+    /// `type_implements_trait` is a convenience function for simple cases like
+    ///
+    /// ```ignore (illustrative)
+    /// let copy_trait = infcx.tcx.require_lang_item(LangItem::Copy, span);
+    /// let implements_copy = infcx.type_implements_trait(copy_trait, [ty], param_env)
+    /// .must_apply_modulo_regions();
+    /// ```
+    ///
+    /// In most cases you should instead create an [Obligation] and check whether
+    ///  it holds via [`evaluate_obligation`] or one of its helper functions like
+    /// [`predicate_must_hold_modulo_regions`], because it properly handles higher ranked traits
+    /// and it is more convenient and safer when your `params` are inside a [`Binder`].
+    ///
+    /// [Obligation]: traits::Obligation
+    /// [`evaluate_obligation`]: crate::traits::query::evaluate_obligation::InferCtxtExt::evaluate_obligation
+    /// [`predicate_must_hold_modulo_regions`]: crate::traits::query::evaluate_obligation::InferCtxtExt::predicate_must_hold_modulo_regions
+    /// [`Binder`]: ty::Binder
     #[instrument(level = "debug", skip(self, params), ret)]
     fn type_implements_trait(
         &self,
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 3cd11d7c8e8..a98871b2d60 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -540,7 +540,7 @@ fn plug_infer_with_placeholders<'tcx>(
                                 universe: self.universe,
                                 bound: ty::BoundRegion {
                                     var: self.next_var(),
-                                    kind: ty::BoundRegionKind::BrAnon,
+                                    kind: ty::BoundRegionKind::Anon,
                                 },
                             }),
                         )
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index e3d17a910cc..21141f6e18f 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -624,9 +624,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                         debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2);
 
                         use rustc_hir::def::DefKind;
-                        use ty::Unevaluated;
                         match (c1.kind(), c2.kind()) {
-                            (Unevaluated(a), Unevaluated(b))
+                            (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b))
                                 if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
                             {
                                 if let Ok(new_obligations) = infcx
@@ -644,7 +643,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
                                     ));
                                 }
                             }
-                            (_, Unevaluated(_)) | (Unevaluated(_), _) => (),
+                            (_, ty::ConstKind::Unevaluated(_))
+                            | (ty::ConstKind::Unevaluated(_), _) => (),
                             (_, _) => {
                                 if let Ok(new_obligations) = infcx
                                     .at(&obligation.cause, obligation.param_env)
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index e7d3004aa20..041cfc21267 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -660,7 +660,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             .into()
                         }
                         GenericParamDefKind::Lifetime => {
-                            let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
+                            let kind = ty::BoundRegionKind::Named(param.def_id, param.name);
                             let bound_var = ty::BoundVariableKind::Region(kind);
                             bound_vars.push(bound_var);
                             ty::Region::new_bound(tcx, ty::INNERMOST, ty::BoundRegion {
@@ -951,18 +951,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 });
 
                 // We must additionally check that the return type impls `Future`.
-
-                // FIXME(async_closures): Investigate this before stabilization.
-                // We instantiate this binder eagerly because the `confirm_future_candidate`
-                // method doesn't support higher-ranked futures, which the `AsyncFn`
-                // traits expressly allow the user to write. To fix this correctly,
-                // we'd need to instantiate trait bounds before we get to selection,
-                // like the new trait solver does.
                 let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
-                let placeholder_output_ty = self.infcx.enter_forall_and_leak_universe(sig.output());
                 nested.push(obligation.with(
                     tcx,
-                    ty::TraitRef::new(tcx, future_trait_def_id, [placeholder_output_ty]),
+                    sig.output().map_bound(|output_ty| {
+                        ty::TraitRef::new(tcx, future_trait_def_id, [output_ty])
+                    }),
                 ));
 
                 (trait_ref, Ty::from_closure_kind(tcx, ty::ClosureKind::Fn))
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index b1e5e526315..cffb62ab559 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -890,9 +890,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         );
 
                         use rustc_hir::def::DefKind;
-                        use ty::Unevaluated;
                         match (c1.kind(), c2.kind()) {
-                            (Unevaluated(a), Unevaluated(b))
+                            (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b))
                                 if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
                             {
                                 if let Ok(InferOk { obligations, value: () }) = self
@@ -912,7 +911,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                     );
                                 }
                             }
-                            (_, Unevaluated(_)) | (Unevaluated(_), _) => (),
+                            (_, ty::ConstKind::Unevaluated(_))
+                            | (ty::ConstKind::Unevaluated(_), _) => (),
                             (_, _) => {
                                 if let Ok(InferOk { obligations, value: () }) = self
                                     .infcx
@@ -1310,7 +1310,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Option<EvaluationResult> {
         let tcx = self.tcx();
-        if self.can_use_global_caches(param_env) {
+        if self.can_use_global_caches(param_env, trait_pred) {
             if let Some(res) = tcx.evaluation_cache.get(&(param_env, trait_pred), tcx) {
                 return Some(res);
             }
@@ -1331,7 +1331,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return;
         }
 
-        if self.can_use_global_caches(param_env) && !trait_pred.has_infer() {
+        if self.can_use_global_caches(param_env, trait_pred) && !trait_pred.has_infer() {
             debug!(?trait_pred, ?result, "insert_evaluation_cache global");
             // This may overwrite the cache with the same value
             // FIXME: Due to #50507 this overwrites the different values
@@ -1476,7 +1476,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     }
 
     /// Returns `true` if the global caches can be used.
-    fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
+    fn can_use_global_caches(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        pred: ty::PolyTraitPredicate<'tcx>,
+    ) -> bool {
         // If there are any inference variables in the `ParamEnv`, then we
         // always use a cache local to this particular scope. Otherwise, we
         // switch to a global cache.
@@ -1494,7 +1498,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             TypingMode::Coherence => false,
             // Avoid using the global cache when we're defining opaque types
             // as their hidden type may impact the result of candidate selection.
-            TypingMode::Analysis { defining_opaque_types } => defining_opaque_types.is_empty(),
+            //
+            // HACK: This is still theoretically unsound. Goals can indirectly rely
+            // on opaques in the defining scope, and it's easier to do so with TAIT.
+            // However, if we disqualify *all* goals from being cached, perf suffers.
+            // This is likely fixed by better caching in general in the new solver.
+            // See: <https://github.com/rust-lang/rust/issues/132064>.
+            TypingMode::Analysis { defining_opaque_types } => {
+                defining_opaque_types.is_empty() || !pred.has_opaque_types()
+            }
             // The global cache is only used if there are no opaque types in
             // the defining scope or we're outside of analysis.
             //
@@ -1512,7 +1524,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let tcx = self.tcx();
         let pred = cache_fresh_trait_pred.skip_binder();
 
-        if self.can_use_global_caches(param_env) {
+        if self.can_use_global_caches(param_env, cache_fresh_trait_pred) {
             if let Some(res) = tcx.selection_cache.get(&(param_env, pred), tcx) {
                 return Some(res);
             }
@@ -1562,7 +1574,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             return;
         }
 
-        if self.can_use_global_caches(param_env) {
+        if self.can_use_global_caches(param_env, cache_fresh_trait_pred) {
             if let Err(Overflow(OverflowError::Canonical)) = candidate {
                 // Don't cache overflow globally; we only produce this in certain modes.
             } else if !pred.has_infer() && !candidate.has_infer() {
@@ -3183,7 +3195,7 @@ fn bind_coroutine_hidden_types_above<'tcx>(
                         ty::ReErased => {
                             let br = ty::BoundRegion {
                                 var: ty::BoundVar::from_u32(counter),
-                                kind: ty::BrAnon,
+                                kind: ty::BoundRegionKind::Anon,
                             };
                             counter += 1;
                             ty::Region::new_bound(tcx, current_depth, br)
@@ -3196,9 +3208,11 @@ fn bind_coroutine_hidden_types_above<'tcx>(
             bty.instantiate(tcx, args)
         })
         .collect();
-    let bound_vars =
-        tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain(
-            (num_bound_variables..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon)),
-        ));
+    let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
+        bound_vars.iter().chain(
+            (num_bound_variables..counter)
+                .map(|_| ty::BoundVariableKind::Region(ty::BoundRegionKind::Anon)),
+        ),
+    );
     ty::Binder::bind_with_vars(hidden_types, bound_vars)
 }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 42b710687cf..0838978a891 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -76,12 +76,13 @@ fn fn_sig_for_fn_abi<'tcx>(
         ty::Closure(def_id, args) => {
             let sig = args.as_closure().sig();
 
-            let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
-                sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
-            );
+            let bound_vars =
+                tcx.mk_bound_variable_kinds_from_iter(sig.bound_vars().iter().chain(iter::once(
+                    ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
+                )));
             let br = ty::BoundRegion {
                 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                kind: ty::BoundRegionKind::BrEnv,
+                kind: ty::BoundRegionKind::ClosureEnv,
             };
             let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
             let env_ty = tcx.closure_env_ty(
@@ -105,12 +106,13 @@ fn fn_sig_for_fn_abi<'tcx>(
         ty::CoroutineClosure(def_id, args) => {
             let coroutine_ty = Ty::new_coroutine_closure(tcx, def_id, args);
             let sig = args.as_coroutine_closure().coroutine_closure_sig();
-            let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
-                sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
-            );
+            let bound_vars =
+                tcx.mk_bound_variable_kinds_from_iter(sig.bound_vars().iter().chain(iter::once(
+                    ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
+                )));
             let br = ty::BoundRegion {
                 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                kind: ty::BoundRegionKind::BrEnv,
+                kind: ty::BoundRegionKind::ClosureEnv,
             };
             let env_region = ty::Region::new_bound(tcx, ty::INNERMOST, br);
             // When this `CoroutineClosure` comes from a `ConstructCoroutineInClosureShim`,
@@ -161,11 +163,11 @@ fn fn_sig_for_fn_abi<'tcx>(
             let sig = args.as_coroutine().sig();
 
             let bound_vars = tcx.mk_bound_variable_kinds_from_iter(iter::once(
-                ty::BoundVariableKind::Region(ty::BrEnv),
+                ty::BoundVariableKind::Region(ty::BoundRegionKind::ClosureEnv),
             ));
             let br = ty::BoundRegion {
                 var: ty::BoundVar::from_usize(bound_vars.len() - 1),
-                kind: ty::BoundRegionKind::BrEnv,
+                kind: ty::BoundRegionKind::ClosureEnv,
             };
 
             let env_ty = Ty::new_mut_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), ty);
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 3655fa5ae0e..f97e8d48c8e 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -140,7 +140,7 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty
         kind,
         def_id: owner_id.to_def_id(),
         trait_item_def_id: Some(owner_id.to_def_id()),
-        container: ty::TraitContainer,
+        container: ty::AssocItemContainer::Trait,
         fn_has_self_parameter: has_self,
         opt_rpitit_info: None,
     }
@@ -159,7 +159,7 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
         kind,
         def_id: def_id.to_def_id(),
         trait_item_def_id: impl_item_ref.trait_item_def_id,
-        container: ty::ImplContainer,
+        container: ty::AssocItemContainer::Impl,
         fn_has_self_parameter: has_self,
         opt_rpitit_info: None,
     }
@@ -267,7 +267,7 @@ fn associated_type_for_impl_trait_in_trait(
         kind: ty::AssocKind::Type,
         def_id,
         trait_item_def_id: None,
-        container: ty::TraitContainer,
+        container: ty::AssocItemContainer::Trait,
         fn_has_self_parameter: false,
         opt_rpitit_info: Some(ImplTraitInTraitData::Trait {
             fn_def_id: fn_def_id.to_def_id(),
@@ -319,7 +319,7 @@ fn associated_type_for_impl_trait_in_impl(
         kind: ty::AssocKind::Type,
         def_id,
         trait_item_def_id: Some(trait_assoc_def_id),
-        container: ty::ImplContainer,
+        container: ty::AssocItemContainer::Impl,
         fn_has_self_parameter: false,
         opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
     });
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 731d42fc006..2127ba8a423 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -135,7 +135,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
 
     if tcx.def_kind(def_id) == DefKind::AssocFn
         && let assoc_item = tcx.associated_item(def_id)
-        && assoc_item.container == ty::AssocItemContainer::TraitContainer
+        && assoc_item.container == ty::AssocItemContainer::Trait
         && assoc_item.defaultness(tcx).has_value()
     {
         let sig = tcx.fn_sig(def_id).instantiate_identity();
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 26c1ba2a5c4..6fee8d3fe33 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -531,6 +531,7 @@ impl str {
     #[rustc_allow_incoherent_impl]
     #[must_use]
     #[stable(feature = "repeat_str", since = "1.16.0")]
+    #[inline]
     pub fn repeat(&self, n: usize) -> String {
         unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) }
     }
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 7e6c042274d..ab76cd7a6be 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -2122,7 +2122,6 @@ impl<T: ?Sized> UnsafeCell<T> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(unsafe_cell_from_mut)]
     /// use std::cell::UnsafeCell;
     ///
     /// let mut val = 42;
@@ -2132,7 +2131,9 @@ impl<T: ?Sized> UnsafeCell<T> {
     /// assert_eq!(*uc.get_mut(), 41);
     /// ```
     #[inline(always)]
-    #[unstable(feature = "unsafe_cell_from_mut", issue = "111645")]
+    #[stable(feature = "unsafe_cell_from_mut", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "unsafe_cell_from_mut", since = "CURRENT_RUSTC_VERSION")]
+    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))]
     pub const fn from_mut(value: &mut T) -> &mut UnsafeCell<T> {
         // SAFETY: `UnsafeCell<T>` has the same memory layout as `T` due to #[repr(transparent)].
         unsafe { &mut *(value as *mut T as *mut UnsafeCell<T>) }
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 701e34b135e..02cc0f9d770 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1,7 +1,7 @@
 //! impl char {}
 
 use super::*;
-use crate::macros::const_panic;
+use crate::panic::const_panic;
 use crate::slice;
 use crate::str::from_utf8_unchecked_mut;
 use crate::unicode::printable::is_printable;
@@ -320,7 +320,7 @@ impl char {
     /// '1'.is_digit(37);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_char_is_digit", issue = "132241")]
+    #[rustc_const_unstable(feature = "const_char_classify", issue = "132241")]
     #[inline]
     pub const fn is_digit(self, radix: u32) -> bool {
         self.to_digit(radix).is_some()
@@ -711,7 +711,7 @@ impl char {
     /// '𝕊'.encode_utf16(&mut b);
     /// ```
     #[stable(feature = "unicode_encode_char", since = "1.15.0")]
-    #[rustc_const_unstable(feature = "const_char_encode_utf16", issue = "130660")]
+    #[rustc_const_stable(feature = "const_char_encode_utf16", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] {
         encode_utf16_raw(self as u32, dst)
@@ -856,8 +856,9 @@ impl char {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_char_classify", issue = "132241")]
     #[inline]
-    pub fn is_whitespace(self) -> bool {
+    pub const fn is_whitespace(self) -> bool {
         match self {
             ' ' | '\x09'..='\x0d' => true,
             c => c > '\x7f' && unicode::White_Space(c),
@@ -1819,7 +1820,10 @@ pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
 /// Panics if the buffer is not large enough.
 /// A buffer of length 2 is large enough to encode any `char`.
 #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
-#[rustc_const_unstable(feature = "const_char_encode_utf16", issue = "130660")]
+#[cfg_attr(
+    bootstrap,
+    rustc_const_stable(feature = "const_char_encode_utf16", since = "CURRENT_RUSTC_VERSION")
+)]
 #[doc(hidden)]
 #[inline]
 pub const fn encode_utf16_raw(mut code: u32, dst: &mut [u16]) -> &mut [u16] {
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 4ea5cbf8626..85571222b5c 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -3,11 +3,12 @@
 use crate::cmp::Ordering;
 use crate::error::Error;
 use crate::ffi::c_char;
+use crate::intrinsics::const_eval_select;
 use crate::iter::FusedIterator;
 use crate::marker::PhantomData;
 use crate::ptr::NonNull;
 use crate::slice::memchr;
-use crate::{fmt, intrinsics, ops, slice, str};
+use crate::{fmt, ops, slice, str};
 
 // FIXME: because this is doc(inline)d, we *have* to use intra-doc links because the actual link
 //   depends on where the item is being documented. however, since this is libcore, we can't
@@ -411,37 +412,35 @@ impl CStr {
     #[rustc_const_stable(feature = "const_cstr_unchecked", since = "1.59.0")]
     #[rustc_allow_const_fn_unstable(const_eval_select)]
     pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
-        #[inline]
-        fn rt_impl(bytes: &[u8]) -> &CStr {
-            // Chance at catching some UB at runtime with debug builds.
-            debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
-
-            // SAFETY: Casting to CStr is safe because its internal representation
-            // is a [u8] too (safe only inside std).
-            // Dereferencing the obtained pointer is safe because it comes from a
-            // reference. Making a reference is then safe because its lifetime
-            // is bound by the lifetime of the given `bytes`.
-            unsafe { &*(bytes as *const [u8] as *const CStr) }
-        }
-
-        const fn const_impl(bytes: &[u8]) -> &CStr {
-            // Saturating so that an empty slice panics in the assert with a good
-            // message, not here due to underflow.
-            let mut i = bytes.len().saturating_sub(1);
-            assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated");
-
-            // Ending nul byte exists, skip to the rest.
-            while i != 0 {
-                i -= 1;
-                let byte = bytes[i];
-                assert!(byte != 0, "input contained interior nul");
+        const_eval_select!(
+            @capture { bytes: &[u8] } -> &CStr:
+            if const {
+                // Saturating so that an empty slice panics in the assert with a good
+                // message, not here due to underflow.
+                let mut i = bytes.len().saturating_sub(1);
+                assert!(!bytes.is_empty() && bytes[i] == 0, "input was not nul-terminated");
+
+                // Ending nul byte exists, skip to the rest.
+                while i != 0 {
+                    i -= 1;
+                    let byte = bytes[i];
+                    assert!(byte != 0, "input contained interior nul");
+                }
+
+                // SAFETY: See runtime cast comment below.
+                unsafe { &*(bytes as *const [u8] as *const CStr) }
+            } else {
+                // Chance at catching some UB at runtime with debug builds.
+                debug_assert!(!bytes.is_empty() && bytes[bytes.len() - 1] == 0);
+
+                // SAFETY: Casting to CStr is safe because its internal representation
+                // is a [u8] too (safe only inside std).
+                // Dereferencing the obtained pointer is safe because it comes from a
+                // reference. Making a reference is then safe because its lifetime
+                // is bound by the lifetime of the given `bytes`.
+                unsafe { &*(bytes as *const [u8] as *const CStr) }
             }
-
-            // SAFETY: See `rt_impl` cast.
-            unsafe { &*(bytes as *const [u8] as *const CStr) }
-        }
-
-        intrinsics::const_eval_select((bytes,), const_impl, rt_impl)
+        )
     }
 
     /// Returns the inner pointer to this C string.
@@ -735,29 +734,27 @@ impl AsRef<CStr> for CStr {
 #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0"))]
 #[rustc_allow_const_fn_unstable(const_eval_select)]
 const unsafe fn strlen(ptr: *const c_char) -> usize {
-    const fn strlen_ct(s: *const c_char) -> usize {
-        let mut len = 0;
-
-        // SAFETY: Outer caller has provided a pointer to a valid C string.
-        while unsafe { *s.add(len) } != 0 {
-            len += 1;
-        }
+    const_eval_select!(
+        @capture { s: *const c_char = ptr } -> usize:
+        if const {
+            let mut len = 0;
+
+            // SAFETY: Outer caller has provided a pointer to a valid C string.
+            while unsafe { *s.add(len) } != 0 {
+                len += 1;
+            }
 
-        len
-    }
+            len
+        } else {
+            extern "C" {
+                /// Provided by libc or compiler_builtins.
+                fn strlen(s: *const c_char) -> usize;
+            }
 
-    #[inline]
-    fn strlen_rt(s: *const c_char) -> usize {
-        extern "C" {
-            /// Provided by libc or compiler_builtins.
-            fn strlen(s: *const c_char) -> usize;
+            // SAFETY: Outer caller has provided a pointer to a valid C string.
+            unsafe { strlen(s) }
         }
-
-        // SAFETY: Outer caller has provided a pointer to a valid C string.
-        unsafe { strlen(s) }
-    }
-
-    intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt)
+    )
 }
 
 /// An iterator over the bytes of a [`CStr`], without the nul terminator.
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index f1540803f97..d43f25d9fd1 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -88,7 +88,10 @@ unsafe trait GenericRadix: Sized {
                 };
             }
         }
-        let buf = &buf[curr..];
+        // SAFETY: `curr` is initialized to `buf.len()` and is only decremented, so it can't overflow. It is
+        // decremented exactly once for each digit. Since u128 is the widest fixed width integer format supported,
+        // the maximum number of digits (bits) is 128 for base-2, so `curr` won't underflow as well.
+        let buf = unsafe { buf.get_unchecked(curr..) };
         // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
         // valid UTF-8
         let buf = unsafe {
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index fc09da7bcbc..d33a403cfda 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -8,16 +8,16 @@
 //! Note: any changes to the constness of intrinsics should be discussed with the language team.
 //! This includes changes in the stability of the constness.
 //!
-//! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
-//! from <https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics> to
-//! <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs> and add a
-//! `#[rustc_const_unstable(feature = "const_such_and_such", issue = "01234")]` to the intrinsic declaration.
+//! In order to make an intrinsic usable at compile-time, it needs to be declared in the "new"
+//! style, i.e. as a `#[rustc_intrinsic]` function, not inside an `extern` block. Then copy the
+//! implementation from <https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics> to
+//! <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs>
+//! and make the intrinsic declaration a `const fn`.
 //!
 //! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
-//! `#[rustc_const_stable_indirect]` needs to be added to the intrinsic (`#[rustc_const_unstable]`
-//! can be removed then). Such a change should not be done without T-lang consultation, because it
-//! may bake a feature into the language that cannot be replicated in user code without compiler
-//! support.
+//! `#[rustc_const_stable_intrinsic]` needs to be added to the intrinsic. Such a change requires
+//! T-lang approval, because it may bake a feature into the language that cannot be replicated in
+//! user code without compiler support.
 //!
 //! # Volatiles
 //!
@@ -936,21 +936,31 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     pub fn abort() -> !;
 
-    /// Informs the optimizer that this point in the code is not reachable,
-    /// enabling further optimizations.
-    ///
-    /// N.B., this is very different from the `unreachable!()` macro: Unlike the
-    /// macro, which panics when it is executed, it is *undefined behavior* to
-    /// reach code marked with this function.
+    /// Executes a breakpoint trap, for inspection by a debugger.
     ///
-    /// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`].
-    #[cfg_attr(
-        bootstrap,
-        rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")
-    )]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
+    /// This intrinsic does not have a stable counterpart.
     #[rustc_nounwind]
-    pub fn unreachable() -> !;
+    pub fn breakpoint();
+}
+
+/// Informs the optimizer that this point in the code is not reachable,
+/// enabling further optimizations.
+///
+/// N.B., this is very different from the `unreachable!()` macro: Unlike the
+/// macro, which panics when it is executed, it is *undefined behavior* to
+/// reach code marked with this function.
+///
+/// The stabilized version of this intrinsic is [`core::hint::unreachable_unchecked`].
+#[cfg_attr(
+    bootstrap,
+    rustc_const_stable(feature = "const_unreachable_unchecked", since = "1.57.0")
+)]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn unreachable() -> ! {
+    unreachable!()
 }
 
 /// Informs the optimizer that a condition is always true.
@@ -964,7 +974,7 @@ extern "rust-intrinsic" {
 ///
 /// The stabilized version of this intrinsic is [`core::hint::assert_unchecked`].
 #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assume", since = "1.77.0"))]
-#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
@@ -990,7 +1000,7 @@ pub const unsafe fn assume(b: bool) {
     bootstrap,
     rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION")
 )]
-#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
 #[rustc_nounwind]
@@ -1014,7 +1024,7 @@ pub const fn likely(b: bool) -> bool {
     bootstrap,
     rustc_const_stable(feature = "const_likely", since = "CURRENT_RUSTC_VERSION")
 )]
-#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic]
 #[rustc_nounwind]
@@ -1044,437 +1054,465 @@ pub fn select_unpredictable<T>(b: bool, true_val: T, false_val: T) -> T {
     if b { true_val } else { false_val }
 }
 
-extern "rust-intrinsic" {
-    /// Executes a breakpoint trap, for inspection by a debugger.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_nounwind]
-    pub fn breakpoint();
+/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
+/// This will statically either panic, or do nothing.
+///
+/// This intrinsic does not have a stable counterpart.
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type", since = "1.59.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn assert_inhabited<T>() {
+    unreachable!()
+}
 
-    /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
-    /// This will statically either panic, or do nothing.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type", since = "1.59.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn assert_inhabited<T>();
+/// A guard for unsafe functions that cannot ever be executed if `T` does not permit
+/// zero-initialization: This will statically either panic, or do nothing.
+///
+/// This intrinsic does not have a stable counterpart.
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn assert_zero_valid<T>() {
+    unreachable!()
+}
 
-    /// A guard for unsafe functions that cannot ever be executed if `T` does not permit
-    /// zero-initialization: This will statically either panic, or do nothing.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn assert_zero_valid<T>();
+/// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing.
+///
+/// This intrinsic does not have a stable counterpart.
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn assert_mem_uninitialized_valid<T>() {
+    unreachable!()
+}
 
-    /// A guard for `std::mem::uninitialized`. This will statically either panic, or do nothing.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_assert_type2", since = "1.75.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn assert_mem_uninitialized_valid<T>();
+/// Gets a reference to a static `Location` indicating where it was called.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// Consider using [`core::panic::Location::caller`] instead.
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_caller_location", since = "1.79.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn caller_location() -> &'static crate::panic::Location<'static> {
+    unreachable!()
+}
 
-    /// Gets a reference to a static `Location` indicating where it was called.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// Consider using [`core::panic::Location::caller`] instead.
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_caller_location", since = "1.79.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn caller_location() -> &'static crate::panic::Location<'static>;
+/// Moves a value out of scope without running drop glue.
+///
+/// This exists solely for [`crate::mem::forget_unsized`]; normal `forget` uses
+/// `ManuallyDrop` instead.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn forget<T: ?Sized>(_: T) {
+    unreachable!()
+}
 
-    /// Moves a value out of scope without running drop glue.
-    ///
-    /// This exists solely for [`crate::mem::forget_unsized`]; normal `forget` uses
-    /// `ManuallyDrop` instead.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_forget", since = "1.83.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn forget<T: ?Sized>(_: T);
-
-    /// Reinterprets the bits of a value of one type as another type.
-    ///
-    /// Both types must have the same size. Compilation will fail if this is not guaranteed.
-    ///
-    /// `transmute` is semantically equivalent to a bitwise move of one type
-    /// into another. It copies the bits from the source value into the
-    /// destination value, then forgets the original. Note that source and destination
-    /// are passed by-value, which means if `Src` or `Dst` contain padding, that padding
-    /// is *not* guaranteed to be preserved by `transmute`.
-    ///
-    /// Both the argument and the result must be [valid](../../nomicon/what-unsafe-does.html) at
-    /// their given type. Violating this condition leads to [undefined behavior][ub]. The compiler
-    /// will generate code *assuming that you, the programmer, ensure that there will never be
-    /// undefined behavior*. It is therefore your responsibility to guarantee that every value
-    /// passed to `transmute` is valid at both types `Src` and `Dst`. Failing to uphold this condition
-    /// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly
-    /// unsafe**. `transmute` should be the absolute last resort.
-    ///
-    /// Because `transmute` is a by-value operation, alignment of the *transmuted values
-    /// themselves* is not a concern. As with any other function, the compiler already ensures
-    /// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point
-    /// elsewhere* (such as pointers, references, boxes…), the caller has to ensure proper
-    /// alignment of the pointed-to values.
-    ///
-    /// The [nomicon](../../nomicon/transmutes.html) has additional documentation.
-    ///
-    /// [ub]: ../../reference/behavior-considered-undefined.html
-    ///
-    /// # Transmutation between pointers and integers
-    ///
-    /// Special care has to be taken when transmuting between pointers and integers, e.g.
-    /// transmuting between `*const ()` and `usize`.
-    ///
-    /// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless
-    /// the pointer was originally created *from* an integer. (That includes this function
-    /// specifically, integer-to-pointer casts, and helpers like [`dangling`][crate::ptr::dangling],
-    /// but also semantically-equivalent conversions such as punning through `repr(C)` union
-    /// fields.) Any attempt to use the resulting value for integer operations will abort
-    /// const-evaluation. (And even outside `const`, such transmutation is touching on many
-    /// unspecified aspects of the Rust memory model and should be avoided. See below for
-    /// alternatives.)
-    ///
-    /// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not*
-    /// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed
-    /// this way is currently considered undefined behavior.
-    ///
-    /// All this also applies when the integer is nested inside an array, tuple, struct, or enum.
-    /// However, `MaybeUninit<usize>` is not considered an integer type for the purpose of this
-    /// section. Transmuting `*const ()` to `MaybeUninit<usize>` is fine---but then calling
-    /// `assume_init()` on that result is considered as completing the pointer-to-integer transmute
-    /// and thus runs into the issues discussed above.
-    ///
-    /// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a
-    /// lossless process. If you want to round-trip a pointer through an integer in a way that you
-    /// can get back the original pointer, you need to use `as` casts, or replace the integer type
-    /// by `MaybeUninit<$int>` (and never call `assume_init()`). If you are looking for a way to
-    /// store data of arbitrary type, also use `MaybeUninit<T>` (that will also handle uninitialized
-    /// memory due to padding). If you specifically need to store something that is "either an
-    /// integer or a pointer", use `*mut ()`: integers can be converted to pointers and back without
-    /// any loss (via `as` casts or via `transmute`).
-    ///
-    /// # Examples
-    ///
-    /// There are a few things that `transmute` is really useful for.
-    ///
-    /// Turning a pointer into a function pointer. This is *not* portable to
-    /// machines where function pointers and data pointers have different sizes.
-    ///
-    /// ```
-    /// fn foo() -> i32 {
-    ///     0
-    /// }
-    /// // Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
-    /// // This avoids an integer-to-pointer `transmute`, which can be problematic.
-    /// // Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine.
-    /// let pointer = foo as *const ();
-    /// let function = unsafe {
-    ///     std::mem::transmute::<*const (), fn() -> i32>(pointer)
-    /// };
-    /// assert_eq!(function(), 0);
-    /// ```
-    ///
-    /// Extending a lifetime, or shortening an invariant lifetime. This is
-    /// advanced, very unsafe Rust!
-    ///
-    /// ```
-    /// struct R<'a>(&'a i32);
-    /// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
-    ///     std::mem::transmute::<R<'b>, R<'static>>(r)
-    /// }
-    ///
-    /// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
-    ///                                              -> &'b mut R<'c> {
-    ///     std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
-    /// }
-    /// ```
-    ///
-    /// # Alternatives
-    ///
-    /// Don't despair: many uses of `transmute` can be achieved through other means.
-    /// Below are common applications of `transmute` which can be replaced with safer
-    /// constructs.
-    ///
-    /// Turning raw bytes (`[u8; SZ]`) into `u32`, `f64`, etc.:
-    ///
-    /// ```
-    /// let raw_bytes = [0x78, 0x56, 0x34, 0x12];
-    ///
-    /// let num = unsafe {
-    ///     std::mem::transmute::<[u8; 4], u32>(raw_bytes)
-    /// };
-    ///
-    /// // use `u32::from_ne_bytes` instead
-    /// let num = u32::from_ne_bytes(raw_bytes);
-    /// // or use `u32::from_le_bytes` or `u32::from_be_bytes` to specify the endianness
-    /// let num = u32::from_le_bytes(raw_bytes);
-    /// assert_eq!(num, 0x12345678);
-    /// let num = u32::from_be_bytes(raw_bytes);
-    /// assert_eq!(num, 0x78563412);
-    /// ```
-    ///
-    /// Turning a pointer into a `usize`:
-    ///
-    /// ```no_run
-    /// let ptr = &0;
-    /// let ptr_num_transmute = unsafe {
-    ///     std::mem::transmute::<&i32, usize>(ptr)
-    /// };
-    ///
-    /// // Use an `as` cast instead
-    /// let ptr_num_cast = ptr as *const i32 as usize;
-    /// ```
-    ///
-    /// Note that using `transmute` to turn a pointer to a `usize` is (as noted above) [undefined
-    /// behavior][ub] in `const` contexts. Also outside of consts, this operation might not behave
-    /// as expected -- this is touching on many unspecified aspects of the Rust memory model.
-    /// Depending on what the code is doing, the following alternatives are preferable to
-    /// pointer-to-integer transmutation:
-    /// - If the code just wants to store data of arbitrary type in some buffer and needs to pick a
-    ///   type for that buffer, it can use [`MaybeUninit`][crate::mem::MaybeUninit].
-    /// - If the code actually wants to work on the address the pointer points to, it can use `as`
-    ///   casts or [`ptr.addr()`][pointer::addr].
-    ///
-    /// Turning a `*mut T` into a `&mut T`:
-    ///
-    /// ```
-    /// let ptr: *mut i32 = &mut 0;
-    /// let ref_transmuted = unsafe {
-    ///     std::mem::transmute::<*mut i32, &mut i32>(ptr)
-    /// };
-    ///
-    /// // Use a reborrow instead
-    /// let ref_casted = unsafe { &mut *ptr };
-    /// ```
-    ///
-    /// Turning a `&mut T` into a `&mut U`:
-    ///
-    /// ```
-    /// let ptr = &mut 0;
-    /// let val_transmuted = unsafe {
-    ///     std::mem::transmute::<&mut i32, &mut u32>(ptr)
-    /// };
-    ///
-    /// // Now, put together `as` and reborrowing - note the chaining of `as`
-    /// // `as` is not transitive
-    /// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
-    /// ```
-    ///
-    /// Turning a `&str` into a `&[u8]`:
-    ///
-    /// ```
-    /// // this is not a good way to do this.
-    /// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") };
-    /// assert_eq!(slice, &[82, 117, 115, 116]);
-    ///
-    /// // You could use `str::as_bytes`
-    /// let slice = "Rust".as_bytes();
-    /// assert_eq!(slice, &[82, 117, 115, 116]);
-    ///
-    /// // Or, just use a byte string, if you have control over the string
-    /// // literal
-    /// assert_eq!(b"Rust", &[82, 117, 115, 116]);
-    /// ```
-    ///
-    /// Turning a `Vec<&T>` into a `Vec<Option<&T>>`.
-    ///
-    /// To transmute the inner type of the contents of a container, you must make sure to not
-    /// violate any of the container's invariants. For `Vec`, this means that both the size
-    /// *and alignment* of the inner types have to match. Other containers might rely on the
-    /// size of the type, alignment, or even the `TypeId`, in which case transmuting wouldn't
-    /// be possible at all without violating the container invariants.
-    ///
-    /// ```
-    /// let store = [0, 1, 2, 3];
-    /// let v_orig = store.iter().collect::<Vec<&i32>>();
-    ///
-    /// // clone the vector as we will reuse them later
-    /// let v_clone = v_orig.clone();
-    ///
-    /// // Using transmute: this relies on the unspecified data layout of `Vec`, which is a
-    /// // bad idea and could cause Undefined Behavior.
-    /// // However, it is no-copy.
-    /// let v_transmuted = unsafe {
-    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
-    /// };
-    ///
-    /// let v_clone = v_orig.clone();
-    ///
-    /// // This is the suggested, safe way.
-    /// // It may copy the entire vector into a new one though, but also may not.
-    /// let v_collected = v_clone.into_iter()
-    ///                          .map(Some)
-    ///                          .collect::<Vec<Option<&i32>>>();
-    ///
-    /// let v_clone = v_orig.clone();
-    ///
-    /// // This is the proper no-copy, unsafe way of "transmuting" a `Vec`, without relying on the
-    /// // data layout. Instead of literally calling `transmute`, we perform a pointer cast, but
-    /// // in terms of converting the original inner type (`&i32`) to the new one (`Option<&i32>`),
-    /// // this has all the same caveats. Besides the information provided above, also consult the
-    /// // [`from_raw_parts`] documentation.
-    /// let v_from_raw = unsafe {
-    // FIXME Update this when vec_into_raw_parts is stabilized
-    ///     // Ensure the original vector is not dropped.
-    ///     let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
-    ///     Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,
-    ///                         v_clone.len(),
-    ///                         v_clone.capacity())
-    /// };
-    /// ```
-    ///
-    /// [`from_raw_parts`]: ../../std/vec/struct.Vec.html#method.from_raw_parts
-    ///
-    /// Implementing `split_at_mut`:
-    ///
-    /// ```
-    /// use std::{slice, mem};
-    ///
-    /// // There are multiple ways to do this, and there are multiple problems
-    /// // with the following (transmute) way.
-    /// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize)
-    ///                              -> (&mut [T], &mut [T]) {
-    ///     let len = slice.len();
-    ///     assert!(mid <= len);
-    ///     unsafe {
-    ///         let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
-    ///         // first: transmute is not type safe; all it checks is that T and
-    ///         // U are of the same size. Second, right here, you have two
-    ///         // mutable references pointing to the same memory.
-    ///         (&mut slice[0..mid], &mut slice2[mid..len])
-    ///     }
-    /// }
-    ///
-    /// // This gets rid of the type safety problems; `&mut *` will *only* give
-    /// // you a `&mut T` from a `&mut T` or `*mut T`.
-    /// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
-    ///                          -> (&mut [T], &mut [T]) {
-    ///     let len = slice.len();
-    ///     assert!(mid <= len);
-    ///     unsafe {
-    ///         let slice2 = &mut *(slice as *mut [T]);
-    ///         // however, you still have two mutable references pointing to
-    ///         // the same memory.
-    ///         (&mut slice[0..mid], &mut slice2[mid..len])
-    ///     }
-    /// }
-    ///
-    /// // This is how the standard library does it. This is the best method, if
-    /// // you need to do something like this
-    /// fn split_at_stdlib<T>(slice: &mut [T], mid: usize)
-    ///                       -> (&mut [T], &mut [T]) {
-    ///     let len = slice.len();
-    ///     assert!(mid <= len);
-    ///     unsafe {
-    ///         let ptr = slice.as_mut_ptr();
-    ///         // This now has three mutable references pointing at the same
-    ///         // memory. `slice`, the rvalue ret.0, and the rvalue ret.1.
-    ///         // `slice` is never used after `let ptr = ...`, and so one can
-    ///         // treat it as "dead", and therefore, you only have two real
-    ///         // mutable slices.
-    ///         (slice::from_raw_parts_mut(ptr, mid),
-    ///          slice::from_raw_parts_mut(ptr.add(mid), len - mid))
-    ///     }
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_allowed_through_unstable_modules]
-    #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
-    #[rustc_diagnostic_item = "transmute"]
-    #[rustc_nounwind]
-    pub fn transmute<Src, Dst>(src: Src) -> Dst;
-
-    /// Like [`transmute`], but even less checked at compile-time: rather than
-    /// giving an error for `size_of::<Src>() != size_of::<Dst>()`, it's
-    /// **Undefined Behavior** at runtime.
-    ///
-    /// Prefer normal `transmute` where possible, for the extra checking, since
-    /// both do exactly the same thing at runtime, if they both compile.
-    ///
-    /// This is not expected to ever be exposed directly to users, rather it
-    /// may eventually be exposed through some more-constrained API.
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_transmute", since = "1.56.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn transmute_unchecked<Src, Dst>(src: Src) -> Dst;
-
-    /// Returns `true` if the actual type given as `T` requires drop
-    /// glue; returns `false` if the actual type provided for `T`
-    /// implements `Copy`.
-    ///
-    /// If the actual type neither requires drop glue nor implements
-    /// `Copy`, then the return value of this function is unspecified.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_needs_drop", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn needs_drop<T: ?Sized>() -> bool;
+/// Reinterprets the bits of a value of one type as another type.
+///
+/// Both types must have the same size. Compilation will fail if this is not guaranteed.
+///
+/// `transmute` is semantically equivalent to a bitwise move of one type
+/// into another. It copies the bits from the source value into the
+/// destination value, then forgets the original. Note that source and destination
+/// are passed by-value, which means if `Src` or `Dst` contain padding, that padding
+/// is *not* guaranteed to be preserved by `transmute`.
+///
+/// Both the argument and the result must be [valid](../../nomicon/what-unsafe-does.html) at
+/// their given type. Violating this condition leads to [undefined behavior][ub]. The compiler
+/// will generate code *assuming that you, the programmer, ensure that there will never be
+/// undefined behavior*. It is therefore your responsibility to guarantee that every value
+/// passed to `transmute` is valid at both types `Src` and `Dst`. Failing to uphold this condition
+/// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly
+/// unsafe**. `transmute` should be the absolute last resort.
+///
+/// Because `transmute` is a by-value operation, alignment of the *transmuted values
+/// themselves* is not a concern. As with any other function, the compiler already ensures
+/// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point
+/// elsewhere* (such as pointers, references, boxes…), the caller has to ensure proper
+/// alignment of the pointed-to values.
+///
+/// The [nomicon](../../nomicon/transmutes.html) has additional documentation.
+///
+/// [ub]: ../../reference/behavior-considered-undefined.html
+///
+/// # Transmutation between pointers and integers
+///
+/// Special care has to be taken when transmuting between pointers and integers, e.g.
+/// transmuting between `*const ()` and `usize`.
+///
+/// Transmuting *pointers to integers* in a `const` context is [undefined behavior][ub], unless
+/// the pointer was originally created *from* an integer. (That includes this function
+/// specifically, integer-to-pointer casts, and helpers like [`dangling`][crate::ptr::dangling],
+/// but also semantically-equivalent conversions such as punning through `repr(C)` union
+/// fields.) Any attempt to use the resulting value for integer operations will abort
+/// const-evaluation. (And even outside `const`, such transmutation is touching on many
+/// unspecified aspects of the Rust memory model and should be avoided. See below for
+/// alternatives.)
+///
+/// Transmuting *integers to pointers* is a largely unspecified operation. It is likely *not*
+/// equivalent to an `as` cast. Doing non-zero-sized memory accesses with a pointer constructed
+/// this way is currently considered undefined behavior.
+///
+/// All this also applies when the integer is nested inside an array, tuple, struct, or enum.
+/// However, `MaybeUninit<usize>` is not considered an integer type for the purpose of this
+/// section. Transmuting `*const ()` to `MaybeUninit<usize>` is fine---but then calling
+/// `assume_init()` on that result is considered as completing the pointer-to-integer transmute
+/// and thus runs into the issues discussed above.
+///
+/// In particular, doing a pointer-to-integer-to-pointer roundtrip via `transmute` is *not* a
+/// lossless process. If you want to round-trip a pointer through an integer in a way that you
+/// can get back the original pointer, you need to use `as` casts, or replace the integer type
+/// by `MaybeUninit<$int>` (and never call `assume_init()`). If you are looking for a way to
+/// store data of arbitrary type, also use `MaybeUninit<T>` (that will also handle uninitialized
+/// memory due to padding). If you specifically need to store something that is "either an
+/// integer or a pointer", use `*mut ()`: integers can be converted to pointers and back without
+/// any loss (via `as` casts or via `transmute`).
+///
+/// # Examples
+///
+/// There are a few things that `transmute` is really useful for.
+///
+/// Turning a pointer into a function pointer. This is *not* portable to
+/// machines where function pointers and data pointers have different sizes.
+///
+/// ```
+/// fn foo() -> i32 {
+///     0
+/// }
+/// // Crucially, we `as`-cast to a raw pointer before `transmute`ing to a function pointer.
+/// // This avoids an integer-to-pointer `transmute`, which can be problematic.
+/// // Transmuting between raw pointers and function pointers (i.e., two pointer types) is fine.
+/// let pointer = foo as *const ();
+/// let function = unsafe {
+///     std::mem::transmute::<*const (), fn() -> i32>(pointer)
+/// };
+/// assert_eq!(function(), 0);
+/// ```
+///
+/// Extending a lifetime, or shortening an invariant lifetime. This is
+/// advanced, very unsafe Rust!
+///
+/// ```
+/// struct R<'a>(&'a i32);
+/// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
+///     std::mem::transmute::<R<'b>, R<'static>>(r)
+/// }
+///
+/// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
+///                                              -> &'b mut R<'c> {
+///     std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
+/// }
+/// ```
+///
+/// # Alternatives
+///
+/// Don't despair: many uses of `transmute` can be achieved through other means.
+/// Below are common applications of `transmute` which can be replaced with safer
+/// constructs.
+///
+/// Turning raw bytes (`[u8; SZ]`) into `u32`, `f64`, etc.:
+///
+/// ```
+/// let raw_bytes = [0x78, 0x56, 0x34, 0x12];
+///
+/// let num = unsafe {
+///     std::mem::transmute::<[u8; 4], u32>(raw_bytes)
+/// };
+///
+/// // use `u32::from_ne_bytes` instead
+/// let num = u32::from_ne_bytes(raw_bytes);
+/// // or use `u32::from_le_bytes` or `u32::from_be_bytes` to specify the endianness
+/// let num = u32::from_le_bytes(raw_bytes);
+/// assert_eq!(num, 0x12345678);
+/// let num = u32::from_be_bytes(raw_bytes);
+/// assert_eq!(num, 0x78563412);
+/// ```
+///
+/// Turning a pointer into a `usize`:
+///
+/// ```no_run
+/// let ptr = &0;
+/// let ptr_num_transmute = unsafe {
+///     std::mem::transmute::<&i32, usize>(ptr)
+/// };
+///
+/// // Use an `as` cast instead
+/// let ptr_num_cast = ptr as *const i32 as usize;
+/// ```
+///
+/// Note that using `transmute` to turn a pointer to a `usize` is (as noted above) [undefined
+/// behavior][ub] in `const` contexts. Also outside of consts, this operation might not behave
+/// as expected -- this is touching on many unspecified aspects of the Rust memory model.
+/// Depending on what the code is doing, the following alternatives are preferable to
+/// pointer-to-integer transmutation:
+/// - If the code just wants to store data of arbitrary type in some buffer and needs to pick a
+///   type for that buffer, it can use [`MaybeUninit`][crate::mem::MaybeUninit].
+/// - If the code actually wants to work on the address the pointer points to, it can use `as`
+///   casts or [`ptr.addr()`][pointer::addr].
+///
+/// Turning a `*mut T` into a `&mut T`:
+///
+/// ```
+/// let ptr: *mut i32 = &mut 0;
+/// let ref_transmuted = unsafe {
+///     std::mem::transmute::<*mut i32, &mut i32>(ptr)
+/// };
+///
+/// // Use a reborrow instead
+/// let ref_casted = unsafe { &mut *ptr };
+/// ```
+///
+/// Turning a `&mut T` into a `&mut U`:
+///
+/// ```
+/// let ptr = &mut 0;
+/// let val_transmuted = unsafe {
+///     std::mem::transmute::<&mut i32, &mut u32>(ptr)
+/// };
+///
+/// // Now, put together `as` and reborrowing - note the chaining of `as`
+/// // `as` is not transitive
+/// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
+/// ```
+///
+/// Turning a `&str` into a `&[u8]`:
+///
+/// ```
+/// // this is not a good way to do this.
+/// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") };
+/// assert_eq!(slice, &[82, 117, 115, 116]);
+///
+/// // You could use `str::as_bytes`
+/// let slice = "Rust".as_bytes();
+/// assert_eq!(slice, &[82, 117, 115, 116]);
+///
+/// // Or, just use a byte string, if you have control over the string
+/// // literal
+/// assert_eq!(b"Rust", &[82, 117, 115, 116]);
+/// ```
+///
+/// Turning a `Vec<&T>` into a `Vec<Option<&T>>`.
+///
+/// To transmute the inner type of the contents of a container, you must make sure to not
+/// violate any of the container's invariants. For `Vec`, this means that both the size
+/// *and alignment* of the inner types have to match. Other containers might rely on the
+/// size of the type, alignment, or even the `TypeId`, in which case transmuting wouldn't
+/// be possible at all without violating the container invariants.
+///
+/// ```
+/// let store = [0, 1, 2, 3];
+/// let v_orig = store.iter().collect::<Vec<&i32>>();
+///
+/// // clone the vector as we will reuse them later
+/// let v_clone = v_orig.clone();
+///
+/// // Using transmute: this relies on the unspecified data layout of `Vec`, which is a
+/// // bad idea and could cause Undefined Behavior.
+/// // However, it is no-copy.
+/// let v_transmuted = unsafe {
+///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(v_clone)
+/// };
+///
+/// let v_clone = v_orig.clone();
+///
+/// // This is the suggested, safe way.
+/// // It may copy the entire vector into a new one though, but also may not.
+/// let v_collected = v_clone.into_iter()
+///                          .map(Some)
+///                          .collect::<Vec<Option<&i32>>>();
+///
+/// let v_clone = v_orig.clone();
+///
+/// // This is the proper no-copy, unsafe way of "transmuting" a `Vec`, without relying on the
+/// // data layout. Instead of literally calling `transmute`, we perform a pointer cast, but
+/// // in terms of converting the original inner type (`&i32`) to the new one (`Option<&i32>`),
+/// // this has all the same caveats. Besides the information provided above, also consult the
+/// // [`from_raw_parts`] documentation.
+/// let v_from_raw = unsafe {
+// FIXME Update this when vec_into_raw_parts is stabilized
+///     // Ensure the original vector is not dropped.
+///     let mut v_clone = std::mem::ManuallyDrop::new(v_clone);
+///     Vec::from_raw_parts(v_clone.as_mut_ptr() as *mut Option<&i32>,
+///                         v_clone.len(),
+///                         v_clone.capacity())
+/// };
+/// ```
+///
+/// [`from_raw_parts`]: ../../std/vec/struct.Vec.html#method.from_raw_parts
+///
+/// Implementing `split_at_mut`:
+///
+/// ```
+/// use std::{slice, mem};
+///
+/// // There are multiple ways to do this, and there are multiple problems
+/// // with the following (transmute) way.
+/// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize)
+///                              -> (&mut [T], &mut [T]) {
+///     let len = slice.len();
+///     assert!(mid <= len);
+///     unsafe {
+///         let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
+///         // first: transmute is not type safe; all it checks is that T and
+///         // U are of the same size. Second, right here, you have two
+///         // mutable references pointing to the same memory.
+///         (&mut slice[0..mid], &mut slice2[mid..len])
+///     }
+/// }
+///
+/// // This gets rid of the type safety problems; `&mut *` will *only* give
+/// // you a `&mut T` from a `&mut T` or `*mut T`.
+/// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
+///                          -> (&mut [T], &mut [T]) {
+///     let len = slice.len();
+///     assert!(mid <= len);
+///     unsafe {
+///         let slice2 = &mut *(slice as *mut [T]);
+///         // however, you still have two mutable references pointing to
+///         // the same memory.
+///         (&mut slice[0..mid], &mut slice2[mid..len])
+///     }
+/// }
+///
+/// // This is how the standard library does it. This is the best method, if
+/// // you need to do something like this
+/// fn split_at_stdlib<T>(slice: &mut [T], mid: usize)
+///                       -> (&mut [T], &mut [T]) {
+///     let len = slice.len();
+///     assert!(mid <= len);
+///     unsafe {
+///         let ptr = slice.as_mut_ptr();
+///         // This now has three mutable references pointing at the same
+///         // memory. `slice`, the rvalue ret.0, and the rvalue ret.1.
+///         // `slice` is never used after `let ptr = ...`, and so one can
+///         // treat it as "dead", and therefore, you only have two real
+///         // mutable slices.
+///         (slice::from_raw_parts_mut(ptr, mid),
+///          slice::from_raw_parts_mut(ptr.add(mid), len - mid))
+///     }
+/// }
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_allowed_through_unstable_modules]
+#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
+#[rustc_diagnostic_item = "transmute"]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn transmute<Src, Dst>(_src: Src) -> Dst {
+    unreachable!()
+}
 
-    /// Calculates the offset from a pointer.
-    ///
-    /// This is implemented as an intrinsic to avoid converting to and from an
-    /// integer, since the conversion would throw away aliasing information.
-    ///
-    /// This can only be used with `Ptr` as a raw pointer type (`*mut` or `*const`)
-    /// to a `Sized` pointee and with `Delta` as `usize` or `isize`.  Any other
-    /// instantiations may arbitrarily misbehave, and that's *not* a compiler bug.
-    ///
-    /// # Safety
-    ///
-    /// If the computed offset is non-zero, then both the starting and resulting pointer must be
-    /// either in bounds or at the end of an allocated object. If either pointer is out
-    /// of bounds or arithmetic overflow occurs then this operation is undefined behavior.
-    ///
-    /// The stabilized version of this intrinsic is [`pointer::offset`].
-    #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
+/// Like [`transmute`], but even less checked at compile-time: rather than
+/// giving an error for `size_of::<Src>() != size_of::<Dst>()`, it's
+/// **Undefined Behavior** at runtime.
+///
+/// Prefer normal `transmute` where possible, for the extra checking, since
+/// both do exactly the same thing at runtime, if they both compile.
+///
+/// This is not expected to ever be exposed directly to users, rather it
+/// may eventually be exposed through some more-constrained API.
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_transmute", since = "1.56.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn transmute_unchecked<Src, Dst>(_src: Src) -> Dst {
+    unreachable!()
+}
 
-    /// Calculates the offset from a pointer, potentially wrapping.
-    ///
-    /// This is implemented as an intrinsic to avoid converting to and from an
-    /// integer, since the conversion inhibits certain optimizations.
-    ///
-    /// # Safety
-    ///
-    /// Unlike the `offset` intrinsic, this intrinsic does not restrict the
-    /// resulting pointer to point into or at the end of an allocated
-    /// object, and it wraps with two's complement arithmetic. The resulting
-    /// value is not necessarily valid to be used to actually access memory.
-    ///
-    /// The stabilized version of this intrinsic is [`pointer::wrapping_offset`].
-    #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
+/// Returns `true` if the actual type given as `T` requires drop
+/// glue; returns `false` if the actual type provided for `T`
+/// implements `Copy`.
+///
+/// If the actual type neither requires drop glue nor implements
+/// `Copy`, then the return value of this function is unspecified.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_needs_drop", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn needs_drop<T: ?Sized>() -> bool {
+    unreachable!()
+}
+
+/// Calculates the offset from a pointer.
+///
+/// This is implemented as an intrinsic to avoid converting to and from an
+/// integer, since the conversion would throw away aliasing information.
+///
+/// This can only be used with `Ptr` as a raw pointer type (`*mut` or `*const`)
+/// to a `Sized` pointee and with `Delta` as `usize` or `isize`.  Any other
+/// instantiations may arbitrarily misbehave, and that's *not* a compiler bug.
+///
+/// # Safety
+///
+/// If the computed offset is non-zero, then both the starting and resulting pointer must be
+/// either in bounds or at the end of an allocated object. If either pointer is out
+/// of bounds or arithmetic overflow occurs then this operation is undefined behavior.
+///
+/// The stabilized version of this intrinsic is [`pointer::offset`].
+#[must_use = "returns a new pointer rather than modifying its argument"]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn offset<Ptr, Delta>(_dst: Ptr, _offset: Delta) -> Ptr {
+    unreachable!()
+}
+
+/// Calculates the offset from a pointer, potentially wrapping.
+///
+/// This is implemented as an intrinsic to avoid converting to and from an
+/// integer, since the conversion inhibits certain optimizations.
+///
+/// # Safety
+///
+/// Unlike the `offset` intrinsic, this intrinsic does not restrict the
+/// resulting pointer to point into or at the end of an allocated
+/// object, and it wraps with two's complement arithmetic. The resulting
+/// value is not necessarily valid to be used to actually access memory.
+///
+/// The stabilized version of this intrinsic is [`pointer::wrapping_offset`].
+#[must_use = "returns a new pointer rather than modifying its argument"]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn arith_offset<T>(_dst: *const T, _offset: isize) -> *const T {
+    unreachable!()
+}
 
+extern "rust-intrinsic" {
     /// Masks out bits of the pointer according to a mask.
     ///
     /// Note that, unlike most intrinsics, this is safe to call;
@@ -2143,474 +2181,569 @@ extern "rust-intrinsic" {
     /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`].
     #[rustc_nounwind]
     pub fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int;
+}
 
-    /// Returns the number of bits set in an integer type `T`
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `count_ones` method. For example,
-    /// [`u32::count_ones`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctpop", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn ctpop<T: Copy>(x: T) -> u32;
+/// Returns the number of bits set in an integer type `T`
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `count_ones` method. For example,
+/// [`u32::count_ones`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctpop", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn ctpop<T: Copy>(_x: T) -> u32 {
+    unimplemented!()
+}
 
-    /// Returns the number of leading unset bits (zeroes) in an integer type `T`.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `leading_zeros` method. For example,
-    /// [`u32::leading_zeros`]
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(core_intrinsics)]
-    /// # #![allow(internal_features)]
-    ///
-    /// use std::intrinsics::ctlz;
-    ///
-    /// let x = 0b0001_1100_u8;
-    /// let num_leading = ctlz(x);
-    /// assert_eq!(num_leading, 3);
-    /// ```
-    ///
-    /// An `x` with value `0` will return the bit width of `T`.
-    ///
-    /// ```
-    /// #![feature(core_intrinsics)]
-    /// # #![allow(internal_features)]
-    ///
-    /// use std::intrinsics::ctlz;
-    ///
-    /// let x = 0u16;
-    /// let num_leading = ctlz(x);
-    /// assert_eq!(num_leading, 16);
-    /// ```
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctlz", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn ctlz<T: Copy>(x: T) -> u32;
+/// Returns the number of leading unset bits (zeroes) in an integer type `T`.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `leading_zeros` method. For example,
+/// [`u32::leading_zeros`]
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_intrinsics)]
+/// # #![allow(internal_features)]
+///
+/// use std::intrinsics::ctlz;
+///
+/// let x = 0b0001_1100_u8;
+/// let num_leading = ctlz(x);
+/// assert_eq!(num_leading, 3);
+/// ```
+///
+/// An `x` with value `0` will return the bit width of `T`.
+///
+/// ```
+/// #![feature(core_intrinsics)]
+/// # #![allow(internal_features)]
+///
+/// use std::intrinsics::ctlz;
+///
+/// let x = 0u16;
+/// let num_leading = ctlz(x);
+/// assert_eq!(num_leading, 16);
+/// ```
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ctlz", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn ctlz<T: Copy>(_x: T) -> u32 {
+    unimplemented!()
+}
 
-    /// Like `ctlz`, but extra-unsafe as it returns `undef` when
-    /// given an `x` with value `0`.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(core_intrinsics)]
-    /// # #![allow(internal_features)]
-    ///
-    /// use std::intrinsics::ctlz_nonzero;
-    ///
-    /// let x = 0b0001_1100_u8;
-    /// let num_leading = unsafe { ctlz_nonzero(x) };
-    /// assert_eq!(num_leading, 3);
-    /// ```
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "constctlz", since = "1.50.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn ctlz_nonzero<T: Copy>(x: T) -> u32;
+/// Like `ctlz`, but extra-unsafe as it returns `undef` when
+/// given an `x` with value `0`.
+///
+/// This intrinsic does not have a stable counterpart.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_intrinsics)]
+/// # #![allow(internal_features)]
+///
+/// use std::intrinsics::ctlz_nonzero;
+///
+/// let x = 0b0001_1100_u8;
+/// let num_leading = unsafe { ctlz_nonzero(x) };
+/// assert_eq!(num_leading, 3);
+/// ```
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "constctlz", since = "1.50.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn ctlz_nonzero<T: Copy>(_x: T) -> u32 {
+    unimplemented!()
+}
 
-    /// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `trailing_zeros` method. For example,
-    /// [`u32::trailing_zeros`]
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(core_intrinsics)]
-    /// # #![allow(internal_features)]
-    ///
-    /// use std::intrinsics::cttz;
-    ///
-    /// let x = 0b0011_1000_u8;
-    /// let num_trailing = cttz(x);
-    /// assert_eq!(num_trailing, 3);
-    /// ```
-    ///
-    /// An `x` with value `0` will return the bit width of `T`:
-    ///
-    /// ```
-    /// #![feature(core_intrinsics)]
-    /// # #![allow(internal_features)]
-    ///
-    /// use std::intrinsics::cttz;
-    ///
-    /// let x = 0u16;
-    /// let num_trailing = cttz(x);
-    /// assert_eq!(num_trailing, 16);
-    /// ```
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn cttz<T: Copy>(x: T) -> u32;
+/// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `trailing_zeros` method. For example,
+/// [`u32::trailing_zeros`]
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_intrinsics)]
+/// # #![allow(internal_features)]
+///
+/// use std::intrinsics::cttz;
+///
+/// let x = 0b0011_1000_u8;
+/// let num_trailing = cttz(x);
+/// assert_eq!(num_trailing, 3);
+/// ```
+///
+/// An `x` with value `0` will return the bit width of `T`:
+///
+/// ```
+/// #![feature(core_intrinsics)]
+/// # #![allow(internal_features)]
+///
+/// use std::intrinsics::cttz;
+///
+/// let x = 0u16;
+/// let num_trailing = cttz(x);
+/// assert_eq!(num_trailing, 16);
+/// ```
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn cttz<T: Copy>(_x: T) -> u32 {
+    unimplemented!()
+}
 
-    /// Like `cttz`, but extra-unsafe as it returns `undef` when
-    /// given an `x` with value `0`.
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(core_intrinsics)]
-    /// # #![allow(internal_features)]
-    ///
-    /// use std::intrinsics::cttz_nonzero;
-    ///
-    /// let x = 0b0011_1000_u8;
-    /// let num_trailing = unsafe { cttz_nonzero(x) };
-    /// assert_eq!(num_trailing, 3);
-    /// ```
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn cttz_nonzero<T: Copy>(x: T) -> u32;
+/// Like `cttz`, but extra-unsafe as it returns `undef` when
+/// given an `x` with value `0`.
+///
+/// This intrinsic does not have a stable counterpart.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(core_intrinsics)]
+/// # #![allow(internal_features)]
+///
+/// use std::intrinsics::cttz_nonzero;
+///
+/// let x = 0b0011_1000_u8;
+/// let num_trailing = unsafe { cttz_nonzero(x) };
+/// assert_eq!(num_trailing, 3);
+/// ```
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn cttz_nonzero<T: Copy>(_x: T) -> u32 {
+    unimplemented!()
+}
 
-    /// Reverses the bytes in an integer type `T`.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `swap_bytes` method. For example,
-    /// [`u32::swap_bytes`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bswap", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn bswap<T: Copy>(x: T) -> T;
+/// Reverses the bytes in an integer type `T`.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `swap_bytes` method. For example,
+/// [`u32::swap_bytes`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bswap", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn bswap<T: Copy>(_x: T) -> T {
+    unimplemented!()
+}
 
-    /// Reverses the bits in an integer type `T`.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `reverse_bits` method. For example,
-    /// [`u32::reverse_bits`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bitreverse", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn bitreverse<T: Copy>(x: T) -> T;
+/// Reverses the bits in an integer type `T`.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `reverse_bits` method. For example,
+/// [`u32::reverse_bits`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_bitreverse", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn bitreverse<T: Copy>(_x: T) -> T {
+    unimplemented!()
+}
 
-    /// Does a three-way comparison between the two integer arguments.
-    ///
-    /// This is included as an intrinsic as it's useful to let it be one thing
-    /// in MIR, rather than the multiple checks and switches that make its IR
-    /// large and difficult to optimize.
-    ///
-    /// The stabilized version of this intrinsic is [`Ord::cmp`].
-    #[rustc_const_unstable(feature = "const_three_way_compare", issue = "none")]
-    #[rustc_safe_intrinsic]
-    pub fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> crate::cmp::Ordering;
+/// Does a three-way comparison between the two integer arguments.
+///
+/// This is included as an intrinsic as it's useful to let it be one thing
+/// in MIR, rather than the multiple checks and switches that make its IR
+/// large and difficult to optimize.
+///
+/// The stabilized version of this intrinsic is [`Ord::cmp`].
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_three_way_compare", issue = "none"))]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn three_way_compare<T: Copy>(_lhs: T, _rhss: T) -> crate::cmp::Ordering {
+    unimplemented!()
+}
 
-    /// Performs checked integer addition.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `overflowing_add` method. For example,
-    /// [`u32::overflowing_add`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
+/// Performs checked integer addition.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `overflowing_add` method. For example,
+/// [`u32::overflowing_add`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn add_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) {
+    unimplemented!()
+}
 
-    /// Performs checked integer subtraction
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `overflowing_sub` method. For example,
-    /// [`u32::overflowing_sub`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
+/// Performs checked integer subtraction
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `overflowing_sub` method. For example,
+/// [`u32::overflowing_sub`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn sub_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) {
+    unimplemented!()
+}
 
-    /// Performs checked integer multiplication
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `overflowing_mul` method. For example,
-    /// [`u32::overflowing_mul`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
+/// Performs checked integer multiplication
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `overflowing_mul` method. For example,
+/// [`u32::overflowing_mul`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_overflow", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn mul_with_overflow<T: Copy>(_x: T, _y: T) -> (T, bool) {
+    unimplemented!()
+}
 
-    /// Performs an exact division, resulting in undefined behavior where
-    /// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`
-    ///
-    /// This intrinsic does not have a stable counterpart.
-    #[rustc_const_unstable(feature = "const_exact_div", issue = "none")]
-    #[rustc_nounwind]
-    pub fn exact_div<T: Copy>(x: T, y: T) -> T;
+/// Performs an exact division, resulting in undefined behavior where
+/// `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`
+///
+/// This intrinsic does not have a stable counterpart.
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_exact_div", issue = "none"))]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn exact_div<T: Copy>(_x: T, _y: T) -> T {
+    unimplemented!()
+}
 
-    /// Performs an unchecked division, resulting in undefined behavior
-    /// where `y == 0` or `x == T::MIN && y == -1`
-    ///
-    /// Safe wrappers for this intrinsic are available on the integer
-    /// primitives via the `checked_div` method. For example,
-    /// [`u32::checked_div`]
-    #[cfg_attr(
-        bootstrap,
-        rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0")
-    )]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
-    /// Returns the remainder of an unchecked division, resulting in
-    /// undefined behavior when `y == 0` or `x == T::MIN && y == -1`
-    ///
-    /// Safe wrappers for this intrinsic are available on the integer
-    /// primitives via the `checked_rem` method. For example,
-    /// [`u32::checked_rem`]
-    #[cfg_attr(
-        bootstrap,
-        rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0")
-    )]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
+/// Performs an unchecked division, resulting in undefined behavior
+/// where `y == 0` or `x == T::MIN && y == -1`
+///
+/// Safe wrappers for this intrinsic are available on the integer
+/// primitives via the `checked_div` method. For example,
+/// [`u32::checked_div`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_div", since = "1.52.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn unchecked_div<T: Copy>(_x: T, _y: T) -> T {
+    unimplemented!()
+}
+/// Returns the remainder of an unchecked division, resulting in
+/// undefined behavior when `y == 0` or `x == T::MIN && y == -1`
+///
+/// Safe wrappers for this intrinsic are available on the integer
+/// primitives via the `checked_rem` method. For example,
+/// [`u32::checked_rem`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked_rem", since = "1.52.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn unchecked_rem<T: Copy>(_x: T, _y: T) -> T {
+    unimplemented!()
+}
 
-    /// Performs an unchecked left shift, resulting in undefined behavior when
-    /// `y < 0` or `y >= N`, where N is the width of T in bits.
-    ///
-    /// Safe wrappers for this intrinsic are available on the integer
-    /// primitives via the `checked_shl` method. For example,
-    /// [`u32::checked_shl`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn unchecked_shl<T: Copy, U: Copy>(x: T, y: U) -> T;
-    /// Performs an unchecked right shift, resulting in undefined behavior when
-    /// `y < 0` or `y >= N`, where N is the width of T in bits.
-    ///
-    /// Safe wrappers for this intrinsic are available on the integer
-    /// primitives via the `checked_shr` method. For example,
-    /// [`u32::checked_shr`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn unchecked_shr<T: Copy, U: Copy>(x: T, y: U) -> T;
+/// Performs an unchecked left shift, resulting in undefined behavior when
+/// `y < 0` or `y >= N`, where N is the width of T in bits.
+///
+/// Safe wrappers for this intrinsic are available on the integer
+/// primitives via the `checked_shl` method. For example,
+/// [`u32::checked_shl`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn unchecked_shl<T: Copy, U: Copy>(_x: T, _y: U) -> T {
+    unimplemented!()
+}
+/// Performs an unchecked right shift, resulting in undefined behavior when
+/// `y < 0` or `y >= N`, where N is the width of T in bits.
+///
+/// Safe wrappers for this intrinsic are available on the integer
+/// primitives via the `checked_shr` method. For example,
+/// [`u32::checked_shr`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn unchecked_shr<T: Copy, U: Copy>(_x: T, _y: U) -> T {
+    unimplemented!()
+}
 
-    /// Returns the result of an unchecked addition, resulting in
-    /// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.
-    ///
-    /// The stable counterpart of this intrinsic is `unchecked_add` on the various
-    /// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`].
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
+/// Returns the result of an unchecked addition, resulting in
+/// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.
+///
+/// The stable counterpart of this intrinsic is `unchecked_add` on the various
+/// integer types, such as [`u16::unchecked_add`] and [`i64::unchecked_add`].
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn unchecked_add<T: Copy>(_x: T, _y: T) -> T {
+    unimplemented!()
+}
 
-    /// Returns the result of an unchecked subtraction, resulting in
-    /// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`.
-    ///
-    /// The stable counterpart of this intrinsic is `unchecked_sub` on the various
-    /// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`].
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
+/// Returns the result of an unchecked subtraction, resulting in
+/// undefined behavior when `x - y > T::MAX` or `x - y < T::MIN`.
+///
+/// The stable counterpart of this intrinsic is `unchecked_sub` on the various
+/// integer types, such as [`u16::unchecked_sub`] and [`i64::unchecked_sub`].
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn unchecked_sub<T: Copy>(_x: T, _y: T) -> T {
+    unimplemented!()
+}
 
-    /// Returns the result of an unchecked multiplication, resulting in
-    /// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`.
-    ///
-    /// The stable counterpart of this intrinsic is `unchecked_mul` on the various
-    /// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`].
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
+/// Returns the result of an unchecked multiplication, resulting in
+/// undefined behavior when `x * y > T::MAX` or `x * y < T::MIN`.
+///
+/// The stable counterpart of this intrinsic is `unchecked_mul` on the various
+/// integer types, such as [`u16::unchecked_mul`] and [`i64::unchecked_mul`].
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "unchecked_math", since = "1.79.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn unchecked_mul<T: Copy>(_x: T, _y: T) -> T {
+    unimplemented!()
+}
 
-    /// Performs rotate left.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `rotate_left` method. For example,
-    /// [`u32::rotate_left`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn rotate_left<T: Copy>(x: T, shift: u32) -> T;
+/// Performs rotate left.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `rotate_left` method. For example,
+/// [`u32::rotate_left`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn rotate_left<T: Copy>(_x: T, _shift: u32) -> T {
+    unimplemented!()
+}
 
-    /// Performs rotate right.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `rotate_right` method. For example,
-    /// [`u32::rotate_right`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn rotate_right<T: Copy>(x: T, shift: u32) -> T;
+/// Performs rotate right.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `rotate_right` method. For example,
+/// [`u32::rotate_right`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_rotate", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn rotate_right<T: Copy>(_x: T, _shift: u32) -> T {
+    unimplemented!()
+}
 
-    /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `wrapping_add` method. For example,
-    /// [`u32::wrapping_add`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn wrapping_add<T: Copy>(a: T, b: T) -> T;
-    /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `wrapping_sub` method. For example,
-    /// [`u32::wrapping_sub`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
-    /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `wrapping_mul` method. For example,
-    /// [`u32::wrapping_mul`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
+/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `wrapping_add` method. For example,
+/// [`u32::wrapping_add`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn wrapping_add<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
+}
+/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `wrapping_sub` method. For example,
+/// [`u32::wrapping_sub`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn wrapping_sub<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
+}
+/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `wrapping_mul` method. For example,
+/// [`u32::wrapping_mul`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn wrapping_mul<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
+}
 
-    /// Computes `a + b`, saturating at numeric bounds.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `saturating_add` method. For example,
-    /// [`u32::saturating_add`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
-    /// Computes `a - b`, saturating at numeric bounds.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized versions of this intrinsic are available on the integer
-    /// primitives via the `saturating_sub` method. For example,
-    /// [`u32::saturating_sub`]
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
+/// Computes `a + b`, saturating at numeric bounds.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `saturating_add` method. For example,
+/// [`u32::saturating_add`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn saturating_add<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
+}
+/// Computes `a - b`, saturating at numeric bounds.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized versions of this intrinsic are available on the integer
+/// primitives via the `saturating_sub` method. For example,
+/// [`u32::saturating_sub`]
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_int_saturating", since = "1.40.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn saturating_sub<T: Copy>(_a: T, _b: T) -> T {
+    unimplemented!()
+}
 
-    /// This is an implementation detail of [`crate::ptr::read`] and should
-    /// not be used anywhere else.  See its comments for why this exists.
-    ///
-    /// This intrinsic can *only* be called where the pointer is a local without
-    /// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it
-    /// trivially obeys runtime-MIR rules about derefs in operands.
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_read", since = "1.71.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn read_via_copy<T>(ptr: *const T) -> T;
+/// This is an implementation detail of [`crate::ptr::read`] and should
+/// not be used anywhere else.  See its comments for why this exists.
+///
+/// This intrinsic can *only* be called where the pointer is a local without
+/// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it
+/// trivially obeys runtime-MIR rules about derefs in operands.
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_read", since = "1.71.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn read_via_copy<T>(_ptr: *const T) -> T {
+    unimplemented!()
+}
 
-    /// This is an implementation detail of [`crate::ptr::write`] and should
-    /// not be used anywhere else.  See its comments for why this exists.
-    ///
-    /// This intrinsic can *only* be called where the pointer is a local without
-    /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so
-    /// that it trivially obeys runtime-MIR rules about derefs in operands.
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn write_via_move<T>(ptr: *mut T, value: T);
+/// This is an implementation detail of [`crate::ptr::write`] and should
+/// not be used anywhere else.  See its comments for why this exists.
+///
+/// This intrinsic can *only* be called where the pointer is a local without
+/// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so
+/// that it trivially obeys runtime-MIR rules about derefs in operands.
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn write_via_move<T>(_ptr: *mut T, _value: T) {
+    unimplemented!()
+}
 
-    /// Returns the value of the discriminant for the variant in 'v';
-    /// if `T` has no discriminant, returns `0`.
-    ///
-    /// Note that, unlike most intrinsics, this is safe to call;
-    /// it does not require an `unsafe` block.
-    /// Therefore, implementations must not require the user to uphold
-    /// any safety invariants.
-    ///
-    /// The stabilized version of this intrinsic is [`core::mem::discriminant`].
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_discriminant", since = "1.75.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
+/// Returns the value of the discriminant for the variant in 'v';
+/// if `T` has no discriminant, returns `0`.
+///
+/// Note that, unlike most intrinsics, this is safe to call;
+/// it does not require an `unsafe` block.
+/// Therefore, implementations must not require the user to uphold
+/// any safety invariants.
+///
+/// The stabilized version of this intrinsic is [`core::mem::discriminant`].
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_discriminant", since = "1.75.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn discriminant_value<T>(_v: &T) -> <T as DiscriminantKind>::Discriminant {
+    unimplemented!()
+}
 
+extern "rust-intrinsic" {
     /// Rust's "try catch" construct for unwinding. Invokes the function pointer `try_fn` with the
     /// data pointer `data`, and calls `catch_fn` if unwinding occurs while `try_fn` runs.
     ///
@@ -2638,25 +2771,32 @@ extern "rust-intrinsic" {
     /// in ways that are not allowed for regular writes).
     #[rustc_nounwind]
     pub fn nontemporal_store<T>(ptr: *mut T, val: T);
+}
 
-    /// See documentation of `<*const T>::offset_from` for details.
-    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0"))]
-    #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-    #[rustc_nounwind]
-    pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
+/// See documentation of `<*const T>::offset_from` for details.
+#[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_offset_from", since = "1.65.0"))]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn ptr_offset_from<T>(_ptr: *const T, _base: *const T) -> isize {
+    unimplemented!()
+}
 
-    /// See documentation of `<*const T>::sub_ptr` for details.
-    #[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
-    #[rustc_nounwind]
-    pub fn ptr_offset_from_unsigned<T>(ptr: *const T, base: *const T) -> usize;
+/// See documentation of `<*const T>::sub_ptr` for details.
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892"))]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn ptr_offset_from_unsigned<T>(_ptr: *const T, _base: *const T) -> usize {
+    unimplemented!()
 }
 
 /// See documentation of `<*const T>::guaranteed_eq` for details.
 /// Returns `2` if the result is unknown.
 /// Returns `1` if the pointers are guaranteed equal
 /// Returns `0` if the pointers are guaranteed inequal
-#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
-#[unstable(feature = "core_intrinsics", issue = "none")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020"))]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 #[rustc_do_not_const_check]
@@ -2666,59 +2806,71 @@ pub const fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8 {
     (ptr == other) as u8
 }
 
-extern "rust-intrinsic" {
-    /// Determines whether the raw bytes of the two values are equal.
-    ///
-    /// This is particularly handy for arrays, since it allows things like just
-    /// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`.
-    ///
-    /// Above some backend-decided threshold this will emit calls to `memcmp`,
-    /// like slice equality does, instead of causing massive code size.
-    ///
-    /// Since this works by comparing the underlying bytes, the actual `T` is
-    /// not particularly important.  It will be used for its size and alignment,
-    /// but any validity restrictions will be ignored, not enforced.
-    ///
-    /// # Safety
-    ///
-    /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized.
-    /// Note that this is a stricter criterion than just the *values* being
-    /// fully-initialized: if `T` has padding, it's UB to call this intrinsic.
-    ///
-    /// At compile-time, it is furthermore UB to call this if any of the bytes
-    /// in `*a` or `*b` have provenance.
-    ///
-    /// (The implementation is allowed to branch on the results of comparisons,
-    /// which is UB if any of their inputs are `undef`.)
-    #[rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none")]
-    #[rustc_nounwind]
-    pub fn raw_eq<T>(a: &T, b: &T) -> bool;
+/// Determines whether the raw bytes of the two values are equal.
+///
+/// This is particularly handy for arrays, since it allows things like just
+/// comparing `i96`s instead of forcing `alloca`s for `[6 x i16]`.
+///
+/// Above some backend-decided threshold this will emit calls to `memcmp`,
+/// like slice equality does, instead of causing massive code size.
+///
+/// Since this works by comparing the underlying bytes, the actual `T` is
+/// not particularly important.  It will be used for its size and alignment,
+/// but any validity restrictions will be ignored, not enforced.
+///
+/// # Safety
+///
+/// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized.
+/// Note that this is a stricter criterion than just the *values* being
+/// fully-initialized: if `T` has padding, it's UB to call this intrinsic.
+///
+/// At compile-time, it is furthermore UB to call this if any of the bytes
+/// in `*a` or `*b` have provenance.
+///
+/// (The implementation is allowed to branch on the results of comparisons,
+/// which is UB if any of their inputs are `undef`.)
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_intrinsic_raw_eq", issue = "none"))]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn raw_eq<T>(_a: &T, _b: &T) -> bool {
+    unimplemented!()
+}
 
-    /// Lexicographically compare `[left, left + bytes)` and `[right, right + bytes)`
-    /// as unsigned bytes, returning negative if `left` is less, zero if all the
-    /// bytes match, or positive if `left` is greater.
-    ///
-    /// This underlies things like `<[u8]>::cmp`, and will usually lower to `memcmp`.
-    ///
-    /// # Safety
-    ///
-    /// `left` and `right` must each be [valid] for reads of `bytes` bytes.
-    ///
-    /// Note that this applies to the whole range, not just until the first byte
-    /// that differs.  That allows optimizations that can read in large chunks.
-    ///
-    /// [valid]: crate::ptr#safety
-    #[rustc_const_unstable(feature = "const_intrinsic_compare_bytes", issue = "none")]
-    #[rustc_nounwind]
-    pub fn compare_bytes(left: *const u8, right: *const u8, bytes: usize) -> i32;
+/// Lexicographically compare `[left, left + bytes)` and `[right, right + bytes)`
+/// as unsigned bytes, returning negative if `left` is less, zero if all the
+/// bytes match, or positive if `left` is greater.
+///
+/// This underlies things like `<[u8]>::cmp`, and will usually lower to `memcmp`.
+///
+/// # Safety
+///
+/// `left` and `right` must each be [valid] for reads of `bytes` bytes.
+///
+/// Note that this applies to the whole range, not just until the first byte
+/// that differs.  That allows optimizations that can read in large chunks.
+///
+/// [valid]: crate::ptr#safety
+#[cfg_attr(
+    bootstrap,
+    rustc_const_unstable(feature = "const_intrinsic_compare_bytes", issue = "none")
+)]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn compare_bytes(_left: *const u8, _right: *const u8, _bytes: usize) -> i32 {
+    unimplemented!()
+}
 
-    /// See documentation of [`std::hint::black_box`] for details.
-    ///
-    /// [`std::hint::black_box`]: crate::hint::black_box
-    #[rustc_const_unstable(feature = "const_black_box", issue = "none")]
-    #[rustc_safe_intrinsic]
-    #[rustc_nounwind]
-    pub fn black_box<T>(dummy: T) -> T;
+/// See documentation of [`std::hint::black_box`] for details.
+///
+/// [`std::hint::black_box`]: crate::hint::black_box
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_black_box", issue = "none"))]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const fn black_box<T>(_dummy: T) -> T {
+    unimplemented!()
 }
 
 /// Selects which function to call depending on the context.
@@ -2788,6 +2940,68 @@ where
     unreachable!()
 }
 
+/// A macro to make it easier to invoke const_eval_select. Use as follows:
+/// ```rust,ignore (just a macro example)
+/// const_eval_select!(
+///     @capture { arg1: i32 = some_expr, arg2: T = other_expr } -> U:
+///     if const #[attributes_for_const_arm] {
+///         // Compile-time code goes here.
+///     } else #[attributes_for_runtime_arm] {
+///         // Run-time code goes here.
+///     }
+/// )
+/// ```
+/// The `@capture` block declares which surrounding variables / expressions can be
+/// used inside the `if const`.
+/// Note that the two arms of this `if` really each become their own function, which is why the
+/// macro supports setting attributes for those functions. The runtime function is always
+/// markes as `#[inline]`.
+///
+/// See [`const_eval_select()`] for the rules and requirements around that intrinsic.
+pub(crate) macro const_eval_select {
+    (
+        @capture { $($arg:ident : $ty:ty = $val:expr),* $(,)? } $( -> $ret:ty )? :
+        if const
+            $(#[$compiletime_attr:meta])* $compiletime:block
+        else
+            $(#[$runtime_attr:meta])* $runtime:block
+    ) => {{
+        #[inline] // avoid the overhead of an extra fn call
+        $(#[$runtime_attr])*
+        fn runtime($($arg: $ty),*) $( -> $ret )? {
+            $runtime
+        }
+
+        #[inline] // prevent codegen on this function
+        $(#[$compiletime_attr])*
+        const fn compiletime($($arg: $ty),*) $( -> $ret )? {
+            // Don't warn if one of the arguments is unused.
+            $(let _ = $arg;)*
+
+            $compiletime
+        }
+
+        const_eval_select(($($val,)*), compiletime, runtime)
+    }},
+    // We support leaving away the `val` expressions for *all* arguments
+    // (but not for *some* arguments, that's too tricky).
+    (
+        @capture { $($arg:ident : $ty:ty),* $(,)? } $( -> $ret:ty )? :
+        if const
+            $(#[$compiletime_attr:meta])* $compiletime:block
+        else
+            $(#[$runtime_attr:meta])* $runtime:block
+    ) => {
+        $crate::intrinsics::const_eval_select!(
+            @capture { $($arg : $ty = $arg),* } $(-> $ret)? :
+            if const
+                $(#[$compiletime_attr])* $compiletime
+            else
+                $(#[$runtime_attr])* $runtime
+        )
+    },
+}
+
 /// Returns whether the argument's value is statically known at
 /// compile-time.
 ///
@@ -2830,7 +3044,7 @@ where
 /// # Stability concerns
 ///
 /// While it is safe to call, this intrinsic may behave differently in
-/// a `const` context than otherwise. See the [`const_eval_select`]
+/// a `const` context than otherwise. See the [`const_eval_select()`]
 /// documentation for an explanation of the issues this can cause. Unlike
 /// `const_eval_select`, this intrinsic isn't guaranteed to behave
 /// deterministically even in a `const` context.
@@ -2886,7 +3100,7 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
 #[rustc_nounwind]
 #[inline]
 #[rustc_intrinsic]
-// This has fallback `const fn` MIR, so shouldn't need stability, see #122652
+// Const-unstable because `swap_nonoverlapping` is const-unstable.
 #[rustc_const_unstable(feature = "const_typed_swap", issue = "none")]
 pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) {
     // SAFETY: The caller provided single non-overlapping items behind
@@ -2908,8 +3122,7 @@ pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) {
 /// user has UB checks disabled, the checks will still get optimized out. This intrinsic is
 /// primarily used by [`ub_checks::assert_unsafe_precondition`].
 #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_ub_checks", issue = "none"))]
-#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // just for UB checks
-#[unstable(feature = "core_intrinsics", issue = "none")]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)] // just for UB checks
 #[inline(always)]
 #[rustc_intrinsic]
 pub const fn ub_checks() -> bool {
@@ -2925,7 +3138,6 @@ pub const fn ub_checks() -> bool {
 ///    - At compile time, a compile error occurs if this constraint is violated.
 ///    - At runtime, it is not checked.
 #[rustc_const_unstable(feature = "const_heap", issue = "79597")]
-#[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_nounwind]
 #[rustc_intrinsic]
 #[miri::intrinsic_fallback_is_spec]
@@ -2994,7 +3206,7 @@ pub unsafe fn vtable_align(_ptr: *const ()) -> usize {
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_size_of", since = "1.40.0"))]
-#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn size_of<T>() -> usize {
@@ -3012,7 +3224,7 @@ pub const fn size_of<T>() -> usize {
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_min_align_of", since = "1.40.0"))]
-#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn min_align_of<T>() -> usize {
@@ -3025,7 +3237,7 @@ pub const fn min_align_of<T>() -> usize {
 /// It's "tracking issue" is [#91971](https://github.com/rust-lang/rust/issues/91971).
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
-#[rustc_const_unstable(feature = "const_pref_align_of", issue = "91971")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_pref_align_of", issue = "91971"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn pref_align_of<T>() -> usize {
@@ -3043,7 +3255,7 @@ pub const unsafe fn pref_align_of<T>() -> usize {
 /// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`].
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
-#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "variant_count", issue = "73662"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn variant_count<T>() -> usize {
@@ -3059,7 +3271,7 @@ pub const fn variant_count<T>() -> usize {
 /// See [`crate::mem::size_of_val_raw`] for safety conditions.
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
-#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_size_of_val", issue = "46571"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize {
@@ -3075,7 +3287,7 @@ pub const unsafe fn size_of_val<T: ?Sized>(_ptr: *const T) -> usize {
 /// See [`crate::mem::align_of_val_raw`] for safety conditions.
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
-#[rustc_const_unstable(feature = "const_align_of_val", issue = "46571")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_align_of_val", issue = "46571"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize {
@@ -3092,7 +3304,7 @@ pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize {
 /// The stabilized version of this intrinsic is [`core::any::type_name`].
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
-#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_name", issue = "63084"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn type_name<T: ?Sized>() -> &'static str {
@@ -3111,7 +3323,7 @@ pub const fn type_name<T: ?Sized>() -> &'static str {
 /// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
-#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_type_id", issue = "77125"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn type_id<T: ?Sized + 'static>() -> u128 {
@@ -3126,7 +3338,7 @@ pub const fn type_id<T: ?Sized + 'static>() -> u128 {
 #[rustc_nounwind]
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))]
-#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(_data: D, _meta: M) -> P {
@@ -3155,7 +3367,7 @@ impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
     bootstrap,
     cfg_attr(bootstrap, rustc_const_stable(feature = "ptr_metadata_const", since = "1.83.0"))
 )]
-#[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
+#[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *const P) -> M {
@@ -3261,18 +3473,13 @@ pub const fn ptr_metadata<P: ptr::Pointee<Metadata = M> + ?Sized, M>(_ptr: *cons
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 #[rustc_diagnostic_item = "ptr_copy_nonoverlapping"]
 pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
-    extern "rust-intrinsic" {
-        #[cfg_attr(
-            bootstrap,
-            rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")
-        )]
-        #[cfg_attr(
-            not(bootstrap),
-            rustc_const_unstable(feature = "core_intrinsics", issue = "none")
-        )]
-        #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-        #[rustc_nounwind]
-        pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))]
+    #[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    const unsafe fn copy_nonoverlapping<T>(_src: *const T, _dst: *mut T, _count: usize) {
+        unreachable!()
     }
 
     ub_checks::assert_unsafe_precondition!(
@@ -3373,18 +3580,13 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 #[rustc_diagnostic_item = "ptr_copy"]
 pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
-    extern "rust-intrinsic" {
-        #[cfg_attr(
-            bootstrap,
-            rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0")
-        )]
-        #[cfg_attr(
-            not(bootstrap),
-            rustc_const_unstable(feature = "core_intrinsics", issue = "none")
-        )]
-        #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-        #[rustc_nounwind]
-        fn copy<T>(src: *const T, dst: *mut T, count: usize);
+    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_intrinsic_copy", since = "1.83.0"))]
+    #[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    const unsafe fn copy<T>(_src: *const T, _dst: *mut T, _count: usize) {
+        unreachable!()
     }
 
     // SAFETY: the safety contract for `copy` must be upheld by the caller.
@@ -3462,11 +3664,13 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 #[rustc_diagnostic_item = "ptr_write_bytes"]
 pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
-    extern "rust-intrinsic" {
-        #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))]
-        #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)]
-        #[rustc_nounwind]
-        fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
+    #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_ptr_write", since = "1.83.0"))]
+    #[cfg_attr(not(bootstrap), rustc_const_stable_intrinsic)]
+    #[rustc_nounwind]
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    const unsafe fn write_bytes<T>(_dst: *mut T, _val: u8, _count: usize) {
+        unreachable!()
     }
 
     // SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
@@ -3494,8 +3698,7 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
 /// The stabilized version of this intrinsic is
 /// [`f16::min`]
 #[rustc_nounwind]
-// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
-#[rustc_const_unstable(feature = "f16", issue = "116909")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn minnumf16(_x: f16, _y: f16) -> f16 {
@@ -3512,7 +3715,7 @@ pub const fn minnumf16(_x: f16, _y: f16) -> f16 {
 /// The stabilized version of this intrinsic is
 /// [`f32::min`]
 #[rustc_nounwind]
-#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn minnumf32(_x: f32, _y: f32) -> f32 {
@@ -3529,7 +3732,7 @@ pub const fn minnumf32(_x: f32, _y: f32) -> f32 {
 /// The stabilized version of this intrinsic is
 /// [`f64::min`]
 #[rustc_nounwind]
-#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn minnumf64(_x: f64, _y: f64) -> f64 {
@@ -3546,8 +3749,7 @@ pub const fn minnumf64(_x: f64, _y: f64) -> f64 {
 /// The stabilized version of this intrinsic is
 /// [`f128::min`]
 #[rustc_nounwind]
-// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
-#[rustc_const_unstable(feature = "f128", issue = "116909")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn minnumf128(_x: f128, _y: f128) -> f128 {
@@ -3564,8 +3766,7 @@ pub const fn minnumf128(_x: f128, _y: f128) -> f128 {
 /// The stabilized version of this intrinsic is
 /// [`f16::max`]
 #[rustc_nounwind]
-// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
-#[rustc_const_unstable(feature = "f16", issue = "116909")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn maxnumf16(_x: f16, _y: f16) -> f16 {
@@ -3582,7 +3783,7 @@ pub const fn maxnumf16(_x: f16, _y: f16) -> f16 {
 /// The stabilized version of this intrinsic is
 /// [`f32::max`]
 #[rustc_nounwind]
-#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn maxnumf32(_x: f32, _y: f32) -> f32 {
@@ -3599,7 +3800,7 @@ pub const fn maxnumf32(_x: f32, _y: f32) -> f32 {
 /// The stabilized version of this intrinsic is
 /// [`f64::max`]
 #[rustc_nounwind]
-#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn maxnumf64(_x: f64, _y: f64) -> f64 {
@@ -3616,8 +3817,7 @@ pub const fn maxnumf64(_x: f64, _y: f64) -> f64 {
 /// The stabilized version of this intrinsic is
 /// [`f128::max`]
 #[rustc_nounwind]
-// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
-#[rustc_const_unstable(feature = "f128", issue = "116909")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const fn maxnumf128(_x: f128, _y: f128) -> f128 {
@@ -3629,8 +3829,7 @@ pub const fn maxnumf128(_x: f128, _y: f128) -> f128 {
 /// The stabilized version of this intrinsic is
 /// [`f16::abs`](../../std/primitive.f16.html#method.abs)
 #[rustc_nounwind]
-// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
-#[rustc_const_unstable(feature = "f16", issue = "116909")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn fabsf16(_x: f16) -> f16 {
@@ -3642,7 +3841,7 @@ pub const unsafe fn fabsf16(_x: f16) -> f16 {
 /// The stabilized version of this intrinsic is
 /// [`f32::abs`](../../std/primitive.f32.html#method.abs)
 #[rustc_nounwind]
-#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn fabsf32(_x: f32) -> f32 {
@@ -3654,7 +3853,7 @@ pub const unsafe fn fabsf32(_x: f32) -> f32 {
 /// The stabilized version of this intrinsic is
 /// [`f64::abs`](../../std/primitive.f64.html#method.abs)
 #[rustc_nounwind]
-#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn fabsf64(_x: f64) -> f64 {
@@ -3666,8 +3865,7 @@ pub const unsafe fn fabsf64(_x: f64) -> f64 {
 /// The stabilized version of this intrinsic is
 /// [`f128::abs`](../../std/primitive.f128.html#method.abs)
 #[rustc_nounwind]
-// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
-#[rustc_const_unstable(feature = "f128", issue = "116909")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn fabsf128(_x: f128) -> f128 {
@@ -3679,8 +3877,7 @@ pub const unsafe fn fabsf128(_x: f128) -> f128 {
 /// The stabilized version of this intrinsic is
 /// [`f16::copysign`](../../std/primitive.f16.html#method.copysign)
 #[rustc_nounwind]
-// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
-#[rustc_const_unstable(feature = "f16", issue = "116909")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f16", issue = "116909"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 {
@@ -3692,7 +3889,7 @@ pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 {
 /// The stabilized version of this intrinsic is
 /// [`f32::copysign`](../../std/primitive.f32.html#method.copysign)
 #[rustc_nounwind]
-#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 {
@@ -3703,7 +3900,7 @@ pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 {
 /// The stabilized version of this intrinsic is
 /// [`f64::copysign`](../../std/primitive.f64.html#method.copysign)
 #[rustc_nounwind]
-#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_float_methods", issue = "130843"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 {
@@ -3715,8 +3912,7 @@ pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 {
 /// The stabilized version of this intrinsic is
 /// [`f128::copysign`](../../std/primitive.f128.html#method.copysign)
 #[rustc_nounwind]
-// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
-#[rustc_const_unstable(feature = "f128", issue = "116909")]
+#[cfg_attr(bootstrap, rustc_const_unstable(feature = "f128", issue = "116909"))]
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 {
@@ -3734,14 +3930,15 @@ pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize
         fn miri_promise_symbolic_alignment(ptr: *const (), align: usize);
     }
 
-    fn runtime(ptr: *const (), align: usize) {
-        // SAFETY: this call is always safe.
-        unsafe {
-            miri_promise_symbolic_alignment(ptr, align);
+    const_eval_select!(
+        @capture { ptr: *const (), align: usize}:
+        if const {
+            // Do nothing.
+        } else {
+            // SAFETY: this call is always safe.
+            unsafe {
+                miri_promise_symbolic_alignment(ptr, align);
+            }
         }
-    }
-
-    const fn compiletime(_ptr: *const (), _align: usize) {}
-
-    const_eval_select((ptr, align), compiletime, runtime);
+    )
 }
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index ff0b91510f1..2f4f33dcc85 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -107,23 +107,21 @@
 //
 // Library features:
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(const_exact_div))]
 #![cfg_attr(bootstrap, feature(const_fmt_arguments_new))]
 #![feature(array_ptr_get)]
 #![feature(asm_experimental_arch)]
 #![feature(const_align_of_val)]
 #![feature(const_align_of_val_raw)]
-#![feature(const_align_offset)]
 #![feature(const_alloc_layout)]
 #![feature(const_black_box)]
-#![feature(const_char_encode_utf16)]
+#![feature(const_eq_ignore_ascii_case)]
 #![feature(const_eval_select)]
-#![feature(const_exact_div)]
 #![feature(const_float_methods)]
 #![feature(const_heap)]
 #![feature(const_nonnull_new)]
 #![feature(const_option_ext)]
 #![feature(const_pin_2)]
-#![feature(const_pointer_is_aligned)]
 #![feature(const_ptr_is_null)]
 #![feature(const_ptr_sub_ptr)]
 #![feature(const_raw_ptr_comparison)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 9a91ff82acd..771c2d31b60 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -12,54 +12,6 @@ macro_rules! panic {
     };
 }
 
-/// Helper macro for panicking in a `const fn`.
-/// Invoke as:
-/// ```rust,ignore (just an example)
-/// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar);
-/// ```
-/// where the first message will be printed in const-eval,
-/// and the second message will be printed at runtime.
-// All uses of this macro are FIXME(const-hack).
-#[unstable(feature = "panic_internals", issue = "none")]
-#[doc(hidden)]
-pub macro const_panic {
-    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{
-        #[inline]
-        #[track_caller]
-        fn runtime($($arg: $ty),*) -> ! {
-            $crate::panic!($runtime_msg);
-        }
-
-        #[inline]
-        #[track_caller]
-        const fn compiletime($(_: $ty),*) -> ! {
-            $crate::panic!($const_msg);
-        }
-
-        // Wrap call to `const_eval_select` in a function so that we can
-        // add the `rustc_allow_const_fn_unstable`. This is okay to do
-        // because both variants will panic, just with different messages.
-        #[rustc_allow_const_fn_unstable(const_eval_select)]
-        #[inline(always)]
-        #[track_caller]
-        #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "CURRENT_RUSTC_VERSION"))]
-        const fn do_panic($($arg: $ty),*) -> ! {
-            $crate::intrinsics::const_eval_select(($($arg),* ,), compiletime, runtime)
-        }
-
-        do_panic($($val),*)
-    }},
-    // We support leaving away the `val` expressions for *all* arguments
-    // (but not for *some* arguments, that's too tricky).
-    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => {
-        $crate::macros::const_panic!(
-            $const_msg,
-            $runtime_msg,
-            $($arg: $ty = $arg),*
-        )
-    },
-}
-
 /// Asserts that two expressions are equal to each other (using [`PartialEq`]).
 ///
 /// Assertions are always checked in both debug and release builds, and cannot
@@ -244,19 +196,6 @@ pub macro assert_matches {
     },
 }
 
-/// A version of `assert` that prints a non-formatting message in const contexts.
-///
-/// See [`const_panic!`].
-#[unstable(feature = "panic_internals", issue = "none")]
-#[doc(hidden)]
-pub macro const_assert {
-    ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{
-        if !$crate::intrinsics::likely($condition) {
-            $crate::macros::const_panic!($const_msg, $runtime_msg, $($arg)*)
-        }
-    }}
-}
-
 /// A macro for defining `#[cfg]` match-like statements.
 ///
 /// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 7709e7de01b..0484611958d 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -14,9 +14,9 @@
 use crate::convert::FloatToInt;
 #[cfg(not(test))]
 use crate::intrinsics;
-use crate::macros::const_assert;
 use crate::mem;
 use crate::num::FpCategory;
+use crate::panic::const_assert;
 
 /// Basic mathematical constants.
 #[unstable(feature = "f128", issue = "116909")]
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index eb0225c58b8..898caf835bf 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -14,9 +14,9 @@
 use crate::convert::FloatToInt;
 #[cfg(not(test))]
 use crate::intrinsics;
-use crate::macros::const_assert;
 use crate::mem;
 use crate::num::FpCategory;
+use crate::panic::const_assert;
 
 /// Basic mathematical constants.
 #[unstable(feature = "f16", issue = "116909")]
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 686a6c50927..20ece883da6 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -14,9 +14,9 @@
 use crate::convert::FloatToInt;
 #[cfg(not(test))]
 use crate::intrinsics;
-use crate::macros::const_assert;
 use crate::mem;
 use crate::num::FpCategory;
+use crate::panic::const_assert;
 
 /// The radix or base of the internal representation of `f32`.
 /// Use [`f32::RADIX`] instead.
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 798cb4b1b5c..5640e71788b 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -14,9 +14,9 @@
 use crate::convert::FloatToInt;
 #[cfg(not(test))]
 use crate::intrinsics;
-use crate::macros::const_assert;
 use crate::mem;
 use crate::num::FpCategory;
+use crate::panic::const_assert;
 
 /// The radix or base of the internal representation of `f64`.
 /// Use [`f64::RADIX`] instead.
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index f4930ca5c7d..5a69dc0c724 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -2,7 +2,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use crate::macros::const_panic;
+use crate::panic::const_panic;
 use crate::str::FromStr;
 use crate::ub_checks::assert_unsafe_precondition;
 use crate::{ascii, intrinsics, mem};
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index c95a000561c..f8f3962ce55 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -189,3 +189,59 @@ pub unsafe trait PanicPayload: crate::fmt::Display {
         None
     }
 }
+
+/// Helper macro for panicking in a `const fn`.
+/// Invoke as:
+/// ```rust,ignore (just an example)
+/// core::macros::const_panic!("boring message", "flavored message {a} {b:?}", a: u32 = foo.len(), b: Something = bar);
+/// ```
+/// where the first message will be printed in const-eval,
+/// and the second message will be printed at runtime.
+// All uses of this macro are FIXME(const-hack).
+#[unstable(feature = "panic_internals", issue = "none")]
+#[doc(hidden)]
+pub macro const_panic {
+    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty = $val:expr),* $(,)?) => {{
+        // Wrap call to `const_eval_select` in a function so that we can
+        // add the `rustc_allow_const_fn_unstable`. This is okay to do
+        // because both variants will panic, just with different messages.
+        #[rustc_allow_const_fn_unstable(const_eval_select)]
+        #[inline(always)]
+        #[track_caller]
+        #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_panic", since = "CURRENT_RUSTC_VERSION"))]
+        const fn do_panic($($arg: $ty),*) -> ! {
+            $crate::intrinsics::const_eval_select!(
+                @capture { $($arg: $ty),* } -> !:
+                if const #[track_caller] {
+                    $crate::panic!($const_msg)
+                } else #[track_caller] {
+                    $crate::panic!($runtime_msg)
+                }
+            )
+        }
+
+        do_panic($($val),*)
+    }},
+    // We support leaving away the `val` expressions for *all* arguments
+    // (but not for *some* arguments, that's too tricky).
+    ($const_msg:literal, $runtime_msg:literal, $($arg:ident : $ty:ty),* $(,)?) => {
+        $crate::panic::const_panic!(
+            $const_msg,
+            $runtime_msg,
+            $($arg: $ty = $arg),*
+        )
+    },
+}
+
+/// A version of `assert` that prints a non-formatting message in const contexts.
+///
+/// See [`const_panic!`].
+#[unstable(feature = "panic_internals", issue = "none")]
+#[doc(hidden)]
+pub macro const_assert {
+    ($condition: expr, $const_msg:literal, $runtime_msg:literal, $($arg:tt)*) => {{
+        if !$crate::intrinsics::likely($condition) {
+            $crate::panic::const_panic!($const_msg, $runtime_msg, $($arg)*)
+        }
+    }}
+}
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 9071d6719a3..f603eb2971f 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -29,6 +29,7 @@
 )]
 
 use crate::fmt;
+use crate::intrinsics::const_eval_select;
 use crate::panic::{Location, PanicInfo};
 
 #[cfg(feature = "panic_immediate_abort")]
@@ -89,40 +90,35 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
 #[cfg_attr(not(bootstrap), rustc_const_stable_indirect)] // must follow stable const rules since it is exposed to stable
 #[rustc_allow_const_fn_unstable(const_eval_select)]
 pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
-    #[inline] // this should always be inlined into `panic_nounwind_fmt`
-    #[track_caller]
-    fn runtime(fmt: fmt::Arguments<'_>, force_no_backtrace: bool) -> ! {
-        if cfg!(feature = "panic_immediate_abort") {
-            super::intrinsics::abort()
+    const_eval_select!(
+        @capture { fmt: fmt::Arguments<'_>, force_no_backtrace: bool } -> !:
+        if const #[track_caller] {
+            // We don't unwind anyway at compile-time so we can call the regular `panic_fmt`.
+            panic_fmt(fmt)
+        } else #[track_caller] {
+            if cfg!(feature = "panic_immediate_abort") {
+                super::intrinsics::abort()
+            }
+
+            // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
+            // that gets resolved to the `#[panic_handler]` function.
+            extern "Rust" {
+                #[lang = "panic_impl"]
+                fn panic_impl(pi: &PanicInfo<'_>) -> !;
+            }
+
+            // PanicInfo with the `can_unwind` flag set to false forces an abort.
+            let pi = PanicInfo::new(
+                &fmt,
+                Location::caller(),
+                /* can_unwind */ false,
+                force_no_backtrace,
+            );
+
+            // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
+            unsafe { panic_impl(&pi) }
         }
-
-        // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
-        // that gets resolved to the `#[panic_handler]` function.
-        extern "Rust" {
-            #[lang = "panic_impl"]
-            fn panic_impl(pi: &PanicInfo<'_>) -> !;
-        }
-
-        // PanicInfo with the `can_unwind` flag set to false forces an abort.
-        let pi = PanicInfo::new(
-            &fmt,
-            Location::caller(),
-            /* can_unwind */ false,
-            force_no_backtrace,
-        );
-
-        // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
-        unsafe { panic_impl(&pi) }
-    }
-
-    #[inline]
-    #[track_caller]
-    const fn comptime(fmt: fmt::Arguments<'_>, _force_no_backtrace: bool) -> ! {
-        // We don't unwind anyway at compile-time so we can call the regular `panic_fmt`.
-        panic_fmt(fmt);
-    }
-
-    super::intrinsics::const_eval_select((fmt, force_no_backtrace), comptime, runtime);
+    )
 }
 
 // Next we define a bunch of higher-level wrappers that all bottom out in the two core functions
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index f00984da527..2d7507e2d53 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -33,26 +33,23 @@ impl<T: ?Sized> *const T {
     #[rustc_diagnostic_item = "ptr_const_is_null"]
     #[inline]
     pub const fn is_null(self) -> bool {
-        #[inline]
-        fn runtime_impl(ptr: *const u8) -> bool {
-            ptr.addr() == 0
-        }
-
-        #[inline]
-        #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
-        const fn const_impl(ptr: *const u8) -> bool {
-            match (ptr).guaranteed_eq(null_mut()) {
-                Some(res) => res,
-                // To remain maximally convervative, we stop execution when we don't
-                // know whether the pointer is null or not.
-                // We can *not* return `false` here, that would be unsound in `NonNull::new`!
-                None => panic!("null-ness of this pointer cannot be determined in const context"),
-            }
-        }
-
         // Compare via a cast to a thin pointer, so fat pointers are only
         // considering their "data" part for null-ness.
-        const_eval_select((self as *const u8,), const_impl, runtime_impl)
+        let ptr = self as *const u8;
+        const_eval_select!(
+            @capture { ptr: *const u8 } -> bool:
+            if const #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")] {
+                match (ptr).guaranteed_eq(null_mut()) {
+                    Some(res) => res,
+                    // To remain maximally convervative, we stop execution when we don't
+                    // know whether the pointer is null or not.
+                    // We can *not* return `false` here, that would be unsound in `NonNull::new`!
+                    None => panic!("null-ness of this pointer cannot be determined in const context"),
+                }
+            } else {
+                ptr.addr() == 0
+            }
+        )
     }
 
     /// Casts to a pointer of another type.
@@ -410,22 +407,21 @@ impl<T: ?Sized> *const T {
         #[inline]
         #[rustc_allow_const_fn_unstable(const_eval_select)]
         const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool {
-            #[inline]
-            fn runtime(this: *const (), count: isize, size: usize) -> bool {
-                // We know `size <= isize::MAX` so the `as` cast here is not lossy.
-                let Some(byte_offset) = count.checked_mul(size as isize) else {
-                    return false;
-                };
-                let (_, overflow) = this.addr().overflowing_add_signed(byte_offset);
-                !overflow
-            }
-
-            const fn comptime(_: *const (), _: isize, _: usize) -> bool {
-                true
-            }
-
             // We can use const_eval_select here because this is only for UB checks.
-            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+            const_eval_select!(
+                @capture { this: *const (), count: isize, size: usize } -> bool:
+                if const {
+                    true
+                } else {
+                    // `size` is the size of a Rust type, so we know that
+                    // `size <= isize::MAX` and thus `as` cast here is not lossy.
+                    let Some(byte_offset) = count.checked_mul(size as isize) else {
+                        return false;
+                    };
+                    let (_, overflow) = this.addr().overflowing_add_signed(byte_offset);
+                    !overflow
+                }
+            )
         }
 
         ub_checks::assert_unsafe_precondition!(
@@ -763,14 +759,14 @@ impl<T: ?Sized> *const T {
     {
         #[rustc_allow_const_fn_unstable(const_eval_select)]
         const fn runtime_ptr_ge(this: *const (), origin: *const ()) -> bool {
-            fn runtime(this: *const (), origin: *const ()) -> bool {
-                this >= origin
-            }
-            const fn comptime(_: *const (), _: *const ()) -> bool {
-                true
-            }
-
-            intrinsics::const_eval_select((this, origin), comptime, runtime)
+            const_eval_select!(
+                @capture { this: *const (), origin: *const () } -> bool:
+                if const {
+                    true
+                } else {
+                    this >= origin
+                }
+            )
         }
 
         ub_checks::assert_unsafe_precondition!(
@@ -924,20 +920,18 @@ impl<T: ?Sized> *const T {
         #[inline]
         #[rustc_allow_const_fn_unstable(const_eval_select)]
         const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool {
-            #[inline]
-            fn runtime(this: *const (), count: usize, size: usize) -> bool {
-                let Some(byte_offset) = count.checked_mul(size) else {
-                    return false;
-                };
-                let (_, overflow) = this.addr().overflowing_add(byte_offset);
-                byte_offset <= (isize::MAX as usize) && !overflow
-            }
-
-            const fn comptime(_: *const (), _: usize, _: usize) -> bool {
-                true
-            }
-
-            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+            const_eval_select!(
+                @capture { this: *const (), count: usize, size: usize } -> bool:
+                if const {
+                    true
+                } else {
+                    let Some(byte_offset) = count.checked_mul(size) else {
+                        return false;
+                    };
+                    let (_, overflow) = this.addr().overflowing_add(byte_offset);
+                    byte_offset <= (isize::MAX as usize) && !overflow
+                }
+            )
         }
 
         #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild.
@@ -1033,19 +1027,17 @@ impl<T: ?Sized> *const T {
         #[inline]
         #[rustc_allow_const_fn_unstable(const_eval_select)]
         const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool {
-            #[inline]
-            fn runtime(this: *const (), count: usize, size: usize) -> bool {
-                let Some(byte_offset) = count.checked_mul(size) else {
-                    return false;
-                };
-                byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset
-            }
-
-            const fn comptime(_: *const (), _: usize, _: usize) -> bool {
-                true
-            }
-
-            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+            const_eval_select!(
+                @capture { this: *const (), count: usize, size: usize } -> bool:
+                if const {
+                    true
+                } else {
+                    let Some(byte_offset) = count.checked_mul(size) else {
+                        return false;
+                    };
+                    byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset
+                }
+            )
         }
 
         #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild.
@@ -1358,15 +1350,6 @@ impl<T: ?Sized> *const T {
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
     /// the returned offset is correct in all terms other than alignment.
     ///
-    /// When this is called during compile-time evaluation (which is unstable), the implementation
-    /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the
-    /// actual alignment of pointers is not known yet during compile-time, so an offset with
-    /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8;
-    /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet
-    /// known, so the execution has to be correct for either choice. It is therefore impossible to
-    /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual
-    /// for unstable APIs.)
-    ///
     /// # Panics
     ///
     /// The function panics if `align` is not a power-of-two.
@@ -1395,8 +1378,7 @@ impl<T: ?Sized> *const T {
     #[must_use]
     #[inline]
     #[stable(feature = "align_offset", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
-    pub const fn align_offset(self, align: usize) -> usize
+    pub fn align_offset(self, align: usize) -> usize
     where
         T: Sized,
     {
@@ -1431,94 +1413,10 @@ impl<T: ?Sized> *const T {
     /// assert!(ptr.is_aligned());
     /// assert!(!ptr.wrapping_byte_add(1).is_aligned());
     /// ```
-    ///
-    /// # At compiletime
-    /// **Note: Alignment at compiletime is experimental and subject to change. See the
-    /// [tracking issue] for details.**
-    ///
-    /// At compiletime, the compiler may not know where a value will end up in memory.
-    /// Calling this function on a pointer created from a reference at compiletime will only
-    /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
-    /// is never aligned if cast to a type with a stricter alignment than the reference's
-    /// underlying allocation.
-    ///
-    /// ```
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of primitives is less than their size.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    /// #[repr(align(8))]
-    /// struct AlignedI64(i64);
-    ///
-    /// const _: () = {
-    ///     let data = AlignedI32(42);
-    ///     let ptr = &data as *const AlignedI32;
-    ///     assert!(ptr.is_aligned());
-    ///
-    ///     // At runtime either `ptr1` or `ptr2` would be aligned, but at compiletime neither is aligned.
-    ///     let ptr1 = ptr.cast::<AlignedI64>();
-    ///     let ptr2 = ptr.wrapping_add(1).cast::<AlignedI64>();
-    ///     assert!(!ptr1.is_aligned());
-    ///     assert!(!ptr2.is_aligned());
-    /// };
-    /// ```
-    ///
-    /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
-    /// pointer is aligned, even if the compiletime pointer wasn't aligned.
-    ///
-    /// ```
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of primitives is less than their size.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    /// #[repr(align(8))]
-    /// struct AlignedI64(i64);
-    ///
-    /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
-    /// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
-    /// const _: () = assert!(!COMPTIME_PTR.cast::<AlignedI64>().is_aligned());
-    /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).cast::<AlignedI64>().is_aligned());
-    ///
-    /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
-    /// let runtime_ptr = COMPTIME_PTR;
-    /// assert_ne!(
-    ///     runtime_ptr.cast::<AlignedI64>().is_aligned(),
-    ///     runtime_ptr.wrapping_add(1).cast::<AlignedI64>().is_aligned(),
-    /// );
-    /// ```
-    ///
-    /// If a pointer is created from a fixed address, this function behaves the same during
-    /// runtime and compiletime.
-    ///
-    /// ```
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of primitives is less than their size.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    /// #[repr(align(8))]
-    /// struct AlignedI64(i64);
-    ///
-    /// const _: () = {
-    ///     let ptr = 40 as *const AlignedI32;
-    ///     assert!(ptr.is_aligned());
-    ///
-    ///     // For pointers with a known address, runtime and compiletime behavior are identical.
-    ///     let ptr1 = ptr.cast::<AlignedI64>();
-    ///     let ptr2 = ptr.wrapping_add(1).cast::<AlignedI64>();
-    ///     assert!(ptr1.is_aligned());
-    ///     assert!(!ptr2.is_aligned());
-    /// };
-    /// ```
-    ///
-    /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
     #[must_use]
     #[inline]
     #[stable(feature = "pointer_is_aligned", since = "1.79.0")]
-    #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
-    pub const fn is_aligned(self) -> bool
+    pub fn is_aligned(self) -> bool
     where
         T: Sized,
     {
@@ -1555,105 +1453,15 @@ impl<T: ?Sized> *const T {
     ///
     /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
     /// ```
-    ///
-    /// # At compiletime
-    /// **Note: Alignment at compiletime is experimental and subject to change. See the
-    /// [tracking issue] for details.**
-    ///
-    /// At compiletime, the compiler may not know where a value will end up in memory.
-    /// Calling this function on a pointer created from a reference at compiletime will only
-    /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
-    /// cannot be stricter aligned than the reference's underlying allocation.
-    ///
-    /// ```
-    /// #![feature(pointer_is_aligned_to)]
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of i32 is less than 4.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    ///
-    /// const _: () = {
-    ///     let data = AlignedI32(42);
-    ///     let ptr = &data as *const AlignedI32;
-    ///
-    ///     assert!(ptr.is_aligned_to(1));
-    ///     assert!(ptr.is_aligned_to(2));
-    ///     assert!(ptr.is_aligned_to(4));
-    ///
-    ///     // At compiletime, we know for sure that the pointer isn't aligned to 8.
-    ///     assert!(!ptr.is_aligned_to(8));
-    ///     assert!(!ptr.wrapping_add(1).is_aligned_to(8));
-    /// };
-    /// ```
-    ///
-    /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
-    /// pointer is aligned, even if the compiletime pointer wasn't aligned.
-    ///
-    /// ```
-    /// #![feature(pointer_is_aligned_to)]
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of i32 is less than 4.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    ///
-    /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
-    /// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
-    /// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
-    /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
-    ///
-    /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
-    /// let runtime_ptr = COMPTIME_PTR;
-    /// assert_ne!(
-    ///     runtime_ptr.is_aligned_to(8),
-    ///     runtime_ptr.wrapping_add(1).is_aligned_to(8),
-    /// );
-    /// ```
-    ///
-    /// If a pointer is created from a fixed address, this function behaves the same during
-    /// runtime and compiletime.
-    ///
-    /// ```
-    /// #![feature(pointer_is_aligned_to)]
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// const _: () = {
-    ///     let ptr = 40 as *const u8;
-    ///     assert!(ptr.is_aligned_to(1));
-    ///     assert!(ptr.is_aligned_to(2));
-    ///     assert!(ptr.is_aligned_to(4));
-    ///     assert!(ptr.is_aligned_to(8));
-    ///     assert!(!ptr.is_aligned_to(16));
-    /// };
-    /// ```
-    ///
-    /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
     #[must_use]
     #[inline]
     #[unstable(feature = "pointer_is_aligned_to", issue = "96284")]
-    #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
-    pub const fn is_aligned_to(self, align: usize) -> bool {
+    pub fn is_aligned_to(self, align: usize) -> bool {
         if !align.is_power_of_two() {
             panic!("is_aligned_to: align is not a power-of-two");
         }
 
-        #[inline]
-        fn runtime_impl(ptr: *const (), align: usize) -> bool {
-            ptr.addr() & (align - 1) == 0
-        }
-
-        #[inline]
-        #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
-        const fn const_impl(ptr: *const (), align: usize) -> bool {
-            // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
-            ptr.align_offset(align) == 0
-        }
-
-        // The cast to `()` is used to
-        //   1. deal with fat pointers; and
-        //   2. ensure that `align_offset` (in `const_impl`) doesn't actually try to compute an offset.
-        const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl)
+        self.addr() & (align - 1) == 0
     }
 }
 
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 7c2205fdcd1..b98e2b5eac8 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1852,9 +1852,7 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
 ///
 /// Any questions go to @nagisa.
 #[allow(ptr_to_integer_transmute_in_consts)]
-#[lang = "align_offset"]
-#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
-pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
+pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
     // FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <=
     // 1, where the method versions of these operations are not inlined.
     use intrinsics::{
@@ -1915,11 +1913,7 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
 
     let stride = mem::size_of::<T>();
 
-    // SAFETY: This is just an inlined `p.addr()` (which is not
-    // a `const fn` so we cannot call it).
-    // During const eval, we hook this function to ensure that the pointer never
-    // has provenance, making this sound.
-    let addr: usize = unsafe { mem::transmute(p) };
+    let addr: usize = p.addr();
 
     // SAFETY: `a` is a power-of-two, therefore non-zero.
     let a_minus_one = unsafe { unchecked_sub(a, 1) };
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 60a2dcd1ee7..344ba46a50e 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -405,23 +405,21 @@ impl<T: ?Sized> *mut T {
         #[inline]
         #[rustc_allow_const_fn_unstable(const_eval_select)]
         const fn runtime_offset_nowrap(this: *const (), count: isize, size: usize) -> bool {
-            #[inline]
-            fn runtime(this: *const (), count: isize, size: usize) -> bool {
-                // `size` is the size of a Rust type, so we know that
-                // `size <= isize::MAX` and thus `as` cast here is not lossy.
-                let Some(byte_offset) = count.checked_mul(size as isize) else {
-                    return false;
-                };
-                let (_, overflow) = this.addr().overflowing_add_signed(byte_offset);
-                !overflow
-            }
-
-            const fn comptime(_: *const (), _: isize, _: usize) -> bool {
-                true
-            }
-
             // We can use const_eval_select here because this is only for UB checks.
-            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+            const_eval_select!(
+                @capture { this: *const (), count: isize, size: usize } -> bool:
+                if const {
+                    true
+                } else {
+                    // `size` is the size of a Rust type, so we know that
+                    // `size <= isize::MAX` and thus `as` cast here is not lossy.
+                    let Some(byte_offset) = count.checked_mul(size as isize) else {
+                        return false;
+                    };
+                    let (_, overflow) = this.addr().overflowing_add_signed(byte_offset);
+                    !overflow
+                }
+            )
         }
 
         ub_checks::assert_unsafe_precondition!(
@@ -1003,20 +1001,18 @@ impl<T: ?Sized> *mut T {
         #[inline]
         #[rustc_allow_const_fn_unstable(const_eval_select)]
         const fn runtime_add_nowrap(this: *const (), count: usize, size: usize) -> bool {
-            #[inline]
-            fn runtime(this: *const (), count: usize, size: usize) -> bool {
-                let Some(byte_offset) = count.checked_mul(size) else {
-                    return false;
-                };
-                let (_, overflow) = this.addr().overflowing_add(byte_offset);
-                byte_offset <= (isize::MAX as usize) && !overflow
-            }
-
-            const fn comptime(_: *const (), _: usize, _: usize) -> bool {
-                true
-            }
-
-            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+            const_eval_select!(
+                @capture { this: *const (), count: usize, size: usize } -> bool:
+                if const {
+                    true
+                } else {
+                    let Some(byte_offset) = count.checked_mul(size) else {
+                        return false;
+                    };
+                    let (_, overflow) = this.addr().overflowing_add(byte_offset);
+                    byte_offset <= (isize::MAX as usize) && !overflow
+                }
+            )
         }
 
         #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild.
@@ -1112,19 +1108,17 @@ impl<T: ?Sized> *mut T {
         #[inline]
         #[rustc_allow_const_fn_unstable(const_eval_select)]
         const fn runtime_sub_nowrap(this: *const (), count: usize, size: usize) -> bool {
-            #[inline]
-            fn runtime(this: *const (), count: usize, size: usize) -> bool {
-                let Some(byte_offset) = count.checked_mul(size) else {
-                    return false;
-                };
-                byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset
-            }
-
-            const fn comptime(_: *const (), _: usize, _: usize) -> bool {
-                true
-            }
-
-            intrinsics::const_eval_select((this, count, size), comptime, runtime)
+            const_eval_select!(
+                @capture { this: *const (), count: usize, size: usize } -> bool:
+                if const {
+                    true
+                } else {
+                    let Some(byte_offset) = count.checked_mul(size) else {
+                        return false;
+                    };
+                    byte_offset <= (isize::MAX as usize) && this.addr() >= byte_offset
+                }
+            )
         }
 
         #[cfg(debug_assertions)] // Expensive, and doesn't catch much in the wild.
@@ -1636,8 +1630,7 @@ impl<T: ?Sized> *mut T {
     #[must_use]
     #[inline]
     #[stable(feature = "align_offset", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
-    pub const fn align_offset(self, align: usize) -> usize
+    pub fn align_offset(self, align: usize) -> usize
     where
         T: Sized,
     {
@@ -1675,95 +1668,10 @@ impl<T: ?Sized> *mut T {
     /// assert!(ptr.is_aligned());
     /// assert!(!ptr.wrapping_byte_add(1).is_aligned());
     /// ```
-    ///
-    /// # At compiletime
-    /// **Note: Alignment at compiletime is experimental and subject to change. See the
-    /// [tracking issue] for details.**
-    ///
-    /// At compiletime, the compiler may not know where a value will end up in memory.
-    /// Calling this function on a pointer created from a reference at compiletime will only
-    /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
-    /// is never aligned if cast to a type with a stricter alignment than the reference's
-    /// underlying allocation.
-    ///
-    /// ```
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of primitives is less than their size.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    /// #[repr(align(8))]
-    /// struct AlignedI64(i64);
-    ///
-    /// const _: () = {
-    ///     let mut data = AlignedI32(42);
-    ///     let ptr = &mut data as *mut AlignedI32;
-    ///     assert!(ptr.is_aligned());
-    ///
-    ///     // At runtime either `ptr1` or `ptr2` would be aligned, but at compiletime neither is aligned.
-    ///     let ptr1 = ptr.cast::<AlignedI64>();
-    ///     let ptr2 = ptr.wrapping_add(1).cast::<AlignedI64>();
-    ///     assert!(!ptr1.is_aligned());
-    ///     assert!(!ptr2.is_aligned());
-    /// };
-    /// ```
-    ///
-    /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
-    /// pointer is aligned, even if the compiletime pointer wasn't aligned.
-    ///
-    /// ```
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of primitives is less than their size.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    /// #[repr(align(8))]
-    /// struct AlignedI64(i64);
-    ///
-    /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
-    /// // Also, note that mutable references are not allowed in the final value of constants.
-    /// const COMPTIME_PTR: *mut AlignedI32 = (&AlignedI32(42) as *const AlignedI32).cast_mut();
-    /// const _: () = assert!(!COMPTIME_PTR.cast::<AlignedI64>().is_aligned());
-    /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).cast::<AlignedI64>().is_aligned());
-    ///
-    /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
-    /// let runtime_ptr = COMPTIME_PTR;
-    /// assert_ne!(
-    ///     runtime_ptr.cast::<AlignedI64>().is_aligned(),
-    ///     runtime_ptr.wrapping_add(1).cast::<AlignedI64>().is_aligned(),
-    /// );
-    /// ```
-    ///
-    /// If a pointer is created from a fixed address, this function behaves the same during
-    /// runtime and compiletime.
-    ///
-    /// ```
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of primitives is less than their size.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    /// #[repr(align(8))]
-    /// struct AlignedI64(i64);
-    ///
-    /// const _: () = {
-    ///     let ptr = 40 as *mut AlignedI32;
-    ///     assert!(ptr.is_aligned());
-    ///
-    ///     // For pointers with a known address, runtime and compiletime behavior are identical.
-    ///     let ptr1 = ptr.cast::<AlignedI64>();
-    ///     let ptr2 = ptr.wrapping_add(1).cast::<AlignedI64>();
-    ///     assert!(ptr1.is_aligned());
-    ///     assert!(!ptr2.is_aligned());
-    /// };
-    /// ```
-    ///
-    /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
     #[must_use]
     #[inline]
     #[stable(feature = "pointer_is_aligned", since = "1.79.0")]
-    #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
-    pub const fn is_aligned(self) -> bool
+    pub fn is_aligned(self) -> bool
     where
         T: Sized,
     {
@@ -1800,106 +1708,15 @@ impl<T: ?Sized> *mut T {
     ///
     /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
     /// ```
-    ///
-    /// # At compiletime
-    /// **Note: Alignment at compiletime is experimental and subject to change. See the
-    /// [tracking issue] for details.**
-    ///
-    /// At compiletime, the compiler may not know where a value will end up in memory.
-    /// Calling this function on a pointer created from a reference at compiletime will only
-    /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
-    /// cannot be stricter aligned than the reference's underlying allocation.
-    ///
-    /// ```
-    /// #![feature(pointer_is_aligned_to)]
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of i32 is less than 4.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    ///
-    /// const _: () = {
-    ///     let mut data = AlignedI32(42);
-    ///     let ptr = &mut data as *mut AlignedI32;
-    ///
-    ///     assert!(ptr.is_aligned_to(1));
-    ///     assert!(ptr.is_aligned_to(2));
-    ///     assert!(ptr.is_aligned_to(4));
-    ///
-    ///     // At compiletime, we know for sure that the pointer isn't aligned to 8.
-    ///     assert!(!ptr.is_aligned_to(8));
-    ///     assert!(!ptr.wrapping_add(1).is_aligned_to(8));
-    /// };
-    /// ```
-    ///
-    /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
-    /// pointer is aligned, even if the compiletime pointer wasn't aligned.
-    ///
-    /// ```
-    /// #![feature(pointer_is_aligned_to)]
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of i32 is less than 4.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    ///
-    /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
-    /// // Also, note that mutable references are not allowed in the final value of constants.
-    /// const COMPTIME_PTR: *mut AlignedI32 = (&AlignedI32(42) as *const AlignedI32).cast_mut();
-    /// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
-    /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
-    ///
-    /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
-    /// let runtime_ptr = COMPTIME_PTR;
-    /// assert_ne!(
-    ///     runtime_ptr.is_aligned_to(8),
-    ///     runtime_ptr.wrapping_add(1).is_aligned_to(8),
-    /// );
-    /// ```
-    ///
-    /// If a pointer is created from a fixed address, this function behaves the same during
-    /// runtime and compiletime.
-    ///
-    /// ```
-    /// #![feature(pointer_is_aligned_to)]
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// const _: () = {
-    ///     let ptr = 40 as *mut u8;
-    ///     assert!(ptr.is_aligned_to(1));
-    ///     assert!(ptr.is_aligned_to(2));
-    ///     assert!(ptr.is_aligned_to(4));
-    ///     assert!(ptr.is_aligned_to(8));
-    ///     assert!(!ptr.is_aligned_to(16));
-    /// };
-    /// ```
-    ///
-    /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
     #[must_use]
     #[inline]
     #[unstable(feature = "pointer_is_aligned_to", issue = "96284")]
-    #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
-    pub const fn is_aligned_to(self, align: usize) -> bool {
+    pub fn is_aligned_to(self, align: usize) -> bool {
         if !align.is_power_of_two() {
             panic!("is_aligned_to: align is not a power-of-two");
         }
 
-        #[inline]
-        fn runtime_impl(ptr: *mut (), align: usize) -> bool {
-            ptr.addr() & (align - 1) == 0
-        }
-
-        #[inline]
-        #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
-        const fn const_impl(ptr: *mut (), align: usize) -> bool {
-            // We can't use the address of `self` in a `const fn`, so we use `align_offset` instead.
-            ptr.align_offset(align) == 0
-        }
-
-        // The cast to `()` is used to
-        //   1. deal with fat pointers; and
-        //   2. ensure that `align_offset` (in `const_impl`) doesn't actually try to compute an offset.
-        const_eval_select((self.cast::<()>(), align), const_impl, runtime_impl)
+        self.addr() & (align - 1) == 0
     }
 }
 
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index 44eeb052661..ad24e50aa15 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -1192,8 +1192,7 @@ impl<T: ?Sized> NonNull<T> {
     #[inline]
     #[must_use]
     #[stable(feature = "non_null_convenience", since = "1.80.0")]
-    #[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
-    pub const fn align_offset(self, align: usize) -> usize
+    pub fn align_offset(self, align: usize) -> usize
     where
         T: Sized,
     {
@@ -1224,98 +1223,10 @@ impl<T: ?Sized> NonNull<T> {
     /// assert!(ptr.is_aligned());
     /// assert!(!NonNull::new(ptr.as_ptr().wrapping_byte_add(1)).unwrap().is_aligned());
     /// ```
-    ///
-    /// # At compiletime
-    /// **Note: Alignment at compiletime is experimental and subject to change. See the
-    /// [tracking issue] for details.**
-    ///
-    /// At compiletime, the compiler may not know where a value will end up in memory.
-    /// Calling this function on a pointer created from a reference at compiletime will only
-    /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
-    /// is never aligned if cast to a type with a stricter alignment than the reference's
-    /// underlying allocation.
-    ///
-    /// ```
-    /// #![feature(const_nonnull_new)]
-    /// #![feature(const_pointer_is_aligned)]
-    /// use std::ptr::NonNull;
-    ///
-    /// // On some platforms, the alignment of primitives is less than their size.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    /// #[repr(align(8))]
-    /// struct AlignedI64(i64);
-    ///
-    /// const _: () = {
-    ///     let data = [AlignedI32(42), AlignedI32(42)];
-    ///     let ptr = NonNull::<AlignedI32>::new(&data[0] as *const _ as *mut _).unwrap();
-    ///     assert!(ptr.is_aligned());
-    ///
-    ///     // At runtime either `ptr1` or `ptr2` would be aligned, but at compiletime neither is aligned.
-    ///     let ptr1 = ptr.cast::<AlignedI64>();
-    ///     let ptr2 = unsafe { ptr.add(1).cast::<AlignedI64>() };
-    ///     assert!(!ptr1.is_aligned());
-    ///     assert!(!ptr2.is_aligned());
-    /// };
-    /// ```
-    ///
-    /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
-    /// pointer is aligned, even if the compiletime pointer wasn't aligned.
-    ///
-    /// ```
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of primitives is less than their size.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    /// #[repr(align(8))]
-    /// struct AlignedI64(i64);
-    ///
-    /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
-    /// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
-    /// const _: () = assert!(!COMPTIME_PTR.cast::<AlignedI64>().is_aligned());
-    /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).cast::<AlignedI64>().is_aligned());
-    ///
-    /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
-    /// let runtime_ptr = COMPTIME_PTR;
-    /// assert_ne!(
-    ///     runtime_ptr.cast::<AlignedI64>().is_aligned(),
-    ///     runtime_ptr.wrapping_add(1).cast::<AlignedI64>().is_aligned(),
-    /// );
-    /// ```
-    ///
-    /// If a pointer is created from a fixed address, this function behaves the same during
-    /// runtime and compiletime.
-    ///
-    /// ```
-    /// #![feature(const_pointer_is_aligned)]
-    /// #![feature(const_nonnull_new)]
-    /// use std::ptr::NonNull;
-    ///
-    /// // On some platforms, the alignment of primitives is less than their size.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    /// #[repr(align(8))]
-    /// struct AlignedI64(i64);
-    ///
-    /// const _: () = {
-    ///     let ptr = NonNull::new(40 as *mut AlignedI32).unwrap();
-    ///     assert!(ptr.is_aligned());
-    ///
-    ///     // For pointers with a known address, runtime and compiletime behavior are identical.
-    ///     let ptr1 = ptr.cast::<AlignedI64>();
-    ///     let ptr2 = NonNull::new(ptr.as_ptr().wrapping_add(1)).unwrap().cast::<AlignedI64>();
-    ///     assert!(ptr1.is_aligned());
-    ///     assert!(!ptr2.is_aligned());
-    /// };
-    /// ```
-    ///
-    /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
     #[inline]
     #[must_use]
     #[stable(feature = "pointer_is_aligned", since = "1.79.0")]
-    #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
-    pub const fn is_aligned(self) -> bool
+    pub fn is_aligned(self) -> bool
     where
         T: Sized,
     {
@@ -1352,85 +1263,10 @@ impl<T: ?Sized> NonNull<T> {
     ///
     /// assert_ne!(ptr.is_aligned_to(8), ptr.wrapping_add(1).is_aligned_to(8));
     /// ```
-    ///
-    /// # At compiletime
-    /// **Note: Alignment at compiletime is experimental and subject to change. See the
-    /// [tracking issue] for details.**
-    ///
-    /// At compiletime, the compiler may not know where a value will end up in memory.
-    /// Calling this function on a pointer created from a reference at compiletime will only
-    /// return `true` if the pointer is guaranteed to be aligned. This means that the pointer
-    /// cannot be stricter aligned than the reference's underlying allocation.
-    ///
-    /// ```
-    /// #![feature(pointer_is_aligned_to)]
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of i32 is less than 4.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    ///
-    /// const _: () = {
-    ///     let data = AlignedI32(42);
-    ///     let ptr = &data as *const AlignedI32;
-    ///
-    ///     assert!(ptr.is_aligned_to(1));
-    ///     assert!(ptr.is_aligned_to(2));
-    ///     assert!(ptr.is_aligned_to(4));
-    ///
-    ///     // At compiletime, we know for sure that the pointer isn't aligned to 8.
-    ///     assert!(!ptr.is_aligned_to(8));
-    ///     assert!(!ptr.wrapping_add(1).is_aligned_to(8));
-    /// };
-    /// ```
-    ///
-    /// Due to this behavior, it is possible that a runtime pointer derived from a compiletime
-    /// pointer is aligned, even if the compiletime pointer wasn't aligned.
-    ///
-    /// ```
-    /// #![feature(pointer_is_aligned_to)]
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// // On some platforms, the alignment of i32 is less than 4.
-    /// #[repr(align(4))]
-    /// struct AlignedI32(i32);
-    ///
-    /// // At compiletime, neither `COMPTIME_PTR` nor `COMPTIME_PTR + 1` is aligned.
-    /// const COMPTIME_PTR: *const AlignedI32 = &AlignedI32(42);
-    /// const _: () = assert!(!COMPTIME_PTR.is_aligned_to(8));
-    /// const _: () = assert!(!COMPTIME_PTR.wrapping_add(1).is_aligned_to(8));
-    ///
-    /// // At runtime, either `runtime_ptr` or `runtime_ptr + 1` is aligned.
-    /// let runtime_ptr = COMPTIME_PTR;
-    /// assert_ne!(
-    ///     runtime_ptr.is_aligned_to(8),
-    ///     runtime_ptr.wrapping_add(1).is_aligned_to(8),
-    /// );
-    /// ```
-    ///
-    /// If a pointer is created from a fixed address, this function behaves the same during
-    /// runtime and compiletime.
-    ///
-    /// ```
-    /// #![feature(pointer_is_aligned_to)]
-    /// #![feature(const_pointer_is_aligned)]
-    ///
-    /// const _: () = {
-    ///     let ptr = 40 as *const u8;
-    ///     assert!(ptr.is_aligned_to(1));
-    ///     assert!(ptr.is_aligned_to(2));
-    ///     assert!(ptr.is_aligned_to(4));
-    ///     assert!(ptr.is_aligned_to(8));
-    ///     assert!(!ptr.is_aligned_to(16));
-    /// };
-    /// ```
-    ///
-    /// [tracking issue]: https://github.com/rust-lang/rust/issues/104203
     #[inline]
     #[must_use]
     #[unstable(feature = "pointer_is_aligned_to", issue = "96284")]
-    #[rustc_const_unstable(feature = "const_pointer_is_aligned", issue = "104203")]
-    pub const fn is_aligned_to(self, align: usize) -> bool {
+    pub fn is_aligned_to(self, align: usize) -> bool {
         self.pointer.is_aligned_to(align)
     }
 }
diff --git a/library/core/src/slice/ascii.rs b/library/core/src/slice/ascii.rs
index 21e0460072f..17ad4fd8f67 100644
--- a/library/core/src/slice/ascii.rs
+++ b/library/core/src/slice/ascii.rs
@@ -3,6 +3,7 @@
 use core::ascii::EscapeDefault;
 
 use crate::fmt::{self, Write};
+use crate::intrinsics::const_eval_select;
 use crate::{ascii, iter, mem, ops};
 
 #[cfg(not(test))]
@@ -51,10 +52,30 @@ impl [u8] {
     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
     /// but without allocating and copying temporaries.
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")]
     #[must_use]
     #[inline]
-    pub fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
-        self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b))
+    pub const fn eq_ignore_ascii_case(&self, other: &[u8]) -> bool {
+        if self.len() != other.len() {
+            return false;
+        }
+
+        // FIXME(const-hack): This implementation can be reverted when
+        // `core::iter::zip` is allowed in const. The original implementation:
+        //  self.len() == other.len() && iter::zip(self, other).all(|(a, b)| a.eq_ignore_ascii_case(b))
+        let mut a = self;
+        let mut b = other;
+
+        while let ([first_a, rest_a @ ..], [first_b, rest_b @ ..]) = (a, b) {
+            if first_a.eq_ignore_ascii_case(&first_b) {
+                a = rest_a;
+                b = rest_b;
+            } else {
+                return false;
+            }
+        }
+
+        true
     }
 
     /// Converts this slice to its ASCII upper case equivalent in-place.
@@ -346,89 +367,91 @@ pub const fn is_ascii_simple(mut bytes: &[u8]) -> bool {
 /// If any of these loads produces something for which `contains_nonascii`
 /// (above) returns true, then we know the answer is false.
 #[inline]
-#[rustc_allow_const_fn_unstable(const_raw_ptr_comparison, const_pointer_is_aligned)] // only in a debug assertion
-#[rustc_allow_const_fn_unstable(const_align_offset)] // behavior does not change when `align_offset` fails
+#[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior
 const fn is_ascii(s: &[u8]) -> bool {
-    const USIZE_SIZE: usize = mem::size_of::<usize>();
-
-    let len = s.len();
-    let align_offset = s.as_ptr().align_offset(USIZE_SIZE);
-
-    // If we wouldn't gain anything from the word-at-a-time implementation, fall
-    // back to a scalar loop.
-    //
-    // We also do this for architectures where `size_of::<usize>()` isn't
-    // sufficient alignment for `usize`, because it's a weird edge case.
-    if len < USIZE_SIZE || len < align_offset || USIZE_SIZE < mem::align_of::<usize>() {
-        return is_ascii_simple(s);
-    }
-
-    // We always read the first word unaligned, which means `align_offset` is
-    // 0, we'd read the same value again for the aligned read.
-    let offset_to_aligned = if align_offset == 0 { USIZE_SIZE } else { align_offset };
+    // The runtime version behaves the same as the compiletime version, it's
+    // just more optimized.
+    const_eval_select!(
+        @capture { s: &[u8] } -> bool:
+        if const {
+            is_ascii_simple(s)
+        } else {
+            const USIZE_SIZE: usize = mem::size_of::<usize>();
+
+            let len = s.len();
+            let align_offset = s.as_ptr().align_offset(USIZE_SIZE);
+
+            // If we wouldn't gain anything from the word-at-a-time implementation, fall
+            // back to a scalar loop.
+            //
+            // We also do this for architectures where `size_of::<usize>()` isn't
+            // sufficient alignment for `usize`, because it's a weird edge case.
+            if len < USIZE_SIZE || len < align_offset || USIZE_SIZE < mem::align_of::<usize>() {
+                return is_ascii_simple(s);
+            }
 
-    let start = s.as_ptr();
-    // SAFETY: We verify `len < USIZE_SIZE` above.
-    let first_word = unsafe { (start as *const usize).read_unaligned() };
+            // We always read the first word unaligned, which means `align_offset` is
+            // 0, we'd read the same value again for the aligned read.
+            let offset_to_aligned = if align_offset == 0 { USIZE_SIZE } else { align_offset };
 
-    if contains_nonascii(first_word) {
-        return false;
-    }
-    // We checked this above, somewhat implicitly. Note that `offset_to_aligned`
-    // is either `align_offset` or `USIZE_SIZE`, both of are explicitly checked
-    // above.
-    debug_assert!(offset_to_aligned <= len);
-
-    // SAFETY: word_ptr is the (properly aligned) usize ptr we use to read the
-    // middle chunk of the slice.
-    let mut word_ptr = unsafe { start.add(offset_to_aligned) as *const usize };
-
-    // `byte_pos` is the byte index of `word_ptr`, used for loop end checks.
-    let mut byte_pos = offset_to_aligned;
-
-    // Paranoia check about alignment, since we're about to do a bunch of
-    // unaligned loads. In practice this should be impossible barring a bug in
-    // `align_offset` though.
-    // While this method is allowed to spuriously fail in CTFE, if it doesn't
-    // have alignment information it should have given a `usize::MAX` for
-    // `align_offset` earlier, sending things through the scalar path instead of
-    // this one, so this check should pass if it's reachable.
-    debug_assert!(word_ptr.is_aligned_to(mem::align_of::<usize>()));
-
-    // Read subsequent words until the last aligned word, excluding the last
-    // aligned word by itself to be done in tail check later, to ensure that
-    // tail is always one `usize` at most to extra branch `byte_pos == len`.
-    while byte_pos < len - USIZE_SIZE {
-        // Sanity check that the read is in bounds
-        debug_assert!(byte_pos + USIZE_SIZE <= len);
-        // And that our assumptions about `byte_pos` hold.
-        debug_assert!(matches!(
-            word_ptr.cast::<u8>().guaranteed_eq(start.wrapping_add(byte_pos)),
-            // These are from the same allocation, so will hopefully always be
-            // known to match even in CTFE, but if it refuses to compare them
-            // that's ok since it's just a debug check anyway.
-            None | Some(true),
-        ));
-
-        // SAFETY: We know `word_ptr` is properly aligned (because of
-        // `align_offset`), and we know that we have enough bytes between `word_ptr` and the end
-        let word = unsafe { word_ptr.read() };
-        if contains_nonascii(word) {
-            return false;
-        }
+            let start = s.as_ptr();
+            // SAFETY: We verify `len < USIZE_SIZE` above.
+            let first_word = unsafe { (start as *const usize).read_unaligned() };
 
-        byte_pos += USIZE_SIZE;
-        // SAFETY: We know that `byte_pos <= len - USIZE_SIZE`, which means that
-        // after this `add`, `word_ptr` will be at most one-past-the-end.
-        word_ptr = unsafe { word_ptr.add(1) };
-    }
+            if contains_nonascii(first_word) {
+                return false;
+            }
+            // We checked this above, somewhat implicitly. Note that `offset_to_aligned`
+            // is either `align_offset` or `USIZE_SIZE`, both of are explicitly checked
+            // above.
+            debug_assert!(offset_to_aligned <= len);
+
+            // SAFETY: word_ptr is the (properly aligned) usize ptr we use to read the
+            // middle chunk of the slice.
+            let mut word_ptr = unsafe { start.add(offset_to_aligned) as *const usize };
+
+            // `byte_pos` is the byte index of `word_ptr`, used for loop end checks.
+            let mut byte_pos = offset_to_aligned;
+
+            // Paranoia check about alignment, since we're about to do a bunch of
+            // unaligned loads. In practice this should be impossible barring a bug in
+            // `align_offset` though.
+            // While this method is allowed to spuriously fail in CTFE, if it doesn't
+            // have alignment information it should have given a `usize::MAX` for
+            // `align_offset` earlier, sending things through the scalar path instead of
+            // this one, so this check should pass if it's reachable.
+            debug_assert!(word_ptr.is_aligned_to(mem::align_of::<usize>()));
+
+            // Read subsequent words until the last aligned word, excluding the last
+            // aligned word by itself to be done in tail check later, to ensure that
+            // tail is always one `usize` at most to extra branch `byte_pos == len`.
+            while byte_pos < len - USIZE_SIZE {
+                // Sanity check that the read is in bounds
+                debug_assert!(byte_pos + USIZE_SIZE <= len);
+                // And that our assumptions about `byte_pos` hold.
+                debug_assert!(word_ptr.cast::<u8>() == start.wrapping_add(byte_pos));
+
+                // SAFETY: We know `word_ptr` is properly aligned (because of
+                // `align_offset`), and we know that we have enough bytes between `word_ptr` and the end
+                let word = unsafe { word_ptr.read() };
+                if contains_nonascii(word) {
+                    return false;
+                }
+
+                byte_pos += USIZE_SIZE;
+                // SAFETY: We know that `byte_pos <= len - USIZE_SIZE`, which means that
+                // after this `add`, `word_ptr` will be at most one-past-the-end.
+                word_ptr = unsafe { word_ptr.add(1) };
+            }
 
-    // Sanity check to ensure there really is only one `usize` left. This should
-    // be guaranteed by our loop condition.
-    debug_assert!(byte_pos <= len && len - byte_pos <= USIZE_SIZE);
+            // Sanity check to ensure there really is only one `usize` left. This should
+            // be guaranteed by our loop condition.
+            debug_assert!(byte_pos <= len && len - byte_pos <= USIZE_SIZE);
 
-    // SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start.
-    let last_word = unsafe { (start.add(len - USIZE_SIZE) as *const usize).read_unaligned() };
+            // SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start.
+            let last_word = unsafe { (start.add(len - USIZE_SIZE) as *const usize).read_unaligned() };
 
-    !contains_nonascii(last_word)
+            !contains_nonascii(last_word)
+        }
+    )
 }
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index ebb4bdb1449..aafa19c0dd3 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -1,6 +1,6 @@
 //! Indexing implementations for `[T]`.
 
-use crate::macros::const_panic;
+use crate::panic::const_panic;
 use crate::ub_checks::assert_unsafe_precondition;
 use crate::{ops, range};
 
diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs
index 57604623262..339adad1b17 100644
--- a/library/core/src/slice/memchr.rs
+++ b/library/core/src/slice/memchr.rs
@@ -1,6 +1,7 @@
 // Original implementation taken from rust-memchr.
 // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
 
+use crate::intrinsics::const_eval_select;
 use crate::mem;
 
 const LO_USIZE: usize = usize::repeat_u8(0x01);
@@ -50,58 +51,64 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option<usize> {
     None
 }
 
-#[rustc_allow_const_fn_unstable(const_cmp)]
-#[rustc_allow_const_fn_unstable(const_align_offset)]
+#[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior
 #[cfg_attr(bootstrap, rustc_const_stable(feature = "const_memchr", since = "1.65.0"))]
 const fn memchr_aligned(x: u8, text: &[u8]) -> Option<usize> {
-    // Scan for a single byte value by reading two `usize` words at a time.
-    //
-    // Split `text` in three parts
-    // - unaligned initial part, before the first word aligned address in text
-    // - body, scan by 2 words at a time
-    // - the last remaining part, < 2 word size
-
-    // search up to an aligned boundary
-    let len = text.len();
-    let ptr = text.as_ptr();
-    let mut offset = ptr.align_offset(USIZE_BYTES);
-
-    if offset > 0 {
-        // FIXME(const-hack, fee1-dead): replace with min
-        offset = if offset < len { offset } else { len };
-        // FIXME(const-hack, fee1-dead): replace with range slicing
-        // SAFETY: offset is within bounds
-        let slice = unsafe { super::from_raw_parts(text.as_ptr(), offset) };
-        if let Some(index) = memchr_naive(x, slice) {
-            return Some(index);
-        }
-    }
-
-    // search the body of the text
-    let repeated_x = usize::repeat_u8(x);
-    while offset <= len - 2 * USIZE_BYTES {
-        // SAFETY: the while's predicate guarantees a distance of at least 2 * usize_bytes
-        // between the offset and the end of the slice.
-        unsafe {
-            let u = *(ptr.add(offset) as *const usize);
-            let v = *(ptr.add(offset + USIZE_BYTES) as *const usize);
+    // The runtime version behaves the same as the compiletime version, it's
+    // just more optimized.
+    const_eval_select!(
+        @capture { x: u8, text: &[u8] } -> Option<usize>:
+        if const {
+            memchr_naive(x, text)
+        } else {
+            // Scan for a single byte value by reading two `usize` words at a time.
+            //
+            // Split `text` in three parts
+            // - unaligned initial part, before the first word aligned address in text
+            // - body, scan by 2 words at a time
+            // - the last remaining part, < 2 word size
+
+            // search up to an aligned boundary
+            let len = text.len();
+            let ptr = text.as_ptr();
+            let mut offset = ptr.align_offset(USIZE_BYTES);
+
+            if offset > 0 {
+                offset = offset.min(len);
+                let slice = &text[..offset];
+                if let Some(index) = memchr_naive(x, slice) {
+                    return Some(index);
+                }
+            }
 
-            // break if there is a matching byte
-            let zu = contains_zero_byte(u ^ repeated_x);
-            let zv = contains_zero_byte(v ^ repeated_x);
-            if zu || zv {
-                break;
+            // search the body of the text
+            let repeated_x = usize::repeat_u8(x);
+            while offset <= len - 2 * USIZE_BYTES {
+                // SAFETY: the while's predicate guarantees a distance of at least 2 * usize_bytes
+                // between the offset and the end of the slice.
+                unsafe {
+                    let u = *(ptr.add(offset) as *const usize);
+                    let v = *(ptr.add(offset + USIZE_BYTES) as *const usize);
+
+                    // break if there is a matching byte
+                    let zu = contains_zero_byte(u ^ repeated_x);
+                    let zv = contains_zero_byte(v ^ repeated_x);
+                    if zu || zv {
+                        break;
+                    }
+                }
+                offset += USIZE_BYTES * 2;
             }
-        }
-        offset += USIZE_BYTES * 2;
-    }
 
-    // Find the byte after the point the body loop stopped.
-    // FIXME(const-hack): Use `?` instead.
-    // FIXME(const-hack, fee1-dead): use range slicing
-    // SAFETY: offset is within bounds
-    let slice = unsafe { super::from_raw_parts(text.as_ptr().add(offset), text.len() - offset) };
-    if let Some(i) = memchr_naive(x, slice) { Some(offset + i) } else { None }
+            // Find the byte after the point the body loop stopped.
+            // FIXME(const-hack): Use `?` instead.
+            // FIXME(const-hack, fee1-dead): use range slicing
+            let slice =
+            // SAFETY: offset is within bounds
+                unsafe { super::from_raw_parts(text.as_ptr().add(offset), text.len() - offset) };
+            if let Some(i) = memchr_naive(x, slice) { Some(offset + i) } else { None }
+        }
+    )
 }
 
 /// Returns the last index matching the byte `x` in `text`.
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index 2bc1f1e4973..c7bae42765f 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -82,7 +82,6 @@ use crate::{mem, ptr};
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_str_from_utf8_shared", since = "1.63.0")]
-#[rustc_allow_const_fn_unstable(str_internals)]
 #[rustc_diagnostic_item = "str_from_utf8"]
 pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     // FIXME(const-hack): This should use `?` again, once it's `const`
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 58d6e07de8d..0f7c2c999d0 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -2474,9 +2474,10 @@ impl str {
     /// assert!(!"Ferrös".eq_ignore_ascii_case("FERRÖS"));
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
+    #[rustc_const_unstable(feature = "const_eq_ignore_ascii_case", issue = "131719")]
     #[must_use]
     #[inline]
-    pub fn eq_ignore_ascii_case(&self, other: &str) -> bool {
+    pub const fn eq_ignore_ascii_case(&self, other: &str) -> bool {
         self.as_bytes().eq_ignore_ascii_case(other.as_bytes())
     }
 
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index 665c9fc67d0..52e2364893e 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -886,8 +886,8 @@ impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {}
 /// # Examples
 ///
 /// ```
-/// assert_eq!("Hello world".find(&['l', 'l'] as &[_]), Some(2));
-/// assert_eq!("Hello world".find(&['l', 'l'][..]), Some(2));
+/// assert_eq!("Hello world".find(&['o', 'l'][..]), Some(2));
+/// assert_eq!("Hello world".find(&['h', 'w'][..]), Some(6));
 /// ```
 impl<'b> Pattern for &'b [char] {
     pattern_methods!('a, CharSliceSearcher<'a, 'b>, MultiCharEqPattern, CharSliceSearcher);
diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs
index cca8ff74dda..0f724dd9613 100644
--- a/library/core/src/str/validations.rs
+++ b/library/core/src/str/validations.rs
@@ -1,6 +1,7 @@
 //! Operations related to UTF-8 validation.
 
 use super::Utf8Error;
+use crate::intrinsics::const_eval_select;
 use crate::mem;
 
 /// Returns the initial codepoint accumulator for the first byte.
@@ -122,15 +123,25 @@ const fn contains_nonascii(x: usize) -> bool {
 /// Walks through `v` checking that it's a valid UTF-8 sequence,
 /// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`.
 #[inline(always)]
-#[rustc_const_unstable(feature = "str_internals", issue = "none")]
+#[rustc_allow_const_fn_unstable(const_eval_select)] // fallback impl has same behavior
 pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
     let mut index = 0;
     let len = v.len();
 
-    let usize_bytes = mem::size_of::<usize>();
-    let ascii_block_size = 2 * usize_bytes;
+    const USIZE_BYTES: usize = mem::size_of::<usize>();
+
+    let ascii_block_size = 2 * USIZE_BYTES;
     let blocks_end = if len >= ascii_block_size { len - ascii_block_size + 1 } else { 0 };
-    let align = v.as_ptr().align_offset(usize_bytes);
+    // Below, we safely fall back to a slower codepath if the offset is `usize::MAX`,
+    // so the end-to-end behavior is the same at compiletime and runtime.
+    let align = const_eval_select!(
+        @capture { v: &[u8] } -> usize:
+        if const {
+            usize::MAX
+        } else {
+            v.as_ptr().align_offset(USIZE_BYTES)
+        }
+    );
 
     while index < len {
         let old_offset = index;
@@ -209,11 +220,11 @@ pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
             // Ascii case, try to skip forward quickly.
             // When the pointer is aligned, read 2 words of data per iteration
             // until we find a word containing a non-ascii byte.
-            if align != usize::MAX && align.wrapping_sub(index) % usize_bytes == 0 {
+            if align != usize::MAX && align.wrapping_sub(index) % USIZE_BYTES == 0 {
                 let ptr = v.as_ptr();
                 while index < blocks_end {
                     // SAFETY: since `align - index` and `ascii_block_size` are
-                    // multiples of `usize_bytes`, `block = ptr.add(index)` is
+                    // multiples of `USIZE_BYTES`, `block = ptr.add(index)` is
                     // always aligned with a `usize` so it's safe to dereference
                     // both `block` and `block.add(1)`.
                     unsafe {
diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs
index 91566439ade..8fcbda141da 100644
--- a/library/core/src/ub_checks.rs
+++ b/library/core/src/ub_checks.rs
@@ -95,20 +95,18 @@ pub use intrinsics::ub_checks as check_library_ub;
 #[inline]
 #[rustc_allow_const_fn_unstable(const_eval_select)]
 pub(crate) const fn check_language_ub() -> bool {
-    #[inline]
-    fn runtime() -> bool {
-        // Disable UB checks in Miri.
-        !cfg!(miri)
-    }
-
-    #[inline]
-    const fn comptime() -> bool {
-        // Always disable UB checks.
-        false
-    }
-
     // Only used for UB checks so we may const_eval_select.
-    intrinsics::ub_checks() && const_eval_select((), comptime, runtime)
+    intrinsics::ub_checks()
+        && const_eval_select!(
+            @capture { } -> bool:
+            if const {
+                // Always disable UB checks.
+                false
+            } else {
+                // Disable UB checks in Miri.
+                !cfg!(miri)
+            }
+        )
 }
 
 /// Checks whether `ptr` is properly aligned with respect to the given alignment, and
@@ -120,7 +118,15 @@ pub(crate) const fn check_language_ub() -> bool {
 #[inline]
 #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")]
 pub(crate) const fn is_aligned_and_not_null(ptr: *const (), align: usize, is_zst: bool) -> bool {
-    ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
+    // This is just for safety checks so we can const_eval_select.
+    const_eval_select!(
+        @capture { ptr: *const (), align: usize, is_zst: bool } -> bool:
+        if const #[rustc_const_unstable(feature = "const_ub_checks", issue = "none")] {
+            is_zst || !ptr.is_null()
+        } else {
+            ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
+        }
+    )
 }
 
 #[inline]
@@ -142,26 +148,23 @@ pub(crate) const fn is_nonoverlapping(
     size: usize,
     count: usize,
 ) -> bool {
-    #[inline]
-    fn runtime(src: *const (), dst: *const (), size: usize, count: usize) -> bool {
-        let src_usize = src.addr();
-        let dst_usize = dst.addr();
-        let Some(size) = size.checked_mul(count) else {
-            crate::panicking::panic_nounwind(
-                "is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
-            )
-        };
-        let diff = src_usize.abs_diff(dst_usize);
-        // If the absolute distance between the ptrs is at least as big as the size of the buffer,
-        // they do not overlap.
-        diff >= size
-    }
-
-    #[inline]
-    const fn comptime(_: *const (), _: *const (), _: usize, _: usize) -> bool {
-        true
-    }
-
     // This is just for safety checks so we can const_eval_select.
-    const_eval_select((src, dst, size, count), comptime, runtime)
+    const_eval_select!(
+        @capture { src: *const (), dst: *const (), size: usize, count: usize } -> bool:
+        if const {
+            true
+        } else {
+            let src_usize = src.addr();
+            let dst_usize = dst.addr();
+            let Some(size) = size.checked_mul(count) else {
+                crate::panicking::panic_nounwind(
+                    "is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
+                )
+            };
+            let diff = src_usize.abs_diff(dst_usize);
+            // If the absolute distance between the ptrs is at least as big as the size of the buffer,
+            // they do not overlap.
+            diff >= size
+        }
+    )
 }
diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs
index 839f06ab84d..4655d35e9c4 100644
--- a/library/core/src/unicode/unicode_data.rs
+++ b/library/core/src/unicode/unicode_data.rs
@@ -572,7 +572,7 @@ pub mod white_space {
         0, 0, 0, 0, 0, 0, 0, 0, 0,
     ];
     #[inline]
-    pub fn lookup(c: char) -> bool {
+    pub const fn lookup(c: char) -> bool {
         match c as u32 >> 8 {
             0 => WHITESPACE_MAP[c as usize & 0xff] & 1 != 0,
             22 => c as u32 == 0x1680,
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index db64dba2125..b9706ea2a9e 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -1,4 +1,5 @@
 // tidy-alphabetical-start
+#![cfg_attr(bootstrap, feature(const_three_way_compare))]
 #![cfg_attr(bootstrap, feature(strict_provenance))]
 #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))]
 #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
@@ -16,15 +17,12 @@
 #![feature(cell_update)]
 #![feature(clone_to_uninit)]
 #![feature(const_align_of_val_raw)]
-#![feature(const_align_offset)]
 #![feature(const_black_box)]
 #![feature(const_eval_select)]
 #![feature(const_heap)]
 #![feature(const_nonnull_new)]
 #![feature(const_option_ext)]
 #![feature(const_pin_2)]
-#![feature(const_pointer_is_aligned)]
-#![feature(const_three_way_compare)]
 #![feature(const_trait_impl)]
 #![feature(core_intrinsics)]
 #![feature(core_io_borrowed_buf)]
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 78d1b137e63..91f8c977d08 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -360,22 +360,6 @@ fn align_offset_zst() {
 }
 
 #[test]
-fn align_offset_zst_const() {
-    const {
-        // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
-        // all, because no amount of elements will align the pointer.
-        let mut p = 1;
-        while p < 1024 {
-            assert!(ptr::without_provenance::<()>(p).align_offset(p) == 0);
-            if p != 1 {
-                assert!(ptr::without_provenance::<()>(p + 1).align_offset(p) == !0);
-            }
-            p = (p + 1).next_power_of_two();
-        }
-    }
-}
-
-#[test]
 fn align_offset_stride_one() {
     // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
     // number of bytes.
@@ -397,25 +381,6 @@ fn align_offset_stride_one() {
 }
 
 #[test]
-fn align_offset_stride_one_const() {
-    const {
-        // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
-        // number of bytes.
-        let mut align = 1;
-        while align < 1024 {
-            let mut ptr = 1;
-            while ptr < 2 * align {
-                let expected = ptr % align;
-                let offset = if expected == 0 { 0 } else { align - expected };
-                assert!(ptr::without_provenance::<u8>(ptr).align_offset(align) == offset);
-                ptr += 1;
-            }
-            align = (align + 1).next_power_of_two();
-        }
-    }
-}
-
-#[test]
 fn align_offset_various_strides() {
     unsafe fn test_stride<T>(ptr: *const T, align: usize) -> bool {
         let numptr = ptr as usize;
@@ -496,192 +461,6 @@ fn align_offset_various_strides() {
 }
 
 #[test]
-fn align_offset_various_strides_const() {
-    const unsafe fn test_stride<T>(ptr: *const T, numptr: usize, align: usize) {
-        let mut expected = usize::MAX;
-        // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
-        let mut el = 0;
-        while el < align {
-            if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
-                expected = el;
-                break;
-            }
-            el += 1;
-        }
-        let got = ptr.align_offset(align);
-        assert!(got == expected);
-    }
-
-    const {
-        // For pointers of stride != 1, we verify the algorithm against the naivest possible
-        // implementation
-        let mut align = 1;
-        let limit = 32;
-        while align < limit {
-            let mut ptr = 1;
-            while ptr < 4 * align {
-                unsafe {
-                    #[repr(packed)]
-                    struct A3(#[allow(dead_code)] u16, #[allow(dead_code)] u8);
-                    test_stride::<A3>(ptr::without_provenance::<A3>(ptr), ptr, align);
-
-                    struct A4(#[allow(dead_code)] u32);
-                    test_stride::<A4>(ptr::without_provenance::<A4>(ptr), ptr, align);
-
-                    #[repr(packed)]
-                    struct A5(#[allow(dead_code)] u32, #[allow(dead_code)] u8);
-                    test_stride::<A5>(ptr::without_provenance::<A5>(ptr), ptr, align);
-
-                    #[repr(packed)]
-                    struct A6(#[allow(dead_code)] u32, #[allow(dead_code)] u16);
-                    test_stride::<A6>(ptr::without_provenance::<A6>(ptr), ptr, align);
-
-                    #[repr(packed)]
-                    struct A7(
-                        #[allow(dead_code)] u32,
-                        #[allow(dead_code)] u16,
-                        #[allow(dead_code)] u8,
-                    );
-                    test_stride::<A7>(ptr::without_provenance::<A7>(ptr), ptr, align);
-
-                    #[repr(packed)]
-                    struct A8(#[allow(dead_code)] u32, #[allow(dead_code)] u32);
-                    test_stride::<A8>(ptr::without_provenance::<A8>(ptr), ptr, align);
-
-                    #[repr(packed)]
-                    struct A9(
-                        #[allow(dead_code)] u32,
-                        #[allow(dead_code)] u32,
-                        #[allow(dead_code)] u8,
-                    );
-                    test_stride::<A9>(ptr::without_provenance::<A9>(ptr), ptr, align);
-
-                    #[repr(packed)]
-                    struct A10(
-                        #[allow(dead_code)] u32,
-                        #[allow(dead_code)] u32,
-                        #[allow(dead_code)] u16,
-                    );
-                    test_stride::<A10>(ptr::without_provenance::<A10>(ptr), ptr, align);
-
-                    test_stride::<u32>(ptr::without_provenance::<u32>(ptr), ptr, align);
-                    test_stride::<u128>(ptr::without_provenance::<u128>(ptr), ptr, align);
-                }
-                ptr += 1;
-            }
-            align = (align + 1).next_power_of_two();
-        }
-    }
-}
-
-#[test]
-fn align_offset_with_provenance_const() {
-    const {
-        // On some platforms (e.g. msp430-none-elf), the alignment of `i32` is less than 4.
-        #[repr(align(4))]
-        struct AlignedI32(i32);
-
-        let data = AlignedI32(42);
-
-        // `stride % align == 0` (usual case)
-
-        let ptr: *const i32 = &data.0;
-        assert!(ptr.align_offset(1) == 0);
-        assert!(ptr.align_offset(2) == 0);
-        assert!(ptr.align_offset(4) == 0);
-        assert!(ptr.align_offset(8) == usize::MAX);
-        assert!(ptr.wrapping_byte_add(1).align_offset(1) == 0);
-        assert!(ptr.wrapping_byte_add(1).align_offset(2) == usize::MAX);
-        assert!(ptr.wrapping_byte_add(2).align_offset(1) == 0);
-        assert!(ptr.wrapping_byte_add(2).align_offset(2) == 0);
-        assert!(ptr.wrapping_byte_add(2).align_offset(4) == usize::MAX);
-        assert!(ptr.wrapping_byte_add(3).align_offset(1) == 0);
-        assert!(ptr.wrapping_byte_add(3).align_offset(2) == usize::MAX);
-
-        assert!(ptr.wrapping_add(42).align_offset(4) == 0);
-        assert!(ptr.wrapping_add(42).align_offset(8) == usize::MAX);
-
-        let ptr1: *const i8 = ptr.cast();
-        assert!(ptr1.align_offset(1) == 0);
-        assert!(ptr1.align_offset(2) == 0);
-        assert!(ptr1.align_offset(4) == 0);
-        assert!(ptr1.align_offset(8) == usize::MAX);
-        assert!(ptr1.wrapping_byte_add(1).align_offset(1) == 0);
-        assert!(ptr1.wrapping_byte_add(1).align_offset(2) == 1);
-        assert!(ptr1.wrapping_byte_add(1).align_offset(4) == 3);
-        assert!(ptr1.wrapping_byte_add(1).align_offset(8) == usize::MAX);
-        assert!(ptr1.wrapping_byte_add(2).align_offset(1) == 0);
-        assert!(ptr1.wrapping_byte_add(2).align_offset(2) == 0);
-        assert!(ptr1.wrapping_byte_add(2).align_offset(4) == 2);
-        assert!(ptr1.wrapping_byte_add(2).align_offset(8) == usize::MAX);
-        assert!(ptr1.wrapping_byte_add(3).align_offset(1) == 0);
-        assert!(ptr1.wrapping_byte_add(3).align_offset(2) == 1);
-        assert!(ptr1.wrapping_byte_add(3).align_offset(4) == 1);
-        assert!(ptr1.wrapping_byte_add(3).align_offset(8) == usize::MAX);
-
-        let ptr2: *const i16 = ptr.cast();
-        assert!(ptr2.align_offset(1) == 0);
-        assert!(ptr2.align_offset(2) == 0);
-        assert!(ptr2.align_offset(4) == 0);
-        assert!(ptr2.align_offset(8) == usize::MAX);
-        assert!(ptr2.wrapping_byte_add(1).align_offset(1) == 0);
-        assert!(ptr2.wrapping_byte_add(1).align_offset(2) == usize::MAX);
-        assert!(ptr2.wrapping_byte_add(2).align_offset(1) == 0);
-        assert!(ptr2.wrapping_byte_add(2).align_offset(2) == 0);
-        assert!(ptr2.wrapping_byte_add(2).align_offset(4) == 1);
-        assert!(ptr2.wrapping_byte_add(2).align_offset(8) == usize::MAX);
-        assert!(ptr2.wrapping_byte_add(3).align_offset(1) == 0);
-        assert!(ptr2.wrapping_byte_add(3).align_offset(2) == usize::MAX);
-
-        let ptr3: *const i64 = ptr.cast();
-        assert!(ptr3.align_offset(1) == 0);
-        assert!(ptr3.align_offset(2) == 0);
-        assert!(ptr3.align_offset(4) == 0);
-        assert!(ptr3.align_offset(8) == usize::MAX);
-        assert!(ptr3.wrapping_byte_add(1).align_offset(1) == 0);
-        assert!(ptr3.wrapping_byte_add(1).align_offset(2) == usize::MAX);
-
-        // `stride % align != 0` (edge case)
-
-        let ptr4: *const [u8; 3] = ptr.cast();
-        assert!(ptr4.align_offset(1) == 0);
-        assert!(ptr4.align_offset(2) == 0);
-        assert!(ptr4.align_offset(4) == 0);
-        assert!(ptr4.align_offset(8) == usize::MAX);
-        assert!(ptr4.wrapping_byte_add(1).align_offset(1) == 0);
-        assert!(ptr4.wrapping_byte_add(1).align_offset(2) == 1);
-        assert!(ptr4.wrapping_byte_add(1).align_offset(4) == 1);
-        assert!(ptr4.wrapping_byte_add(1).align_offset(8) == usize::MAX);
-        assert!(ptr4.wrapping_byte_add(2).align_offset(1) == 0);
-        assert!(ptr4.wrapping_byte_add(2).align_offset(2) == 0);
-        assert!(ptr4.wrapping_byte_add(2).align_offset(4) == 2);
-        assert!(ptr4.wrapping_byte_add(2).align_offset(8) == usize::MAX);
-        assert!(ptr4.wrapping_byte_add(3).align_offset(1) == 0);
-        assert!(ptr4.wrapping_byte_add(3).align_offset(2) == 1);
-        assert!(ptr4.wrapping_byte_add(3).align_offset(4) == 3);
-        assert!(ptr4.wrapping_byte_add(3).align_offset(8) == usize::MAX);
-
-        let ptr5: *const [u8; 5] = ptr.cast();
-        assert!(ptr5.align_offset(1) == 0);
-        assert!(ptr5.align_offset(2) == 0);
-        assert!(ptr5.align_offset(4) == 0);
-        assert!(ptr5.align_offset(8) == usize::MAX);
-        assert!(ptr5.wrapping_byte_add(1).align_offset(1) == 0);
-        assert!(ptr5.wrapping_byte_add(1).align_offset(2) == 1);
-        assert!(ptr5.wrapping_byte_add(1).align_offset(4) == 3);
-        assert!(ptr5.wrapping_byte_add(1).align_offset(8) == usize::MAX);
-        assert!(ptr5.wrapping_byte_add(2).align_offset(1) == 0);
-        assert!(ptr5.wrapping_byte_add(2).align_offset(2) == 0);
-        assert!(ptr5.wrapping_byte_add(2).align_offset(4) == 2);
-        assert!(ptr5.wrapping_byte_add(2).align_offset(8) == usize::MAX);
-        assert!(ptr5.wrapping_byte_add(3).align_offset(1) == 0);
-        assert!(ptr5.wrapping_byte_add(3).align_offset(2) == 1);
-        assert!(ptr5.wrapping_byte_add(3).align_offset(4) == 1);
-        assert!(ptr5.wrapping_byte_add(3).align_offset(8) == usize::MAX);
-    }
-}
-
-#[test]
 fn align_offset_issue_103361() {
     #[cfg(target_pointer_width = "64")]
     const SIZE: usize = 1 << 47;
@@ -694,23 +473,6 @@ fn align_offset_issue_103361() {
 }
 
 #[test]
-fn align_offset_issue_103361_const() {
-    #[cfg(target_pointer_width = "64")]
-    const SIZE: usize = 1 << 47;
-    #[cfg(target_pointer_width = "32")]
-    const SIZE: usize = 1 << 30;
-    #[cfg(target_pointer_width = "16")]
-    const SIZE: usize = 1 << 13;
-    struct HugeSize(#[allow(dead_code)] [u8; SIZE - 1]);
-
-    const {
-        assert!(ptr::without_provenance::<HugeSize>(SIZE - 1).align_offset(SIZE) == SIZE - 1);
-        assert!(ptr::without_provenance::<HugeSize>(SIZE).align_offset(SIZE) == 0);
-        assert!(ptr::without_provenance::<HugeSize>(SIZE + 1).align_offset(SIZE) == 1);
-    }
-}
-
-#[test]
 fn is_aligned() {
     let data = 42;
     let ptr: *const i32 = &data;
@@ -727,25 +489,6 @@ fn is_aligned() {
 }
 
 #[test]
-fn is_aligned_const() {
-    const {
-        let data = 42;
-        let ptr: *const i32 = &data;
-        assert!(ptr.is_aligned());
-        assert!(ptr.is_aligned_to(1));
-        assert!(ptr.is_aligned_to(2));
-        assert!(ptr.is_aligned_to(4));
-        assert!(ptr.wrapping_byte_add(2).is_aligned_to(1));
-        assert!(ptr.wrapping_byte_add(2).is_aligned_to(2));
-        assert!(!ptr.wrapping_byte_add(2).is_aligned_to(4));
-
-        // At comptime neither `ptr` nor `ptr+1` is aligned to 8.
-        assert!(!ptr.is_aligned_to(8));
-        assert!(!ptr.wrapping_add(1).is_aligned_to(8));
-    }
-}
-
-#[test]
 fn offset_from() {
     let mut a = [0; 5];
     let ptr1: *mut i32 = &mut a[1];
diff --git a/library/rustc-std-workspace-core/README.md b/library/rustc-std-workspace-core/README.md
index 40e0b62afab..55a36e74106 100644
--- a/library/rustc-std-workspace-core/README.md
+++ b/library/rustc-std-workspace-core/README.md
@@ -27,3 +27,6 @@ it'll look like
 
 when Cargo invokes the compiler, satisfying the implicit `extern crate core`
 directive injected by the compiler.
+
+The sources for the crates.io version can be found in
+[`src/rustc-std-workspace`](../../src/rustc-std-workspace).
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index b5450d0a20c..5b94f036248 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -32,14 +32,12 @@
 //!
 //! Once you are familiar with the contents of the standard library you may
 //! begin to find the verbosity of the prose distracting. At this stage in your
-//! development you may want to press the <code>
-//! <svg style="width:0.75rem;height:0.75rem" viewBox="0 0 12 12"
-//! stroke="currentColor" fill="none">
-//! <path d="M2,2l4,4l4,-4M2,6l4,4l4,-4"/></svg> Summary</code> button near the
-//! top of the page to collapse it into a more skimmable view.
+//! development you may want to press the
+//! "<svg style="width:0.75rem;height:0.75rem" viewBox="0 0 12 12" stroke="currentColor" fill="none"><path d="M2,2l4,4l4,-4M2,6l4,4l4,-4"/></svg>&nbsp;Summary"
+//! button near the top of the page to collapse it into a more skimmable view.
 //!
 //! While you are looking at the top of the page, also notice the
-//! <code>source</code> link. Rust's API documentation comes with the source
+//! "Source" link. Rust's API documentation comes with the source
 //! code and you are encouraged to read it. The standard library source is
 //! generally high quality and a peek behind the curtains is
 //! often enlightening.
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index ef5adaf2290..7c3fa7d6507 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -143,7 +143,7 @@ pub trait CommandExt: Sealed {
     ///
     /// This function, unlike `spawn`, will **not** `fork` the process to create
     /// a new child. Like spawn, however, the default behavior for the stdio
-    /// descriptors will be to inherited from the current process.
+    /// descriptors will be to inherit them from the current process.
     ///
     /// # Notes
     ///
diff --git a/library/std/src/sys/alloc/windows.rs b/library/std/src/sys/alloc/windows.rs
index a77dda6e817..7e2402afab9 100644
--- a/library/std/src/sys/alloc/windows.rs
+++ b/library/std/src/sys/alloc/windows.rs
@@ -3,7 +3,6 @@ use crate::alloc::{GlobalAlloc, Layout, System};
 use crate::ffi::c_void;
 use crate::mem::MaybeUninit;
 use crate::ptr;
-use crate::sync::atomic::{AtomicPtr, Ordering};
 use crate::sys::c;
 
 #[cfg(test)]
@@ -81,40 +80,18 @@ windows_targets::link!("kernel32.dll" "system" fn HeapReAlloc(
 // See https://docs.microsoft.com/windows/win32/api/heapapi/nf-heapapi-heapfree
 windows_targets::link!("kernel32.dll" "system" fn HeapFree(hheap: c::HANDLE, dwflags: u32, lpmem: *const c_void) -> c::BOOL);
 
-// Cached handle to the default heap of the current process.
-// Either a non-null handle returned by `GetProcessHeap`, or null when not yet initialized or `GetProcessHeap` failed.
-static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
-
-// Get a handle to the default heap of the current process, or null if the operation fails.
-// If this operation is successful, `HEAP` will be successfully initialized and contain
-// a non-null handle returned by `GetProcessHeap`.
-#[inline]
-fn init_or_get_process_heap() -> c::HANDLE {
-    // `HEAP` has not yet been successfully initialized
-    let heap = unsafe { GetProcessHeap() };
-    if !heap.is_null() {
-        // SAFETY: No locking is needed because within the same process,
-        // successful calls to `GetProcessHeap` will always return the same value, even on different threads.
-        HEAP.store(heap, Ordering::Release);
-
-        // SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
-        heap
-    } else {
-        // Could not get the current process heap.
-        ptr::null_mut()
-    }
+fn get_process_heap() -> *mut c_void {
+    // SAFETY: GetProcessHeap simply returns a valid handle or NULL so is always safe to call.
+    unsafe { GetProcessHeap() }
 }
 
-/// This is outlined from `process_heap_alloc` so that `process_heap_alloc`
-/// does not need any stack allocations.
 #[inline(never)]
-#[cold]
-extern "C" fn process_heap_init_and_alloc(
-    _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`
+fn process_heap_alloc(
+    _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`,
     flags: u32,
     bytes: usize,
 ) -> *mut c_void {
-    let heap = init_or_get_process_heap();
+    let heap = get_process_heap();
     if core::intrinsics::unlikely(heap.is_null()) {
         return ptr::null_mut();
     }
@@ -122,28 +99,6 @@ extern "C" fn process_heap_init_and_alloc(
     unsafe { HeapAlloc(heap, flags, bytes) }
 }
 
-#[inline(never)]
-fn process_heap_alloc(
-    _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`,
-    flags: u32,
-    bytes: usize,
-) -> *mut c_void {
-    let heap = HEAP.load(Ordering::Relaxed);
-    if core::intrinsics::likely(!heap.is_null()) {
-        // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
-        unsafe { HeapAlloc(heap, flags, bytes) }
-    } else {
-        process_heap_init_and_alloc(MaybeUninit::uninit(), flags, bytes)
-    }
-}
-
-// Get a non-null handle to the default heap of the current process.
-// SAFETY: `HEAP` must have been successfully initialized.
-#[inline]
-unsafe fn get_process_heap() -> c::HANDLE {
-    HEAP.load(Ordering::Acquire)
-}
-
 // Header containing a pointer to the start of an allocated block.
 // SAFETY: Size and alignment must be <= `MIN_ALIGN`.
 #[repr(C)]
@@ -232,9 +187,9 @@ unsafe impl GlobalAlloc for System {
             }
         };
 
-        // SAFETY: because `ptr` has been successfully allocated with this allocator,
-        // `HEAP` must have been successfully initialized.
-        let heap = unsafe { get_process_heap() };
+        // because `ptr` has been successfully allocated with this allocator,
+        // there must be a valid process heap.
+        let heap = get_process_heap();
 
         // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
         // `block` is a pointer to the start of an allocated block.
@@ -244,9 +199,9 @@ unsafe impl GlobalAlloc for System {
     #[inline]
     unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
         if layout.align() <= MIN_ALIGN {
-            // SAFETY: because `ptr` has been successfully allocated with this allocator,
-            // `HEAP` must have been successfully initialized.
-            let heap = unsafe { get_process_heap() };
+            // because `ptr` has been successfully allocated with this allocator,
+            // there must be a valid process heap.
+            let heap = get_process_heap();
 
             // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`,
             // `ptr` is a pointer to the start of an allocated block.
diff --git a/rustfmt.toml b/rustfmt.toml
index 4d48236a393..16a0d67ab52 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -26,8 +26,6 @@ ignore = [
     "/tests/ui-fulldeps/",            # Some are whitespace-sensitive (e.g. `// ~ERROR` comments).
 
     # Do not format submodules.
-    # FIXME: sync submodule list with tidy/bootstrap/etc
-    # tidy/src/walk.rs:filter_dirs
     "library/backtrace",
     "library/portable-simd",
     "library/stdarch",
@@ -41,6 +39,7 @@ ignore = [
     "src/llvm-project",
     "src/tools/cargo",
     "src/tools/clippy",
+    "src/tools/enzyme",
     "src/tools/miri",
     "src/tools/rust-analyzer",
     "src/tools/rustc-perf",
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 9ddcde7eb2c..3394f2a84a0 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -219,8 +219,7 @@ impl Step for Std {
                 .join(compiler.host)
                 .join("bin");
             if src_sysroot_bin.exists() {
-                let target_sysroot_bin =
-                    builder.sysroot_target_libdir(compiler, target).parent().unwrap().join("bin");
+                let target_sysroot_bin = builder.sysroot_target_bindir(compiler, target);
                 t!(fs::create_dir_all(&target_sysroot_bin));
                 builder.cp_link_r(&src_sysroot_bin, &target_sysroot_bin);
             }
@@ -1977,6 +1976,14 @@ impl Step for Assemble {
             }
         }
 
+        {
+            // `llvm-strip` is used by rustc, which is actually just a symlink to `llvm-objcopy`,
+            // so copy and rename `llvm-objcopy`.
+            let src_exe = exe("llvm-objcopy", target_compiler.host);
+            let dst_exe = exe("rust-objcopy", target_compiler.host);
+            builder.copy_link(&libdir_bin.join(src_exe), &libdir_bin.join(dst_exe));
+        }
+
         // In addition to `rust-lld` also install `wasm-component-ld` when
         // LLD is enabled. This is a relatively small binary that primarily
         // delegates to the `rust-lld` binary for linking and then runs
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 759e720c208..c022285211f 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -459,8 +459,7 @@ impl Step for Rustc {
 
             // Copy over lld if it's there
             if builder.config.lld_enabled {
-                let src_dir =
-                    builder.sysroot_target_libdir(compiler, host).parent().unwrap().join("bin");
+                let src_dir = builder.sysroot_target_bindir(compiler, host);
                 let rust_lld = exe("rust-lld", compiler.host);
                 builder.copy_link(&src_dir.join(&rust_lld), &dst_dir.join(&rust_lld));
                 let self_contained_lld_src_dir = src_dir.join("gcc-ld");
@@ -474,9 +473,16 @@ impl Step for Rustc {
                     );
                 }
             }
+
+            {
+                let src_dir = builder.sysroot_target_bindir(compiler, host);
+                let llvm_objcopy = exe("llvm-objcopy", compiler.host);
+                let rust_objcopy = exe("rust-objcopy", compiler.host);
+                builder.copy_link(&src_dir.join(&llvm_objcopy), &dst_dir.join(&rust_objcopy));
+            }
+
             if builder.tool_enabled("wasm-component-ld") {
-                let src_dir =
-                    builder.sysroot_target_libdir(compiler, host).parent().unwrap().join("bin");
+                let src_dir = builder.sysroot_target_bindir(compiler, host);
                 let ld = exe("wasm-component-ld", compiler.host);
                 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld));
             }
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 19472bac4af..f1b3cf6da13 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -1161,6 +1161,11 @@ impl<'a> Builder<'a> {
         self.ensure(compile::Sysroot::new(compiler))
     }
 
+    /// Returns the bindir for a compiler's sysroot.
+    pub fn sysroot_target_bindir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
+        self.sysroot_target_libdir(compiler, target).parent().unwrap().join("bin")
+    }
+
     /// Returns the libdir where the standard library and other artifacts are
     /// found for a compiler's sysroot.
     pub fn sysroot_target_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index ece5f174d06..c40de76abbf 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -114,7 +114,6 @@ ENV CARGO_TARGET_AARCH64_UNKNOWN_FUCHSIA_RUSTFLAGS \
 ENV TARGETS=x86_64-unknown-fuchsia
 ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
 ENV TARGETS=$TARGETS,wasm32-unknown-unknown
-ENV TARGETS=$TARGETS,wasm32-wasi
 ENV TARGETS=$TARGETS,wasm32-wasip1
 ENV TARGETS=$TARGETS,wasm32-wasip1-threads
 ENV TARGETS=$TARGETS,wasm32-wasip2
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index c0ce358486b..340dfd67b7d 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -6,6 +6,8 @@ runners:
 
   - &job-linux-4c
     os: ubuntu-20.04
+    # Free some disk space to avoid running out of space during the build.
+    free_disk: true
     <<: *base-job
 
   # Large runner used mainly for its bigger disk capacity
@@ -135,7 +137,7 @@ auto:
   - image: dist-aarch64-linux
     env:
       CODEGEN_BACKENDS: llvm,cranelift
-    <<: *job-linux-4c-largedisk
+    <<: *job-linux-4c
 
   - image: dist-android
     <<: *job-linux-4c
@@ -156,28 +158,28 @@ auto:
     <<: *job-linux-4c
 
   - image: dist-loongarch64-linux
-    <<: *job-linux-4c-largedisk
+    <<: *job-linux-4c
 
   - image: dist-loongarch64-musl
-    <<: *job-linux-4c-largedisk
+    <<: *job-linux-4c
 
   - image: dist-ohos
     <<: *job-linux-4c
 
   - image: dist-powerpc-linux
-    <<: *job-linux-4c-largedisk
+    <<: *job-linux-4c
 
   - image: dist-powerpc64-linux
-    <<: *job-linux-4c-largedisk
+    <<: *job-linux-4c
 
   - image: dist-powerpc64le-linux
-    <<: *job-linux-4c-largedisk
+    <<: *job-linux-4c
 
   - image: dist-riscv64-linux
     <<: *job-linux-4c
 
   - image: dist-s390x-linux
-    <<: *job-linux-4c-largedisk
+    <<: *job-linux-4c
 
   - image: dist-various-1
     <<: *job-linux-4c
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject 1f07c242f8162a711a5ac5a4ea8fa7ec884ee7a
+Subproject 2d482e203eb6d6e353814cf1415c5f94e590b9e
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 23ce619966541bf2c80d45fdfeecf3393e360a1
+Subproject da0f6dad767670da0e8cd5af8a7090db3272f62
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 8bede1b919a81ab7d0c961f6bbf68d3efa297bd
+Subproject 9db78608b17d5f4a6c033b8a3038466b87d6320
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 59d94ea75a0b157e148af14c73c2dd60efb7b60
+Subproject 6a5accdaf10255882b1e6c59dfe5f1c79ac9548
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 04bb40d750c..500eaafb63f 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -192,8 +192,8 @@ target | std | notes
 [`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare Armv8-M Mainline, hardfloat
 [`wasm32-unknown-emscripten`](platform-support/wasm32-unknown-emscripten.md) | ✓ | WebAssembly via Emscripten
 [`wasm32-unknown-unknown`](platform-support/wasm32-unknown-unknown.md) | ✓ | WebAssembly
-`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
-[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI
+[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASIp1
+[`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ | WebAssembly with WASIp2
 [`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads
 [`wasm32v1-none`](platform-support/wasm32v1-none.md) | * | WebAssembly limited to 1.0 features and no imports
 [`x86_64-apple-ios`](platform-support/apple-ios.md) | ✓ | 64-bit x86 iOS
@@ -377,7 +377,6 @@ target | std | host | notes
 `thumbv7a-pc-windows-msvc` | ✓ |  |
 `thumbv7a-uwp-windows-msvc` | ✓ |  |
 `thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.3
-[`wasm32-wasip2`](platform-support/wasm32-wasip2.md) | ✓ |  | WebAssembly
 [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? |  | WebAssembly
 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ |  | x86 64-bit tvOS
 [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ |  | x86 64-bit Apple WatchOS simulator
diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1.md b/src/doc/rustc/src/platform-support/wasm32-wasip1.md
index 0e4def6768d..e5e8d554ecf 100644
--- a/src/doc/rustc/src/platform-support/wasm32-wasip1.md
+++ b/src/doc/rustc/src/platform-support/wasm32-wasip1.md
@@ -98,10 +98,6 @@ the target with:
 rustup target add wasm32-wasip1
 ```
 
-> **Note**: the `wasm32-wasip1` target is new and may only be available
-> on nightly by the time you're reading this. If `wasm32-wasip1` isn't
-> available on stable Rust then `wasm32-wasi` should be available instead.
-
 Rust programs can be built for that target:
 
 ```text
diff --git a/src/doc/unstable-book/src/compiler-flags/branch-protection.md b/src/doc/unstable-book/src/compiler-flags/branch-protection.md
index 9276220f447..f0cc44a07f3 100644
--- a/src/doc/unstable-book/src/compiler-flags/branch-protection.md
+++ b/src/doc/unstable-book/src/compiler-flags/branch-protection.md
@@ -9,11 +9,12 @@ This option is only accepted when targeting AArch64 architectures.
 It takes some combination of the following values, separated by a `,`.
 
 - `pac-ret` - Enable pointer authentication for non-leaf functions.
+- `pc` - Use PC as a diversifier using PAuthLR instructions
 - `leaf` - Enable pointer authentication for all functions, including leaf functions.
 - `b-key` - Sign return addresses with key B, instead of the default key A.
 - `bti` - Enable branch target identification.
 
-`leaf` and `b-key` are only valid if `pac-ret` was previously specified.
+`leaf`, `b-key` and `pc` are only valid if `pac-ret` was previously specified.
 For example, `-Z branch-protection=bti,pac-ret,leaf` is valid, but
 `-Z branch-protection=bti,leaf,pac-ret` is not.
 
diff --git a/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md b/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md
index 138a98dbe3d..bde4bf58133 100644
--- a/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md
+++ b/src/doc/unstable-book/src/compiler-flags/wasm-c-abi.md
@@ -4,7 +4,7 @@ This option controls whether Rust uses the spec-compliant C ABI when compiling
 for the `wasm32-unknown-unknown` target.
 
 This makes it possible to be ABI-compatible with all other spec-compliant Wasm
-like Rusts `wasm32-wasi`.
+like Rusts `wasm32-wasip1`.
 
 This compiler flag is perma-unstable, as it will be enabled by default in the
 future with no option to fall back to the old non-spec-compliant ABI.
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 b1c429c7676..5264f778a93 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
@@ -31,9 +31,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | NVPTX        | `reg32`        | None\*                             | `r`                  |
 | NVPTX        | `reg64`        | None\*                             | `l`                  |
 | Hexagon      | `reg`          | `r[0-28]`                          | `r`                  |
-| PowerPC      | `reg`          | `r[0-31]`                          | `r`                  |
-| PowerPC      | `reg_nonzero`  | `r[1-31]`                          | `b`                  |
+| PowerPC      | `reg`          | `r0`, `r[3-12]`, `r[14-28]`        | `r`                  |
+| PowerPC      | `reg_nonzero`  | `r[3-12]`, `r[14-28]`              | `b`                  |
 | PowerPC      | `freg`         | `f[0-31]`                          | `f`                  |
+| PowerPC      | `vreg`         | `v[0-31]`                          | Only clobbers        |
 | PowerPC      | `cr`           | `cr[0-7]`, `cr`                    | Only clobbers        |
 | PowerPC      | `xer`          | `xer`                              | Only clobbers        |
 | wasm32       | `local`        | None\*                             | `r`                  |
@@ -76,9 +77,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | NVPTX        | `reg32`                         | None           | `i8`, `i16`, `i32`, `f32`               |
 | NVPTX        | `reg64`                         | None           | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
 | Hexagon      | `reg`                           | None           | `i8`, `i16`, `i32`, `f32`               |
-| PowerPC      | `reg`                           | None           | `i8`, `i16`, `i32`                      |
-| PowerPC      | `reg_nonzero`                   | None           | `i8`, `i16`, `i32`                      |
+| PowerPC      | `reg`                           | None           | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
+| PowerPC      | `reg_nonzero`                   | None           | `i8`, `i16`, `i32`, `i64` (powerpc64 only) |
 | PowerPC      | `freg`                          | None           | `f32`, `f64`                            |
+| PowerPC      | `vreg`                          | N/A            | Only clobbers                           |
 | PowerPC      | `cr`                            | N/A            | Only clobbers                           |
 | PowerPC      | `xer`                           | N/A            | Only clobbers                           |
 | wasm32       | `local`                         | None           | `i8` `i16` `i32` `i64` `f32` `f64`      |
@@ -105,6 +107,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | Hexagon      | `r29`         | `sp`      |
 | Hexagon      | `r30`         | `fr`      |
 | Hexagon      | `r31`         | `lr`      |
+| PowerPC      | `r1`          | `sp`      |
+| PowerPC      | `r31`         | `fp`      |
+| PowerPC      | `r[0-31]`     | `[0-31]`  |
+| PowerPC      | `f[0-31]`     | `fr[0-31]`|
 | BPF          | `r[0-10]`     | `w[0-10]` |
 | AVR          | `XH`          | `r27`     |
 | AVR          | `XL`          | `r26`     |
@@ -145,14 +151,18 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | Architecture | Unsupported register                    | Reason                                                                                                                                                                              |
 | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
 | All          | `sp`, `r15` (s390x)                     | The stack pointer must be restored to its original value at the end of an asm code block.                                                                                           |
-| All          | `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output.                                                                                                                             |
-| All          | `r19` (Hexagon), `x19` (Arm64EC)        | This is used internally by LLVM as a "base pointer" for functions with complex stack frames.                                                                                        |
+| All          | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output.                                                 |
+| All          | `r19` (Hexagon), `r29` (PowerPC), `r30` (PowerPC), `x19` (Arm64EC) | These are used internally by LLVM as "base pointer" for functions with complex stack frames.                                                             |
 | MIPS         | `$0` or `$zero`                         | This is a constant zero register which can't be modified.                                                                                                                           |
 | MIPS         | `$1` or `$at`                           | Reserved for assembler.                                                                                                                                                             |
 | MIPS         | `$26`/`$k0`, `$27`/`$k1`                | OS-reserved registers.                                                                                                                                                              |
 | MIPS         | `$28`/`$gp`                             | Global pointer cannot be used as inputs or outputs.                                                                                                                                 |
 | MIPS         | `$ra`                                   | Return address cannot be used as inputs or outputs.                                                                                                                                 |
 | Hexagon      | `lr`                                    | This is the link register which cannot be used as an input or output.                                                                                                               |
+| PowerPC      | `r2`, `r13`                             | These are system reserved registers.                                                                                                                                                |
+| PowerPC      | `lr`                                    | The link register cannot be used as an input or output.                                                                                                                             |
+| PowerPC      | `ctr`                                   | The counter register cannot be used as an input or output.                                                                                                                          |
+| PowerPC      | `vrsave`                                | The vrsave register cannot be used as an input or output.                                                                                                                           |
 | AVR          | `r0`, `r1`, `r1r0`                      | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs.  If modified, they must be restored to their original values before the end of the block. |
 |MSP430        | `r0`, `r2`, `r3`                        | These are the program counter, status register, and constant generator respectively. Neither the status register nor constant generator can be written to.                          |
 | M68k         | `a4`, `a5`                              | Used internally by LLVM for the base pointer and global base pointer. |
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c367eed53e0..6b6142a6eaa 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -304,7 +304,9 @@ pub(crate) fn clean_middle_region(region: ty::Region<'_>) -> Option<Lifetime> {
     match *region {
         ty::ReStatic => Some(Lifetime::statik()),
         _ if !region.has_name() => None,
-        ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => Some(Lifetime(name)),
+        ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. }) => {
+            Some(Lifetime(name))
+        }
         ty::ReEarlyParam(ref data) => Some(Lifetime(data.name)),
         ty::ReBound(..)
         | ty::ReLateParam(..)
@@ -1317,8 +1319,8 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
             simplify::move_bounds_to_generic_parameters(&mut generics);
 
             let provided = match assoc_item.container {
-                ty::ImplContainer => true,
-                ty::TraitContainer => tcx.defaultness(assoc_item.def_id).has_value(),
+                ty::AssocItemContainer::Impl => true,
+                ty::AssocItemContainer::Trait => tcx.defaultness(assoc_item.def_id).has_value(),
             };
             if provided {
                 AssocConstItem(Box::new(Constant {
@@ -1335,10 +1337,10 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
 
             if assoc_item.fn_has_self_parameter {
                 let self_ty = match assoc_item.container {
-                    ty::ImplContainer => {
+                    ty::AssocItemContainer::Impl => {
                         tcx.type_of(assoc_item.container_id(tcx)).instantiate_identity()
                     }
-                    ty::TraitContainer => tcx.types.self_param,
+                    ty::AssocItemContainer::Trait => tcx.types.self_param,
                 };
                 let self_arg_ty =
                     tcx.fn_sig(assoc_item.def_id).instantiate_identity().input(0).skip_binder();
@@ -1355,13 +1357,13 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
             }
 
             let provided = match assoc_item.container {
-                ty::ImplContainer => true,
-                ty::TraitContainer => assoc_item.defaultness(tcx).has_value(),
+                ty::AssocItemContainer::Impl => true,
+                ty::AssocItemContainer::Trait => assoc_item.defaultness(tcx).has_value(),
             };
             if provided {
                 let defaultness = match assoc_item.container {
-                    ty::ImplContainer => Some(assoc_item.defaultness(tcx)),
-                    ty::TraitContainer => None,
+                    ty::AssocItemContainer::Impl => Some(assoc_item.defaultness(tcx)),
+                    ty::AssocItemContainer::Trait => None,
                 };
                 MethodItem(item, defaultness)
             } else {
@@ -1392,7 +1394,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
             }
 
             let mut predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
-            if let ty::TraitContainer = assoc_item.container {
+            if let ty::AssocItemContainer::Trait = assoc_item.container {
                 let bounds = tcx.explicit_item_bounds(assoc_item.def_id).iter_identity_copied();
                 predicates = tcx.arena.alloc_from_iter(bounds.chain(predicates.iter().copied()));
             }
@@ -1403,7 +1405,7 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
                 });
             simplify::move_bounds_to_generic_parameters(&mut generics);
 
-            if let ty::TraitContainer = assoc_item.container {
+            if let ty::AssocItemContainer::Trait = assoc_item.container {
                 // Move bounds that are (likely) directly attached to the associated type
                 // from the where-clause to the associated type.
                 // There is no guarantee that this is what the user actually wrote but we have
@@ -1896,7 +1898,9 @@ fn clean_trait_object_lifetime_bound<'tcx>(
     match *region {
         ty::ReStatic => Some(Lifetime::statik()),
         ty::ReEarlyParam(region) if region.name != kw::Empty => Some(Lifetime(region.name)),
-        ty::ReBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) if name != kw::Empty => {
+        ty::ReBound(_, ty::BoundRegion { kind: ty::BoundRegionKind::Named(_, name), .. })
+            if name != kw::Empty =>
+        {
             Some(Lifetime(name))
         }
         ty::ReEarlyParam(_)
@@ -2141,7 +2145,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
                 .iter()
                 .flat_map(|pred| pred.bound_vars())
                 .filter_map(|var| match var {
-                    ty::BoundVariableKind::Region(ty::BrNamed(def_id, name))
+                    ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name))
                         if name != kw::UnderscoreLifetime =>
                     {
                         Some(GenericParamDef::lifetime(def_id, name))
@@ -2907,7 +2911,7 @@ fn clean_extern_crate<'tcx>(
                     None => false,
                 }
         })
-        && !cx.output_format.is_json();
+        && !cx.is_json_output();
 
     let krate_owner_def_id = krate.owner_id.def_id;
     if please_inline {
@@ -3000,7 +3004,7 @@ fn clean_use_statement_inner<'tcx>(
     // forcefully don't inline if this is not public or if the
     // #[doc(no_inline)] attribute is present.
     // Don't inline doc(hidden) imports so they can be stripped at a later stage.
-    let mut denied = cx.output_format.is_json()
+    let mut denied = cx.is_json_output()
         || !(visibility.is_public()
             || (cx.render_options.document_private && is_visible_from_parent_mod))
         || pub_underscore
@@ -3118,7 +3122,7 @@ fn clean_bound_vars(bound_vars: &ty::List<ty::BoundVariableKind>) -> Vec<Generic
     bound_vars
         .into_iter()
         .filter_map(|var| match var {
-            ty::BoundVariableKind::Region(ty::BrNamed(def_id, name))
+            ty::BoundVariableKind::Region(ty::BoundRegionKind::Named(def_id, name))
                 if name != kw::UnderscoreLifetime =>
             {
                 Some(GenericParamDef::lifetime(def_id, name))
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index d49b4320db6..e5c9539b5e7 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -703,8 +703,8 @@ impl Item {
             | TyMethodItem(..) | MethodItem(..) => {
                 let assoc_item = tcx.associated_item(def_id);
                 let is_trait_item = match assoc_item.container {
-                    ty::TraitContainer => true,
-                    ty::ImplContainer => {
+                    ty::AssocItemContainer::Trait => true,
+                    ty::AssocItemContainer::Impl => {
                         // Trait impl items always inherit the impl's visibility --
                         // we don't want to show `pub`.
                         tcx.impl_trait_ref(tcx.parent(assoc_item.def_id)).is_some()
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index d3a545fe0b6..560831197f0 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -206,7 +206,7 @@ fn clean_middle_generic_args_with_constraints<'tcx>(
 ) -> GenericArgs {
     let args = clean_middle_generic_args(cx, ty_args.map_bound(|args| &args[..]), has_self, did);
 
-    if cx.tcx.fn_trait_kind_from_def_id(did).is_some() {
+    if cx.tcx.is_trait(did) && cx.tcx.trait_def(did).paren_sugar {
         let ty = ty_args
             .iter()
             .nth(if has_self { 1 } else { 0 })
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 0f7d4d3e8f3..7ba3cfb66bd 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -121,6 +121,13 @@ impl<'tcx> DocContext<'tcx> {
             _ => None,
         }
     }
+
+    /// Returns `true` if the JSON output format is enabled for generating the crate content.
+    ///
+    /// If another option like `--show-coverage` is enabled, it will return `false`.
+    pub(crate) fn is_json_output(&self) -> bool {
+        self.output_format.is_json() && !self.show_coverage
+    }
 }
 
 /// Creates a new `DiagCtxt` that can be used to emit warnings and errors.
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index d27e737764d..9f9a093da8a 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -132,6 +132,7 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> {
 
     fn print_results(&self) {
         let output_format = self.ctx.output_format;
+        // In this case we want to ensure that the `OutputFormat` is JSON and NOT the `DocContext`.
         if output_format.is_json() {
             println!("{}", self.to_json());
             return;
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index aba04283e59..4ef5f7f20a9 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -23,7 +23,7 @@ pub(crate) const STRIP_HIDDEN: Pass = Pass {
 /// Strip items marked `#[doc(hidden)]`
 pub(crate) fn strip_hidden(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
     let mut retained = ItemIdSet::default();
-    let is_json_output = cx.output_format.is_json() && !cx.show_coverage;
+    let is_json_output = cx.is_json_output();
 
     // strip all #[doc(hidden)] items
     let krate = {
diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs
index 2e9f06bd0a3..b9b2431f06f 100644
--- a/src/librustdoc/passes/strip_priv_imports.rs
+++ b/src/librustdoc/passes/strip_priv_imports.rs
@@ -13,7 +13,7 @@ pub(crate) const STRIP_PRIV_IMPORTS: Pass = Pass {
 };
 
 pub(crate) fn strip_priv_imports(krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
-    let is_json_output = cx.output_format.is_json() && !cx.show_coverage;
+    let is_json_output = cx.is_json_output();
     ImportStripper {
         tcx: cx.tcx,
         is_json_output,
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index 78f0ad27740..1bd8a7838ec 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -18,7 +18,7 @@ pub(crate) const STRIP_PRIVATE: Pass = Pass {
 pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
     // This stripper collects all *retained* nodes.
     let mut retained = ItemIdSet::default();
-    let is_json_output = cx.output_format.is_json() && !cx.show_coverage;
+    let is_json_output = cx.is_json_output();
 
     // strip all private items
     {
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index a59c43bfbf9..3134d25e544 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -9,7 +9,6 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir};
 use rustc_interface::interface;
 use rustc_macros::{Decodable, Encodable};
-use rustc_middle::hir::map::Map;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_serialize::opaque::{FileEncoder, MemDecoder};
@@ -107,8 +106,6 @@ pub(crate) type AllCallLocations = FxIndexMap<DefPathHash, FnCallLocations>;
 
 /// Visitor for traversing a crate and finding instances of function calls.
 struct FindCalls<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    map: Map<'tcx>,
     cx: Context<'tcx>,
     target_crates: Vec<CrateNum>,
     calls: &'a mut AllCallLocations,
@@ -122,13 +119,13 @@ where
     type NestedFilter = nested_filter::OnlyBodies;
 
     fn nested_visit_map(&mut self) -> Self::Map {
-        self.map
+        self.cx.tcx().hir()
     }
 
     fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
         intravisit::walk_expr(self, ex);
 
-        let tcx = self.tcx;
+        let tcx = self.cx.tcx();
 
         // If we visit an item that contains an expression outside a function body,
         // then we need to exit before calling typeck (which will panic). See
@@ -294,8 +291,7 @@ pub(crate) fn run(
 
         // Run call-finder on all items
         let mut calls = FxIndexMap::default();
-        let mut finder =
-            FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates, bin_crate };
+        let mut finder = FindCalls { calls: &mut calls, cx, target_crates, bin_crate };
         tcx.hir().visit_all_item_likes_in_crate(&mut finder);
 
         // The visitor might have found a type error, which we need to
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index f789aca7378..31c33fbf497 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -235,7 +235,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             return false;
         }
 
-        if self.cx.output_format.is_json() {
+        if self.cx.is_json_output() {
             return false;
         }
 
diff --git a/src/rustc-std-workspace/README.md b/src/rustc-std-workspace/README.md
new file mode 100644
index 00000000000..a8e925f243d
--- /dev/null
+++ b/src/rustc-std-workspace/README.md
@@ -0,0 +1,4 @@
+See [`library/rustc-std-workspace-core/README.md`](../../library/rustc-std-workspace-core/README.md) for context.
+
+These are the crates.io versions of these crates, as opposed to the versions
+in `library` which are the ones used inside the rustc workspace.
diff --git a/src/rustc-std-workspace/rustc-std-workspace-alloc/Cargo.toml b/src/rustc-std-workspace/rustc-std-workspace-alloc/Cargo.toml
new file mode 100644
index 00000000000..1a8ebdcfeae
--- /dev/null
+++ b/src/rustc-std-workspace/rustc-std-workspace-alloc/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "rustc-std-workspace-alloc"
+version = "1.0.1"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+edition = "2021"
+license = 'MIT/Apache-2.0'
+description = """
+crate for integration of crates.io crates into rust-lang/rust standard library workspace
+"""
+
+repository = "https://github.com/rust-lang/rust/tree/master/src/rustc-std-workspace"
diff --git a/src/rustc-std-workspace/rustc-std-workspace-alloc/src/lib.rs b/src/rustc-std-workspace/rustc-std-workspace-alloc/src/lib.rs
new file mode 100644
index 00000000000..938b8bb29b6
--- /dev/null
+++ b/src/rustc-std-workspace/rustc-std-workspace-alloc/src/lib.rs
@@ -0,0 +1,3 @@
+#![no_std]
+extern crate alloc as the_alloc;
+pub use the_alloc::*;
diff --git a/src/rustc-std-workspace/rustc-std-workspace-core/Cargo.toml b/src/rustc-std-workspace/rustc-std-workspace-core/Cargo.toml
new file mode 100644
index 00000000000..116cf3fb6bc
--- /dev/null
+++ b/src/rustc-std-workspace/rustc-std-workspace-core/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "rustc-std-workspace-core"
+version = "1.0.1"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+edition = "2021"
+license = "MIT/Apache-2.0"
+description = """
+crate for integration of crates.io crates into rust-lang/rust standard library workspace
+"""
+
+repository = "https://github.com/rust-lang/rust/tree/master/src/rustc-std-workspace"
diff --git a/src/rustc-std-workspace/rustc-std-workspace-core/src/lib.rs b/src/rustc-std-workspace/rustc-std-workspace-core/src/lib.rs
new file mode 100644
index 00000000000..38b1615a024
--- /dev/null
+++ b/src/rustc-std-workspace/rustc-std-workspace-core/src/lib.rs
@@ -0,0 +1,3 @@
+#![no_std]
+extern crate core as the_core;
+pub use the_core::*;
diff --git a/src/rustc-std-workspace/rustc-std-workspace-std/Cargo.toml b/src/rustc-std-workspace/rustc-std-workspace-std/Cargo.toml
new file mode 100644
index 00000000000..fcd1ca3deaf
--- /dev/null
+++ b/src/rustc-std-workspace/rustc-std-workspace-std/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "rustc-std-workspace-std"
+version = "1.0.1"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+edition = "2021"
+license = "MIT/Apache-2.0"
+description = """
+crate for integration of crates.io crates into rust-lang/rust standard library workspace
+"""
+
+repository = "https://github.com/rust-lang/rust/tree/master/src/rustc-std-workspace"
diff --git a/src/rustc-std-workspace/rustc-std-workspace-std/src/lib.rs b/src/rustc-std-workspace/rustc-std-workspace-std/src/lib.rs
new file mode 100644
index 00000000000..f40d09cafbb
--- /dev/null
+++ b/src/rustc-std-workspace/rustc-std-workspace-std/src/lib.rs
@@ -0,0 +1 @@
+pub use std::*;
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 925cbfe09a4..39d9158a1ff 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -157,7 +157,6 @@ static TARGETS: &[&str] = &[
     "thumbv8m.main-none-eabihf",
     "wasm32-unknown-emscripten",
     "wasm32-unknown-unknown",
-    "wasm32-wasi",
     "wasm32-wasip1",
     "wasm32-wasip1-threads",
     "wasm32-wasip2",
diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs
index a5a7b9f74a6..1879391ec29 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes.rs
@@ -3,11 +3,11 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
 use rustc_ast::{AttrStyle, Attribute};
 use rustc_errors::Applicability;
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::{EarlyContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 
 // Separate each crate's features.
-pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) {
+pub fn check<'cx>(cx: &EarlyContext<'cx>, attr: &'cx Attribute) {
     if !in_external_macro(cx.sess(), attr.span)
         && let AttrStyle::Outer = attr.style
         && let Some(ident) = attr.ident()
diff --git a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
index 5d4e864b9b0..788377fe83c 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/allow_attributes_without_reason.rs
@@ -2,12 +2,12 @@ use super::{ALLOW_ATTRIBUTES_WITHOUT_REASON, Attribute};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
 use rustc_ast::{MetaItemInner, MetaItemKind};
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::{EarlyContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_span::sym;
 use rustc_span::symbol::Symbol;
 
-pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
+pub(super) fn check<'cx>(cx: &EarlyContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
     // Check if the reason is present
     if let Some(item) = items.last().and_then(MetaItemInner::meta_item)
         && let MetaItemKind::NameValue(_) = &item.kind
diff --git a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
index 0baf889faa0..fecf3166406 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/blanket_clippy_restriction_lints.rs
@@ -2,11 +2,11 @@ use super::BLANKET_CLIPPY_RESTRICTION_LINTS;
 use super::utils::extract_clippy_lint;
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use rustc_ast::MetaItemInner;
-use rustc_lint::{LateContext, Level, LintContext};
+use rustc_lint::{EarlyContext, Level, LintContext};
 use rustc_span::symbol::Symbol;
 use rustc_span::{DUMMY_SP, sym};
 
-pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner]) {
+pub(super) fn check(cx: &EarlyContext<'_>, name: Symbol, items: &[MetaItemInner]) {
     for lint in items {
         if let Some(lint_name) = extract_clippy_lint(lint) {
             if lint_name.as_str() == "restriction" && name != sym::allow {
@@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner])
     }
 }
 
-pub(super) fn check_command_line(cx: &LateContext<'_>) {
+pub(super) fn check_command_line(cx: &EarlyContext<'_>) {
     for (name, level) in &cx.sess().opts.lint_opts {
         if name == "clippy::restriction" && *level > Level::Allow {
             span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs
index 1898c145c76..d3153ec6613 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs
@@ -1,11 +1,11 @@
 use super::DEPRECATED_SEMVER;
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::{LitKind, MetaItemLit};
-use rustc_lint::LateContext;
+use rustc_lint::EarlyContext;
 use rustc_span::Span;
 use semver::Version;
 
-pub(super) fn check(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) {
+pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) {
     if let LitKind::Str(is, _) = lit.kind {
         if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() {
             return;
diff --git a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
index 55f8e1072db..2ddbc7a6a76 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/duplicated_attributes.rs
@@ -2,12 +2,12 @@ use super::DUPLICATED_ATTRIBUTES;
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::{Attribute, MetaItem};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_lint::LateContext;
+use rustc_lint::EarlyContext;
 use rustc_span::{Span, sym};
 use std::collections::hash_map::Entry;
 
 fn emit_if_duplicated(
-    cx: &LateContext<'_>,
+    cx: &EarlyContext<'_>,
     attr: &MetaItem,
     attr_paths: &mut FxHashMap<String, Span>,
     complete_path: String,
@@ -26,7 +26,7 @@ fn emit_if_duplicated(
 }
 
 fn check_duplicated_attr(
-    cx: &LateContext<'_>,
+    cx: &EarlyContext<'_>,
     attr: &MetaItem,
     attr_paths: &mut FxHashMap<String, Span>,
     parent: &mut Vec<String>,
@@ -65,7 +65,7 @@ fn check_duplicated_attr(
     }
 }
 
-pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
+pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
     let mut attr_paths = FxHashMap::default();
 
     for attr in attrs {
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs b/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs
index 5d2ea36b366..32c28c09c36 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mixed_attributes_style.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint;
 use rustc_ast::{AttrKind, AttrStyle, Attribute};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::{EarlyContext, LintContext};
 use rustc_span::source_map::SourceMap;
 use rustc_span::{SourceFile, Span, Symbol};
 
@@ -32,7 +32,7 @@ impl From<&AttrKind> for SimpleAttrKind {
     }
 }
 
-pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) {
+pub(super) fn check(cx: &EarlyContext<'_>, item_span: Span, attrs: &[Attribute]) {
     let mut inner_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
     let mut outer_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
 
@@ -64,7 +64,7 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute])
     }
 }
 
-fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) {
+fn lint_mixed_attrs(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
     let mut attrs_iter = attrs.iter().filter(|attr| !attr.span.from_expansion());
     let span = if let (Some(first), Some(last)) = (attrs_iter.next(), attrs_iter.last()) {
         first.span.with_hi(last.span.hi())
diff --git a/src/tools/clippy/clippy_lints/src/attrs/mod.rs b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
index 1a34ca99fc2..684756ce87f 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/mod.rs
@@ -14,8 +14,8 @@ mod utils;
 
 use clippy_config::Conf;
 use clippy_config::msrvs::{self, Msrv};
-use rustc_ast::{Attribute, MetaItemInner, MetaItemKind};
-use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
+use rustc_ast::{Attribute, MetaItemInner, MetaItemKind, self as ast};
+use rustc_hir::{ImplItem, Item, TraitItem};
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
 use rustc_span::sym;
@@ -414,15 +414,7 @@ pub struct Attributes {
 }
 
 impl_lint_pass!(Attributes => [
-    ALLOW_ATTRIBUTES,
-    ALLOW_ATTRIBUTES_WITHOUT_REASON,
     INLINE_ALWAYS,
-    DEPRECATED_SEMVER,
-    USELESS_ATTRIBUTE,
-    BLANKET_CLIPPY_RESTRICTION_LINTS,
-    SHOULD_PANIC_WITHOUT_EXPECT,
-    MIXED_ATTRIBUTES_STYLE,
-    DUPLICATED_ATTRIBUTES,
 ]);
 
 impl Attributes {
@@ -434,53 +426,11 @@ impl Attributes {
 }
 
 impl<'tcx> LateLintPass<'tcx> for Attributes {
-    fn check_crate(&mut self, cx: &LateContext<'tcx>) {
-        blanket_clippy_restriction_lints::check_command_line(cx);
-        duplicated_attributes::check(cx, cx.tcx.hir().krate_attrs());
-    }
-
-    fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
-        if let Some(items) = &attr.meta_item_list() {
-            if let Some(ident) = attr.ident() {
-                if is_lint_level(ident.name, attr.id) {
-                    blanket_clippy_restriction_lints::check(cx, ident.name, items);
-                }
-                if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
-                    allow_attributes::check(cx, attr);
-                }
-                if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
-                {
-                    allow_attributes_without_reason::check(cx, ident.name, items, attr);
-                }
-                if items.is_empty() || !attr.has_name(sym::deprecated) {
-                    return;
-                }
-                for item in items {
-                    if let MetaItemInner::MetaItem(mi) = &item
-                        && let MetaItemKind::NameValue(lit) = &mi.kind
-                        && mi.has_name(sym::since)
-                    {
-                        deprecated_semver::check(cx, item.span(), lit);
-                    }
-                }
-            }
-        }
-        if attr.has_name(sym::should_panic) {
-            should_panic_without_expect::check(cx, attr);
-        }
-    }
-
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
         let attrs = cx.tcx.hir().attrs(item.hir_id());
         if is_relevant_item(cx, item) {
             inline_always::check(cx, item.span, item.ident.name, attrs);
         }
-        match item.kind {
-            ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs),
-            _ => {},
-        }
-        mixed_attributes_style::check(cx, item.span, attrs);
-        duplicated_attributes::check(cx, attrs);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
@@ -526,3 +476,77 @@ impl EarlyLintPass for EarlyAttributes {
 
     extract_msrv_attr!(EarlyContext);
 }
+
+pub struct PostExpansionEarlyAttributes {
+    msrv: Msrv,
+}
+
+impl PostExpansionEarlyAttributes {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            msrv: conf.msrv.clone(),
+        }
+    }
+}
+
+impl_lint_pass!(PostExpansionEarlyAttributes => [
+    ALLOW_ATTRIBUTES,
+    ALLOW_ATTRIBUTES_WITHOUT_REASON,
+    DEPRECATED_SEMVER,
+    USELESS_ATTRIBUTE,
+    BLANKET_CLIPPY_RESTRICTION_LINTS,
+    SHOULD_PANIC_WITHOUT_EXPECT,
+    MIXED_ATTRIBUTES_STYLE,
+    DUPLICATED_ATTRIBUTES,
+]);
+
+impl EarlyLintPass for PostExpansionEarlyAttributes {
+    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
+        blanket_clippy_restriction_lints::check_command_line(cx);
+        duplicated_attributes::check(cx, &krate.attrs);
+    }
+
+    fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
+        if let Some(items) = &attr.meta_item_list() {
+            if let Some(ident) = attr.ident() {
+                if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
+                    allow_attributes::check(cx, attr);
+                }
+                if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
+                {
+                    allow_attributes_without_reason::check(cx, ident.name, items, attr);
+                }
+                if is_lint_level(ident.name, attr.id) {
+                    blanket_clippy_restriction_lints::check(cx, ident.name, items);
+                }
+                if items.is_empty() || !attr.has_name(sym::deprecated) {
+                    return;
+                }
+                for item in items {
+                    if let MetaItemInner::MetaItem(mi) = &item
+                        && let MetaItemKind::NameValue(lit) = &mi.kind
+                        && mi.has_name(sym::since)
+                    {
+                        deprecated_semver::check(cx, item.span(), lit);
+                    }
+                }
+            }
+        }
+
+        if attr.has_name(sym::should_panic) {
+            should_panic_without_expect::check(cx, attr);
+        }
+    }
+
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &'_ ast::Item) {
+        match item.kind {
+            ast::ItemKind::ExternCrate(..) | ast::ItemKind::Use(..) => useless_attribute::check(cx, item, &item.attrs),
+            _ => {},
+        }
+
+        mixed_attributes_style::check(cx, item.span, &item.attrs);
+        duplicated_attributes::check(cx, &item.attrs);
+    }
+
+    extract_msrv_attr!(EarlyContext);
+}
diff --git a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
index 2d45cbbf621..fadd5272880 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs
@@ -4,12 +4,12 @@ use rustc_ast::token::{Token, TokenKind};
 use rustc_ast::tokenstream::TokenTree;
 use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
 use rustc_errors::Applicability;
-use rustc_lint::LateContext;
+use rustc_lint::EarlyContext;
 use rustc_span::sym;
 
-pub(super) fn check(cx: &LateContext<'_>, attr: &Attribute) {
+pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
     if let AttrKind::Normal(normal_attr) = &attr.kind {
-        if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args {
+        if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args {
             // `#[should_panic = ".."]` found, good
             return;
         }
diff --git a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
index 72e6ce59d59..92b9f9cba52 100644
--- a/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs/useless_attribute.rs
@@ -1,15 +1,15 @@
 use super::utils::{extract_clippy_lint, is_lint_level, is_word};
-use super::{Attribute, USELESS_ATTRIBUTE};
+use super::USELESS_ATTRIBUTE;
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::{SpanRangeExt, first_line_of_span};
 use rustc_ast::MetaItemInner;
 use rustc_errors::Applicability;
-use rustc_hir::{Item, ItemKind};
-use rustc_lint::{LateContext, LintContext};
+use rustc_ast::{Item, ItemKind, Attribute};
+use rustc_lint::{EarlyContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_span::sym;
 
-pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) {
+pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
     let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
 
     for attr in attrs {
diff --git a/src/tools/clippy/clippy_lints/src/ctfe.rs b/src/tools/clippy/clippy_lints/src/ctfe.rs
index 2fe37a64db6..181514e8372 100644
--- a/src/tools/clippy/clippy_lints/src/ctfe.rs
+++ b/src/tools/clippy/clippy_lints/src/ctfe.rs
@@ -1,29 +1,16 @@
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, FnDecl};
-use rustc_lint::Level::Deny;
-use rustc_lint::{LateContext, LateLintPass, Lint};
+use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 
-/// Ensures that Constant-time Function Evaluation is being done (specifically, MIR lint passes).
-/// As Clippy deactivates codegen, this lint ensures that CTFE (used in hard errors) is still ran.
-pub static CLIPPY_CTFE: &Lint = &Lint {
-    name: &"clippy::CLIPPY_CTFE",
-    default_level: Deny,
-    desc: "Ensure CTFE is being made",
-    edition_lint_opts: None,
-    report_in_external_macro: true,
-    future_incompatible: None,
-    is_externally_loaded: true,
-    crate_level_only: false,
-    eval_always: true,
-    ..Lint::default_fields_for_macro()
-};
 
-// No static CLIPPY_CTFE_INFO because we want this lint to be invisible
-
-declare_lint_pass! { ClippyCtfe => [CLIPPY_CTFE] }
+declare_lint_pass! {
+    /// Ensures that Constant-time Function Evaluation is being done (specifically, MIR lint passes).
+    /// As Clippy deactivates codegen, this lint ensures that CTFE (used in hard errors) is still ran.
+    ClippyCtfe => []
+}
 
 impl<'tcx> LateLintPass<'tcx> for ClippyCtfe {
     fn check_fn(
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 14110539709..3fd07ced0e4 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -412,6 +412,8 @@ use rustc_lint::{Lint, LintId};
 pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     // NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
     store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf)));
+
+    store.register_early_pass(move || Box::new(attrs::PostExpansionEarlyAttributes::new(conf)));
 }
 
 #[derive(Default)]
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index 21f9a71f2c5..094b1947324 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -80,7 +80,7 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
     fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
-        if bk == ty::BorrowKind::MutBorrow {
+        if bk == ty::BorrowKind::Mutable {
             if let PlaceBase::Local(id) = cmt.place.base {
                 if Some(id) == self.hir_id_low && !BreakAfterExprVisitor::is_found(self.cx, diag_expr_id) {
                     self.span_low = Some(self.cx.tcx.hir().span(diag_expr_id));
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index f95a0f63fab..e587d695c84 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::ty::AssocItemContainer;
 use rustc_session::declare_lint_pass;
 use rustc_span::{Span, sym};
 
@@ -138,7 +139,6 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
-        use rustc_middle::ty::{ImplContainer, TraitContainer};
         if rustc_middle::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable_or_proc_macro(cx) {
             return;
         }
@@ -156,8 +156,8 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
         let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
         let container_id = assoc_item.container_id(cx.tcx);
         let trait_def_id = match assoc_item.container {
-            TraitContainer => Some(container_id),
-            ImplContainer => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
+            AssocItemContainer::Trait => Some(container_id),
+            AssocItemContainer::Impl => cx.tcx.impl_trait_ref(container_id).map(|t| t.skip_binder().def_id),
         };
 
         if let Some(trait_def_id) = trait_def_id {
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index 5c631a176c4..f8c815d9729 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -417,8 +417,8 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
             // a closure, it'll return this variant whereas if you have just an index access, it'll
             // return `ImmBorrow`. So if there is "Unique" and it's a mutable reference, we add it
             // to the mutably used variables set.
-            if borrow == ty::BorrowKind::MutBorrow
-                || (borrow == ty::BorrowKind::UniqueImmBorrow && base_ty.ref_mutability() == Some(Mutability::Mut))
+            if borrow == ty::BorrowKind::Mutable
+                || (borrow == ty::BorrowKind::UniqueImmutable && base_ty.ref_mutability() == Some(Mutability::Mut))
             {
                 self.add_mutably_used_var(*vid);
             } else if self.is_in_unsafe_block(id) {
@@ -426,7 +426,7 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
                 // upon!
                 self.add_mutably_used_var(*vid);
             }
-        } else if borrow == ty::ImmBorrow {
+        } else if borrow == ty::BorrowKind::Immutable {
             // If there is an `async block`, it'll contain a call to a closure which we need to
             // go into to ensure all "mutate" checks are found.
             if let Node::Expr(Expr {
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 11c97b4ef00..0dcaec1c9a7 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -102,7 +102,7 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
     struct S(HirIdSet);
     impl Delegate<'_> for S {
         fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
-            if matches!(kind, BorrowKind::ImmBorrow | BorrowKind::UniqueImmBorrow) {
+            if matches!(kind, BorrowKind::Immutable | BorrowKind::UniqueImmutable) {
                 self.0.insert(match place.place.base {
                     PlaceBase::Local(id) => id,
                     PlaceBase::Upvar(id) => id.var_path.hir_id,
@@ -127,7 +127,7 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> HirIdSet {
     struct S(HirIdSet);
     impl Delegate<'_> for S {
         fn borrow(&mut self, place: &PlaceWithHirId<'_>, _: HirId, kind: BorrowKind) {
-            if matches!(kind, BorrowKind::MutBorrow) {
+            if matches!(kind, BorrowKind::Mutable) {
                 self.0.insert(match place.place.base {
                     PlaceBase::Local(id) => id,
                     PlaceBase::Upvar(id) => id.var_path.hir_id,
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 096b3ff9a2e..89bb429e265 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -217,7 +217,7 @@ fn is_option_as_mut_use(tcx: TyCtxt<'_>, expr_id: HirId) -> bool {
 
 impl<'tcx> Delegate<'tcx> for MutationVisitor<'tcx> {
     fn borrow(&mut self, cat: &PlaceWithHirId<'tcx>, diag_expr_id: HirId, bk: ty::BorrowKind) {
-        if let ty::BorrowKind::MutBorrow = bk
+        if let ty::BorrowKind::Mutable = bk
             && is_potentially_local_place(self.local_id, &cat.place)
             && !is_option_as_mut_use(self.tcx, diag_expr_id)
         {
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index bfb3a76ad25..c5e2c8c09a2 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -21,7 +21,7 @@ use rustc_hir::{
     ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety,
     TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
 };
-use rustc_lint::{LateContext, LintContext};
+use rustc_lint::{LateContext, LintContext, EarlyContext};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_span::symbol::{Ident, kw};
@@ -429,11 +429,12 @@ impl_with_search_pat!((_cx: LateContext<'tcx>, self: ImplItem<'_>) => impl_item_
 impl_with_search_pat!((_cx: LateContext<'tcx>, self: FieldDef<'_>) => field_def_search_pat(self));
 impl_with_search_pat!((_cx: LateContext<'tcx>, self: Variant<'_>) => variant_search_pat(self));
 impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ty<'_>) => ty_search_pat(self));
-impl_with_search_pat!((_cx: LateContext<'tcx>, self: Attribute) => attr_search_pat(self));
 impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(*self));
 impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&self.node));
 impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self));
 
+impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self));
+
 impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) {
     type Context = LateContext<'cx>;
 
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index ad85dfa2d1e..0f712068e65 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1209,8 +1209,8 @@ pub fn can_move_expr_to_closure<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'
                             let capture = match capture.info.capture_kind {
                                 UpvarCapture::ByValue => CaptureKind::Value,
                                 UpvarCapture::ByRef(kind) => match kind {
-                                    BorrowKind::ImmBorrow => CaptureKind::Ref(Mutability::Not),
-                                    BorrowKind::UniqueImmBorrow | BorrowKind::MutBorrow => {
+                                    BorrowKind::Immutable => CaptureKind::Ref(Mutability::Not),
+                                    BorrowKind::UniqueImmutable | BorrowKind::Mutable => {
                                         CaptureKind::Ref(Mutability::Mut)
                                     },
                                 },
@@ -3340,8 +3340,8 @@ pub fn get_path_from_caller_to_method_type<'tcx>(
     let assoc_item = tcx.associated_item(method);
     let def_id = assoc_item.container_id(tcx);
     match assoc_item.container {
-        rustc_ty::TraitContainer => get_path_to_callee(tcx, from, def_id),
-        rustc_ty::ImplContainer => {
+        rustc_ty::AssocItemContainer::Trait => get_path_to_callee(tcx, from, def_id),
+        rustc_ty::AssocItemContainer::Impl => {
             let ty = tcx.type_of(def_id).instantiate_identity();
             get_path_to_ty(tcx, from, ty, args)
         },
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index 8af3bdccaa1..4bfc9dd9213 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -67,7 +67,7 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
     fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
 
     fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, bk: ty::BorrowKind) {
-        if bk == ty::BorrowKind::MutBorrow {
+        if bk == ty::BorrowKind::Mutable {
             self.update(cmt);
         }
     }
diff --git a/src/tools/clippy/tests/ui/allow_attributes.stderr b/src/tools/clippy/tests/ui/allow_attributes.stderr
index 10dac0bc808..023b4d7e404 100644
--- a/src/tools/clippy/tests/ui/allow_attributes.stderr
+++ b/src/tools/clippy/tests/ui/allow_attributes.stderr
@@ -19,13 +19,5 @@ error: #[allow] attribute found
 LL |     #[allow(unused)]
    |       ^^^^^ help: replace it with: `expect`
 
-error: #[allow] attribute found
-  --> tests/ui/allow_attributes.rs:52:7
-   |
-LL |     #[allow(unused)]
-   |       ^^^^^ help: replace it with: `expect`
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
index 86d7845df04..9c1ac5af91b 100644
--- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
+++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
@@ -43,14 +43,5 @@ LL |     #[allow(unused)]
    |
    = help: try adding a reason at the end with `, reason = ".."`
 
-error: `allow` attribute without specifying a reason
-  --> tests/ui/allow_attributes_without_reason.rs:46:5
-   |
-LL |     #[allow(unused)]
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a reason at the end with `, reason = ".."`
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/attrs.stderr b/src/tools/clippy/tests/ui/attrs.stderr
index cd409fc8701..a7fdceaba6f 100644
--- a/src/tools/clippy/tests/ui/attrs.stderr
+++ b/src/tools/clippy/tests/ui/attrs.stderr
@@ -1,12 +1,3 @@
-error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
-  --> tests/ui/attrs.rs:5:1
-   |
-LL | #[inline(always)]
-   | ^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::inline-always` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
-
 error: the since field must contain a semver-compliant version
   --> tests/ui/attrs.rs:27:14
    |
@@ -22,5 +13,14 @@ error: the since field must contain a semver-compliant version
 LL | #[deprecated(since = "1")]
    |              ^^^^^^^^^^^
 
+error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
+  --> tests/ui/attrs.rs:5:1
+   |
+LL | #[inline(always)]
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::inline-always` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
+
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
index d410f25b2c2..1bad259b09a 100644
--- a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
+++ b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
@@ -1,12 +1,17 @@
 error: `clippy::restriction` is not meant to be enabled as a group
+   |
+   = note: because of the command line `--warn clippy::restriction`
+   = help: enable the restriction lints you need individually
+   = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
+
+error: `clippy::restriction` is not meant to be enabled as a group
   --> tests/ui/blanket_clippy_restriction_lints.rs:6:9
    |
 LL | #![warn(clippy::restriction)]
    |         ^^^^^^^^^^^^^^^^^^^
    |
    = help: enable the restriction lints you need individually
-   = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
 
 error: `clippy::restriction` is not meant to be enabled as a group
   --> tests/ui/blanket_clippy_restriction_lints.rs:8:9
@@ -24,10 +29,5 @@ LL | #![forbid(clippy::restriction)]
    |
    = help: enable the restriction lints you need individually
 
-error: `clippy::restriction` is not meant to be enabled as a group
-   |
-   = note: because of the command line `--warn clippy::restriction`
-   = help: enable the restriction lints you need individually
-
 error: aborting due to 4 previous errors
 
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 0e735dc77c4..c79825e9e2a 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -583,10 +583,6 @@ fn wasm_special() {
         ("wasm32-unknown-emscripten", "emscripten", true),
         ("wasm32-unknown-emscripten", "wasm32", true),
         ("wasm32-unknown-emscripten", "wasm32-bare", false),
-        ("wasm32-wasi", "emscripten", false),
-        ("wasm32-wasi", "wasm32", true),
-        ("wasm32-wasi", "wasm32-bare", false),
-        ("wasm32-wasi", "wasi", true),
         ("wasm32-wasip1", "emscripten", false),
         ("wasm32-wasip1", "wasm32", true),
         ("wasm32-wasip1", "wasm32-bare", false),
diff --git a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml
index 4b97637088c..e0135a0269a 100644
--- a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml
@@ -51,6 +51,7 @@ jobs:
           cargo workspaces rename --from proc-macro-api proc_macro_api
           cargo workspaces rename --from proc-macro-srv proc_macro_srv
           cargo workspaces rename --from project-model project_model
+          cargo workspaces rename --from test-fixture test_fixture
           cargo workspaces rename --from test-utils test_utils
           cargo workspaces rename --from text-edit text_edit
           # Remove library crates from the workspaces so we don't auto-publish them as well
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 424357e8473..55705de9b2c 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -1492,9 +1492,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5bc2cfc7264d84215a08875ef90a1d35f76b5c9ad1993515d2da7e4e40b2b4b"
+checksum = "709fde78db053c78c87776ec738677649f791645883f82ff145f68caf9f18e1a"
 dependencies = [
  "bitflags 2.6.0",
  "ra-ap-rustc_index",
@@ -1503,9 +1503,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8929140697812e5dd09e19cf446d85146332363f0dbc125d4214834c34ead96"
+checksum = "da115d496e5abd65e2dceb6883d7597593badfe23fea3439202b8da5a11ea250"
 dependencies = [
  "arrayvec",
  "ra-ap-rustc_index_macros",
@@ -1514,9 +1514,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "514a3f5d04c8b4a2750f29746cc9abb1f78deb7e72e4ad1dc95bbc608f3db157"
+checksum = "be86d06a75a8125c1ace197d5030e6e02721348d32e572baea35c891669ad1e2"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1525,9 +1525,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "276fcb1205da071a0cd64416f3f0e198043c11f176c5b501a45dbf0cb33979f2"
+checksum = "b64b46ae0d8f59acc32e64e0085532b831f0d6182d870a7cd86c046c2c46e722"
 dependencies = [
  "unicode-properties",
  "unicode-xid",
@@ -1535,9 +1535,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "961b30b22cfac296b14b72e9f95e79c16cebc8c926872755fb1568a6c4243a62"
+checksum = "dbdaad19ddbd0ff46e947ca8dbb6ae678a112d3938669fb3ad6bfd244917e24b"
 dependencies = [
  "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
@@ -1545,9 +1545,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.75.0"
+version = "0.76.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "614232513814a4b714fea7f11345d31c0c277bca3089bb6ca1ec20870bfc022a"
+checksum = "dc5761e37c78d98ede9f20f6b66526093d0be66aa256d5cbdf214495843ba74d"
 dependencies = [
  "ra-ap-rustc_index",
  "rustc-hash 2.0.0",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 1099d2cb918..94e7de553bf 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -84,11 +84,11 @@ tt = { path = "./crates/tt", version = "0.0.0" }
 vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.75", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.75", default-features = false }
-ra-ap-rustc_index = { version = "0.75", default-features = false }
-ra-ap-rustc_abi = { version = "0.75", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.75", default-features = false }
+ra-ap-rustc_lexer = { version = "0.76", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.76", default-features = false }
+ra-ap-rustc_index = { version = "0.76", default-features = false }
+ra-ap-rustc_abi = { version = "0.76", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.76", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 test-fixture = { path = "./crates/test-fixture" }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index 0b108b54e67..1ab49e91569 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -407,7 +407,7 @@ impl ExprCollector<'_> {
                 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
                 let generic_args = e
                     .generic_arg_list()
-                    .and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
+                    .and_then(|it| GenericArgs::from_ast(&mut self.ctx(), it))
                     .map(Box::new);
                 self.alloc_expr(
                     Expr::MethodCall { receiver, method_name, args, generic_args },
@@ -533,7 +533,7 @@ impl ExprCollector<'_> {
             ast::Expr::TryExpr(e) => self.collect_try_operator(syntax_ptr, e),
             ast::Expr::CastExpr(e) => {
                 let expr = self.collect_expr_opt(e.expr());
-                let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty());
+                let type_ref = TypeRef::from_ast_opt(&mut self.ctx(), e.ty());
                 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
             }
             ast::Expr::RefExpr(e) => {
@@ -572,13 +572,15 @@ impl ExprCollector<'_> {
                     arg_types.reserve_exact(num_params);
                     for param in pl.params() {
                         let pat = this.collect_pat_top(param.pat());
-                        let type_ref = param.ty().map(|it| TypeRef::from_ast(&this.ctx(), it));
+                        let type_ref = param.ty().map(|it| TypeRef::from_ast(&mut this.ctx(), it));
                         args.push(pat);
                         arg_types.push(type_ref);
                     }
                 }
-                let ret_type =
-                    e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&this.ctx(), it));
+                let ret_type = e
+                    .ret_type()
+                    .and_then(|r| r.ty())
+                    .map(|it| TypeRef::from_ast(&mut this.ctx(), it));
 
                 let prev_is_lowering_coroutine = mem::take(&mut this.is_lowering_coroutine);
                 let prev_try_block_label = this.current_try_block_label.take();
@@ -705,7 +707,7 @@ impl ExprCollector<'_> {
             ast::Expr::UnderscoreExpr(_) => self.alloc_expr(Expr::Underscore, syntax_ptr),
             ast::Expr::AsmExpr(e) => self.lower_inline_asm(e, syntax_ptr),
             ast::Expr::OffsetOfExpr(e) => {
-                let container = TypeRef::from_ast_opt(&self.ctx(), e.ty());
+                let container = TypeRef::from_ast_opt(&mut self.ctx(), e.ty());
                 let fields = e.fields().map(|it| it.as_name()).collect();
                 self.alloc_expr(Expr::OffsetOf(OffsetOf { container, fields }), syntax_ptr)
             }
@@ -1317,7 +1319,7 @@ impl ExprCollector<'_> {
                     return;
                 }
                 let pat = self.collect_pat_top(stmt.pat());
-                let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
+                let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&mut self.ctx(), it));
                 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
                 let else_branch = stmt
                     .let_else()
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index f49018eaf38..6d07dc8f9be 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -37,6 +37,7 @@ pub struct FunctionData {
     pub name: Name,
     pub params: Box<[TypeRefId]>,
     pub ret_type: TypeRefId,
+    // FIXME: why are these stored here? They should be accessed via the query
     pub attrs: Attrs,
     pub visibility: RawVisibility,
     pub abi: Option<Symbol>,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
index a59bbf7e221..22005695af6 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
@@ -21,7 +21,79 @@
 //!
 //! This is a work of fiction. Any similarities to Kotlin's `BindingContext` are
 //! a coincidence.
-pub mod keys;
+
+pub mod keys {
+    use std::marker::PhantomData;
+
+    use hir_expand::{attrs::AttrId, MacroCallId};
+    use rustc_hash::FxHashMap;
+    use syntax::{ast, AstNode, AstPtr};
+
+    use crate::{
+        dyn_map::{DynMap, Policy},
+        BlockId, ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId,
+        LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId,
+        TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId,
+    };
+
+    pub type Key<K, V> = crate::dyn_map::Key<AstPtr<K>, V, AstPtrPolicy<K, V>>;
+
+    pub const BLOCK: Key<ast::BlockExpr, BlockId> = Key::new();
+    pub const FUNCTION: Key<ast::Fn, FunctionId> = Key::new();
+    pub const CONST: Key<ast::Const, ConstId> = Key::new();
+    pub const STATIC: Key<ast::Static, StaticId> = Key::new();
+    pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new();
+    pub const IMPL: Key<ast::Impl, ImplId> = Key::new();
+    pub const TRAIT: Key<ast::Trait, TraitId> = Key::new();
+    pub const TRAIT_ALIAS: Key<ast::TraitAlias, TraitAliasId> = Key::new();
+    pub const STRUCT: Key<ast::Struct, StructId> = Key::new();
+    pub const UNION: Key<ast::Union, UnionId> = Key::new();
+    pub const ENUM: Key<ast::Enum, EnumId> = Key::new();
+    pub const EXTERN_CRATE: Key<ast::ExternCrate, ExternCrateId> = Key::new();
+    pub const USE: Key<ast::Use, UseId> = Key::new();
+
+    pub const ENUM_VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
+    pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
+    pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
+    pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new();
+    pub const CONST_PARAM: Key<ast::ConstParam, TypeOrConstParamId> = Key::new();
+    pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
+
+    pub const MACRO_RULES: Key<ast::MacroRules, MacroRulesId> = Key::new();
+    pub const MACRO2: Key<ast::MacroDef, Macro2Id> = Key::new();
+    pub const PROC_MACRO: Key<ast::Fn, ProcMacroId> = Key::new();
+    pub const MACRO_CALL: Key<ast::MacroCall, MacroCallId> = Key::new();
+    pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
+    pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, MacroCallId, Box<[Option<MacroCallId>]>)> =
+        Key::new();
+
+    /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
+    /// equal if they point to exactly the same object.
+    ///
+    /// In general, we do not guarantee that we have exactly one instance of a
+    /// syntax tree for each file. We probably should add such guarantee, but, for
+    /// the time being, we will use identity-less AstPtr comparison.
+    pub struct AstPtrPolicy<AST, ID> {
+        _phantom: PhantomData<(AST, ID)>,
+    }
+
+    impl<AST: AstNode + 'static, ID: 'static> Policy for AstPtrPolicy<AST, ID> {
+        type K = AstPtr<AST>;
+        type V = ID;
+        fn insert(map: &mut DynMap, key: AstPtr<AST>, value: ID) {
+            map.map
+                .entry::<FxHashMap<AstPtr<AST>, ID>>()
+                .or_insert_with(Default::default)
+                .insert(key, value);
+        }
+        fn get<'a>(map: &'a DynMap, key: &AstPtr<AST>) -> Option<&'a ID> {
+            map.map.get::<FxHashMap<AstPtr<AST>, ID>>()?.get(key)
+        }
+        fn is_empty(map: &DynMap) -> bool {
+            map.map.get::<FxHashMap<AstPtr<AST>, ID>>().map_or(true, |it| it.is_empty())
+        }
+    }
+}
 
 use std::{
     hash::Hash,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs
deleted file mode 100644
index 9d330a7bf1c..00000000000
--- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map/keys.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-//! keys to be used with `DynMap`
-
-use std::marker::PhantomData;
-
-use hir_expand::{attrs::AttrId, MacroCallId};
-use rustc_hash::FxHashMap;
-use syntax::{ast, AstNode, AstPtr};
-
-use crate::{
-    dyn_map::{DynMap, Policy},
-    BlockId, ConstId, EnumId, EnumVariantId, ExternCrateId, FieldId, FunctionId, ImplId,
-    LifetimeParamId, Macro2Id, MacroRulesId, ProcMacroId, StaticId, StructId, TraitAliasId,
-    TraitId, TypeAliasId, TypeOrConstParamId, UnionId, UseId,
-};
-
-pub type Key<K, V> = crate::dyn_map::Key<AstPtr<K>, V, AstPtrPolicy<K, V>>;
-
-pub const BLOCK: Key<ast::BlockExpr, BlockId> = Key::new();
-pub const FUNCTION: Key<ast::Fn, FunctionId> = Key::new();
-pub const CONST: Key<ast::Const, ConstId> = Key::new();
-pub const STATIC: Key<ast::Static, StaticId> = Key::new();
-pub const TYPE_ALIAS: Key<ast::TypeAlias, TypeAliasId> = Key::new();
-pub const IMPL: Key<ast::Impl, ImplId> = Key::new();
-pub const TRAIT: Key<ast::Trait, TraitId> = Key::new();
-pub const TRAIT_ALIAS: Key<ast::TraitAlias, TraitAliasId> = Key::new();
-pub const STRUCT: Key<ast::Struct, StructId> = Key::new();
-pub const UNION: Key<ast::Union, UnionId> = Key::new();
-pub const ENUM: Key<ast::Enum, EnumId> = Key::new();
-pub const EXTERN_CRATE: Key<ast::ExternCrate, ExternCrateId> = Key::new();
-pub const USE: Key<ast::Use, UseId> = Key::new();
-
-pub const ENUM_VARIANT: Key<ast::Variant, EnumVariantId> = Key::new();
-pub const TUPLE_FIELD: Key<ast::TupleField, FieldId> = Key::new();
-pub const RECORD_FIELD: Key<ast::RecordField, FieldId> = Key::new();
-pub const TYPE_PARAM: Key<ast::TypeParam, TypeOrConstParamId> = Key::new();
-pub const CONST_PARAM: Key<ast::ConstParam, TypeOrConstParamId> = Key::new();
-pub const LIFETIME_PARAM: Key<ast::LifetimeParam, LifetimeParamId> = Key::new();
-
-pub const MACRO_RULES: Key<ast::MacroRules, MacroRulesId> = Key::new();
-pub const MACRO2: Key<ast::MacroDef, Macro2Id> = Key::new();
-pub const PROC_MACRO: Key<ast::Fn, ProcMacroId> = Key::new();
-pub const MACRO_CALL: Key<ast::MacroCall, MacroCallId> = Key::new();
-pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
-pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, MacroCallId, Box<[Option<MacroCallId>]>)> =
-    Key::new();
-
-/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
-/// equal if they point to exactly the same object.
-///
-/// In general, we do not guarantee that we have exactly one instance of a
-/// syntax tree for each file. We probably should add such guarantee, but, for
-/// the time being, we will use identity-less AstPtr comparison.
-pub struct AstPtrPolicy<AST, ID> {
-    _phantom: PhantomData<(AST, ID)>,
-}
-
-impl<AST: AstNode + 'static, ID: 'static> Policy for AstPtrPolicy<AST, ID> {
-    type K = AstPtr<AST>;
-    type V = ID;
-    fn insert(map: &mut DynMap, key: AstPtr<AST>, value: ID) {
-        map.map
-            .entry::<FxHashMap<AstPtr<AST>, ID>>()
-            .or_insert_with(Default::default)
-            .insert(key, value);
-    }
-    fn get<'a>(map: &'a DynMap, key: &AstPtr<AST>) -> Option<&'a ID> {
-        map.map.get::<FxHashMap<AstPtr<AST>, ID>>()?.get(key)
-    }
-    fn is_empty(map: &DynMap) -> bool {
-        map.map.get::<FxHashMap<AstPtr<AST>, ID>>().map_or(true, |it| it.is_empty())
-    }
-}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
index d430733fcad..5315c1c6fbd 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
@@ -161,14 +161,14 @@ impl Expander {
         types_map: &mut TypesMap,
         types_source_map: &mut TypesSourceMap,
     ) -> Option<Path> {
-        let ctx = LowerCtx::with_span_map_cell(
+        let mut ctx = LowerCtx::with_span_map_cell(
             db,
             self.current_file_id,
             self.span_map.clone(),
             types_map,
             types_source_map,
         );
-        Path::from_src(&ctx, path)
+        Path::from_src(&mut ctx, path)
     }
 
     fn within_limit<F, T: ast::AstNode>(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
index 6b79850e9c4..11e9bb0d886 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -451,7 +451,7 @@ pub(crate) struct GenericParamsCollector {
 impl GenericParamsCollector {
     pub(crate) fn fill(
         &mut self,
-        lower_ctx: &LowerCtx<'_>,
+        lower_ctx: &mut LowerCtx<'_>,
         node: &dyn HasGenericParams,
         add_param_attrs: impl FnMut(
             Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
@@ -468,7 +468,7 @@ impl GenericParamsCollector {
 
     pub(crate) fn fill_bounds(
         &mut self,
-        lower_ctx: &LowerCtx<'_>,
+        lower_ctx: &mut LowerCtx<'_>,
         type_bounds: Option<ast::TypeBoundList>,
         target: Either<TypeRefId, LifetimeRef>,
     ) {
@@ -479,7 +479,7 @@ impl GenericParamsCollector {
 
     fn fill_params(
         &mut self,
-        lower_ctx: &LowerCtx<'_>,
+        lower_ctx: &mut LowerCtx<'_>,
         params: ast::GenericParamList,
         mut add_param_attrs: impl FnMut(
             Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
@@ -535,7 +535,11 @@ impl GenericParamsCollector {
         }
     }
 
-    fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx<'_>, where_clause: ast::WhereClause) {
+    fn fill_where_predicates(
+        &mut self,
+        lower_ctx: &mut LowerCtx<'_>,
+        where_clause: ast::WhereClause,
+    ) {
         for pred in where_clause.predicates() {
             let target = if let Some(type_ref) = pred.ty() {
                 Either::Left(TypeRef::from_ast(lower_ctx, type_ref))
@@ -569,7 +573,7 @@ impl GenericParamsCollector {
 
     fn add_where_predicate_from_bound(
         &mut self,
-        lower_ctx: &LowerCtx<'_>,
+        lower_ctx: &mut LowerCtx<'_>,
         bound: ast::TypeBound,
         hrtb_lifetimes: Option<&[Name]>,
         target: Either<TypeRefId, LifetimeRef>,
@@ -670,8 +674,9 @@ impl GenericParamsCollector {
                 {
                     let (mut macro_types_map, mut macro_types_source_map) =
                         (TypesMap::default(), TypesSourceMap::default());
-                    let ctx = expander.ctx(db, &mut macro_types_map, &mut macro_types_source_map);
-                    let type_ref = TypeRef::from_ast(&ctx, expanded.tree());
+                    let mut ctx =
+                        expander.ctx(db, &mut macro_types_map, &mut macro_types_source_map);
+                    let type_ref = TypeRef::from_ast(&mut ctx, expanded.tree());
                     self.fill_implicit_impl_trait_args(
                         db,
                         generics_types_map,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
index 2582340c0f8..4d83ef99c84 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
@@ -98,7 +98,7 @@ pub struct TraitRef {
 
 impl TraitRef {
     /// Converts an `ast::PathType` to a `hir::TraitRef`.
-    pub(crate) fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> Option<Self> {
+    pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> Option<Self> {
         // FIXME: Use `Path::from_src`
         match node {
             ast::Type::PathType(path) => {
@@ -240,7 +240,7 @@ pub enum TraitBoundModifier {
 
 impl TypeRef {
     /// Converts an `ast::TypeRef` to a `hir::TypeRef`.
-    pub fn from_ast(ctx: &LowerCtx<'_>, node: ast::Type) -> TypeRefId {
+    pub fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::Type) -> TypeRefId {
         let ty = match &node {
             ast::Type::ParenType(inner) => return TypeRef::from_ast_opt(ctx, inner.ty()),
             ast::Type::TupleType(inner) => TypeRef::Tuple(EmptyOptimizedThinVec::from_iter(
@@ -321,8 +321,9 @@ impl TypeRef {
                     // Disallow nested impl traits
                     TypeRef::Error
                 } else {
-                    let _guard = ctx.outer_impl_trait_scope(true);
-                    TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
+                    ctx.with_outer_impl_trait_scope(true, |ctx| {
+                        TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
+                    })
                 }
             }
             ast::Type::DynTraitType(inner) => {
@@ -336,7 +337,7 @@ impl TypeRef {
         ctx.alloc_type_ref(ty, AstPtr::new(&node))
     }
 
-    pub(crate) fn from_ast_opt(ctx: &LowerCtx<'_>, node: Option<ast::Type>) -> TypeRefId {
+    pub(crate) fn from_ast_opt(ctx: &mut LowerCtx<'_>, node: Option<ast::Type>) -> TypeRefId {
         match node {
             Some(node) => TypeRef::from_ast(ctx, node),
             None => ctx.alloc_error_type(),
@@ -410,7 +411,7 @@ impl TypeRef {
 }
 
 pub(crate) fn type_bounds_from_ast(
-    lower_ctx: &LowerCtx<'_>,
+    lower_ctx: &mut LowerCtx<'_>,
     type_bounds_opt: Option<ast::TypeBoundList>,
 ) -> ThinVec<TypeBound> {
     if let Some(type_bounds) = type_bounds_opt {
@@ -423,8 +424,8 @@ pub(crate) fn type_bounds_from_ast(
 }
 
 impl TypeBound {
-    pub(crate) fn from_ast(ctx: &LowerCtx<'_>, node: ast::TypeBound) -> Self {
-        let lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?);
+    pub(crate) fn from_ast(ctx: &mut LowerCtx<'_>, node: ast::TypeBound) -> Self {
+        let mut lower_path_type = |path_type: ast::PathType| ctx.lower_path(path_type.path()?);
 
         match node.kind() {
             ast::TypeBoundKind::PathType(path_type) => {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index a04f12cab76..e96e38eceeb 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
@@ -361,9 +361,7 @@ impl ItemScope {
         self.macro_invocations.get(&call).copied()
     }
 
-    pub(crate) fn iter_macro_invoc(
-        &self,
-    ) -> impl Iterator<Item = (&AstId<ast::MacroCall>, &MacroCallId)> {
+    pub fn iter_macro_invoc(&self) -> impl Iterator<Item = (&AstId<ast::MacroCall>, &MacroCallId)> {
         self.macro_invocations.iter()
     }
 }
@@ -401,9 +399,7 @@ impl ItemScope {
         self.macro_invocations.insert(call, call_id);
     }
 
-    pub(crate) fn attr_macro_invocs(
-        &self,
-    ) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
+    pub fn attr_macro_invocs(&self) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
         self.attr_macros.iter().map(|(k, v)| (*k, *v))
     }
 
@@ -440,7 +436,7 @@ impl ItemScope {
         });
     }
 
-    pub(crate) fn derive_macro_invocs(
+    pub fn derive_macro_invocs(
         &self,
     ) -> impl Iterator<
         Item = (
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index bd17fce37b7..d519c1708b3 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -234,11 +234,11 @@ impl<'a> Ctx<'a> {
     fn lower_struct(&mut self, strukt: &ast::Struct) -> Option<FileItemTreeId<Struct>> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
+        let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
         let visibility = self.lower_visibility(strukt);
         let name = strukt.name()?.as_name();
         let ast_id = self.source_ast_id_map.ast_id(strukt);
-        let (fields, kind, attrs) = self.lower_fields(&strukt.kind(), &body_ctx);
+        let (fields, kind, attrs) = self.lower_fields(&strukt.kind(), &mut body_ctx);
         let (generic_params, generics_source_map) =
             self.lower_generic_params(HasImplicitSelf::No, strukt);
         types_map.shrink_to_fit();
@@ -273,7 +273,7 @@ impl<'a> Ctx<'a> {
     fn lower_fields(
         &mut self,
         strukt_kind: &ast::StructKind,
-        body_ctx: &LowerCtx<'_>,
+        body_ctx: &mut LowerCtx<'_>,
     ) -> (Box<[Field]>, FieldsShape, Vec<(usize, RawAttrs)>) {
         match strukt_kind {
             ast::StructKind::Record(it) => {
@@ -308,7 +308,11 @@ impl<'a> Ctx<'a> {
         }
     }
 
-    fn lower_record_field(&mut self, field: &ast::RecordField, body_ctx: &LowerCtx<'_>) -> Field {
+    fn lower_record_field(
+        &mut self,
+        field: &ast::RecordField,
+        body_ctx: &mut LowerCtx<'_>,
+    ) -> Field {
         let name = match field.name() {
             Some(name) => name.as_name(),
             None => Name::missing(),
@@ -323,7 +327,7 @@ impl<'a> Ctx<'a> {
         &mut self,
         idx: usize,
         field: &ast::TupleField,
-        body_ctx: &LowerCtx<'_>,
+        body_ctx: &mut LowerCtx<'_>,
     ) -> Field {
         let name = Name::new_tuple_field(idx);
         let visibility = self.lower_visibility(field);
@@ -334,13 +338,13 @@ impl<'a> Ctx<'a> {
     fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
+        let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
         let visibility = self.lower_visibility(union);
         let name = union.name()?.as_name();
         let ast_id = self.source_ast_id_map.ast_id(union);
         let (fields, _, attrs) = match union.record_field_list() {
             Some(record_field_list) => {
-                self.lower_fields(&StructKind::Record(record_field_list), &body_ctx)
+                self.lower_fields(&StructKind::Record(record_field_list), &mut body_ctx)
             }
             None => (Box::default(), FieldsShape::Record, Vec::default()),
         };
@@ -409,12 +413,12 @@ impl<'a> Ctx<'a> {
     fn lower_variant(&mut self, variant: &ast::Variant) -> Idx<Variant> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
+        let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
         let name = match variant.name() {
             Some(name) => name.as_name(),
             None => Name::missing(),
         };
-        let (fields, kind, attrs) = self.lower_fields(&variant.kind(), &body_ctx);
+        let (fields, kind, attrs) = self.lower_fields(&variant.kind(), &mut body_ctx);
         let ast_id = self.source_ast_id_map.ast_id(variant);
         types_map.shrink_to_fit();
         types_source_map.shrink_to_fit();
@@ -436,7 +440,7 @@ impl<'a> Ctx<'a> {
     fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
+        let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
 
         let visibility = self.lower_visibility(func);
         let name = func.name()?.as_name();
@@ -457,7 +461,7 @@ impl<'a> Ctx<'a> {
                     RawAttrs::new(self.db.upcast(), &self_param, self.span_map()),
                 );
                 let self_type = match self_param.ty() {
-                    Some(type_ref) => TypeRef::from_ast(&body_ctx, type_ref),
+                    Some(type_ref) => TypeRef::from_ast(&mut body_ctx, type_ref),
                     None => {
                         let self_type = body_ctx.alloc_type_ref_desugared(TypeRef::Path(
                             Name::new_symbol_root(sym::Self_.clone()).into(),
@@ -492,7 +496,7 @@ impl<'a> Ctx<'a> {
                         Param { type_ref: None }
                     }
                     None => {
-                        let type_ref = TypeRef::from_ast_opt(&body_ctx, param.ty());
+                        let type_ref = TypeRef::from_ast_opt(&mut body_ctx, param.ty());
                         Param { type_ref: Some(type_ref) }
                     }
                 };
@@ -502,7 +506,7 @@ impl<'a> Ctx<'a> {
 
         let ret_type = match func.ret_type() {
             Some(rt) => match rt.ty() {
-                Some(type_ref) => TypeRef::from_ast(&body_ctx, type_ref),
+                Some(type_ref) => TypeRef::from_ast(&mut body_ctx, type_ref),
                 None if rt.thin_arrow_token().is_some() => body_ctx.alloc_error_type(),
                 None => body_ctx.alloc_type_ref_desugared(TypeRef::unit()),
             },
@@ -581,11 +585,11 @@ impl<'a> Ctx<'a> {
     ) -> Option<FileItemTreeId<TypeAlias>> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
+        let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
         let name = type_alias.name()?.as_name();
-        let type_ref = type_alias.ty().map(|it| TypeRef::from_ast(&body_ctx, it));
+        let type_ref = type_alias.ty().map(|it| TypeRef::from_ast(&mut body_ctx, it));
         let visibility = self.lower_visibility(type_alias);
-        let bounds = self.lower_type_bounds(type_alias, &body_ctx);
+        let bounds = self.lower_type_bounds(type_alias, &mut body_ctx);
         let ast_id = self.source_ast_id_map.ast_id(type_alias);
         let (generic_params, generics_source_map) =
             self.lower_generic_params(HasImplicitSelf::No, type_alias);
@@ -612,9 +616,9 @@ impl<'a> Ctx<'a> {
     fn lower_static(&mut self, static_: &ast::Static) -> Option<FileItemTreeId<Static>> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
+        let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
         let name = static_.name()?.as_name();
-        let type_ref = TypeRef::from_ast_opt(&body_ctx, static_.ty());
+        let type_ref = TypeRef::from_ast_opt(&mut body_ctx, static_.ty());
         let visibility = self.lower_visibility(static_);
         let mutable = static_.mut_token().is_some();
         let has_safe_kw = static_.safe_token().is_some();
@@ -639,9 +643,9 @@ impl<'a> Ctx<'a> {
     fn lower_const(&mut self, konst: &ast::Const) -> FileItemTreeId<Const> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
+        let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
         let name = konst.name().map(|it| it.as_name());
-        let type_ref = TypeRef::from_ast_opt(&body_ctx, konst.ty());
+        let type_ref = TypeRef::from_ast_opt(&mut body_ctx, konst.ty());
         let visibility = self.lower_visibility(konst);
         let ast_id = self.source_ast_id_map.ast_id(konst);
         types_map.shrink_to_fit();
@@ -724,14 +728,14 @@ impl<'a> Ctx<'a> {
     fn lower_impl(&mut self, impl_def: &ast::Impl) -> FileItemTreeId<Impl> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
+        let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
 
         let ast_id = self.source_ast_id_map.ast_id(impl_def);
         // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
         // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
         // equals itself.
-        let self_ty = TypeRef::from_ast_opt(&body_ctx, impl_def.self_ty());
-        let target_trait = impl_def.trait_().and_then(|tr| TraitRef::from_ast(&body_ctx, tr));
+        let self_ty = TypeRef::from_ast_opt(&mut body_ctx, impl_def.self_ty());
+        let target_trait = impl_def.trait_().and_then(|tr| TraitRef::from_ast(&mut body_ctx, tr));
         let is_negative = impl_def.excl_token().is_some();
         let is_unsafe = impl_def.unsafe_token().is_some();
 
@@ -870,13 +874,8 @@ impl<'a> Ctx<'a> {
     ) -> (Arc<GenericParams>, TypesSourceMap) {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
+        let mut body_ctx = self.body_ctx(&mut types_map, &mut types_source_map);
         debug_assert!(self.generic_param_attr_buffer.is_empty(),);
-        let add_param_attrs = |item: Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
-                               param| {
-            let attrs = RawAttrs::new(self.db.upcast(), &param, body_ctx.span_map());
-            debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none());
-        };
         body_ctx.take_impl_traits_bounds();
         let mut generics = GenericParamsCollector::default();
 
@@ -892,16 +891,19 @@ impl<'a> Ctx<'a> {
             );
             // add super traits as bounds on Self
             // i.e., `trait Foo: Bar` is equivalent to `trait Foo where Self: Bar`
-            generics.fill_bounds(
-                &body_ctx,
-                bounds,
-                Either::Left(body_ctx.alloc_type_ref_desugared(TypeRef::Path(
-                    Name::new_symbol_root(sym::Self_.clone()).into(),
-                ))),
-            );
+            let bound_target = Either::Left(body_ctx.alloc_type_ref_desugared(TypeRef::Path(
+                Name::new_symbol_root(sym::Self_.clone()).into(),
+            )));
+            generics.fill_bounds(&mut body_ctx, bounds, bound_target);
         }
 
-        generics.fill(&body_ctx, node, add_param_attrs);
+        let span_map = body_ctx.span_map().clone();
+        let add_param_attrs = |item: Either<LocalTypeOrConstParamId, LocalLifetimeParamId>,
+                               param| {
+            let attrs = RawAttrs::new(self.db.upcast(), &param, span_map.as_ref());
+            debug_assert!(self.generic_param_attr_buffer.insert(item, attrs).is_none());
+        };
+        generics.fill(&mut body_ctx, node, add_param_attrs);
 
         let generics = generics.finish(types_map, &mut types_source_map);
         (generics, types_source_map)
@@ -910,7 +912,7 @@ impl<'a> Ctx<'a> {
     fn lower_type_bounds(
         &mut self,
         node: &dyn ast::HasTypeBounds,
-        body_ctx: &LowerCtx<'_>,
+        body_ctx: &mut LowerCtx<'_>,
     ) -> Box<[TypeBound]> {
         match node.type_bound_list() {
             Some(bound_list) => {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index f6ed826f04c..eb55ba1d53d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -47,7 +47,6 @@ pub mod resolver;
 
 pub mod nameres;
 
-pub mod child_by_source;
 pub mod src;
 
 pub mod find_path;
@@ -354,9 +353,9 @@ impl_loc!(ProcMacroLoc, id: Function, container: CrateRootModuleId);
 pub struct BlockId(ra_salsa::InternId);
 #[derive(Debug, Hash, PartialEq, Eq, Clone)]
 pub struct BlockLoc {
-    ast_id: AstId<ast::BlockExpr>,
+    pub ast_id: AstId<ast::BlockExpr>,
     /// The containing module.
-    module: ModuleId,
+    pub module: ModuleId,
 }
 impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
 
@@ -838,16 +837,18 @@ impl InTypeConstId {
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum GeneralConstId {
     ConstId(ConstId),
+    StaticId(StaticId),
     ConstBlockId(ConstBlockId),
     InTypeConstId(InTypeConstId),
 }
 
-impl_from!(ConstId, ConstBlockId, InTypeConstId for GeneralConstId);
+impl_from!(ConstId, StaticId, ConstBlockId, InTypeConstId for GeneralConstId);
 
 impl GeneralConstId {
     pub fn generic_def(self, db: &dyn DefDatabase) -> Option<GenericDefId> {
         match self {
             GeneralConstId::ConstId(it) => Some(it.into()),
+            GeneralConstId::StaticId(_) => None,
             GeneralConstId::ConstBlockId(it) => it.lookup(db).parent.as_generic_def_id(db),
             GeneralConstId::InTypeConstId(it) => it.lookup(db).owner.as_generic_def_id(db),
         }
@@ -855,6 +856,9 @@ impl GeneralConstId {
 
     pub fn name(self, db: &dyn DefDatabase) -> String {
         match self {
+            GeneralConstId::StaticId(it) => {
+                db.static_data(it).name.display(db.upcast(), Edition::CURRENT).to_string()
+            }
             GeneralConstId::ConstId(const_id) => db
                 .const_data(const_id)
                 .name
@@ -935,7 +939,7 @@ impl_from!(
 );
 
 impl GenericDefId {
-    fn file_id_and_params_of(
+    pub fn file_id_and_params_of(
         self,
         db: &dyn DefDatabase,
     ) -> (HirFileId, Option<ast::GenericParamList>) {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
index df5847929c5..6d1a3d17447 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
@@ -1,10 +1,7 @@
 //! Context for lowering paths.
-use std::cell::{OnceCell, RefCell};
+use std::{cell::OnceCell, mem};
 
-use hir_expand::{
-    span_map::{SpanMap, SpanMapRef},
-    AstId, HirFileId, InFile,
-};
+use hir_expand::{span_map::SpanMap, AstId, HirFileId, InFile};
 use span::{AstIdMap, AstIdNode};
 use stdx::thin_vec::ThinVec;
 use syntax::ast;
@@ -21,28 +18,11 @@ pub struct LowerCtx<'a> {
     file_id: HirFileId,
     span_map: OnceCell<SpanMap>,
     ast_id_map: OnceCell<Arc<AstIdMap>>,
-    impl_trait_bounds: RefCell<Vec<ThinVec<TypeBound>>>,
+    impl_trait_bounds: Vec<ThinVec<TypeBound>>,
     // Prevent nested impl traits like `impl Foo<impl Bar>`.
-    outer_impl_trait: RefCell<bool>,
-    types_map: RefCell<(&'a mut TypesMap, &'a mut TypesSourceMap)>,
-}
-
-pub(crate) struct OuterImplTraitGuard<'a, 'b> {
-    ctx: &'a LowerCtx<'b>,
-    old: bool,
-}
-
-impl<'a, 'b> OuterImplTraitGuard<'a, 'b> {
-    fn new(ctx: &'a LowerCtx<'b>, impl_trait: bool) -> Self {
-        let old = ctx.outer_impl_trait.replace(impl_trait);
-        Self { ctx, old }
-    }
-}
-
-impl Drop for OuterImplTraitGuard<'_, '_> {
-    fn drop(&mut self) {
-        self.ctx.outer_impl_trait.replace(self.old);
-    }
+    outer_impl_trait: bool,
+    types_map: &'a mut TypesMap,
+    types_source_map: &'a mut TypesSourceMap,
 }
 
 impl<'a> LowerCtx<'a> {
@@ -57,9 +37,10 @@ impl<'a> LowerCtx<'a> {
             file_id,
             span_map: OnceCell::new(),
             ast_id_map: OnceCell::new(),
-            impl_trait_bounds: RefCell::new(Vec::new()),
-            outer_impl_trait: RefCell::default(),
-            types_map: RefCell::new((types_map, types_source_map)),
+            impl_trait_bounds: Vec::new(),
+            outer_impl_trait: false,
+            types_map,
+            types_source_map,
         }
     }
 
@@ -75,17 +56,18 @@ impl<'a> LowerCtx<'a> {
             file_id,
             span_map,
             ast_id_map: OnceCell::new(),
-            impl_trait_bounds: RefCell::new(Vec::new()),
-            outer_impl_trait: RefCell::default(),
-            types_map: RefCell::new((types_map, types_source_map)),
+            impl_trait_bounds: Vec::new(),
+            outer_impl_trait: false,
+            types_map,
+            types_source_map,
         }
     }
 
-    pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
-        self.span_map.get_or_init(|| self.db.span_map(self.file_id)).as_ref()
+    pub(crate) fn span_map(&self) -> &SpanMap {
+        self.span_map.get_or_init(|| self.db.span_map(self.file_id))
     }
 
-    pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
+    pub(crate) fn lower_path(&mut self, ast: ast::Path) -> Option<Path> {
         Path::from_src(self, ast)
     }
 
@@ -96,44 +78,44 @@ impl<'a> LowerCtx<'a> {
         )
     }
 
-    pub fn update_impl_traits_bounds(&self, bounds: ThinVec<TypeBound>) {
-        self.impl_trait_bounds.borrow_mut().push(bounds);
+    pub fn update_impl_traits_bounds_from_type_ref(&mut self, type_ref: TypeRefId) {
+        TypeRef::walk(type_ref, self.types_map, &mut |tr| {
+            if let TypeRef::ImplTrait(bounds) = tr {
+                self.impl_trait_bounds.push(bounds.clone());
+            }
+        });
     }
 
-    pub fn take_impl_traits_bounds(&self) -> Vec<ThinVec<TypeBound>> {
-        self.impl_trait_bounds.take()
+    pub fn take_impl_traits_bounds(&mut self) -> Vec<ThinVec<TypeBound>> {
+        mem::take(&mut self.impl_trait_bounds)
     }
 
     pub(crate) fn outer_impl_trait(&self) -> bool {
-        *self.outer_impl_trait.borrow()
+        self.outer_impl_trait
     }
 
-    pub(crate) fn outer_impl_trait_scope<'b>(
-        &'b self,
+    pub(crate) fn with_outer_impl_trait_scope<R>(
+        &mut self,
         impl_trait: bool,
-    ) -> OuterImplTraitGuard<'b, 'a> {
-        OuterImplTraitGuard::new(self, impl_trait)
+        f: impl FnOnce(&mut Self) -> R,
+    ) -> R {
+        let old = mem::replace(&mut self.outer_impl_trait, impl_trait);
+        let result = f(self);
+        self.outer_impl_trait = old;
+        result
     }
 
-    pub(crate) fn alloc_type_ref(&self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
-        let mut types_map = self.types_map.borrow_mut();
-        let (types_map, types_source_map) = &mut *types_map;
-        let id = types_map.types.alloc(type_ref);
-        types_source_map.types_map_back.insert(id, InFile::new(self.file_id, node));
+    pub(crate) fn alloc_type_ref(&mut self, type_ref: TypeRef, node: TypePtr) -> TypeRefId {
+        let id = self.types_map.types.alloc(type_ref);
+        self.types_source_map.types_map_back.insert(id, InFile::new(self.file_id, node));
         id
     }
 
-    pub(crate) fn alloc_type_ref_desugared(&self, type_ref: TypeRef) -> TypeRefId {
-        self.types_map.borrow_mut().0.types.alloc(type_ref)
-    }
-
-    pub(crate) fn alloc_error_type(&self) -> TypeRefId {
-        self.types_map.borrow_mut().0.types.alloc(TypeRef::Error)
+    pub(crate) fn alloc_type_ref_desugared(&mut self, type_ref: TypeRef) -> TypeRefId {
+        self.types_map.types.alloc(type_ref)
     }
 
-    // FIXME: If we alloc while holding this, well... Bad Things will happen. Need to change this
-    // to use proper mutability instead of interior mutability.
-    pub(crate) fn types_map(&self) -> std::cell::Ref<'_, TypesMap> {
-        std::cell::Ref::map(self.types_map.borrow(), |it| &*it.0)
+    pub(crate) fn alloc_error_type(&mut self) -> TypeRefId {
+        self.types_map.types.alloc(TypeRef::Error)
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
index dc6947c5b56..aa2c4a6f1bc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
@@ -121,7 +121,7 @@ pub enum GenericArg {
 impl Path {
     /// Converts an `ast::Path` to `Path`. Works with use trees.
     /// It correctly handles `$crate` based path from macro call.
-    pub fn from_src(ctx: &LowerCtx<'_>, path: ast::Path) -> Option<Path> {
+    pub fn from_src(ctx: &mut LowerCtx<'_>, path: ast::Path) -> Option<Path> {
         lower::lower_path(ctx, path)
     }
 
@@ -284,7 +284,7 @@ impl<'a> PathSegments<'a> {
 
 impl GenericArgs {
     pub(crate) fn from_ast(
-        lower_ctx: &LowerCtx<'_>,
+        lower_ctx: &mut LowerCtx<'_>,
         node: ast::GenericArgList,
     ) -> Option<GenericArgs> {
         lower::lower_generic_args(lower_ctx, node)
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
index c328b9c6ce2..553e615b94f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path/lower.rs
@@ -19,12 +19,11 @@ use crate::{
 
 /// Converts an `ast::Path` to `Path`. Works with use trees.
 /// It correctly handles `$crate` based path from macro call.
-pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path> {
+pub(super) fn lower_path(ctx: &mut LowerCtx<'_>, mut path: ast::Path) -> Option<Path> {
     let mut kind = PathKind::Plain;
     let mut type_anchor = None;
     let mut segments = Vec::new();
     let mut generic_args = Vec::new();
-    let span_map = ctx.span_map();
     loop {
         let segment = path.segment()?;
 
@@ -37,7 +36,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
                 if name_ref.text() == "$crate" {
                     break kind = resolve_crate_root(
                         ctx.db.upcast(),
-                        span_map.span_for_range(name_ref.syntax().text_range()).ctx,
+                        ctx.span_map().span_for_range(name_ref.syntax().text_range()).ctx,
                     )
                     .map(PathKind::DollarCrate)
                     .unwrap_or(PathKind::Crate);
@@ -151,7 +150,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
     // We follow what it did anyway :)
     if segments.len() == 1 && kind == PathKind::Plain {
         if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
-            let syn_ctxt = span_map.span_for_range(path.segment()?.syntax().text_range()).ctx;
+            let syn_ctxt = ctx.span_map().span_for_range(path.segment()?.syntax().text_range()).ctx;
             if let Some(macro_call_id) = ctx.db.lookup_intern_syntax_context(syn_ctxt).outer_expn {
                 if ctx.db.lookup_intern_macro_call(macro_call_id).def.local_inner {
                     kind = match resolve_crate_root(ctx.db.upcast(), syn_ctxt) {
@@ -183,7 +182,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
 }
 
 pub(super) fn lower_generic_args(
-    lower_ctx: &LowerCtx<'_>,
+    lower_ctx: &mut LowerCtx<'_>,
     node: ast::GenericArgList,
 ) -> Option<GenericArgs> {
     let mut args = Vec::new();
@@ -192,13 +191,7 @@ pub(super) fn lower_generic_args(
         match generic_arg {
             ast::GenericArg::TypeArg(type_arg) => {
                 let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.ty());
-                let types_map = lower_ctx.types_map();
-                TypeRef::walk(type_ref, &types_map, &mut |tr| {
-                    if let TypeRef::ImplTrait(bounds) = tr {
-                        lower_ctx.update_impl_traits_bounds(bounds.clone());
-                    }
-                });
-                drop(types_map);
+                lower_ctx.update_impl_traits_bounds_from_type_ref(type_ref);
                 args.push(GenericArg::Type(type_ref));
             }
             ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
@@ -208,27 +201,22 @@ pub(super) fn lower_generic_args(
                 }
                 if let Some(name_ref) = assoc_type_arg.name_ref() {
                     // Nested impl traits like `impl Foo<Assoc = impl Bar>` are allowed
-                    let _guard = lower_ctx.outer_impl_trait_scope(false);
-                    let name = name_ref.as_name();
-                    let args = assoc_type_arg
-                        .generic_arg_list()
-                        .and_then(|args| lower_generic_args(lower_ctx, args));
-                    let type_ref = assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
-                    let type_ref = type_ref.inspect(|&tr| {
-                        let types_map = lower_ctx.types_map();
-                        TypeRef::walk(tr, &types_map, &mut |tr| {
-                            if let TypeRef::ImplTrait(bounds) = tr {
-                                lower_ctx.update_impl_traits_bounds(bounds.clone());
-                            }
-                        });
-                        drop(types_map);
+                    lower_ctx.with_outer_impl_trait_scope(false, |lower_ctx| {
+                        let name = name_ref.as_name();
+                        let args = assoc_type_arg
+                            .generic_arg_list()
+                            .and_then(|args| lower_generic_args(lower_ctx, args));
+                        let type_ref =
+                            assoc_type_arg.ty().map(|it| TypeRef::from_ast(lower_ctx, it));
+                        let type_ref = type_ref
+                            .inspect(|&tr| lower_ctx.update_impl_traits_bounds_from_type_ref(tr));
+                        let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
+                            l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
+                        } else {
+                            Box::default()
+                        };
+                        bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds });
                     });
-                    let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
-                        l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
-                    } else {
-                        Box::default()
-                    };
-                    bindings.push(AssociatedTypeBinding { name, args, type_ref, bounds });
                 }
             }
             ast::GenericArg::LifetimeArg(lifetime_arg) => {
@@ -258,7 +246,7 @@ pub(super) fn lower_generic_args(
 /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
 /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
 fn lower_generic_args_from_fn_path(
-    ctx: &LowerCtx<'_>,
+    ctx: &mut LowerCtx<'_>,
     params: Option<ast::ParamList>,
     ret_type: Option<ast::RetType>,
 ) -> Option<GenericArgs> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 4bc78afacc0..05cd7bd37b4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -615,7 +615,7 @@ pub(crate) fn associated_ty_data_query(
     let type_alias_data = db.type_alias_data(type_alias);
     let generic_params = generics(db.upcast(), type_alias.into());
     let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
-    let ctx =
+    let mut ctx =
         crate::TyLoweringContext::new(db, &resolver, &type_alias_data.types_map, type_alias.into())
             .with_type_param_mode(crate::lower::ParamLoweringMode::Variable);
 
@@ -627,14 +627,16 @@ pub(crate) fn associated_ty_data_query(
         .build();
     let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner);
 
-    let mut bounds: Vec<_> = type_alias_data
-        .bounds
-        .iter()
-        .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false))
-        .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty))
-        .collect();
+    let mut bounds = Vec::new();
+    for bound in &type_alias_data.bounds {
+        ctx.lower_type_bound(bound, self_ty.clone(), false).for_each(|pred| {
+            if let Some(pred) = generic_predicate_to_inline_bound(db, &pred, &self_ty) {
+                bounds.push(pred);
+            }
+        });
+    }
 
-    if !ctx.unsized_types.borrow().contains(&self_ty) {
+    if !ctx.unsized_types.contains(&self_ty) {
         let sized_trait = db
             .lang_item(resolver.krate(), LangItem::Sized)
             .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
index 091cfcd4654..142766c039b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
@@ -8,7 +8,7 @@ use hir_def::{
     path::Path,
     resolver::{Resolver, ValueNs},
     type_ref::LiteralConstRef,
-    ConstBlockLoc, EnumVariantId, GeneralConstId, StaticId,
+    ConstBlockLoc, EnumVariantId, GeneralConstId, HasModule as _, StaticId,
 };
 use hir_expand::Lookup;
 use stdx::never;
@@ -56,6 +56,21 @@ pub enum ConstEvalError {
     MirEvalError(MirEvalError),
 }
 
+impl ConstEvalError {
+    pub fn pretty_print(
+        &self,
+        f: &mut String,
+        db: &dyn HirDatabase,
+        span_formatter: impl Fn(span::FileId, span::TextRange) -> String,
+        edition: span::Edition,
+    ) -> std::result::Result<(), std::fmt::Error> {
+        match self {
+            ConstEvalError::MirLowerError(e) => e.pretty_print(f, db, span_formatter, edition),
+            ConstEvalError::MirEvalError(e) => e.pretty_print(f, db, span_formatter, edition),
+        }
+    }
+}
+
 impl From<MirLowerError> for ConstEvalError {
     fn from(value: MirLowerError) -> Self {
         match value {
@@ -236,6 +251,10 @@ pub(crate) fn const_eval_query(
         GeneralConstId::ConstId(c) => {
             db.monomorphized_mir_body(c.into(), subst, db.trait_environment(c.into()))?
         }
+        GeneralConstId::StaticId(s) => {
+            let krate = s.module(db.upcast()).krate();
+            db.monomorphized_mir_body(s.into(), subst, TraitEnvironment::empty(krate))?
+        }
         GeneralConstId::ConstBlockId(c) => {
             let ConstBlockLoc { parent, root } = db.lookup_intern_anonymous_const(c);
             let body = db.body(parent);
@@ -249,7 +268,7 @@ pub(crate) fn const_eval_query(
         }
         GeneralConstId::InTypeConstId(c) => db.mir_body(c.into())?,
     };
-    let c = interpret_mir(db, body, false, trait_env).0?;
+    let c = interpret_mir(db, body, false, trait_env)?.0?;
     Ok(c)
 }
 
@@ -262,7 +281,7 @@ pub(crate) fn const_eval_static_query(
         Substitution::empty(Interner),
         db.trait_environment_for_body(def.into()),
     )?;
-    let c = interpret_mir(db, body, false, None).0?;
+    let c = interpret_mir(db, body, false, None)?.0?;
     Ok(c)
 }
 
@@ -294,7 +313,7 @@ pub(crate) fn const_eval_discriminant_variant(
         Substitution::empty(Interner),
         db.trait_environment_for_body(def),
     )?;
-    let c = interpret_mir(db, mir_body, false, None).0?;
+    let c = interpret_mir(db, mir_body, false, None)?.0?;
     let c = if is_signed {
         try_const_isize(db, &c).unwrap()
     } else {
@@ -335,7 +354,7 @@ pub(crate) fn eval_to_const(
         }
     }
     if let Ok(mir_body) = lower_to_mir(ctx.db, ctx.owner, ctx.body, &infer, expr) {
-        if let Ok(result) = interpret_mir(db, Arc::new(mir_body), true, None).0 {
+        if let Ok((Ok(result), _)) = interpret_mir(db, Arc::new(mir_body), true, None) {
             return result;
         }
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 277dabe9aa3..4e95bdf219f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -2033,7 +2033,7 @@ impl HirDisplayWithTypesMap for TypeRefId {
             TypeRef::Macro(macro_call) => {
                 let (mut types_map, mut types_source_map) =
                     (TypesMap::default(), TypesSourceMap::default());
-                let ctx = hir_def::lower::LowerCtx::new(
+                let mut ctx = hir_def::lower::LowerCtx::new(
                     f.db.upcast(),
                     macro_call.file_id,
                     &mut types_map,
@@ -2041,7 +2041,7 @@ impl HirDisplayWithTypesMap for TypeRefId {
                 );
                 let macro_call = macro_call.to_node(f.db.upcast());
                 match macro_call.path() {
-                    Some(path) => match Path::from_src(&ctx, path) {
+                    Some(path) => match Path::from_src(&mut ctx, path) {
                         Some(path) => path.hir_fmt(f, &types_map)?,
                         None => write!(f, "{{macro}}")?,
                     },
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 3685ed56964..01e0b635b22 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -1420,7 +1420,7 @@ impl<'a> InferenceContext<'a> {
             Some(path) => path,
             None => return (self.err_ty(), None),
         };
-        let ctx = crate::lower::TyLoweringContext::new(
+        let mut ctx = crate::lower::TyLoweringContext::new(
             self.db,
             &self.resolver,
             &self.body.types,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index 442daa9f9ee..7550d197a3b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -151,7 +151,7 @@ impl InferenceContext<'_> {
             let last = path.segments().last()?;
 
             // Don't use `self.make_ty()` here as we need `orig_ns`.
-            let ctx = crate::lower::TyLoweringContext::new(
+            let mut ctx = crate::lower::TyLoweringContext::new(
                 self.db,
                 &self.resolver,
                 &self.body.types,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index c5fa20bc8ac..0c1f63880cd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -6,8 +6,9 @@ use base_db::ra_salsa::Cycle;
 use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
 use hir_def::{
     layout::{
-        BackendRepr, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError, LayoutData,
-        Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout, WrappingRange,
+        BackendRepr, FieldsShape, Float, Integer, LayoutCalculator, LayoutCalculatorError,
+        LayoutData, Primitive, ReprOptions, Scalar, Size, StructKind, TargetDataLayout,
+        WrappingRange,
     },
     LocalFieldId, StructId,
 };
@@ -294,11 +295,12 @@ pub fn layout_of_ty_query(
                 .checked_mul(count, dl)
                 .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?;
 
-            let backend_repr = if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) {
-                BackendRepr::Uninhabited
-            } else {
-                BackendRepr::Memory { sized: true }
-            };
+            let backend_repr =
+                if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) {
+                    BackendRepr::Uninhabited
+                } else {
+                    BackendRepr::Memory { sized: true }
+                };
 
             let largest_niche = if count != 0 { element.largest_niche } else { None };
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index e3a92e52f61..b868ea95f85 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -6,8 +6,8 @@
 //!
 //! This usually involves resolving names, collecting generic arguments etc.
 use std::{
-    cell::{Cell, OnceCell, RefCell, RefMut},
-    iter,
+    cell::OnceCell,
+    iter, mem,
     ops::{self, Not as _},
 };
 
@@ -72,47 +72,32 @@ use crate::{
     TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
 };
 
-#[derive(Debug)]
-enum ImplTraitLoweringState {
+#[derive(Debug, Default)]
+struct ImplTraitLoweringState {
     /// When turning `impl Trait` into opaque types, we have to collect the
     /// bounds at the same time to get the IDs correct (without becoming too
-    /// complicated). I don't like using interior mutability (as for the
-    /// counter), but I've tried and failed to make the lifetimes work for
-    /// passing around a `&mut TyLoweringContext`. The core problem is that
-    /// we're grouping the mutable data (the counter and this field) together
-    /// with the immutable context (the references to the DB and resolver).
-    /// Splitting this up would be a possible fix.
-    Opaque(RefCell<Arena<ImplTrait>>),
-    Param(Cell<u16>),
-    Variable(Cell<u16>),
-    Disallowed,
+    /// complicated).
+    mode: ImplTraitLoweringMode,
+    // This is structured as a struct with fields and not as an enum because it helps with the borrow checker.
+    opaque_type_data: Arena<ImplTrait>,
+    param_and_variable_counter: u16,
 }
 impl ImplTraitLoweringState {
-    fn new(impl_trait_mode: ImplTraitLoweringMode) -> ImplTraitLoweringState {
-        match impl_trait_mode {
-            ImplTraitLoweringMode::Opaque => Self::Opaque(RefCell::new(Arena::new())),
-            ImplTraitLoweringMode::Param => Self::Param(Cell::new(0)),
-            ImplTraitLoweringMode::Variable => Self::Variable(Cell::new(0)),
-            ImplTraitLoweringMode::Disallowed => Self::Disallowed,
-        }
+    fn new(mode: ImplTraitLoweringMode) -> ImplTraitLoweringState {
+        Self { mode, opaque_type_data: Arena::new(), param_and_variable_counter: 0 }
     }
-
-    fn take(&self) -> Self {
-        match self {
-            Self::Opaque(x) => Self::Opaque(RefCell::new(x.take())),
-            Self::Param(x) => Self::Param(Cell::new(x.get())),
-            Self::Variable(x) => Self::Variable(Cell::new(x.get())),
-            Self::Disallowed => Self::Disallowed,
+    fn param(counter: u16) -> Self {
+        Self {
+            mode: ImplTraitLoweringMode::Param,
+            opaque_type_data: Arena::new(),
+            param_and_variable_counter: counter,
         }
     }
-
-    fn swap(&self, impl_trait_mode: &Self) {
-        match (self, impl_trait_mode) {
-            (Self::Opaque(x), Self::Opaque(y)) => x.swap(y),
-            (Self::Param(x), Self::Param(y)) => x.swap(y),
-            (Self::Variable(x), Self::Variable(y)) => x.swap(y),
-            (Self::Disallowed, Self::Disallowed) => (),
-            _ => panic!("mismatched lowering mode"),
+    fn variable(counter: u16) -> Self {
+        Self {
+            mode: ImplTraitLoweringMode::Variable,
+            opaque_type_data: Arena::new(),
+            param_and_variable_counter: counter,
         }
     }
 }
@@ -137,9 +122,9 @@ pub struct TyLoweringContext<'a> {
     /// possible currently, so this should be fine for now.
     pub type_param_mode: ParamLoweringMode,
     impl_trait_mode: ImplTraitLoweringState,
-    expander: RefCell<Option<Expander>>,
+    expander: Option<Expander>,
     /// Tracks types with explicit `?Sized` bounds.
-    pub(crate) unsized_types: RefCell<FxHashSet<Ty>>,
+    pub(crate) unsized_types: FxHashSet<Ty>,
 }
 
 impl<'a> TyLoweringContext<'a> {
@@ -159,7 +144,7 @@ impl<'a> TyLoweringContext<'a> {
         types_source_map: Option<&'a TypesSourceMap>,
         owner: Option<TypeOwnerId>,
     ) -> Self {
-        let impl_trait_mode = ImplTraitLoweringState::Disallowed;
+        let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
         let type_param_mode = ParamLoweringMode::Placeholder;
         let in_binders = DebruijnIndex::INNERMOST;
         Self {
@@ -172,38 +157,26 @@ impl<'a> TyLoweringContext<'a> {
             in_binders,
             impl_trait_mode,
             type_param_mode,
-            expander: RefCell::new(None),
-            unsized_types: RefCell::default(),
+            expander: None,
+            unsized_types: FxHashSet::default(),
         }
     }
 
     pub fn with_debruijn<T>(
-        &self,
+        &mut self,
         debruijn: DebruijnIndex,
-        f: impl FnOnce(&TyLoweringContext<'_>) -> T,
+        f: impl FnOnce(&mut TyLoweringContext<'_>) -> T,
     ) -> T {
-        let impl_trait_mode = self.impl_trait_mode.take();
-        let expander = self.expander.take();
-        let unsized_types = self.unsized_types.take();
-        let new_ctx = Self {
-            in_binders: debruijn,
-            impl_trait_mode,
-            expander: RefCell::new(expander),
-            unsized_types: RefCell::new(unsized_types),
-            generics: self.generics.clone(),
-            ..*self
-        };
-        let result = f(&new_ctx);
-        self.impl_trait_mode.swap(&new_ctx.impl_trait_mode);
-        self.expander.replace(new_ctx.expander.into_inner());
-        self.unsized_types.replace(new_ctx.unsized_types.into_inner());
+        let old_debruijn = mem::replace(&mut self.in_binders, debruijn);
+        let result = f(self);
+        self.in_binders = old_debruijn;
         result
     }
 
     pub fn with_shifted_in<T>(
-        &self,
+        &mut self,
         debruijn: DebruijnIndex,
-        f: impl FnOnce(&TyLoweringContext<'_>) -> T,
+        f: impl FnOnce(&mut TyLoweringContext<'_>) -> T,
     ) -> T {
         self.with_debruijn(self.in_binders.shifted_in_from(debruijn), f)
     }
@@ -227,7 +200,7 @@ impl<'a> TyLoweringContext<'a> {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
 pub enum ImplTraitLoweringMode {
     /// `impl Trait` gets lowered into an opaque type that doesn't unify with
     /// anything except itself. This is used in places where values flow 'out',
@@ -244,6 +217,7 @@ pub enum ImplTraitLoweringMode {
     /// currently checking.
     Variable,
     /// `impl Trait` is disallowed and will be an error.
+    #[default]
     Disallowed,
 }
 
@@ -254,12 +228,13 @@ pub enum ParamLoweringMode {
 }
 
 impl<'a> TyLoweringContext<'a> {
-    pub fn lower_ty(&self, type_ref: TypeRefId) -> Ty {
+    pub fn lower_ty(&mut self, type_ref: TypeRefId) -> Ty {
         self.lower_ty_ext(type_ref).0
     }
 
-    pub fn lower_const(&self, const_ref: &ConstRef, const_type: Ty) -> Const {
+    pub fn lower_const(&mut self, const_ref: &ConstRef, const_type: Ty) -> Const {
         let Some(owner) = self.owner else { return unknown_const(const_type) };
+        let debruijn = self.in_binders;
         const_or_path_to_chalk(
             self.db,
             self.resolver,
@@ -268,7 +243,7 @@ impl<'a> TyLoweringContext<'a> {
             const_ref,
             self.type_param_mode,
             || self.generics(),
-            self.in_binders,
+            debruijn,
         )
     }
 
@@ -278,7 +253,7 @@ impl<'a> TyLoweringContext<'a> {
             .as_ref()
     }
 
-    pub fn lower_ty_ext(&self, type_ref_id: TypeRefId) -> (Ty, Option<TypeNs>) {
+    pub fn lower_ty_ext(&mut self, type_ref_id: TypeRefId) -> (Ty, Option<TypeNs>) {
         let mut res = None;
         let type_ref = &self.types_map[type_ref_id];
         let ty = match type_ref {
@@ -337,8 +312,8 @@ impl<'a> TyLoweringContext<'a> {
             }
             TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
             TypeRef::ImplTrait(bounds) => {
-                match &self.impl_trait_mode {
-                    ImplTraitLoweringState::Opaque(opaque_type_data) => {
+                match self.impl_trait_mode.mode {
+                    ImplTraitLoweringMode::Opaque => {
                         let origin = match self.resolver.generic_def() {
                             Some(GenericDefId::FunctionId(it)) => Either::Left(it),
                             Some(GenericDefId::TypeAliasId(it)) => Either::Right(it),
@@ -350,7 +325,7 @@ impl<'a> TyLoweringContext<'a> {
                         // this dance is to make sure the data is in the right
                         // place even if we encounter more opaque types while
                         // lowering the bounds
-                        let idx = opaque_type_data.borrow_mut().alloc(ImplTrait {
+                        let idx = self.impl_trait_mode.opaque_type_data.alloc(ImplTrait {
                             bounds: crate::make_single_type_binders(Vec::default()),
                         });
                         // We don't want to lower the bounds inside the binders
@@ -366,7 +341,7 @@ impl<'a> TyLoweringContext<'a> {
                             .with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
                                 ctx.lower_impl_trait(bounds, self.resolver.krate())
                             });
-                        opaque_type_data.borrow_mut()[idx] = actual_opaque_type_data;
+                        self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
 
                         let impl_trait_id = origin.either(
                             |f| ImplTraitId::ReturnTypeImplTrait(f, idx),
@@ -378,11 +353,13 @@ impl<'a> TyLoweringContext<'a> {
                         let parameters = generics.bound_vars_subst(self.db, self.in_binders);
                         TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner)
                     }
-                    ImplTraitLoweringState::Param(counter) => {
-                        let idx = counter.get();
+                    ImplTraitLoweringMode::Param => {
+                        let idx = self.impl_trait_mode.param_and_variable_counter;
                         // Count the number of `impl Trait` things that appear within our bounds.
                         // Since those have been emitted as implicit type args already.
-                        counter.set(idx + self.count_impl_traits(type_ref_id) as u16);
+                        self.impl_trait_mode.param_and_variable_counter =
+                            idx + self.count_impl_traits(type_ref_id) as u16;
+                        let db = self.db;
                         let kind = self
                             .generics()
                             .expect("param impl trait lowering must be in a generic def")
@@ -398,15 +375,17 @@ impl<'a> TyLoweringContext<'a> {
                             })
                             .nth(idx as usize)
                             .map_or(TyKind::Error, |id| {
-                                TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
+                                TyKind::Placeholder(to_placeholder_idx(db, id.into()))
                             });
                         kind.intern(Interner)
                     }
-                    ImplTraitLoweringState::Variable(counter) => {
-                        let idx = counter.get();
+                    ImplTraitLoweringMode::Variable => {
+                        let idx = self.impl_trait_mode.param_and_variable_counter;
                         // Count the number of `impl Trait` things that appear within our bounds.
                         // Since t hose have been emitted as implicit type args already.
-                        counter.set(idx + self.count_impl_traits(type_ref_id) as u16);
+                        self.impl_trait_mode.param_and_variable_counter =
+                            idx + self.count_impl_traits(type_ref_id) as u16;
+                        let debruijn = self.in_binders;
                         let kind = self
                             .generics()
                             .expect("variable impl trait lowering must be in a generic def")
@@ -423,33 +402,31 @@ impl<'a> TyLoweringContext<'a> {
                             })
                             .nth(idx as usize)
                             .map_or(TyKind::Error, |id| {
-                                TyKind::BoundVar(BoundVar { debruijn: self.in_binders, index: id })
+                                TyKind::BoundVar(BoundVar { debruijn, index: id })
                             });
                         kind.intern(Interner)
                     }
-                    ImplTraitLoweringState::Disallowed => {
+                    ImplTraitLoweringMode::Disallowed => {
                         // FIXME: report error
                         TyKind::Error.intern(Interner)
                     }
                 }
             }
             TypeRef::Macro(macro_call) => {
-                let (mut expander, recursion_start) = {
-                    match RefMut::filter_map(self.expander.borrow_mut(), Option::as_mut) {
+                let (expander, recursion_start) = {
+                    match &mut self.expander {
                         // There already is an expander here, this means we are already recursing
-                        Ok(expander) => (expander, false),
+                        Some(expander) => (expander, false),
                         // No expander was created yet, so we are at the start of the expansion recursion
                         // and therefore have to create an expander.
-                        Err(expander) => (
-                            RefMut::map(expander, |it| {
-                                it.insert(Expander::new(
-                                    self.db.upcast(),
-                                    macro_call.file_id,
-                                    self.resolver.module(),
-                                ))
-                            }),
-                            true,
-                        ),
+                        None => {
+                            let expander = self.expander.insert(Expander::new(
+                                self.db.upcast(),
+                                macro_call.file_id,
+                                self.resolver.module(),
+                            ));
+                            (expander, true)
+                        }
                     }
                 };
                 let ty = {
@@ -465,19 +442,16 @@ impl<'a> TyLoweringContext<'a> {
                             let (mut types_map, mut types_source_map) =
                                 (TypesMap::default(), TypesSourceMap::default());
 
-                            let ctx = expander.ctx(
+                            let mut ctx = expander.ctx(
                                 self.db.upcast(),
                                 &mut types_map,
                                 &mut types_source_map,
                             );
                             // FIXME: Report syntax errors in expansion here
-                            let type_ref = TypeRef::from_ast(&ctx, expanded.tree());
+                            let type_ref = TypeRef::from_ast(&mut ctx, expanded.tree());
 
-                            drop(expander);
-
-                            // FIXME: That may be better served by mutating `self` then restoring, but this requires
-                            // making it `&mut self`.
-                            let inner_ctx = TyLoweringContext {
+                            // Can't mutate `self`, must create a new instance, because of the lifetimes.
+                            let mut inner_ctx = TyLoweringContext {
                                 db: self.db,
                                 resolver: self.resolver,
                                 generics: self.generics.clone(),
@@ -486,30 +460,27 @@ impl<'a> TyLoweringContext<'a> {
                                 in_binders: self.in_binders,
                                 owner: self.owner,
                                 type_param_mode: self.type_param_mode,
-                                impl_trait_mode: self.impl_trait_mode.take(),
-                                expander: RefCell::new(self.expander.take()),
-                                unsized_types: RefCell::new(self.unsized_types.take()),
+                                impl_trait_mode: mem::take(&mut self.impl_trait_mode),
+                                expander: self.expander.take(),
+                                unsized_types: mem::take(&mut self.unsized_types),
                             };
 
                             let ty = inner_ctx.lower_ty(type_ref);
 
-                            self.impl_trait_mode.swap(&inner_ctx.impl_trait_mode);
-                            *self.expander.borrow_mut() = inner_ctx.expander.into_inner();
-                            *self.unsized_types.borrow_mut() = inner_ctx.unsized_types.into_inner();
+                            self.impl_trait_mode = inner_ctx.impl_trait_mode;
+                            self.expander = inner_ctx.expander;
+                            self.unsized_types = inner_ctx.unsized_types;
 
-                            self.expander.borrow_mut().as_mut().unwrap().exit(mark);
+                            self.expander.as_mut().unwrap().exit(mark);
                             Some(ty)
                         }
-                        _ => {
-                            drop(expander);
-                            None
-                        }
+                        _ => None,
                     }
                 };
 
                 // drop the expander, resetting it to pre-recursion state
                 if recursion_start {
-                    *self.expander.borrow_mut() = None;
+                    self.expander = None;
                 }
                 ty.unwrap_or_else(|| TyKind::Error.intern(Interner))
             }
@@ -544,7 +515,7 @@ impl<'a> TyLoweringContext<'a> {
     }
 
     pub(crate) fn lower_ty_relative_path(
-        &self,
+        &mut self,
         ty: Ty,
         // We need the original resolution to lower `Self::AssocTy` correctly
         res: Option<TypeNs>,
@@ -565,7 +536,7 @@ impl<'a> TyLoweringContext<'a> {
     }
 
     pub(crate) fn lower_partly_resolved_path(
-        &self,
+        &mut self,
         resolution: TypeNs,
         resolved_segment: PathSegment<'_>,
         remaining_segments: PathSegments<'_>,
@@ -706,7 +677,7 @@ impl<'a> TyLoweringContext<'a> {
         self.lower_ty_relative_path(ty, Some(resolution), remaining_segments)
     }
 
-    pub(crate) fn lower_path(&self, path: &Path) -> (Ty, Option<TypeNs>) {
+    pub(crate) fn lower_path(&mut self, path: &Path) -> (Ty, Option<TypeNs>) {
         // Resolve the path (in type namespace)
         if let Some(type_ref) = path.type_anchor() {
             let (ty, res) = self.lower_ty_ext(type_ref);
@@ -736,7 +707,7 @@ impl<'a> TyLoweringContext<'a> {
         self.lower_partly_resolved_path(resolution, resolved_segment, remaining_segments, false)
     }
 
-    fn select_associated_type(&self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty {
+    fn select_associated_type(&mut self, res: Option<TypeNs>, segment: PathSegment<'_>) -> Ty {
         let Some((generics, res)) = self.generics().zip(res) else {
             return TyKind::Error.intern(Interner);
         };
@@ -746,6 +717,8 @@ impl<'a> TyLoweringContext<'a> {
             res,
             Some(segment.name.clone()),
             move |name, t, associated_ty| {
+                let generics = self.generics().unwrap();
+
                 if name != segment.name {
                     return None;
                 }
@@ -797,7 +770,7 @@ impl<'a> TyLoweringContext<'a> {
     }
 
     fn lower_path_inner(
-        &self,
+        &mut self,
         segment: PathSegment<'_>,
         typeable: TyDefId,
         infer_args: bool,
@@ -814,7 +787,7 @@ impl<'a> TyLoweringContext<'a> {
     /// Collect generic arguments from a path into a `Substs`. See also
     /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
     pub(super) fn substs_from_path(
-        &self,
+        &mut self,
         path: &Path,
         // Note that we don't call `db.value_type(resolved)` here,
         // `ValueTyDefId` is just a convenient way to pass generics and
@@ -855,7 +828,7 @@ impl<'a> TyLoweringContext<'a> {
     }
 
     pub(super) fn substs_from_path_segment(
-        &self,
+        &mut self,
         segment: PathSegment<'_>,
         def: Option<GenericDefId>,
         infer_args: bool,
@@ -870,7 +843,7 @@ impl<'a> TyLoweringContext<'a> {
     }
 
     fn substs_from_args_and_bindings(
-        &self,
+        &mut self,
         args_and_bindings: Option<&GenericArgs>,
         def: Option<GenericDefId>,
         infer_args: bool,
@@ -959,11 +932,11 @@ impl<'a> TyLoweringContext<'a> {
                     self.db,
                     id,
                     arg,
-                    &mut (),
+                    self,
                     self.types_map,
-                    |_, type_ref| self.lower_ty(type_ref),
-                    |_, const_ref, ty| self.lower_const(const_ref, ty),
-                    |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
+                    |this, type_ref| this.lower_ty(type_ref),
+                    |this, const_ref, ty| this.lower_const(const_ref, ty),
+                    |this, lifetime_ref| this.lower_lifetime(lifetime_ref),
                 );
                 substs.push(arg);
             }
@@ -1016,7 +989,7 @@ impl<'a> TyLoweringContext<'a> {
     }
 
     pub(crate) fn lower_trait_ref_from_resolved_path(
-        &self,
+        &mut self,
         resolved: TraitId,
         segment: PathSegment<'_>,
         explicit_self_ty: Ty,
@@ -1025,7 +998,7 @@ impl<'a> TyLoweringContext<'a> {
         TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs }
     }
 
-    fn lower_trait_ref_from_path(&self, path: &Path, explicit_self_ty: Ty) -> Option<TraitRef> {
+    fn lower_trait_ref_from_path(&mut self, path: &Path, explicit_self_ty: Ty) -> Option<TraitRef> {
         let resolved = match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path)? {
             // FIXME(trait_alias): We need to handle trait alias here.
             TypeNs::TraitId(tr) => tr,
@@ -1035,12 +1008,16 @@ impl<'a> TyLoweringContext<'a> {
         Some(self.lower_trait_ref_from_resolved_path(resolved, segment, explicit_self_ty))
     }
 
-    fn lower_trait_ref(&self, trait_ref: &HirTraitRef, explicit_self_ty: Ty) -> Option<TraitRef> {
+    fn lower_trait_ref(
+        &mut self,
+        trait_ref: &HirTraitRef,
+        explicit_self_ty: Ty,
+    ) -> Option<TraitRef> {
         self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty)
     }
 
     fn trait_ref_substs_from_path(
-        &self,
+        &mut self,
         segment: PathSegment<'_>,
         resolved: TraitId,
         explicit_self_ty: Ty,
@@ -1049,11 +1026,11 @@ impl<'a> TyLoweringContext<'a> {
     }
 
     pub(crate) fn lower_where_predicate<'b>(
-        &'b self,
+        &'b mut self,
         where_predicate: &'b WherePredicate,
         &def: &GenericDefId,
         ignore_bindings: bool,
-    ) -> impl Iterator<Item = QuantifiedWhereClause> + 'b {
+    ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b> {
         match where_predicate {
             WherePredicate::ForLifetime { target, bound, .. }
             | WherePredicate::TypeBound { target, bound } => {
@@ -1087,12 +1064,12 @@ impl<'a> TyLoweringContext<'a> {
         .into_iter()
     }
 
-    pub(crate) fn lower_type_bound(
-        &'a self,
-        bound: &'a TypeBound,
+    pub(crate) fn lower_type_bound<'b>(
+        &'b mut self,
+        bound: &'b TypeBound,
         self_ty: Ty,
         ignore_bindings: bool,
-    ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
+    ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
         let mut trait_ref = None;
         let clause = match bound {
             TypeBound::Path(path, TraitBoundModifier::None) => {
@@ -1111,7 +1088,7 @@ impl<'a> TyLoweringContext<'a> {
                     .lower_trait_ref_from_path(path, self_ty.clone())
                     .map(|trait_ref| trait_ref.hir_trait_id());
                 if trait_id == sized_trait {
-                    self.unsized_types.borrow_mut().insert(self_ty);
+                    self.unsized_types.insert(self_ty);
                 }
                 None
             }
@@ -1131,17 +1108,18 @@ impl<'a> TyLoweringContext<'a> {
         };
         clause.into_iter().chain(
             trait_ref
-                .into_iter()
                 .filter(move |_| !ignore_bindings)
-                .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)),
+                .map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr))
+                .into_iter()
+                .flatten(),
         )
     }
 
-    fn assoc_type_bindings_from_type_bound(
-        &'a self,
-        bound: &'a TypeBound,
+    fn assoc_type_bindings_from_type_bound<'b>(
+        &'b mut self,
+        bound: &'b TypeBound,
         trait_ref: TraitRef,
-    ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
+    ) -> impl Iterator<Item = QuantifiedWhereClause> + use<'b, 'a> {
         let last_segment = match bound {
             TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => {
                 path.segments().last()
@@ -1192,22 +1170,16 @@ impl<'a> TyLoweringContext<'a> {
                     binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
                 );
                 if let Some(type_ref) = binding.type_ref {
-                    match (&self.types_map[type_ref], &self.impl_trait_mode) {
-                        (TypeRef::ImplTrait(_), ImplTraitLoweringState::Disallowed) => (),
-                        (
-                            _,
-                            ImplTraitLoweringState::Disallowed | ImplTraitLoweringState::Opaque(_),
-                        ) => {
+                    match (&self.types_map[type_ref], self.impl_trait_mode.mode) {
+                        (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (),
+                        (_, ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque) => {
                             let ty = self.lower_ty(type_ref);
                             let alias_eq =
                                 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
                             predicates
                                 .push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
                         }
-                        (
-                            _,
-                            ImplTraitLoweringState::Param(_) | ImplTraitLoweringState::Variable(_),
-                        ) => {
+                        (_, ImplTraitLoweringMode::Param | ImplTraitLoweringMode::Variable) => {
                             // Find the generic index for the target of our `bound`
                             let target_param_idx = self
                                 .resolver
@@ -1244,14 +1216,14 @@ impl<'a> TyLoweringContext<'a> {
                                     self.owner,
                                 )
                                 .with_type_param_mode(self.type_param_mode);
-                                match &self.impl_trait_mode {
-                                    ImplTraitLoweringState::Param(_) => {
+                                match self.impl_trait_mode.mode {
+                                    ImplTraitLoweringMode::Param => {
                                         ext.impl_trait_mode =
-                                            ImplTraitLoweringState::Param(Cell::new(counter));
+                                            ImplTraitLoweringState::param(counter);
                                     }
-                                    ImplTraitLoweringState::Variable(_) => {
+                                    ImplTraitLoweringMode::Variable => {
                                         ext.impl_trait_mode =
-                                            ImplTraitLoweringState::Variable(Cell::new(counter));
+                                            ImplTraitLoweringState::variable(counter);
                                     }
                                     _ => unreachable!(),
                                 }
@@ -1278,7 +1250,7 @@ impl<'a> TyLoweringContext<'a> {
             })
     }
 
-    fn lower_dyn_trait(&self, bounds: &[TypeBound]) -> Ty {
+    fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty {
         let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
         // INVARIANT: The principal trait bound, if present, must come first. Others may be in any
         // order but should be in the same order for the same set but possibly different order of
@@ -1287,22 +1259,26 @@ impl<'a> TyLoweringContext<'a> {
         // These invariants are utilized by `TyExt::dyn_trait()` and chalk.
         let mut lifetime = None;
         let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
-            let mut bounds: Vec<_> = bounds
-                .iter()
-                .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false))
-                .filter(|b| match b.skip_binders() {
-                    WhereClause::Implemented(_) | WhereClause::AliasEq(_) => true,
-                    WhereClause::LifetimeOutlives(_) => false,
-                    WhereClause::TypeOutlives(t) => {
-                        lifetime = Some(t.lifetime.clone());
-                        false
+            let mut lowered_bounds = Vec::new();
+            for b in bounds {
+                ctx.lower_type_bound(b, self_ty.clone(), false).for_each(|b| {
+                    let filter = match b.skip_binders() {
+                        WhereClause::Implemented(_) | WhereClause::AliasEq(_) => true,
+                        WhereClause::LifetimeOutlives(_) => false,
+                        WhereClause::TypeOutlives(t) => {
+                            lifetime = Some(t.lifetime.clone());
+                            false
+                        }
+                    };
+                    if filter {
+                        lowered_bounds.push(b);
                     }
-                })
-                .collect();
+                });
+            }
 
             let mut multiple_regular_traits = false;
             let mut multiple_same_projection = false;
-            bounds.sort_unstable_by(|lhs, rhs| {
+            lowered_bounds.sort_unstable_by(|lhs, rhs| {
                 use std::cmp::Ordering;
                 match (lhs.skip_binders(), rhs.skip_binders()) {
                     (WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => {
@@ -1344,13 +1320,13 @@ impl<'a> TyLoweringContext<'a> {
                 return None;
             }
 
-            bounds.first().and_then(|b| b.trait_id())?;
+            lowered_bounds.first().and_then(|b| b.trait_id())?;
 
             // As multiple occurrences of the same auto traits *are* permitted, we deduplicate the
             // bounds. We shouldn't have repeated elements besides auto traits at this point.
-            bounds.dedup();
+            lowered_bounds.dedup();
 
-            Some(QuantifiedWhereClauses::from_iter(Interner, bounds))
+            Some(QuantifiedWhereClauses::from_iter(Interner, lowered_bounds))
         });
 
         if let Some(bounds) = bounds {
@@ -1376,16 +1352,16 @@ impl<'a> TyLoweringContext<'a> {
         }
     }
 
-    fn lower_impl_trait(&self, bounds: &[TypeBound], krate: CrateId) -> ImplTrait {
+    fn lower_impl_trait(&mut self, bounds: &[TypeBound], krate: CrateId) -> ImplTrait {
         cov_mark::hit!(lower_rpit);
         let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
         let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
-            let mut predicates: Vec<_> = bounds
-                .iter()
-                .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false))
-                .collect();
+            let mut predicates = Vec::new();
+            for b in bounds {
+                predicates.extend(ctx.lower_type_bound(b, self_ty.clone(), false));
+            }
 
-            if !ctx.unsized_types.borrow().contains(&self_ty) {
+            if !ctx.unsized_types.contains(&self_ty) {
                 let sized_trait = ctx
                     .db
                     .lang_item(krate, LangItem::Sized)
@@ -1562,7 +1538,7 @@ pub(crate) fn field_types_query(
     };
     let generics = generics(db.upcast(), def);
     let mut res = ArenaMap::default();
-    let ctx = TyLoweringContext::new(db, &resolver, var_data.types_map(), def.into())
+    let mut ctx = TyLoweringContext::new(db, &resolver, var_data.types_map(), def.into())
         .with_type_param_mode(ParamLoweringMode::Variable);
     for (field_id, field_data) in var_data.fields().iter() {
         res.insert(field_id, make_binders(db, &generics, ctx.lower_ty(field_data.type_ref)));
@@ -1596,7 +1572,7 @@ pub(crate) fn generic_predicates_for_param_query(
     let generics = generics(db.upcast(), def);
 
     // we have to filter out all other predicates *first*, before attempting to lower them
-    let predicate = |pred: &_, def: &_, ctx: &TyLoweringContext<'_>| match pred {
+    let predicate = |pred: &_, def: &_, ctx: &mut TyLoweringContext<'_>| match pred {
         WherePredicate::ForLifetime { target, bound, .. }
         | WherePredicate::TypeBound { target, bound, .. } => {
             let invalid_target = match target {
@@ -1642,16 +1618,19 @@ pub(crate) fn generic_predicates_for_param_query(
     let mut predicates = Vec::new();
     for (params, def) in resolver.all_generic_params() {
         ctx.types_map = &params.types_map;
-        predicates.extend(
-            params.where_predicates().filter(|pred| predicate(pred, def, &ctx)).flat_map(|pred| {
-                ctx.lower_where_predicate(pred, def, true).map(|p| make_binders(db, &generics, p))
-            }),
-        );
+        for pred in params.where_predicates() {
+            if predicate(pred, def, &mut ctx) {
+                predicates.extend(
+                    ctx.lower_where_predicate(pred, def, true)
+                        .map(|p| make_binders(db, &generics, p)),
+                );
+            }
+        }
     }
 
     let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
     if !subst.is_empty(Interner) {
-        let explicitly_unsized_tys = ctx.unsized_types.into_inner();
+        let explicitly_unsized_tys = ctx.unsized_types;
         if let Some(implicitly_sized_predicates) = implicitly_sized_clauses(
             db,
             param_id.parent,
@@ -1731,7 +1710,7 @@ pub(crate) fn trait_environment_query(
 
     let subst = generics(db.upcast(), def).placeholder_subst(db);
     if !subst.is_empty(Interner) {
-        let explicitly_unsized_tys = ctx.unsized_types.into_inner();
+        let explicitly_unsized_tys = ctx.unsized_types;
         if let Some(implicitly_sized_clauses) =
             implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
         {
@@ -1801,16 +1780,19 @@ where
     let mut predicates = Vec::new();
     for (params, def) in resolver.all_generic_params() {
         ctx.types_map = &params.types_map;
-        predicates.extend(params.where_predicates().filter(|pred| filter(pred, def)).flat_map(
-            |pred| {
-                ctx.lower_where_predicate(pred, def, false).map(|p| make_binders(db, &generics, p))
-            },
-        ));
+        for pred in params.where_predicates() {
+            if filter(pred, def) {
+                predicates.extend(
+                    ctx.lower_where_predicate(pred, def, false)
+                        .map(|p| make_binders(db, &generics, p)),
+                );
+            }
+        }
     }
 
     if generics.len() > 0 {
         let subst = generics.bound_vars_subst(db, DebruijnIndex::INNERMOST);
-        let explicitly_unsized_tys = ctx.unsized_types.into_inner();
+        let explicitly_unsized_tys = ctx.unsized_types;
         if let Some(implicitly_sized_predicates) =
             implicitly_sized_clauses(db, def, &explicitly_unsized_tys, &subst, &resolver)
         {
@@ -1906,7 +1888,8 @@ pub(crate) fn generic_defaults_query(db: &dyn HirDatabase, def: GenericDefId) ->
                     let mut val = p.default.as_ref().map_or_else(
                         || unknown_const_as_generic(db.const_param_ty(id)),
                         |c| {
-                            let c = ctx.lower_const(c, ctx.lower_ty(p.ty));
+                            let param_ty = ctx.lower_ty(p.ty);
+                            let c = ctx.lower_const(c, param_ty);
                             c.cast(Interner)
                         },
                     );
@@ -1946,11 +1929,11 @@ pub(crate) fn generic_defaults_recover(
 fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
     let data = db.function_data(def);
     let resolver = def.resolver(db.upcast());
-    let ctx_params = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
+    let mut ctx_params = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
         .with_impl_trait_mode(ImplTraitLoweringMode::Variable)
         .with_type_param_mode(ParamLoweringMode::Variable);
     let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
-    let ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
+    let mut ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
         .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
         .with_type_param_mode(ParamLoweringMode::Variable);
     let ret = ctx_ret.lower_ty(data.ret_type);
@@ -1982,7 +1965,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> {
     let data = db.const_data(def);
     let generics = generics(db.upcast(), def.into());
     let resolver = def.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
+    let mut ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
         .with_type_param_mode(ParamLoweringMode::Variable);
 
     make_binders(db, &generics, ctx.lower_ty(data.type_ref))
@@ -1992,7 +1975,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> {
 fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders<Ty> {
     let data = db.static_data(def);
     let resolver = def.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into());
+    let mut ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into());
 
     Binders::empty(Interner, ctx.lower_ty(data.type_ref))
 }
@@ -2001,7 +1984,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
     let struct_data = db.struct_data(def);
     let fields = struct_data.variant_data.fields();
     let resolver = def.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(
+    let mut ctx = TyLoweringContext::new(
         db,
         &resolver,
         struct_data.variant_data.types_map(),
@@ -2038,7 +2021,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
     let var_data = db.enum_variant_data(def);
     let fields = var_data.variant_data.fields();
     let resolver = def.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(
+    let mut ctx = TyLoweringContext::new(
         db,
         &resolver,
         var_data.variant_data.types_map(),
@@ -2087,7 +2070,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
     let generics = generics(db.upcast(), t.into());
     let resolver = t.resolver(db.upcast());
     let type_alias_data = db.type_alias_data(t);
-    let ctx = TyLoweringContext::new(db, &resolver, &type_alias_data.types_map, t.into())
+    let mut ctx = TyLoweringContext::new(db, &resolver, &type_alias_data.types_map, t.into())
         .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
         .with_type_param_mode(ParamLoweringMode::Variable);
     let inner = if type_alias_data.is_extern {
@@ -2169,7 +2152,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
     let impl_data = db.impl_data(impl_id);
     let resolver = impl_id.resolver(db.upcast());
     let generics = generics(db.upcast(), impl_id.into());
-    let ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into())
+    let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into())
         .with_type_param_mode(ParamLoweringMode::Variable);
     make_binders(db, &generics, ctx.lower_ty(impl_data.self_ty))
 }
@@ -2179,7 +2162,8 @@ pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> T
     let parent_data = db.generic_params(def.parent());
     let data = &parent_data[def.local_id()];
     let resolver = def.parent().resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver, &parent_data.types_map, def.parent().into());
+    let mut ctx =
+        TyLoweringContext::new(db, &resolver, &parent_data.types_map, def.parent().into());
     match data {
         TypeOrConstParamData::TypeParamData(_) => {
             never!();
@@ -2201,7 +2185,7 @@ pub(crate) fn impl_self_ty_recover(
 pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
     let impl_data = db.impl_data(impl_id);
     let resolver = impl_id.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into())
+    let mut ctx = TyLoweringContext::new(db, &resolver, &impl_data.types_map, impl_id.into())
         .with_type_param_mode(ParamLoweringMode::Variable);
     let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();
     let target_trait = impl_data.target_trait.as_ref()?;
@@ -2215,17 +2199,13 @@ pub(crate) fn return_type_impl_traits(
     // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
     let data = db.function_data(def);
     let resolver = def.resolver(db.upcast());
-    let ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
+    let mut ctx_ret = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
         .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
         .with_type_param_mode(ParamLoweringMode::Variable);
     let _ret = ctx_ret.lower_ty(data.ret_type);
     let generics = generics(db.upcast(), def.into());
-    let return_type_impl_traits = ImplTraits {
-        impl_traits: match ctx_ret.impl_trait_mode {
-            ImplTraitLoweringState::Opaque(x) => x.into_inner(),
-            _ => unreachable!(),
-        },
-    };
+    let return_type_impl_traits =
+        ImplTraits { impl_traits: ctx_ret.impl_trait_mode.opaque_type_data };
     if return_type_impl_traits.impl_traits.is_empty() {
         None
     } else {
@@ -2239,18 +2219,13 @@ pub(crate) fn type_alias_impl_traits(
 ) -> Option<Arc<Binders<ImplTraits>>> {
     let data = db.type_alias_data(def);
     let resolver = def.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
+    let mut ctx = TyLoweringContext::new(db, &resolver, &data.types_map, def.into())
         .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
         .with_type_param_mode(ParamLoweringMode::Variable);
     if let Some(type_ref) = data.type_ref {
         let _ty = ctx.lower_ty(type_ref);
     }
-    let type_alias_impl_traits = ImplTraits {
-        impl_traits: match ctx.impl_trait_mode {
-            ImplTraitLoweringState::Opaque(x) => x.into_inner(),
-            _ => unreachable!(),
-        },
-    };
+    let type_alias_impl_traits = ImplTraits { impl_traits: ctx.impl_trait_mode.opaque_type_data };
     if type_alias_impl_traits.impl_traits.is_empty() {
         None
     } else {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index e73b9dc27d1..d7029651fc1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -12,8 +12,8 @@ use hir_def::{
     lang_item::LangItem,
     layout::{TagEncoding, Variants},
     resolver::{HasResolver, TypeNs, ValueNs},
-    AdtId, ConstId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup,
-    StaticId, VariantId,
+    AdtId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup, StaticId,
+    VariantId,
 };
 use hir_expand::{mod_path::path, name::Name, HirFileIdExt, InFile};
 use intern::sym;
@@ -40,8 +40,8 @@ use crate::{
     static_lifetime,
     traits::FnTrait,
     utils::{detect_variant_from_bytes, ClosureSubst},
-    CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstScalar, FnDefId, Interner, MemoryMap,
-    Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind,
+    CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstData, ConstScalar, FnDefId, Interner,
+    MemoryMap, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind,
 };
 
 use super::{
@@ -585,13 +585,9 @@ pub fn interpret_mir(
     // (and probably should) do better here, for example by excluding bindings outside of the target expression.
     assert_placeholder_ty_is_unused: bool,
     trait_env: Option<Arc<TraitEnvironment>>,
-) -> (Result<Const>, MirOutput) {
+) -> Result<(Result<Const>, MirOutput)> {
     let ty = body.locals[return_slot()].ty.clone();
-    let mut evaluator =
-        match Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env) {
-            Ok(it) => it,
-            Err(e) => return (Err(e), MirOutput { stdout: vec![], stderr: vec![] }),
-        };
+    let mut evaluator = Evaluator::new(db, body.owner, assert_placeholder_ty_is_unused, trait_env)?;
     let it: Result<Const> = (|| {
         if evaluator.ptr_size() != std::mem::size_of::<usize>() {
             not_supported!("targets with different pointer size from host");
@@ -613,7 +609,7 @@ pub fn interpret_mir(
         };
         Ok(intern_const_scalar(ConstScalar::Bytes(bytes, memory_map), ty))
     })();
-    (it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr })
+    Ok((it, MirOutput { stdout: evaluator.stdout, stderr: evaluator.stderr }))
 }
 
 #[cfg(test)]
@@ -1899,8 +1895,8 @@ impl Evaluator<'_> {
 
     #[allow(clippy::double_parens)]
     fn allocate_const_in_heap(&mut self, locals: &Locals, konst: &Const) -> Result<Interval> {
-        let ty = &konst.data(Interner).ty;
-        let chalk_ir::ConstValue::Concrete(c) = &konst.data(Interner).value else {
+        let ConstData { ty, value: chalk_ir::ConstValue::Concrete(c) } = &konst.data(Interner)
+        else {
             not_supported!("evaluating non concrete constant");
         };
         let result_owner;
@@ -2908,14 +2904,14 @@ impl Evaluator<'_> {
 
 pub fn render_const_using_debug_impl(
     db: &dyn HirDatabase,
-    owner: ConstId,
+    owner: DefWithBodyId,
     c: &Const,
 ) -> Result<String> {
-    let mut evaluator = Evaluator::new(db, owner.into(), false, None)?;
+    let mut evaluator = Evaluator::new(db, owner, false, None)?;
     let locals = &Locals {
         ptr: ArenaMap::new(),
         body: db
-            .mir_body(owner.into())
+            .mir_body(owner)
             .map_err(|_| MirEvalError::NotSupported("unreachable".to_owned()))?,
         drop_flags: DropFlags::default(),
     };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
index 595a78da10f..30d11373732 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
@@ -32,7 +32,7 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String),
         )
         .map_err(|e| MirEvalError::MirLowerError(func_id, e))?;
 
-    let (result, output) = interpret_mir(db, body, false, None);
+    let (result, output) = interpret_mir(db, body, false, None)?;
     result?;
     Ok((output.stdout().into_owned(), output.stderr().into_owned()))
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 88eb3b127e0..ebd84fd2be2 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -34,7 +34,10 @@ pub mod term_search;
 
 mod display;
 
-use std::{mem::discriminant, ops::ControlFlow};
+use std::{
+    mem::discriminant,
+    ops::{ControlFlow, Not},
+};
 
 use arrayvec::ArrayVec;
 use base_db::{CrateDisplayName, CrateId, CrateOrigin};
@@ -2303,22 +2306,15 @@ impl Function {
         self,
         db: &dyn HirDatabase,
         span_formatter: impl Fn(FileId, TextRange) -> String,
-    ) -> String {
+    ) -> Result<String, ConstEvalError> {
         let krate = HasModule::krate(&self.id, db.upcast());
         let edition = db.crate_graph()[krate].edition;
-        let body = match db.monomorphized_mir_body(
+        let body = db.monomorphized_mir_body(
             self.id.into(),
             Substitution::empty(Interner),
             db.trait_environment(self.id.into()),
-        ) {
-            Ok(body) => body,
-            Err(e) => {
-                let mut r = String::new();
-                _ = e.pretty_print(&mut r, db, &span_formatter, edition);
-                return r;
-            }
-        };
-        let (result, output) = interpret_mir(db, body, false, None);
+        )?;
+        let (result, output) = interpret_mir(db, body, false, None)?;
         let mut text = match result {
             Ok(_) => "pass".to_owned(),
             Err(e) => {
@@ -2337,7 +2333,7 @@ impl Function {
             text += "\n--------- stderr ---------\n";
             text += &stderr;
         }
-        text
+        Ok(text)
     }
 }
 
@@ -2560,9 +2556,9 @@ impl Const {
     /// Evaluate the constant and return the result as a string.
     ///
     /// This function is intended for IDE assistance, different from [`Const::render_eval`].
-    pub fn eval(self, db: &dyn HirDatabase, edition: Edition) -> Result<String, ConstEvalError> {
+    pub fn eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
         let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?;
-        Ok(format!("{}", c.display(db, edition)))
+        Ok(format!("{}", c.display(db, self.krate(db).edition(db))))
     }
 
     /// Evaluate the constant and return the result as a string, with more detailed information.
@@ -2597,7 +2593,7 @@ impl Const {
                 }
             }
         }
-        if let Ok(s) = mir::render_const_using_debug_impl(db, self.id, &c) {
+        if let Ok(s) = mir::render_const_using_debug_impl(db, self.id.into(), &c) {
             Ok(s)
         } else {
             Ok(format!("{}", c.display(db, edition)))
@@ -2636,6 +2632,53 @@ impl Static {
     pub fn ty(self, db: &dyn HirDatabase) -> Type {
         Type::from_value_def(db, self.id)
     }
+
+    /// Evaluate the static and return the result as a string.
+    ///
+    /// This function is intended for IDE assistance, different from [`Static::render_eval`].
+    pub fn eval(self, db: &dyn HirDatabase) -> Result<String, ConstEvalError> {
+        let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?;
+        Ok(format!("{}", c.display(db, self.krate(db).edition(db))))
+    }
+
+    /// Evaluate the static and return the result as a string, with more detailed information.
+    ///
+    /// This function is intended for user-facing display.
+    pub fn render_eval(
+        self,
+        db: &dyn HirDatabase,
+        edition: Edition,
+    ) -> Result<String, ConstEvalError> {
+        let c = db.const_eval(self.id.into(), Substitution::empty(Interner), None)?;
+        let data = &c.data(Interner);
+        if let TyKind::Scalar(s) = data.ty.kind(Interner) {
+            if matches!(s, Scalar::Int(_) | Scalar::Uint(_)) {
+                if let hir_ty::ConstValue::Concrete(c) = &data.value {
+                    if let hir_ty::ConstScalar::Bytes(b, _) = &c.interned {
+                        let value = u128::from_le_bytes(mir::pad16(b, false));
+                        let value_signed =
+                            i128::from_le_bytes(mir::pad16(b, matches!(s, Scalar::Int(_))));
+                        let mut result = if let Scalar::Int(_) = s {
+                            value_signed.to_string()
+                        } else {
+                            value.to_string()
+                        };
+                        if value >= 10 {
+                            format_to!(result, " ({value:#X})");
+                            return Ok(result);
+                        } else {
+                            return Ok(result);
+                        }
+                    }
+                }
+            }
+        }
+        if let Ok(s) = mir::render_const_using_debug_impl(db, self.id.into(), &c) {
+            Ok(s)
+        } else {
+            Ok(format!("{}", c.display(db, edition)))
+        }
+    }
 }
 
 impl HasVisibility for Static {
@@ -2697,6 +2740,18 @@ impl Trait {
         hir_ty::dyn_compatibility::dyn_compatibility(db, self.id)
     }
 
+    pub fn dyn_compatibility_all_violations(
+        &self,
+        db: &dyn HirDatabase,
+    ) -> Option<Vec<DynCompatibilityViolation>> {
+        let mut violations = vec![];
+        hir_ty::dyn_compatibility::dyn_compatibility_with_callback(db, self.id, &mut |violation| {
+            violations.push(violation);
+            ControlFlow::Continue(())
+        });
+        violations.is_empty().not().then_some(violations)
+    }
+
     fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
         db.trait_data(self.id)
             .macro_calls
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index feb9a344d8a..9d3f8e5fba4 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -1,5 +1,6 @@
 //! See `Semantics`.
 
+mod child_by_source;
 mod source_to_def;
 
 use std::{
@@ -1271,9 +1272,9 @@ impl<'db> SemanticsImpl<'db> {
         let analyze = self.analyze(ty.syntax())?;
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let ctx =
+        let mut ctx =
             LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map);
-        let type_ref = crate::TypeRef::from_ast(&ctx, ty.clone());
+        let type_ref = crate::TypeRef::from_ast(&mut ctx, ty.clone());
         let ty = hir_ty::TyLoweringContext::new_maybe_unowned(
             self.db,
             &analyze.resolver,
@@ -1289,9 +1290,9 @@ impl<'db> SemanticsImpl<'db> {
         let analyze = self.analyze(path.syntax())?;
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let ctx =
+        let mut ctx =
             LowerCtx::new(self.db.upcast(), analyze.file_id, &mut types_map, &mut types_source_map);
-        let hir_path = Path::from_src(&ctx, path.clone())?;
+        let hir_path = Path::from_src(&mut ctx, path.clone())?;
         match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? {
             TypeNs::TraitId(id) => Some(Trait { id }),
             _ => None,
@@ -1974,9 +1975,9 @@ impl SemanticsScope<'_> {
     pub fn speculative_resolve(&self, ast_path: &ast::Path) -> Option<PathResolution> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let ctx =
+        let mut ctx =
             LowerCtx::new(self.db.upcast(), self.file_id, &mut types_map, &mut types_source_map);
-        let path = Path::from_src(&ctx, ast_path.clone())?;
+        let path = Path::from_src(&mut ctx, ast_path.clone())?;
         resolve_hir_path(
             self.db,
             &self.resolver,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
index 0438278ca27..ec65ea9a9a8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs
@@ -8,7 +8,7 @@ use either::Either;
 use hir_expand::{attrs::collect_attrs, HirFileId};
 use syntax::{ast, AstPtr};
 
-use crate::{
+use hir_def::{
     db::DefDatabase,
     dyn_map::{
         keys::{self, Key},
@@ -23,7 +23,7 @@ use crate::{
     VariantId,
 };
 
-pub trait ChildBySource {
+pub(crate) trait ChildBySource {
     fn child_by_source(&self, db: &dyn DefDatabase, file_id: HirFileId) -> DynMap {
         let mut res = DynMap::default();
         self.child_by_source_to(db, &mut res, file_id);
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index 5357e824d09..08333c2d76c 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -87,7 +87,6 @@
 
 use either::Either;
 use hir_def::{
-    child_by_source::ChildBySource,
     dyn_map::{
         keys::{self, Key},
         DynMap,
@@ -111,7 +110,10 @@ use syntax::{
     AstNode, AstPtr, SyntaxNode,
 };
 
-use crate::{db::HirDatabase, InFile, InlineAsmOperand, SemanticsImpl};
+use crate::{
+    db::HirDatabase, semantics::child_by_source::ChildBySource, InFile, InlineAsmOperand,
+    SemanticsImpl,
+};
 
 #[derive(Default)]
 pub(super) struct SourceToDefCache {
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index 8d6e228e14c..c16454cff68 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -616,9 +616,9 @@ impl SourceAnalyzer {
     ) -> Option<Macro> {
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let ctx =
+        let mut ctx =
             LowerCtx::new(db.upcast(), macro_call.file_id, &mut types_map, &mut types_source_map);
-        let path = macro_call.value.path().and_then(|ast| Path::from_src(&ctx, ast))?;
+        let path = macro_call.value.path().and_then(|ast| Path::from_src(&mut ctx, ast))?;
         self.resolver
             .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
             .map(|(it, _)| it.into())
@@ -731,8 +731,9 @@ impl SourceAnalyzer {
 
         let (mut types_map, mut types_source_map) =
             (TypesMap::default(), TypesSourceMap::default());
-        let ctx = LowerCtx::new(db.upcast(), self.file_id, &mut types_map, &mut types_source_map);
-        let hir_path = Path::from_src(&ctx, path.clone())?;
+        let mut ctx =
+            LowerCtx::new(db.upcast(), self.file_id, &mut types_map, &mut types_source_map);
+        let hir_path = Path::from_src(&mut ctx, path.clone())?;
 
         // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
         // trying to resolve foo::bar.
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
index f01b4ea0fd4..83f4a6b123c 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
@@ -104,7 +104,7 @@ fn edit_struct_def(
                 ast::make::tokens::single_newline().text(),
             );
             edit.insert(tuple_fields_text_range.start(), w.syntax().text());
-            if !w.syntax().last_token().is_some_and(|t| t.kind() == SyntaxKind::COMMA) {
+            if w.syntax().last_token().is_none_or(|t| t.kind() != SyntaxKind::COMMA) {
                 edit.insert(tuple_fields_text_range.start(), ",");
             }
             edit.insert(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs
new file mode 100644
index 00000000000..f4b4c22d98d
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs
@@ -0,0 +1,430 @@
+use either::Either;
+use ide_db::assists::{AssistId, AssistKind, GroupLabel};
+use syntax::{
+    ast::{self, edit::IndentLevel, make, HasGenericParams, HasName},
+    syntax_editor, AstNode,
+};
+
+use crate::{AssistContext, Assists};
+
+// Assist: generate_fn_type_alias_named
+//
+// Generate a type alias for the function with named parameters.
+//
+// ```
+// unsafe fn fo$0o(n: i32) -> i32 { 42i32 }
+// ```
+// ->
+// ```
+// type ${0:FooFn} = unsafe fn(n: i32) -> i32;
+//
+// unsafe fn foo(n: i32) -> i32 { 42i32 }
+// ```
+
+// Assist: generate_fn_type_alias_unnamed
+//
+// Generate a type alias for the function with unnamed parameters.
+//
+// ```
+// unsafe fn fo$0o(n: i32) -> i32 { 42i32 }
+// ```
+// ->
+// ```
+// type ${0:FooFn} = unsafe fn(i32) -> i32;
+//
+// unsafe fn foo(n: i32) -> i32 { 42i32 }
+// ```
+
+pub(crate) fn generate_fn_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    let name = ctx.find_node_at_offset::<ast::Name>()?;
+    let func = &name.syntax().parent()?;
+    let func_node = ast::Fn::cast(func.clone())?;
+    let param_list = func_node.param_list()?;
+
+    let assoc_owner = func.ancestors().nth(2).and_then(Either::<ast::Trait, ast::Impl>::cast);
+    // This is where we'll insert the type alias, since type aliases in `impl`s or `trait`s are not supported
+    let insertion_node = assoc_owner
+        .as_ref()
+        .map_or_else(|| func, |impl_| impl_.as_ref().either(AstNode::syntax, AstNode::syntax));
+
+    for style in ParamStyle::ALL {
+        acc.add_group(
+            &GroupLabel("Generate a type alias for function...".into()),
+            style.assist_id(),
+            style.label(),
+            func_node.syntax().text_range(),
+            |builder| {
+                let mut edit = builder.make_editor(func);
+
+                let alias_name = format!("{}Fn", stdx::to_camel_case(&name.to_string()));
+
+                let mut fn_params_vec = Vec::new();
+
+                if let Some(self_ty) =
+                    param_list.self_param().and_then(|p| ctx.sema.type_of_self(&p))
+                {
+                    let is_ref = self_ty.is_reference();
+                    let is_mut = self_ty.is_mutable_reference();
+
+                    if let Some(adt) = self_ty.strip_references().as_adt() {
+                        let inner_type = make::ty(adt.name(ctx.db()).as_str());
+
+                        let ast_self_ty =
+                            if is_ref { make::ty_ref(inner_type, is_mut) } else { inner_type };
+
+                        fn_params_vec.push(make::unnamed_param(ast_self_ty));
+                    }
+                }
+
+                fn_params_vec.extend(param_list.params().filter_map(|p| match style {
+                    ParamStyle::Named => Some(p),
+                    ParamStyle::Unnamed => p.ty().map(make::unnamed_param),
+                }));
+
+                let generic_params = func_node.generic_param_list();
+
+                let is_unsafe = func_node.unsafe_token().is_some();
+                let ty = make::ty_fn_ptr(
+                    None,
+                    is_unsafe,
+                    func_node.abi(),
+                    fn_params_vec.into_iter(),
+                    func_node.ret_type(),
+                );
+
+                // Insert new alias
+                let ty_alias = make::ty_alias(
+                    &alias_name,
+                    generic_params,
+                    None,
+                    None,
+                    Some((ast::Type::FnPtrType(ty), None)),
+                )
+                .clone_for_update();
+
+                let indent = IndentLevel::from_node(insertion_node);
+                edit.insert_all(
+                    syntax_editor::Position::before(insertion_node),
+                    vec![
+                        ty_alias.syntax().clone().into(),
+                        make::tokens::whitespace(&format!("\n\n{indent}")).into(),
+                    ],
+                );
+
+                if let Some(cap) = ctx.config.snippet_cap {
+                    if let Some(name) = ty_alias.name() {
+                        edit.add_annotation(name.syntax(), builder.make_placeholder_snippet(cap));
+                    }
+                }
+
+                builder.add_file_edits(ctx.file_id(), edit);
+            },
+        );
+    }
+
+    Some(())
+}
+
+enum ParamStyle {
+    Named,
+    Unnamed,
+}
+
+impl ParamStyle {
+    const ALL: &'static [ParamStyle] = &[ParamStyle::Named, ParamStyle::Unnamed];
+
+    fn assist_id(&self) -> AssistId {
+        let s = match self {
+            ParamStyle::Named => "generate_fn_type_alias_named",
+            ParamStyle::Unnamed => "generate_fn_type_alias_unnamed",
+        };
+
+        AssistId(s, AssistKind::Generate)
+    }
+
+    fn label(&self) -> &'static str {
+        match self {
+            ParamStyle::Named => "Generate a type alias for function with named params",
+            ParamStyle::Unnamed => "Generate a type alias for function with unnamed params",
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tests::check_assist_by_label;
+
+    use super::*;
+
+    #[test]
+    fn generate_fn_alias_unnamed_simple() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = fn(u32) -> i32;
+
+fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Unnamed.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_unnamed_unsafe() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+unsafe fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = unsafe fn(u32) -> i32;
+
+unsafe fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Unnamed.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_unnamed_extern() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+extern fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = extern fn(u32) -> i32;
+
+extern fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Unnamed.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_type_unnamed_extern_abi() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+extern "FooABI" fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = extern "FooABI" fn(u32) -> i32;
+
+extern "FooABI" fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Unnamed.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_unnamed_unsafe_extern_abi() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+unsafe extern "FooABI" fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = unsafe extern "FooABI" fn(u32) -> i32;
+
+unsafe extern "FooABI" fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Unnamed.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_unnamed_generics() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+fn fo$0o<A, B>(a: A, b: B) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn}<A, B> = fn(A, B) -> i32;
+
+fn foo<A, B>(a: A, b: B) -> i32 { return 42; }
+"#,
+            ParamStyle::Unnamed.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_unnamed_generics_bounds() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+fn fo$0o<A: Trait, B: Trait>(a: A, b: B) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn}<A: Trait, B: Trait> = fn(A, B) -> i32;
+
+fn foo<A: Trait, B: Trait>(a: A, b: B) -> i32 { return 42; }
+"#,
+            ParamStyle::Unnamed.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_unnamed_self() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+struct S;
+
+impl S {
+    fn fo$0o(&mut self, param: u32) -> i32 { return 42; }
+}
+"#,
+            r#"
+struct S;
+
+type ${0:FooFn} = fn(&mut S, u32) -> i32;
+
+impl S {
+    fn foo(&mut self, param: u32) -> i32 { return 42; }
+}
+"#,
+            ParamStyle::Unnamed.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_named_simple() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = fn(param: u32) -> i32;
+
+fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Named.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_named_unsafe() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+unsafe fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = unsafe fn(param: u32) -> i32;
+
+unsafe fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Named.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_named_extern() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+extern fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = extern fn(param: u32) -> i32;
+
+extern fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Named.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_type_named_extern_abi() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+extern "FooABI" fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = extern "FooABI" fn(param: u32) -> i32;
+
+extern "FooABI" fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Named.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_named_unsafe_extern_abi() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+unsafe extern "FooABI" fn fo$0o(param: u32) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn} = unsafe extern "FooABI" fn(param: u32) -> i32;
+
+unsafe extern "FooABI" fn foo(param: u32) -> i32 { return 42; }
+"#,
+            ParamStyle::Named.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_named_generics() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+fn fo$0o<A, B>(a: A, b: B) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn}<A, B> = fn(a: A, b: B) -> i32;
+
+fn foo<A, B>(a: A, b: B) -> i32 { return 42; }
+"#,
+            ParamStyle::Named.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_named_generics_bounds() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+fn fo$0o<A: Trait, B: Trait>(a: A, b: B) -> i32 { return 42; }
+"#,
+            r#"
+type ${0:FooFn}<A: Trait, B: Trait> = fn(a: A, b: B) -> i32;
+
+fn foo<A: Trait, B: Trait>(a: A, b: B) -> i32 { return 42; }
+"#,
+            ParamStyle::Named.label(),
+        );
+    }
+
+    #[test]
+    fn generate_fn_alias_named_self() {
+        check_assist_by_label(
+            generate_fn_type_alias,
+            r#"
+struct S;
+
+impl S {
+    fn fo$0o(&mut self, param: u32) -> i32 { return 42; }
+}
+"#,
+            r#"
+struct S;
+
+type ${0:FooFn} = fn(&mut S, param: u32) -> i32;
+
+impl S {
+    fn foo(&mut self, param: u32) -> i32 { return 42; }
+}
+"#,
+            ParamStyle::Named.label(),
+        );
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs
index 6b504a918b4..2bd4c4da1e2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs
@@ -51,10 +51,7 @@ pub(crate) fn inline_const_as_literal(acc: &mut Assists, ctx: &AssistContext<'_>
             | ast::Expr::MatchExpr(_)
             | ast::Expr::MacroExpr(_)
             | ast::Expr::BinExpr(_)
-            | ast::Expr::CallExpr(_) => {
-                let edition = ctx.sema.scope(variable.syntax())?.krate().edition(ctx.db());
-                konst.eval(ctx.sema.db, edition).ok()?
-            }
+            | ast::Expr::CallExpr(_) => konst.eval(ctx.sema.db).ok()?,
             _ => return None,
         };
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
index 8aaf5d6fff2..5c95b25f28d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -161,6 +161,7 @@ mod handlers {
     mod generate_enum_is_method;
     mod generate_enum_projection_method;
     mod generate_enum_variant;
+    mod generate_fn_type_alias;
     mod generate_from_impl_for_enum;
     mod generate_function;
     mod generate_getter_or_setter;
@@ -289,6 +290,7 @@ mod handlers {
             generate_enum_projection_method::generate_enum_as_method,
             generate_enum_projection_method::generate_enum_try_into_method,
             generate_enum_variant::generate_enum_variant,
+            generate_fn_type_alias::generate_fn_type_alias,
             generate_from_impl_for_enum::generate_from_impl_for_enum,
             generate_function::generate_function,
             generate_impl::generate_impl,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 933d45d7508..64b7ab1a123 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -1549,6 +1549,36 @@ fn main() {
 }
 
 #[test]
+fn doctest_generate_fn_type_alias_named() {
+    check_doc_test(
+        "generate_fn_type_alias_named",
+        r#####"
+unsafe fn fo$0o(n: i32) -> i32 { 42i32 }
+"#####,
+        r#####"
+type ${0:FooFn} = unsafe fn(n: i32) -> i32;
+
+unsafe fn foo(n: i32) -> i32 { 42i32 }
+"#####,
+    )
+}
+
+#[test]
+fn doctest_generate_fn_type_alias_unnamed() {
+    check_doc_test(
+        "generate_fn_type_alias_unnamed",
+        r#####"
+unsafe fn fo$0o(n: i32) -> i32 { 42i32 }
+"#####,
+        r#####"
+type ${0:FooFn} = unsafe fn(i32) -> i32;
+
+unsafe fn foo(n: i32) -> i32 { 42i32 }
+"#####,
+    )
+}
+
+#[test]
 fn doctest_generate_from_impl_for_enum() {
     check_doc_test(
         "generate_from_impl_for_enum",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
index ec3c2fe3556..0f00ad45f98 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -281,8 +281,8 @@ pub(crate) fn render_resolution_with_import(
     import_edit: LocatedImport,
 ) -> Option<Builder> {
     let resolution = ScopeDef::from(import_edit.original_item);
-    let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?;
-    //this now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead
+    let local_name = get_import_name(resolution, &ctx, &import_edit)?;
+    // This now just renders the alias text, but we need to find the aliases earlier and call this with the alias instead.
     let doc_aliases = ctx.completion.doc_aliases_in_scope(resolution);
     let ctx = ctx.doc_aliases(doc_aliases);
     Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
@@ -294,7 +294,7 @@ pub(crate) fn render_resolution_with_import_pat(
     import_edit: LocatedImport,
 ) -> Option<Builder> {
     let resolution = ScopeDef::from(import_edit.original_item);
-    let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?;
+    let local_name = get_import_name(resolution, &ctx, &import_edit)?;
     Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
 }
 
@@ -357,6 +357,24 @@ pub(crate) fn render_expr(
     Some(item)
 }
 
+fn get_import_name(
+    resolution: ScopeDef,
+    ctx: &RenderContext<'_>,
+    import_edit: &LocatedImport,
+) -> Option<hir::Name> {
+    // FIXME: Temporary workaround for handling aliased import.
+    // This should be removed after we have proper support for importing alias.
+    // <https://github.com/rust-lang/rust-analyzer/issues/14079>
+
+    // If `item_to_import` matches `original_item`, we are importing the item itself (not its parent module).
+    // In this case, we can use the last segment of `import_path`, as it accounts for the aliased name.
+    if import_edit.item_to_import == import_edit.original_item {
+        import_edit.import_path.segments().last().cloned()
+    } else {
+        scope_def_to_name(resolution, ctx, import_edit)
+    }
+}
+
 fn scope_def_to_name(
     resolution: ScopeDef,
     ctx: &RenderContext<'_>,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
index 0b532064fb2..4b949e0d657 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
@@ -1669,3 +1669,54 @@ mod module {
         "#]],
     );
 }
+
+#[test]
+fn re_export_aliased() {
+    check(
+        r#"
+mod outer {
+    mod inner {
+        pub struct BarStruct;
+        pub fn bar_fun() {}
+        pub mod bar {}
+    }
+    pub use inner::bar as foo;
+    pub use inner::bar_fun as foo_fun;
+    pub use inner::BarStruct as FooStruct;
+}
+fn function() {
+    foo$0
+}
+"#,
+        expect![[r#"
+            st FooStruct (use outer::FooStruct) BarStruct
+            md foo (use outer::foo)
+            fn foo_fun() (use outer::foo_fun) fn()
+        "#]],
+    );
+}
+
+#[test]
+fn re_export_aliased_pattern() {
+    check(
+        r#"
+mod outer {
+    mod inner {
+        pub struct BarStruct;
+        pub fn bar_fun() {}
+        pub mod bar {}
+    }
+    pub use inner::bar as foo;
+    pub use inner::bar_fun as foo_fun;
+    pub use inner::BarStruct as FooStruct;
+}
+fn function() {
+    let foo$0
+}
+"#,
+        expect![[r#"
+            st FooStruct (use outer::FooStruct)
+            md foo (use outer::foo)
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 45c723d09d4..1f1b6478d36 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -382,7 +382,7 @@ pub fn semantic_diagnostics(
         // A bunch of parse errors in a file indicate some bigger structural parse changes in the
         // file, so we skip semantic diagnostics so we can show these faster.
         Some(m) => {
-            if !db.parse_errors(file_id).as_deref().is_some_and(|es| es.len() >= 16) {
+            if db.parse_errors(file_id).as_deref().is_none_or(|es| es.len() < 16) {
                 m.diagnostics(db, &mut diags, config.style_lints);
             }
         }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 6cac4f1ee48..332dfacbb43 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -158,7 +158,7 @@ fn hover_offset(
     if let Some(doc_comment) = token_as_doc_comment(&original_token) {
         cov_mark::hit!(no_highlight_on_comment_hover);
         return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| {
-            let res = hover_for_definition(sema, file_id, def, &node, None, config, edition);
+            let res = hover_for_definition(sema, file_id, def, &node, None, false, config, edition);
             Some(RangeInfo::new(range, res))
         });
     }
@@ -172,6 +172,7 @@ fn hover_offset(
             Definition::from(resolution?),
             &original_token.parent()?,
             None,
+            false,
             config,
             edition,
         );
@@ -218,6 +219,7 @@ fn hover_offset(
                                     break 'a vec![(
                                         Definition::Macro(macro_),
                                         sema.resolve_macro_call_arm(&macro_call),
+                                        false,
                                         node,
                                     )];
                                 }
@@ -234,19 +236,34 @@ fn hover_offset(
                             decl,
                             ..
                         }) => {
-                            vec![(Definition::ExternCrateDecl(decl), None, node)]
+                            vec![(Definition::ExternCrateDecl(decl), None, false, node)]
                         }
 
                         class => {
-                            multizip((class.definitions(), iter::repeat(None), iter::repeat(node)))
-                                .collect::<Vec<_>>()
+                            let is_def = matches!(class, IdentClass::NameClass(_));
+                            multizip((
+                                class.definitions(),
+                                iter::repeat(None),
+                                iter::repeat(is_def),
+                                iter::repeat(node),
+                            ))
+                            .collect::<Vec<_>>()
                         }
                     }
                 }
                 .into_iter()
-                .unique_by(|&(def, _, _)| def)
-                .map(|(def, macro_arm, node)| {
-                    hover_for_definition(sema, file_id, def, &node, macro_arm, config, edition)
+                .unique_by(|&(def, _, _, _)| def)
+                .map(|(def, macro_arm, hovered_definition, node)| {
+                    hover_for_definition(
+                        sema,
+                        file_id,
+                        def,
+                        &node,
+                        macro_arm,
+                        hovered_definition,
+                        config,
+                        edition,
+                    )
                 })
                 .collect::<Vec<_>>(),
             )
@@ -366,6 +383,7 @@ pub(crate) fn hover_for_definition(
     def: Definition,
     scope_node: &SyntaxNode,
     macro_arm: Option<u32>,
+    hovered_definition: bool,
     config: &HoverConfig,
     edition: Edition,
 ) -> HoverResult {
@@ -397,6 +415,7 @@ pub(crate) fn hover_for_definition(
         famous_defs.as_ref(),
         &notable_traits,
         macro_arm,
+        hovered_definition,
         config,
         edition,
     );
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index a31b14dbd3e..d9ddc2d015b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -273,7 +273,7 @@ pub(super) fn keyword(
     let markup = process_markup(
         sema.db,
         Definition::Module(doc_owner),
-        &markup(Some(docs.into()), description, None),
+        &markup(Some(docs.into()), description, None, None),
         config,
     );
     Some(HoverResult { markup, actions })
@@ -419,6 +419,7 @@ pub(super) fn definition(
     famous_defs: Option<&FamousDefs<'_, '_>>,
     notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
     macro_arm: Option<u32>,
+    hovered_definition: bool,
     config: &HoverConfig,
     edition: Edition,
 ) -> Markup {
@@ -456,7 +457,7 @@ pub(super) fn definition(
         _ => def.label(db, edition),
     };
     let docs = def.docs(db, famous_defs, edition);
-    let value = (|| match def {
+    let value = || match def {
         Definition::Variant(it) => {
             if !it.parent_enum(db).is_data_carrying(db) {
                 match it.eval(db) {
@@ -485,18 +486,24 @@ pub(super) fn definition(
             }
         }
         Definition::Static(it) => {
-            let source = it.source(db)?;
-            let mut body = source.value.body()?.syntax().clone();
-            if let Some(macro_file) = source.file_id.macro_file() {
-                let span_map = db.expansion_span_map(macro_file);
-                body = prettify_macro_expansion(db, body, &span_map, it.krate(db).into());
+            let body = it.render_eval(db, edition);
+            match body {
+                Ok(it) => Some(it),
+                Err(_) => {
+                    let source = it.source(db)?;
+                    let mut body = source.value.body()?.syntax().clone();
+                    if let Some(macro_file) = source.file_id.macro_file() {
+                        let span_map = db.expansion_span_map(macro_file);
+                        body = prettify_macro_expansion(db, body, &span_map, it.krate(db).into());
+                    }
+                    Some(body.to_string())
+                }
             }
-            Some(body.to_string())
         }
         _ => None,
-    })();
+    };
 
-    let layout_info = match def {
+    let layout_info = || match def {
         Definition::Field(it) => render_memory_layout(
             config.memory_layout,
             || it.layout(db),
@@ -529,34 +536,38 @@ pub(super) fn definition(
         _ => None,
     };
 
-    let dyn_compatibility_info = if let Definition::Trait(it) = def {
-        let mut dyn_compatibility_info = String::new();
-        render_dyn_compatibility(db, &mut dyn_compatibility_info, it.dyn_compatibility(db));
-        Some(dyn_compatibility_info)
-    } else {
-        None
+    let dyn_compatibility_info = || match def {
+        Definition::Trait(it) => {
+            let mut dyn_compatibility_info = String::new();
+            render_dyn_compatibility(db, &mut dyn_compatibility_info, it.dyn_compatibility(db));
+            Some(dyn_compatibility_info)
+        }
+        _ => None,
     };
 
-    let mut desc = String::new();
-    if let Some(notable_traits) = render_notable_trait_comment(db, notable_traits, edition) {
-        desc.push_str(&notable_traits);
-        desc.push('\n');
-    }
-    if let Some(layout_info) = layout_info {
-        desc.push_str(&layout_info);
-        desc.push('\n');
-    }
-    if let Some(dyn_compatibility_info) = dyn_compatibility_info {
-        desc.push_str(&dyn_compatibility_info);
-        desc.push('\n');
+    let mut extra = String::new();
+    if hovered_definition {
+        if let Some(notable_traits) = render_notable_trait(db, notable_traits, edition) {
+            extra.push_str("\n___\n");
+            extra.push_str(&notable_traits);
+        }
+        if let Some(layout_info) = layout_info() {
+            extra.push_str("\n___\n");
+            extra.push_str(&layout_info);
+        }
+        if let Some(dyn_compatibility_info) = dyn_compatibility_info() {
+            extra.push_str("\n___\n");
+            extra.push_str(&dyn_compatibility_info);
+        }
     }
+    let mut desc = String::new();
     desc.push_str(&label);
-    if let Some(value) = value {
+    if let Some(value) = value() {
         desc.push_str(" = ");
         desc.push_str(&value);
     }
 
-    markup(docs.map(Into::into), desc, mod_path)
+    markup(docs.map(Into::into), desc, extra.is_empty().not().then_some(extra), mod_path)
 }
 
 pub(super) fn literal(
@@ -626,7 +637,7 @@ pub(super) fn literal(
     Some(s.into())
 }
 
-fn render_notable_trait_comment(
+fn render_notable_trait(
     db: &RootDatabase,
     notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
     edition: Edition,
@@ -635,7 +646,7 @@ fn render_notable_trait_comment(
     let mut needs_impl_header = true;
     for (trait_, assoc_types) in notable_traits {
         desc.push_str(if mem::take(&mut needs_impl_header) {
-            "// Implements notable traits: "
+            "Implements notable traits: "
         } else {
             ", "
         });
@@ -728,13 +739,12 @@ fn type_info(
         )
         .into()
     } else {
-        let mut desc =
-            match render_notable_trait_comment(db, &notable_traits(db, &original), edition) {
-                Some(desc) => desc + "\n",
-                None => String::new(),
-            };
-        format_to!(desc, "{}", original.display(db, edition));
-        Markup::fenced_block(&desc)
+        let mut desc = format!("```rust\n{}\n```", original.display(db, edition));
+        if let Some(extra) = render_notable_trait(db, &notable_traits(db, &original), edition) {
+            desc.push_str("\n___\n");
+            desc.push_str(&extra);
+        };
+        desc.into()
     };
     if let Some(actions) = HoverAction::goto_type_from_targets(db, targets, edition) {
         res.actions.push(actions);
@@ -786,20 +796,16 @@ fn closure_ty(
     };
     let mut markup = format!("```rust\n{}", c.display_with_id(sema.db, edition));
 
+    if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) {
+        push_new_def(hir::Trait::from(trait_).into())
+    }
+    format_to!(markup, "\n{}\n```", c.display_with_impl(sema.db, edition),);
     if let Some(layout) =
         render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None)
     {
-        format_to!(markup, " {layout}");
+        format_to!(markup, "\n___\n{layout}");
     }
-    if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) {
-        push_new_def(hir::Trait::from(trait_).into())
-    }
-    format_to!(
-        markup,
-        "\n{}\n```{adjusted}\n\n## Captures\n{}",
-        c.display_with_impl(sema.db, edition),
-        captures_rendered,
-    );
+    format_to!(markup, "{adjusted}\n\n## Captures\n{}", captures_rendered,);
 
     let mut res = HoverResult::default();
     if let Some(actions) = HoverAction::goto_type_from_targets(sema.db, targets, edition) {
@@ -824,7 +830,12 @@ fn definition_mod_path(db: &RootDatabase, def: &Definition, edition: Edition) ->
         .map(|module| path(db, module, definition_owner_name(db, def, edition), edition))
 }
 
-fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Markup {
+fn markup(
+    docs: Option<String>,
+    rust: String,
+    extra: Option<String>,
+    mod_path: Option<String>,
+) -> Markup {
     let mut buf = String::new();
 
     if let Some(mod_path) = mod_path {
@@ -832,7 +843,11 @@ fn markup(docs: Option<String>, desc: String, mod_path: Option<String>) -> Marku
             format_to!(buf, "```rust\n{}\n```\n\n", mod_path);
         }
     }
-    format_to!(buf, "```rust\n{}\n```", desc);
+    format_to!(buf, "```rust\n{}\n```", rust);
+
+    if let Some(extra) = extra {
+        buf.push_str(&extra);
+    }
 
     if let Some(doc) = docs {
         format_to!(buf, "\n___\n\n{}", doc);
@@ -862,7 +877,7 @@ fn render_memory_layout(
     let config = config?;
     let layout = layout().ok()?;
 
-    let mut label = String::from("// ");
+    let mut label = String::new();
 
     if let Some(render) = config.size {
         let size = match tag(&layout) {
@@ -994,55 +1009,53 @@ fn render_dyn_compatibility(
     safety: Option<DynCompatibilityViolation>,
 ) {
     let Some(osv) = safety else {
-        buf.push_str("// Dyn Compatible: Yes");
+        buf.push_str("Is Dyn compatible");
         return;
     };
-    buf.push_str("// Dyn Compatible: No\n// - Reason: ");
+    buf.push_str("Is not Dyn compatible due to ");
     match osv {
         DynCompatibilityViolation::SizedSelf => {
-            buf.push_str("has a `Self: Sized` bound");
+            buf.push_str("having a `Self: Sized` bound");
         }
         DynCompatibilityViolation::SelfReferential => {
-            buf.push_str("has a bound that references `Self`");
+            buf.push_str("having a bound that references `Self`");
         }
         DynCompatibilityViolation::Method(func, mvc) => {
             let name = hir::Function::from(func).name(db);
-            format_to!(
-                buf,
-                "has a method `{}` that is non dispatchable because of:\n//   - ",
-                name.as_str()
-            );
+            format_to!(buf, "having a method `{}` that is not dispatchable due to ", name.as_str());
             let desc = match mvc {
                 MethodViolationCode::StaticMethod => "missing a receiver",
-                MethodViolationCode::ReferencesSelfInput => "a parameter references `Self`",
-                MethodViolationCode::ReferencesSelfOutput => "the return type references `Self`",
+                MethodViolationCode::ReferencesSelfInput => "having a parameter referencing `Self`",
+                MethodViolationCode::ReferencesSelfOutput => "the return type referencing `Self`",
                 MethodViolationCode::ReferencesImplTraitInTrait => {
-                    "the return type contains `impl Trait`"
+                    "the return type containing `impl Trait`"
                 }
                 MethodViolationCode::AsyncFn => "being async",
                 MethodViolationCode::WhereClauseReferencesSelf => {
-                    "a where clause references `Self`"
+                    "a where clause referencing `Self`"
+                }
+                MethodViolationCode::Generic => "having a const or type generic parameter",
+                MethodViolationCode::UndispatchableReceiver => {
+                    "having a non-dispatchable receiver type"
                 }
-                MethodViolationCode::Generic => "a non-lifetime generic parameter",
-                MethodViolationCode::UndispatchableReceiver => "a non-dispatchable receiver type",
             };
             buf.push_str(desc);
         }
         DynCompatibilityViolation::AssocConst(const_) => {
             let name = hir::Const::from(const_).name(db);
             if let Some(name) = name {
-                format_to!(buf, "has an associated constant `{}`", name.as_str());
+                format_to!(buf, "having an associated constant `{}`", name.as_str());
             } else {
-                buf.push_str("has an associated constant");
+                buf.push_str("having an associated constant");
             }
         }
         DynCompatibilityViolation::GAT(alias) => {
             let name = hir::TypeAlias::from(alias).name(db);
-            format_to!(buf, "has a generic associated type `{}`", name.as_str());
+            format_to!(buf, "having a generic associated type `{}`", name.as_str());
         }
         DynCompatibilityViolation::HasNonCompatibleSuperTrait(super_trait) => {
             let name = hir::Trait::from(super_trait).name(db);
-            format_to!(buf, "has a dyn incompatible supertrait `{}`", name.as_str());
+            format_to!(buf, "having a dyn incompatible supertrait `{}`", name.as_str());
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index 3e402630419..0ffbf988c35 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -260,7 +260,6 @@ fn foo() {
             *local*
 
             ```rust
-            // size = 4, align = 4
             let local: i32
             ```
         "#]],
@@ -348,9 +347,11 @@ fn main() {
         expect![[r#"
             *|*
             ```rust
-            {closure#0} // size = 8, align = 8, niches = 1
+            {closure#0}
             impl Fn(i32) -> i32
             ```
+            ___
+            size = 8, align = 8, niches = 1
 
             ## Captures
             * `x` by immutable borrow
@@ -370,9 +371,11 @@ fn main() {
         expect![[r#"
             *|*
             ```rust
-            {closure#0} // size = 0, align = 1
+            {closure#0}
             impl Fn(i32) -> i32
             ```
+            ___
+            size = 0, align = 1
 
             ## Captures
             This closure captures nothing
@@ -403,9 +406,11 @@ fn main() {
         expect![[r#"
             *|*
             ```rust
-            {closure#0} // size = 16 (0x10), align = 8, niches = 1
+            {closure#0}
             impl FnOnce()
             ```
+            ___
+            size = 16 (0x10), align = 8, niches = 1
 
             ## Captures
             * `x.f1` by move
@@ -431,9 +436,11 @@ fn main() {
         expect![[r#"
             *|*
             ```rust
-            {closure#0} // size = 8, align = 8, niches = 1
+            {closure#0}
             impl FnMut()
             ```
+            ___
+            size = 8, align = 8, niches = 1
 
             ## Captures
             * `x` by mutable borrow
@@ -455,9 +462,11 @@ fn main() {
 "#,
         expect![[r#"
             ```rust
-            {closure#0} // size = 8, align = 8, niches = 1
+            {closure#0}
             impl FnOnce() -> S2
             ```
+            ___
+            size = 8, align = 8, niches = 1
             Coerced to: &impl FnOnce() -> S2
 
             ## Captures
@@ -551,9 +560,12 @@ fn main() {
             *iter*
 
             ```rust
-            // size = 8, align = 4
             let mut iter: Iter<Scan<OtherStruct<OtherStruct<i32>>, impl Fn(&mut u32, &u32, &mut u32) -> Option<u32>, u32>>
             ```
+
+            ---
+
+            size = 8, align = 4
         "#]],
     );
 }
@@ -793,9 +805,12 @@ struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 }
             ```
 
             ```rust
-            // size = 1, align = 1, offset = 6
             field_a: u8
             ```
+
+            ---
+
+            size = 1, align = 1, offset = 6
         "#]],
     );
 }
@@ -819,7 +834,6 @@ fn main() {
             ```
 
             ```rust
-            // size = 4, align = 4, offset = 0
             pub field_a: u32
             ```
         "#]],
@@ -842,9 +856,12 @@ fn main() {
             ```
 
             ```rust
-            // size = 4, align = 4, offset = 0
             pub field_a: u32
             ```
+
+            ---
+
+            size = 4, align = 4, offset = 0
         "#]],
     );
 }
@@ -867,7 +884,6 @@ fn main() {
             ```
 
             ```rust
-            // size = 4, align = 4, offset = 0
             pub 0: u32
             ```
         "#]],
@@ -888,7 +904,6 @@ fn foo(foo: Foo) {
             ```
 
             ```rust
-            // size = 4, align = 4, offset = 0
             pub 0: u32
             ```
         "#]],
@@ -909,11 +924,14 @@ struct Foo$0(pub u32) where u32: Copy;
             ```
 
             ```rust
-            // size = 4, align = 4
             struct Foo(pub u32)
             where
                 u32: Copy,
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
 }
@@ -932,11 +950,14 @@ struct Foo$0 { field: u32 }
             ```
 
             ```rust
-            // size = 4, align = 4
             struct Foo {
                 field: u32,
             }
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
     check(
@@ -951,7 +972,6 @@ struct Foo$0 where u32: Copy { field: u32 }
             ```
 
             ```rust
-            // size = 4, align = 4
             struct Foo
             where
                 u32: Copy,
@@ -959,6 +979,10 @@ struct Foo$0 where u32: Copy { field: u32 }
                 field: u32,
             }
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
 }
@@ -978,13 +1002,16 @@ fn hover_record_struct_limit() {
             ```
 
             ```rust
-            // size = 12 (0xC), align = 4
             struct Foo {
                 a: u32,
                 b: i32,
                 c: i32,
             }
             ```
+
+            ---
+
+            size = 12 (0xC), align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1000,11 +1027,14 @@ fn hover_record_struct_limit() {
             ```
 
             ```rust
-            // size = 4, align = 4
             struct Foo {
                 a: u32,
             }
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1020,7 +1050,6 @@ fn hover_record_struct_limit() {
             ```
 
             ```rust
-            // size = 16 (0x10), align = 4
             struct Foo {
                 a: u32,
                 b: i32,
@@ -1028,6 +1057,10 @@ fn hover_record_struct_limit() {
                 /* … */
             }
             ```
+
+            ---
+
+            size = 16 (0x10), align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1043,9 +1076,12 @@ fn hover_record_struct_limit() {
             ```
 
             ```rust
-            // size = 12 (0xC), align = 4
             struct Foo
             ```
+
+            ---
+
+            size = 12 (0xC), align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1061,9 +1097,12 @@ fn hover_record_struct_limit() {
             ```
 
             ```rust
-            // size = 12 (0xC), align = 4
             struct Foo { /* … */ }
             ```
+
+            ---
+
+            size = 12 (0xC), align = 4
         "#]],
     );
 
@@ -1081,9 +1120,12 @@ fn hover_record_struct_limit() {
             ```
 
             ```rust
-            // size = 0, align = 1
             struct Foo {}
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -1103,9 +1145,12 @@ fn hover_record_variant_limit() {
             ```
 
             ```rust
-            // size = 12 (0xC), align = 4
             A { a: u32, b: i32, c: i32, }
             ```
+
+            ---
+
+            size = 12 (0xC), align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1121,9 +1166,12 @@ fn hover_record_variant_limit() {
             ```
 
             ```rust
-            // size = 4, align = 4
             A { a: u32, }
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1139,9 +1187,12 @@ fn hover_record_variant_limit() {
             ```
 
             ```rust
-            // size = 16 (0x10), align = 4
             A { a: u32, b: i32, c: i32, /* … */ }
             ```
+
+            ---
+
+            size = 16 (0x10), align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1157,9 +1208,12 @@ fn hover_record_variant_limit() {
             ```
 
             ```rust
-            // size = 12 (0xC), align = 4
             A
             ```
+
+            ---
+
+            size = 12 (0xC), align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1175,9 +1229,12 @@ fn hover_record_variant_limit() {
             ```
 
             ```rust
-            // size = 12 (0xC), align = 4
             A { /* … */ }
             ```
+
+            ---
+
+            size = 12 (0xC), align = 4
         "#]],
     );
 }
@@ -1195,12 +1252,15 @@ fn hover_enum_limit() {
             ```
 
             ```rust
-            // size = 1, align = 1, niches = 254
             enum Foo {
                 A,
                 B,
             }
             ```
+
+            ---
+
+            size = 1, align = 1, niches = 254
         "#]],
     );
     check_hover_enum_variants_limit(
@@ -1214,12 +1274,15 @@ fn hover_enum_limit() {
             ```
 
             ```rust
-            // size = 1, align = 1, niches = 254
             enum Foo {
                 A,
                 /* … */
             }
             ```
+
+            ---
+
+            size = 1, align = 1, niches = 254
         "#]],
     );
     check_hover_enum_variants_limit(
@@ -1233,9 +1296,12 @@ fn hover_enum_limit() {
             ```
 
             ```rust
-            // size = 1, align = 1, niches = 254
             enum Foo { /* … */ }
             ```
+
+            ---
+
+            size = 1, align = 1, niches = 254
         "#]],
     );
     check_hover_enum_variants_limit(
@@ -1249,9 +1315,12 @@ fn hover_enum_limit() {
             ```
 
             ```rust
-            // size = 1, align = 1, niches = 254
             enum Foo
             ```
+
+            ---
+
+            size = 1, align = 1, niches = 254
         "#]],
     );
     check_hover_enum_variants_limit(
@@ -1274,7 +1343,6 @@ fn hover_enum_limit() {
             ```
 
             ```rust
-            // size = 12 (0xC), align = 4, niches = 4294967288
             enum Enum {
                 Variant {},
                 Variant2 { /* … */ },
@@ -1286,6 +1354,10 @@ fn hover_enum_limit() {
                 /* … */
             }
             ```
+
+            ---
+
+            size = 12 (0xC), align = 4, niches = 4294967288
         "#]],
     );
 }
@@ -1303,12 +1375,15 @@ fn hover_union_limit() {
             ```
 
             ```rust
-            // size = 4, align = 4
             union Foo {
                 a: u32,
                 b: i32,
             }
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1322,12 +1397,15 @@ fn hover_union_limit() {
             ```
 
             ```rust
-            // size = 4, align = 4
             union Foo {
                 a: u32,
                 /* … */
             }
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1341,9 +1419,12 @@ fn hover_union_limit() {
             ```
 
             ```rust
-            // size = 4, align = 4
             union Foo { /* … */ }
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
     check_hover_fields_limit(
@@ -1357,9 +1438,12 @@ fn hover_union_limit() {
             ```
 
             ```rust
-            // size = 4, align = 4
             union Foo
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
 }
@@ -1378,11 +1462,14 @@ struct Foo$0 where u32: Copy;
             ```
 
             ```rust
-            // size = 0, align = 1
             struct Foo
             where
                 u32: Copy,
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -1457,7 +1544,7 @@ const foo$0: u32 = {
             ```
 
             ```rust
-            static foo: u32 = 456
+            static foo: u32 = 456 (0x1C8)
             ```
         "#]],
     );
@@ -1548,9 +1635,12 @@ fn main() {
             *zz*
 
             ```rust
-            // size = 8, align = 4
             let zz: Test<i32>
             ```
+
+            ---
+
+            size = 8, align = 4
         "#]],
     );
     check_hover_range(
@@ -1600,9 +1690,12 @@ fn main() { let b$0ar = Some(12); }
             *bar*
 
             ```rust
-            // size = 4, align = 4
             let bar: Option<i32>
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
 }
@@ -1670,7 +1763,6 @@ fn hover_for_local_variable() {
             *foo*
 
             ```rust
-            // size = 4, align = 4
             foo: i32
             ```
         "#]],
@@ -1685,9 +1777,12 @@ fn hover_for_local_variable_pat() {
             *foo*
 
             ```rust
-            // size = 4, align = 4
             foo: i32
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     )
 }
@@ -1700,7 +1795,6 @@ fn hover_local_var_edge() {
             *foo*
 
             ```rust
-            // size = 4, align = 4
             foo: i32
             ```
         "#]],
@@ -1715,9 +1809,12 @@ fn hover_for_param_edge() {
             *foo*
 
             ```rust
-            // size = 4, align = 4
             foo: i32
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     )
 }
@@ -1760,9 +1857,12 @@ fn main() { let foo_$0test = Thing::new(); }
             *foo_test*
 
             ```rust
-            // size = 4, align = 4
             let foo_test: Thing
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     )
 }
@@ -1985,7 +2085,6 @@ fn y() {
             *x*
 
             ```rust
-            // size = 4, align = 4
             let x: i32
             ```
         "#]],
@@ -2116,7 +2215,6 @@ fn foo(bar:u32) { let a = id!(ba$0r); }
             *bar*
 
             ```rust
-            // size = 4, align = 4
             bar: u32
             ```
         "#]],
@@ -2135,7 +2233,6 @@ fn foo(bar:u32) { let a = id!(ba$0r); }
             *bar*
 
             ```rust
-            // size = 4, align = 4
             bar: u32
             ```
         "#]],
@@ -2371,9 +2468,12 @@ fn test_hover_function_pointer_show_identifiers() {
             ```
 
             ```rust
-            // size = 8, align = 8, niches = 1
             type foo = fn(a: i32, b: i32) -> i32
             ```
+
+            ---
+
+            size = 8, align = 8, niches = 1
         "#]],
     );
 }
@@ -2390,9 +2490,12 @@ fn test_hover_function_pointer_no_identifier() {
             ```
 
             ```rust
-            // size = 8, align = 8, niches = 1
             type foo = fn(i32, i32) -> i32
             ```
+
+            ---
+
+            size = 8, align = 8, niches = 1
         "#]],
     );
 }
@@ -2537,7 +2640,6 @@ fn foo() { let bar = Ba$0r; }
             ```
 
             ```rust
-            // size = 0, align = 1
             struct Bar
             ```
 
@@ -2574,7 +2676,6 @@ fn foo() { let bar = Ba$0r; }
             ```
 
             ```rust
-            // size = 0, align = 1
             struct Bar
             ```
 
@@ -2604,7 +2705,6 @@ fn foo() { let bar = Ba$0r; }
             ```
 
             ```rust
-            // size = 0, align = 1
             struct Bar
             ```
 
@@ -2633,12 +2733,15 @@ pub struct B$0ar
             ```
 
             ```rust
-            // size = 0, align = 1
             pub struct Bar
             ```
 
             ---
 
+            size = 0, align = 1
+
+            ---
+
             [external](https://www.google.com)
         "#]],
     );
@@ -2661,12 +2764,15 @@ pub struct B$0ar
             ```
 
             ```rust
-            // size = 0, align = 1
             pub struct Bar
             ```
 
             ---
 
+            size = 0, align = 1
+
+            ---
+
             [baz](Baz)
         "#]],
     );
@@ -2751,9 +2857,12 @@ fn test_hover_layout_of_variant() {
             ```
 
             ```rust
-            // size = 4, align = 2
             Variant1(u8, u16)
             ```
+
+            ---
+
+            size = 4, align = 2
         "#]],
     );
 }
@@ -2794,9 +2903,12 @@ struct S$0<T>(core::marker::PhantomData<T>);
             ```
 
             ```rust
-            // size = 0, align = 1
             struct S<T>(PhantomData<T>)
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -2816,12 +2928,15 @@ fn test_hover_layout_of_enum() {
             ```
 
             ```rust
-            // size = 16 (0x10), align = 8, niches = 254
             enum Foo {
                 Variant1( /* … */ ),
                 Variant2( /* … */ ),
             }
             ```
+
+            ---
+
+            size = 16 (0x10), align = 8, niches = 254
         "#]],
     );
 }
@@ -4133,9 +4248,12 @@ fn main() {
             *f*
 
             ```rust
-            // size = 8, align = 8, niches = 1
             let f: &i32
             ```
+
+            ---
+
+            size = 8, align = 8, niches = 1
             ---
 
             ```rust
@@ -4143,9 +4261,12 @@ fn main() {
             ```
 
             ```rust
-            // size = 4, align = 4, offset = 0
             f: i32
             ```
+
+            ---
+
+            size = 4, align = 4, offset = 0
         "#]],
     );
 }
@@ -4165,9 +4286,12 @@ struct S$0T<const C: usize = 1, T = Foo>(T);
             ```
 
             ```rust
-            // size = 0, align = 1
             struct ST<const C: usize = 1, T = Foo>(T)
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4187,9 +4311,12 @@ struct S$0T<const C: usize = {40 + 2}, T = Foo>(T);
             ```
 
             ```rust
-            // size = 0, align = 1
             struct ST<const C: usize = {const}, T = Foo>(T)
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4210,9 +4337,12 @@ struct S$0T<const C: usize = VAL, T = Foo>(T);
             ```
 
             ```rust
-            // size = 0, align = 1
             struct ST<const C: usize = VAL, T = Foo>(T)
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4231,9 +4361,12 @@ fn main() {
             *value*
 
             ```rust
-            // size = 0, align = 1
             let value: Const<1>
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4252,9 +4385,12 @@ fn main() {
             *value*
 
             ```rust
-            // size = 0, align = 1
             let value: Const<0>
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4273,9 +4409,12 @@ fn main() {
             *value*
 
             ```rust
-            // size = 0, align = 1
             let value: Const<-1>
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4294,9 +4433,12 @@ fn main() {
             *value*
 
             ```rust
-            // size = 0, align = 1
             let value: Const<true>
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4315,9 +4457,12 @@ fn main() {
             *value*
 
             ```rust
-            // size = 0, align = 1
             let value: Const<'🦀'>
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4335,9 +4480,12 @@ impl Foo {
             *self*
 
             ```rust
-            // size = 8, align = 8, niches = 1
             self: &Foo
             ```
+
+            ---
+
+            size = 8, align = 8, niches = 1
         "#]],
     );
 }
@@ -4356,9 +4504,12 @@ impl Foo {
             *self*
 
             ```rust
-            // size = 0, align = 1
             self: Arc<Foo>
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4755,9 +4906,12 @@ type Fo$0o2 = Foo<2>;
             ```
 
             ```rust
-            // size = 0, align = 1
             type Foo2 = Foo<2>
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -4798,12 +4952,15 @@ enum E {
             ```
 
             ```rust
-            // size = 1, align = 1
             A = 8
             ```
 
             ---
 
+            size = 1, align = 1
+
+            ---
+
             This is a doc
         "#]],
     );
@@ -4824,12 +4981,15 @@ enum E {
             ```
 
             ```rust
-            // size = 1, align = 1
             A = 12 (0xC)
             ```
 
             ---
 
+            size = 1, align = 1
+
+            ---
+
             This is a doc
         "#]],
     );
@@ -4851,12 +5011,15 @@ enum E {
             ```
 
             ```rust
-            // size = 1, align = 1
             B = 2
             ```
 
             ---
 
+            size = 1, align = 1
+
+            ---
+
             This is a doc
         "#]],
     );
@@ -4878,12 +5041,15 @@ enum E {
             ```
 
             ```rust
-            // size = 1, align = 1
             B = 5
             ```
 
             ---
 
+            size = 1, align = 1
+
+            ---
+
             This is a doc
         "#]],
     );
@@ -5750,7 +5916,6 @@ fn foo(e: E) {
             ```
 
             ```rust
-            // size = 0, align = 1
             A = 3
             ```
 
@@ -5799,9 +5964,12 @@ fn main() {
             *tile4*
 
             ```rust
-            // size = 32 (0x20), align = 4
             let tile4: [u32; 8]
             ```
+
+            ---
+
+            size = 32 (0x20), align = 4
         "#]],
     );
 }
@@ -6036,7 +6204,6 @@ pub fn gimme() -> theitem::TheItem {
             ```
 
             ```rust
-            // size = 0, align = 1
             pub struct TheItem
             ```
 
@@ -6185,7 +6352,6 @@ mod string {
             ```
 
             ```rust
-            // size = 0, align = 1
             struct String
             ```
 
@@ -6948,7 +7114,6 @@ foo_macro!(
             ```
 
             ```rust
-            // size = 0, align = 1
             pub struct Foo
             ```
 
@@ -6974,7 +7139,6 @@ pub struct Foo(i32);
             ```
 
             ```rust
-            // size = 4, align = 4
             pub struct Foo(i32)
             ```
 
@@ -7099,9 +7263,12 @@ enum Enum {
             ```
 
             ```rust
-            // size = 4, align = 4
             RecordV { field: u32, }
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
 }
@@ -7122,9 +7289,12 @@ enum Enum {
             ```
 
             ```rust
-            // size = 4, align = 4
             field: u32
             ```
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
 }
@@ -7175,7 +7345,6 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: Yes
             trait T {}
             ```
         "#]],
@@ -7195,7 +7364,6 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: Yes
             trait T {}
             ```
         "#]],
@@ -7219,9 +7387,6 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: No
-            // - Reason: has a method `func` that is non dispatchable because of:
-            //   - missing a receiver
             trait T { /* … */ }
             ```
         "#]],
@@ -7245,9 +7410,6 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: No
-            // - Reason: has a method `func` that is non dispatchable because of:
-            //   - missing a receiver
             trait T {
                 fn func();
                 const FLAG: i32;
@@ -7275,9 +7437,6 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: No
-            // - Reason: has a method `func` that is non dispatchable because of:
-            //   - missing a receiver
             trait T {
                 fn func();
                 const FLAG: i32;
@@ -7305,9 +7464,6 @@ impl T$0 for () {}
             ```
 
             ```rust
-            // Dyn Compatible: No
-            // - Reason: has a method `func` that is non dispatchable because of:
-            //   - missing a receiver
             trait T {
                 fn func();
                 const FLAG: i32;
@@ -7784,7 +7940,6 @@ fn test() {
             ```
 
             ```rust
-            // size = 4, align = 4, offset = 0
             f: u32
             ```
         "#]],
@@ -7804,9 +7959,12 @@ fn test() {
             *s*
 
             ```rust
-            // size = 0, align = 1
             let s: S
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -7825,7 +7983,6 @@ fn test() {
             *foo*
 
             ```rust
-            // size = 4, align = 4
             let foo: i32
             ```
         "#]],
@@ -7846,7 +8003,6 @@ format_args!("{aaaaa$0}");
             *aaaaa*
 
             ```rust
-            // size = 16 (0x10), align = 8, niches = 1
             let aaaaa: &str
             ```
         "#]],
@@ -7867,7 +8023,6 @@ format_args!("{$0aaaaa}");
             *aaaaa*
 
             ```rust
-            // size = 16 (0x10), align = 8, niches = 1
             let aaaaa: &str
             ```
         "#]],
@@ -7888,7 +8043,6 @@ format_args!(r"{$0aaaaa}");
             *aaaaa*
 
             ```rust
-            // size = 16 (0x10), align = 8, niches = 1
             let aaaaa: &str
             ```
         "#]],
@@ -7914,7 +8068,6 @@ foo!(r"{$0aaaaa}");
             *aaaaa*
 
             ```rust
-            // size = 16 (0x10), align = 8, niches = 1
             let aaaaa: &str
             ```
         "#]],
@@ -8386,10 +8539,16 @@ fn main(notable$0: u32) {}
             *notable*
 
             ```rust
-            // Implements notable traits: Notable<Assoc = &str, Assoc2 = char>
-            // size = 4, align = 4
             notable: u32
             ```
+
+            ---
+
+            Implements notable traits: Notable\<Assoc = &str, Assoc2 = char>
+
+            ---
+
+            size = 4, align = 4
         "#]],
     );
 }
@@ -8418,8 +8577,6 @@ impl Iterator for S {
             ```
 
             ```rust
-            // Implements notable traits: Notable, Future<Output = u32>, Iterator<Item = S>
-            // size = 0, align = 1
             struct S
             ```
         "#]],
@@ -8478,9 +8635,12 @@ extern "C" {
             ```
 
             ```rust
-            // size = 0, align = 1
             type Ty
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -8506,9 +8666,10 @@ fn main() {
 "#,
         expect![[r#"
             ```rust
-            // Implements notable traits: Notable, Future<Output = u32>, Iterator<Item = S>
             S
-            ```"#]],
+            ```
+            ___
+            Implements notable traits: Notable, Future<Output = u32>, Iterator<Item = S>"#]],
     );
 }
 
@@ -8618,11 +8779,14 @@ struct Pedro$0<'a> {
             ```
 
             ```rust
-            // size = 16 (0x10), align = 8, niches = 1
             struct Pedro<'a> {
                 hola: &str,
             }
             ```
+
+            ---
+
+            size = 16 (0x10), align = 8, niches = 1
         "#]],
     )
 }
@@ -8655,9 +8819,12 @@ fn main(a$0: T) {}
             *a*
 
             ```rust
-            // size = 0, align = 1
             a: T
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -8678,7 +8845,6 @@ fn test() {
             *f*
 
             ```rust
-            // size = 0, align = 1
             let f: fn bar<3>(bool)
             ```
         "#]],
@@ -8706,9 +8872,12 @@ fn main() {
             *x*
 
             ```rust
-            // size = 0, align = 1
             let x: fn f<S, i32>()
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 }
@@ -9037,12 +9206,15 @@ type A$0 = B;
             ```
 
             ```rust
-            // size = 0, align = 1
             type A = B
             ```
 
             ---
 
+            size = 0, align = 1
+
+            ---
+
             *This is the documentation for* `struct B`
 
             Docs for B
@@ -9067,12 +9239,15 @@ type A$0 = B;
             ```
 
             ```rust
-            // size = 0, align = 1
             type A = B
             ```
 
             ---
 
+            size = 0, align = 1
+
+            ---
+
             *This is the documentation for* `struct C`
 
             Docs for C
@@ -9098,12 +9273,15 @@ type A$0 = B;
             ```
 
             ```rust
-            // size = 0, align = 1
             type A = B
             ```
 
             ---
 
+            size = 0, align = 1
+
+            ---
+
             *This is the documentation for* `struct C`
 
             Docs for C
@@ -9127,9 +9305,12 @@ type A$0 = B;
             ```
 
             ```rust
-            // size = 0, align = 1
             type A = B
             ```
+
+            ---
+
+            size = 0, align = 1
         "#]],
     );
 
@@ -9159,7 +9340,6 @@ use a::A$0;
             ```
 
             ```rust
-            // size = 0, align = 1
             pub type A = B
             ```
 
@@ -9171,3 +9351,68 @@ use a::A$0;
         "#]],
     );
 }
+
+#[test]
+fn dyn_compat() {
+    check(
+        r#"
+trait Compat$0 {}
+"#,
+        expect![[r#"
+            *Compat*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            trait Compat
+            ```
+
+            ---
+
+            Is Dyn compatible
+        "#]],
+    );
+    check(
+        r#"
+trait UnCompat$0 {
+    fn f<T>() {}
+}
+"#,
+        expect![[r#"
+            *UnCompat*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            trait UnCompat
+            ```
+
+            ---
+
+            Is not Dyn compatible due to having a method `f` that is not dispatchable due to missing a receiver
+        "#]],
+    );
+    check(
+        r#"
+trait UnCompat {
+    fn f<T>() {}
+}
+fn f<T: UnCompat$0>
+"#,
+        expect![[r#"
+            *UnCompat*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            trait UnCompat
+            ```
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/interpret.rs b/src/tools/rust-analyzer/crates/ide/src/interpret.rs
new file mode 100644
index 00000000000..5fa6f4e4842
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide/src/interpret.rs
@@ -0,0 +1,64 @@
+use hir::{DefWithBody, Semantics};
+use ide_db::{base_db::SourceRootDatabase, FilePosition, LineIndexDatabase, RootDatabase};
+use std::time::{Duration, Instant};
+use stdx::format_to;
+use syntax::{algo::ancestors_at_offset, ast, AstNode, TextRange};
+
+// Feature: Interpret A Function, Static Or Const.
+//
+// |===
+// | Editor  | Action Name
+//
+// | VS Code | **rust-analyzer: Interpret**
+// |===
+pub(crate) fn interpret(db: &RootDatabase, position: FilePosition) -> String {
+    match find_and_interpret(db, position) {
+        Some((duration, mut result)) => {
+            result.push('\n');
+            format_to!(result, "----------------------\n");
+            format_to!(result, "  Finished in {}s\n", duration.as_secs_f32());
+            result
+        }
+        _ => "Not inside a function, const or static".to_owned(),
+    }
+}
+
+fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<(Duration, String)> {
+    let sema = Semantics::new(db);
+    let source_file = sema.parse_guess_edition(position.file_id);
+
+    let item = ancestors_at_offset(source_file.syntax(), position.offset)
+        .filter(|it| !ast::MacroCall::can_cast(it.kind()))
+        .find_map(ast::Item::cast)?;
+    let def: DefWithBody = match item {
+        ast::Item::Fn(it) => sema.to_def(&it)?.into(),
+        ast::Item::Const(it) => sema.to_def(&it)?.into(),
+        ast::Item::Static(it) => sema.to_def(&it)?.into(),
+        _ => return None,
+    };
+    let span_formatter = |file_id, text_range: TextRange| {
+        let path = &db
+            .source_root(db.file_source_root(file_id))
+            .path_for_file(&file_id)
+            .map(|x| x.to_string());
+        let path = path.as_deref().unwrap_or("<unknown file>");
+        match db.line_index(file_id).try_line_col(text_range.start()) {
+            Some(line_col) => format!("file://{path}:{}:{}", line_col.line + 1, line_col.col),
+            None => format!("file://{path} range {text_range:?}"),
+        }
+    };
+    let start_time = Instant::now();
+    let res = match def {
+        DefWithBody::Function(it) => it.eval(db, span_formatter),
+        DefWithBody::Static(it) => it.eval(db),
+        DefWithBody::Const(it) => it.eval(db),
+        _ => unreachable!(),
+    };
+    let res = res.unwrap_or_else(|e| {
+        let mut r = String::new();
+        _ = e.pretty_print(&mut r, db, span_formatter, def.module(db).krate().edition(db));
+        r
+    });
+    let duration = Instant::now() - start_time;
+    Some((duration, res))
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/interpret_function.rs b/src/tools/rust-analyzer/crates/ide/src/interpret_function.rs
deleted file mode 100644
index ff1317d135c..00000000000
--- a/src/tools/rust-analyzer/crates/ide/src/interpret_function.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use hir::Semantics;
-use ide_db::{base_db::SourceRootDatabase, FilePosition, LineIndexDatabase, RootDatabase};
-use std::{fmt::Write, time::Instant};
-use syntax::{algo::ancestors_at_offset, ast, AstNode, TextRange};
-
-// Feature: Interpret Function
-//
-// |===
-// | Editor  | Action Name
-//
-// | VS Code | **rust-analyzer: Interpret Function**
-// |===
-pub(crate) fn interpret_function(db: &RootDatabase, position: FilePosition) -> String {
-    let start_time = Instant::now();
-    let mut result =
-        find_and_interpret(db, position).unwrap_or_else(|| "Not inside a function body".to_owned());
-    let duration = Instant::now() - start_time;
-    writeln!(result).unwrap();
-    writeln!(result, "----------------------").unwrap();
-    writeln!(result, "  Finished in {}s", duration.as_secs_f32()).unwrap();
-    result
-}
-
-fn find_and_interpret(db: &RootDatabase, position: FilePosition) -> Option<String> {
-    let sema = Semantics::new(db);
-    let source_file = sema.parse_guess_edition(position.file_id);
-
-    let item = ancestors_at_offset(source_file.syntax(), position.offset)
-        .filter(|it| !ast::MacroCall::can_cast(it.kind()))
-        .find_map(ast::Item::cast)?;
-    let def = match item {
-        ast::Item::Fn(it) => sema.to_def(&it)?,
-        _ => return None,
-    };
-    let span_formatter = |file_id, text_range: TextRange| {
-        let path = &db
-            .source_root(db.file_source_root(file_id))
-            .path_for_file(&file_id)
-            .map(|x| x.to_string());
-        let path = path.as_deref().unwrap_or("<unknown file>");
-        match db.line_index(file_id).try_line_col(text_range.start()) {
-            Some(line_col) => format!("file://{path}#{}:{}", line_col.line + 1, line_col.col),
-            None => format!("file://{path} range {text_range:?}"),
-        }
-    };
-    Some(def.eval(db, span_formatter))
-}
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index d053c4b3c93..d4ef9570e1a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -33,7 +33,7 @@ mod goto_type_definition;
 mod highlight_related;
 mod hover;
 mod inlay_hints;
-mod interpret_function;
+mod interpret;
 mod join_lines;
 mod markdown_remove;
 mod matching_brace;
@@ -350,7 +350,7 @@ impl Analysis {
     }
 
     pub fn interpret_function(&self, position: FilePosition) -> Cancellable<String> {
-        self.with_db(|db| interpret_function::interpret_function(db, position))
+        self.with_db(|db| interpret::interpret(db, position))
     }
 
     pub fn view_item_tree(&self, file_id: FileId) -> Cancellable<String> {
diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
index 1cbe8c62a81..0f4b5e7d87a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -212,6 +212,7 @@ impl StaticIndex<'_> {
                         def,
                         &node,
                         None,
+                        false,
                         &hover_config,
                         edition,
                     )),
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index a62cbc7fb29..aecafb444c3 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -398,6 +398,8 @@ define_symbols! {
     rustc_const_panic_str,
     rustc_deprecated_safe_2024,
     rustc_has_incoherent_inherent_impls,
+    rustc_intrinsic,
+    rustc_intrinsic_must_be_overridden,
     rustc_layout_scalar_valid_range_end,
     rustc_layout_scalar_valid_range_start,
     rustc_legacy_const_generics,
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
index 7ae1e5f82e5..a50a2182a7b 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
@@ -67,7 +67,7 @@ pub(crate) mod entry {
         }
 
         pub(crate) fn pat_top(p: &mut Parser<'_>) {
-            patterns::pattern_top(p);
+            patterns::pattern(p);
         }
 
         pub(crate) fn ty(p: &mut Parser<'_>) {
@@ -80,7 +80,8 @@ pub(crate) mod entry {
             paths::type_path(p);
         }
         pub(crate) fn item(p: &mut Parser<'_>) {
-            items::item_or_macro(p, true);
+            // We can set `is_in_extern=true`, because it only allows `safe fn`, and there is no ambiguity here.
+            items::item_or_macro(p, true, true);
         }
         // Parse a meta item , which excluded [], e.g : #[ MetaItem ]
         pub(crate) fn meta_item(p: &mut Parser<'_>) {
@@ -116,7 +117,7 @@ pub(crate) mod entry {
 
         pub(crate) fn pattern(p: &mut Parser<'_>) {
             let m = p.start();
-            patterns::pattern_top(p);
+            patterns::pattern(p);
             if p.at(EOF) {
                 m.abandon(p);
                 return;
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index 861fcedda2a..e565874a421 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -66,7 +66,7 @@ pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
 
     // test block_items
     // fn a() { fn b() {} }
-    let m = match items::opt_item(p, m) {
+    let m = match items::opt_item(p, m, false) {
         Ok(()) => return,
         Err(m) => m,
     };
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
index 2333e6c862b..97e0392ce15 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
@@ -660,7 +660,7 @@ fn for_expr(p: &mut Parser<'_>, m: Option<Marker>) -> CompletedMarker {
 fn let_expr(p: &mut Parser<'_>) -> CompletedMarker {
     let m = p.start();
     p.bump(T![let]);
-    patterns::pattern_top(p);
+    patterns::pattern(p);
     p.expect(T![=]);
     expr_let(p);
     m.complete(p, LET_EXPR)
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
index c4dce0daa5b..7d98499008d 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
@@ -20,7 +20,8 @@ use super::*;
 pub(super) fn mod_contents(p: &mut Parser<'_>, stop_on_r_curly: bool) {
     attributes::inner_attrs(p);
     while !(p.at(EOF) || (p.at(T!['}']) && stop_on_r_curly)) {
-        item_or_macro(p, stop_on_r_curly);
+        // We can set `is_in_extern=true`, because it only allows `safe fn`, and there is no ambiguity here.
+        item_or_macro(p, stop_on_r_curly, true);
     }
 }
 
@@ -41,11 +42,11 @@ pub(super) const ITEM_RECOVERY_SET: TokenSet = TokenSet::new(&[
     T![;],
 ]);
 
-pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) {
+pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool, is_in_extern: bool) {
     let m = p.start();
     attributes::outer_attrs(p);
 
-    let m = match opt_item(p, m) {
+    let m = match opt_item(p, m, is_in_extern) {
         Ok(()) => {
             if p.at(T![;]) {
                 p.err_and_bump(
@@ -91,7 +92,7 @@ pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) {
 }
 
 /// Try to parse an item, completing `m` in case of success.
-pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
+pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker, is_in_extern: bool) -> Result<(), Marker> {
     // test_err pub_expr
     // fn foo() { pub 92; }
     let has_visibility = opt_visibility(p, false);
@@ -135,7 +136,9 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
         has_mods = true;
     }
 
-    if p.at_contextual_kw(T![safe]) {
+    // test safe_outside_of_extern
+    // fn foo() { safe = true; }
+    if is_in_extern && p.at_contextual_kw(T![safe]) {
         p.eat_contextual_kw(T![safe]);
         has_mods = true;
     }
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs
index c215185d632..47f86ce8c6c 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs
@@ -94,7 +94,7 @@ pub(crate) fn assoc_item_list(p: &mut Parser<'_>) {
             error_block(p, "expected an item");
             continue;
         }
-        item_or_macro(p, true);
+        item_or_macro(p, true, false);
     }
     p.expect(T!['}']);
     m.complete(p, ASSOC_ITEM_LIST);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
index ed01fca2acd..460051a0f4a 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
@@ -20,14 +20,9 @@ const PAT_TOP_FIRST: TokenSet = PATTERN_FIRST.union(TokenSet::new(&[T![|]]));
 const RANGE_PAT_END_FIRST: TokenSet =
     expressions::LITERAL_FIRST.union(paths::PATH_FIRST).union(TokenSet::new(&[T![-], T![const]]));
 
-pub(crate) fn pattern(p: &mut Parser<'_>) {
-    let m = p.start();
-    pattern_r(p, m, false, PAT_RECOVERY_SET);
-}
-
 /// Parses a pattern list separated by pipes `|`.
-pub(super) fn pattern_top(p: &mut Parser<'_>) {
-    pattern_top_r(p, PAT_RECOVERY_SET);
+pub(crate) fn pattern(p: &mut Parser<'_>) {
+    pattern_r(p, PAT_RECOVERY_SET);
 }
 
 pub(crate) fn pattern_single(p: &mut Parser<'_>) {
@@ -37,9 +32,7 @@ pub(crate) fn pattern_single(p: &mut Parser<'_>) {
 /// Parses a pattern list separated by pipes `|`
 /// using the given `recovery_set`.
 pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
-    let m = p.start();
-    let has_leading_pipe = p.eat(T![|]);
-    pattern_r(p, m, has_leading_pipe, recovery_set);
+    pattern_r(p, recovery_set);
 }
 
 // test or_pattern
@@ -53,7 +46,10 @@ pub(super) fn pattern_top_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
 // }
 /// Parses a pattern list separated by pipes `|`, with no leading `|`,using the
 /// given `recovery_set`.
-fn pattern_r(p: &mut Parser<'_>, m: Marker, has_leading_pipe: bool, recovery_set: TokenSet) {
+fn pattern_r(p: &mut Parser<'_>, recovery_set: TokenSet) {
+    let m = p.start();
+    let has_leading_pipe = p.eat(T![|]);
+
     pattern_single_r(p, recovery_set);
 
     if !p.at(T![|]) && !has_leading_pipe {
@@ -319,6 +315,8 @@ fn record_pat_field(p: &mut Parser<'_>) {
         IDENT | INT_NUMBER if p.nth(1) == T![:] => {
             name_ref_or_index(p);
             p.bump(T![:]);
+            // test record_field_pat_leading_or
+            // fn foo() { let R { a: | 1 | 2 } = 0; }
             pattern(p);
         }
         // test_err record_pat_field_eq_recovery
@@ -438,7 +436,7 @@ fn tuple_pat(p: &mut Parser<'_>) -> CompletedMarker {
         }
         has_rest |= p.at(T![..]);
 
-        pattern_top(p);
+        pattern(p);
         if !p.at(T![')']) {
             has_comma = true;
             p.expect(T![,]);
@@ -465,7 +463,7 @@ fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker {
 
 fn pat_list(p: &mut Parser<'_>, ket: SyntaxKind) {
     while !p.at(EOF) && !p.at(ket) {
-        pattern_top(p);
+        pattern(p);
         if !p.eat(T![,]) {
             if p.at_ts(PAT_TOP_FIRST) {
                 p.error(format!("expected {:?}, got {:?}", T![,], p.current()));
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
index 164d0f36f1b..62b381b6688 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
+++ b/src/tools/rust-analyzer/crates/parser/test_data/generated/runner.rs
@@ -493,6 +493,10 @@ mod ok {
         run_and_expect_no_errors("test_data/parser/inline/ok/record_field_list.rs");
     }
     #[test]
+    fn record_field_pat_leading_or() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/record_field_pat_leading_or.rs");
+    }
+    #[test]
     fn record_lit() { run_and_expect_no_errors("test_data/parser/inline/ok/record_lit.rs"); }
     #[test]
     fn record_literal_field_with_attr() {
@@ -527,6 +531,10 @@ mod ok {
         run_and_expect_no_errors("test_data/parser/inline/ok/return_type_syntax_in_path.rs");
     }
     #[test]
+    fn safe_outside_of_extern() {
+        run_and_expect_no_errors("test_data/parser/inline/ok/safe_outside_of_extern.rs");
+    }
+    #[test]
     fn self_param() { run_and_expect_no_errors("test_data/parser/inline/ok/self_param.rs"); }
     #[test]
     fn self_param_outer_attr() {
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rast
new file mode 100644
index 00000000000..4ef6c1c45f5
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rast
@@ -0,0 +1,54 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "foo"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE " "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          RECORD_PAT
+            PATH
+              PATH_SEGMENT
+                NAME_REF
+                  IDENT "R"
+            WHITESPACE " "
+            RECORD_PAT_FIELD_LIST
+              L_CURLY "{"
+              WHITESPACE " "
+              RECORD_PAT_FIELD
+                NAME_REF
+                  IDENT "a"
+                COLON ":"
+                WHITESPACE " "
+                OR_PAT
+                  PIPE "|"
+                  WHITESPACE " "
+                  LITERAL_PAT
+                    LITERAL
+                      INT_NUMBER "1"
+                  WHITESPACE " "
+                  PIPE "|"
+                  WHITESPACE " "
+                  LITERAL_PAT
+                    LITERAL
+                      INT_NUMBER "2"
+              WHITESPACE " "
+              R_CURLY "}"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          LITERAL
+            INT_NUMBER "0"
+          SEMICOLON ";"
+        WHITESPACE " "
+        R_CURLY "}"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rs
new file mode 100644
index 00000000000..a5e7510c140
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/record_field_pat_leading_or.rs
@@ -0,0 +1 @@
+fn foo() { let R { a: | 1 | 2 } = 0; }
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rast
new file mode 100644
index 00000000000..c9398eaa993
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rast
@@ -0,0 +1,30 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "foo"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE " "
+        EXPR_STMT
+          BIN_EXPR
+            PATH_EXPR
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "safe"
+            WHITESPACE " "
+            EQ "="
+            WHITESPACE " "
+            LITERAL
+              TRUE_KW "true"
+          SEMICOLON ";"
+        WHITESPACE " "
+        R_CURLY "}"
+  WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rs
new file mode 100644
index 00000000000..a4d75e63ea7
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/safe_outside_of_extern.rs
@@ -0,0 +1 @@
+fn foo() { safe = true; }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs
index c965257a5c5..4045e25fdf1 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs
@@ -56,8 +56,8 @@ impl ProcMacroProcessSrv {
         match srv.version_check() {
             Ok(v) if v > CURRENT_API_VERSION => Err(io::Error::new(
                 io::ErrorKind::Other,
-                format!(
-                    "proc-macro server's api version ({v}) is newer than rust-analyzer's ({CURRENT_API_VERSION})"
+                format!( "The version of the proc-macro server ({v}) in your Rust toolchain is newer than the version supported by your rust-analyzer ({CURRENT_API_VERSION}).
+            This will prevent proc-macro expansion from working. Please consider updating your rust-analyzer to ensure compatibility with your current toolchain."
                 ),
             )),
             Ok(v) => {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 51c81a0d1a6..155fb6f7c88 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -172,7 +172,6 @@ impl flags::AnalysisStats {
         let mut num_decls = 0;
         let mut bodies = Vec::new();
         let mut adts = Vec::new();
-        let mut consts = Vec::new();
         let mut file_ids = Vec::new();
         while let Some(module) = visit_queue.pop() {
             if visited_modules.insert(module) {
@@ -193,7 +192,6 @@ impl flags::AnalysisStats {
                         }
                         ModuleDef::Const(c) => {
                             bodies.push(DefWithBody::from(c));
-                            consts.push(c)
                         }
                         ModuleDef::Static(s) => bodies.push(DefWithBody::from(s)),
                         _ => (),
@@ -207,7 +205,6 @@ impl flags::AnalysisStats {
                             AssocItem::Function(f) => bodies.push(DefWithBody::from(f)),
                             AssocItem::Const(c) => {
                                 bodies.push(DefWithBody::from(c));
-                                consts.push(c);
                             }
                             _ => (),
                         }
@@ -220,7 +217,10 @@ impl flags::AnalysisStats {
             visited_modules.len(),
             bodies.len(),
             adts.len(),
-            consts.len(),
+            bodies
+                .iter()
+                .filter(|it| matches!(it, DefWithBody::Const(_) | DefWithBody::Static(_)))
+                .count(),
         );
         let crate_def_map_time = crate_def_map_sw.elapsed();
         eprintln!("{:<20} {}", "Item Collection:", crate_def_map_time);
@@ -247,7 +247,7 @@ impl flags::AnalysisStats {
         }
 
         if !self.skip_const_eval {
-            self.run_const_eval(db, &consts, verbosity);
+            self.run_const_eval(db, &bodies, verbosity);
         }
 
         if self.run_all_ide_things {
@@ -320,18 +320,23 @@ impl flags::AnalysisStats {
         report_metric("data layout time", data_layout_time.time.as_millis() as u64, "ms");
     }
 
-    fn run_const_eval(&self, db: &RootDatabase, consts: &[hir::Const], verbosity: Verbosity) {
+    fn run_const_eval(&self, db: &RootDatabase, bodies: &[DefWithBody], verbosity: Verbosity) {
         let mut sw = self.stop_watch();
         let mut all = 0;
         let mut fail = 0;
-        for &c in consts {
+        for &b in bodies {
+            let res = match b {
+                DefWithBody::Const(c) => c.render_eval(db, Edition::LATEST),
+                DefWithBody::Static(s) => s.render_eval(db, Edition::LATEST),
+                _ => continue,
+            };
             all += 1;
-            let Err(error) = c.render_eval(db, Edition::LATEST) else {
+            let Err(error) = res else {
                 continue;
             };
             if verbosity.is_spammy() {
                 let full_name =
-                    full_name_of_item(db, c.module(db), c.name(db).unwrap_or(Name::missing()));
+                    full_name_of_item(db, b.module(db), b.name(db).unwrap_or(Name::missing()));
                 println!("Const eval for {full_name} failed due {error:?}");
             }
             fail += 1;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs
index 11534bbeba9..7398b9a9ef0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/run_tests.rs
@@ -61,12 +61,11 @@ impl flags::RunTests {
             }
             let mut sw_one = StopWatch::start();
             let result = test.eval(db, span_formatter);
-            if result.trim() == "pass" {
-                pass_count += 1;
-            } else {
-                fail_count += 1;
+            match &result {
+                Ok(result) if result.trim() == "pass" => pass_count += 1,
+                _ => fail_count += 1,
             }
-            println!("{result}");
+            println!("{result:?}");
             eprintln!("{:<20} {}", format!("test {}", full_name), sw_one.elapsed());
         }
         println!("{pass_count} passed, {fail_count} failed, {ignore_count} ignored");
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
index 271a9c0f3d1..1db616898e8 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
@@ -463,6 +463,11 @@ impl ClientCapabilities {
             .unwrap_or_default()
     }
 
+    pub fn diagnostics_refresh(&self) -> bool {
+        (|| -> _ { self.0.workspace.as_ref()?.diagnostic.as_ref()?.refresh_support })()
+            .unwrap_or_default()
+    }
+
     pub fn inlay_hint_resolve_support_properties(&self) -> FxHashSet<&str> {
         self.0
             .text_document
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index 9a51df80fe1..73fce42437f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -417,8 +417,6 @@ impl GlobalState {
                 }
             }
 
-            let supports_diagnostic_pull_model = self.config.text_document_diagnostic();
-
             let client_refresh = became_quiescent || state_changed;
             if client_refresh {
                 // Refresh semantic tokens if the client supports it.
@@ -437,7 +435,7 @@ impl GlobalState {
                     self.send_request::<lsp_types::request::InlayHintRefreshRequest>((), |_, _| ());
                 }
 
-                if supports_diagnostic_pull_model {
+                if self.config.diagnostics_refresh() {
                     self.send_request::<lsp_types::request::WorkspaceDiagnosticRefresh>(
                         (),
                         |_, _| (),
@@ -448,7 +446,7 @@ impl GlobalState {
             let project_or_mem_docs_changed =
                 became_quiescent || state_changed || memdocs_added_or_removed;
             if project_or_mem_docs_changed
-                && !supports_diagnostic_pull_model
+                && !self.config.text_document_diagnostic()
                 && self.config.publish_diagnostics(None)
             {
                 self.update_diagnostics();
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
index fcdc97ce327..2ec83d23b27 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -15,7 +15,11 @@ use parser::{Edition, T};
 use rowan::NodeOrToken;
 use stdx::{format_to, format_to_acc, never};
 
-use crate::{ast, utils::is_raw_identifier, AstNode, SourceFile, SyntaxKind, SyntaxToken};
+use crate::{
+    ast::{self, Param},
+    utils::is_raw_identifier,
+    AstNode, SourceFile, SyntaxKind, SyntaxToken,
+};
 
 /// While the parent module defines basic atomic "constructors", the `ext`
 /// module defines shortcuts for common things.
@@ -198,6 +202,38 @@ pub fn ty_alias(
     ast_from_text(&s)
 }
 
+pub fn ty_fn_ptr<I: Iterator<Item = Param>>(
+    for_lifetime_list: Option<ast::GenericParamList>,
+    is_unsafe: bool,
+    abi: Option<ast::Abi>,
+    params: I,
+    ret_type: Option<ast::RetType>,
+) -> ast::FnPtrType {
+    let mut s = String::from("type __ = ");
+
+    if let Some(list) = for_lifetime_list {
+        format_to!(s, "for{} ", list);
+    }
+
+    if is_unsafe {
+        s.push_str("unsafe ");
+    }
+
+    if let Some(abi) = abi {
+        format_to!(s, "{} ", abi)
+    }
+
+    s.push_str("fn");
+
+    format_to!(s, "({})", params.map(|p| p.to_string()).join(", "));
+
+    if let Some(ret_type) = ret_type {
+        format_to!(s, " {}", ret_type);
+    }
+
+    ast_from_text(&s)
+}
+
 pub fn assoc_item_list() -> ast::AssocItemList {
     ast_from_text("impl C for D {}")
 }
@@ -862,6 +898,10 @@ pub fn item_const(
     ast_from_text(&format!("{visibility} const {name}: {ty} = {expr};"))
 }
 
+pub fn unnamed_param(ty: ast::Type) -> ast::Param {
+    ast_from_text(&format!("fn f({ty}) {{ }}"))
+}
+
 pub fn param(pat: ast::Pat, ty: ast::Type) -> ast::Param {
     ast_from_text(&format!("fn f({pat}: {ty}) {{ }}"))
 }
diff --git a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml
index f9565721dd5..c860e7b1183 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml
@@ -5,7 +5,6 @@ rust-version.workspace = true
 edition.workspace = true
 license.workspace = true
 authors.workspace = true
-publish = false
 
 [dependencies]
 hir-expand.workspace = true
diff --git a/src/tools/rust-analyzer/docs/dev/setup.md b/src/tools/rust-analyzer/docs/dev/setup.md
new file mode 100644
index 00000000000..d8a7840d376
--- /dev/null
+++ b/src/tools/rust-analyzer/docs/dev/setup.md
@@ -0,0 +1,57 @@
+# Setup Guide
+
+This guide gives a simplified opinionated setup for developers contributing to rust-analyzer using Visual Studio Code to make changes and Visual Studio Code Insiders to test those changes. This guide will assume you have Visual Studio Code and Visual Studio Code Insiders installed.
+
+## Prerequisites
+
+Since rust-analyzer is a Rust project, you will need to install Rust. You can download and install the latest stable version of Rust [here](https://www.rust-lang.org/tools/install).
+
+## Step-by-Step Setup
+
+**Step 01**: Fork the rust-analyzer repository and clone the fork to your local machine.
+
+**Step 02**: Open the project in Visual Studio Code.
+
+**Step 03**: Open a terminal and run `cargo build` to build the project.
+
+**Step 04**: Install the language server locally by running the following command:
+
+```sh
+cargo xtask install --server --code-bin code-insiders --dev-rel
+```
+
+In the output of this command, there should be a file path provided to the installed binary on  your local machine.
+It should look something like the following output below:
+
+```
+Installing <path-to-rust-analyzer-binary>
+Installed package `rust-analyzer v0.0.0 (<path-to-rust-analyzer-binary>)` (executable `rust-analyzer.exe`)
+```
+
+In Visual Studio Code Insiders, you will want to open your User Settings (JSON) from the Command Palette. From there you should ensure that the `rust-analyzer.server.path` key is set to the `<path-to-rust-analyzer-binary>`. This will tell Visual Studio Code Insiders to use the locally installed version that you can debug.
+
+The User Settings (JSON) file should contain the following:
+
+```json
+{
+    "rust-analyzer.server.path": "<path-to-rust-analyzer-binary>"
+}
+```
+
+Now you should be able to make changes to rust-analyzer in Visual Studio Code and then view the changes in Visual Studio Code Insiders.
+
+## Debugging rust-analyzer
+The simplest way to debug rust-analyzer is to use the `eprintln!` macro. The reason why we use `eprintln!` instead of `println!` is because the language server uses `stdout` to send messages. So instead we will debug using `stderr`.
+
+An example debugging statement could go into the `main_loop.rs` file which can be found at `crates/rust-analyzer/src/main_loop.rs`. Inside the `main_loop` we will add the following `eprintln!` to test debugging rust-analyzer:
+
+```rs
+eprintln!("Hello, world!");
+```
+
+Now we run `cargo build` and `sh
+cargo xtask install --server --code-bin code-insiders --dev-rel` to reinstall the server.
+
+Now on Visual Studio Code Insiders, we should be able to open the Output tab on our terminal and switch to Rust Analyzer Language Server to see the `eprintln!` statement we just wrote.
+
+If you are able to see your output, you now have a complete workflow for debugging rust-analyzer.
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 6eebdf9f016..ccc8c0e3842 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -125,7 +125,7 @@
             },
             {
                 "command": "rust-analyzer.interpretFunction",
-                "title": "Interpret Function",
+                "title": "Interpret",
                 "category": "rust-analyzer (debug command)"
             },
             {
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index ffb312d06e6..00f4f743a7c 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-a9d17627d241645a54c1134a20f1596127fedb60
+145f9cf95de1fbde3fa11e98461310e0373253e6
diff --git a/src/tools/rust-analyzer/xtask/src/tidy.rs b/src/tools/rust-analyzer/xtask/src/tidy.rs
index c3d531344a1..35412be8764 100644
--- a/src/tools/rust-analyzer/xtask/src/tidy.rs
+++ b/src/tools/rust-analyzer/xtask/src/tidy.rs
@@ -135,7 +135,6 @@ Apache-2.0 WITH LLVM-exception
 Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT
 Apache-2.0/MIT
 BSD-2-Clause OR Apache-2.0 OR MIT
-BSD-3-Clause
 CC0-1.0
 ISC
 MIT
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index 8cbc263689b..edf7658d25f 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -7,7 +7,6 @@ use ignore::DirEntry;
 
 /// The default directory filter.
 pub fn filter_dirs(path: &Path) -> bool {
-    // FIXME: sync submodule exclusion list with rustfmt.toml
     // bootstrap/etc
     let skip = [
         "tidy-test-file",
diff --git a/src/tools/unicode-table-generator/src/cascading_map.rs b/src/tools/unicode-table-generator/src/cascading_map.rs
index 036f0bd7eac..1eb35e819c0 100644
--- a/src/tools/unicode-table-generator/src/cascading_map.rs
+++ b/src/tools/unicode-table-generator/src/cascading_map.rs
@@ -65,7 +65,7 @@ impl RawEmitter {
         self.bytes_used += 256;
 
         writeln!(&mut self.file, "#[inline]").unwrap();
-        writeln!(&mut self.file, "pub fn lookup(c: char) -> bool {{").unwrap();
+        writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap();
         writeln!(&mut self.file, "    match c as u32 >> 8 {{").unwrap();
         for arm in arms {
             writeln!(&mut self.file, "        {},", arm).unwrap();
diff --git a/tests/assembly/aarch64-pointer-auth.rs b/tests/assembly/aarch64-pointer-auth.rs
index 1e53878a2cc..344e9e74bc2 100644
--- a/tests/assembly/aarch64-pointer-auth.rs
+++ b/tests/assembly/aarch64-pointer-auth.rs
@@ -1,9 +1,13 @@
 // Test that PAC instructions are emitted when branch-protection is specified.
 
+//@ revisions: PACRET PAUTHLR_NOP PAUTHLR
 //@ assembly-output: emit-asm
-//@ compile-flags: --target aarch64-unknown-linux-gnu
-//@ compile-flags: -Z branch-protection=pac-ret,leaf
 //@ needs-llvm-components: aarch64
+//@ compile-flags: --target aarch64-unknown-linux-gnu
+//@ [PACRET] compile-flags: -Z branch-protection=pac-ret,leaf
+//@ [PAUTHLR_NOP] compile-flags: -Z branch-protection=pac-ret,pc,leaf
+//@ [PAUTHLR] compile-flags: -C target-feature=+pauth-lr -Z branch-protection=pac-ret,pc,leaf
+//@ min-llvm-version: 19
 
 #![feature(no_core, lang_items)]
 #![no_std]
@@ -13,8 +17,13 @@
 #[lang = "sized"]
 trait Sized {}
 
-// CHECK: hint #25
-// CHECK: hint #29
+// PACRET: hint #25
+// PACRET: hint #29
+// PAUTHLR_NOP: hint #25
+// PAUTHLR_NOP: hint #39
+// PAUTHLR_NOP: hint #29
+// PAUTHLR: paciasppc
+// PAUTHLR: autiasppc
 #[no_mangle]
 pub fn test() -> u8 {
     42
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index 1857633a8bf..7d50647bed1 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -525,9 +525,6 @@
 //@ revisions: wasm32v1_none
 //@ [wasm32v1_none] compile-flags: --target wasm32v1-none
 //@ [wasm32v1_none] needs-llvm-components: webassembly
-//@ revisions: wasm32_wasi
-//@ [wasm32_wasi] compile-flags: --target wasm32-wasi
-//@ [wasm32_wasi] needs-llvm-components: webassembly
 //@ revisions: wasm32_wasip1
 //@ [wasm32_wasip1] compile-flags: --target wasm32-wasip1
 //@ [wasm32_wasip1] needs-llvm-components: webassembly
diff --git a/tests/codegen/asm/powerpc-clobbers.rs b/tests/codegen/asm/powerpc-clobbers.rs
index 0be1b66bd99..e97e8300ca7 100644
--- a/tests/codegen/asm/powerpc-clobbers.rs
+++ b/tests/codegen/asm/powerpc-clobbers.rs
@@ -1,10 +1,12 @@
-//@ revisions: powerpc powerpc64 powerpc64le
+//@ revisions: powerpc powerpc64 powerpc64le aix64
 //@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
 //@[powerpc] needs-llvm-components: powerpc
 //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
 //@[powerpc64] needs-llvm-components: powerpc
 //@[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
 //@[powerpc64le] needs-llvm-components: powerpc
+//@[aix64] compile-flags: --target powerpc64-ibm-aix
+//@[aix64] needs-llvm-components: powerpc
 
 #![crate_type = "rlib"]
 #![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
@@ -22,26 +24,40 @@ macro_rules! asm {
 // CHECK: call void asm sideeffect "", "~{cr}"()
 #[no_mangle]
 pub unsafe fn cr_clobber() {
-    asm!("", out("cr") _, options(nostack, nomem));
+    asm!("", out("cr") _, options(nostack, nomem, preserves_flags));
 }
 
 // CHECK-LABEL: @cr0_clobber
 // CHECK: call void asm sideeffect "", "~{cr0}"()
 #[no_mangle]
 pub unsafe fn cr0_clobber() {
-    asm!("", out("cr0") _, options(nostack, nomem));
+    asm!("", out("cr0") _, options(nostack, nomem, preserves_flags));
 }
 
 // CHECK-LABEL: @cr5_clobber
 // CHECK: call void asm sideeffect "", "~{cr5}"()
 #[no_mangle]
 pub unsafe fn cr5_clobber() {
-    asm!("", out("cr5") _, options(nostack, nomem));
+    asm!("", out("cr5") _, options(nostack, nomem, preserves_flags));
 }
 
 // CHECK-LABEL: @xer_clobber
 // CHECK: call void asm sideeffect "", "~{xer}"()
 #[no_mangle]
 pub unsafe fn xer_clobber() {
-    asm!("", out("xer") _, options(nostack, nomem));
+    asm!("", out("xer") _, options(nostack, nomem, preserves_flags));
+}
+
+// CHECK-LABEL: @v0_clobber
+// CHECK: call void asm sideeffect "", "~{v0}"()
+#[no_mangle]
+pub unsafe fn v0_clobber() {
+    asm!("", out("v0") _, options(nostack, nomem, preserves_flags));
+}
+
+// CHECK-LABEL: @clobber_abi
+// CHECK: asm sideeffect "", "={r0},={r3},={r4},={r5},={r6},={r7},={r8},={r9},={r10},={r11},={r12},={f0},={f1},={f2},={f3},={f4},={f5},={f6},={f7},={f8},={f9},={f10},={f11},={f12},={f13},~{v0},~{v1},~{v2},~{v3},~{v4},~{v5},~{v6},~{v7},~{v8},~{v9},~{v10},~{v11},~{v12},~{v13},~{v14},~{v15},~{v16},~{v17},~{v18},~{v19},~{cr0},~{cr1},~{cr5},~{cr6},~{cr7},~{xer}"()
+#[no_mangle]
+pub unsafe fn clobber_abi() {
+    asm!("", clobber_abi("C"), options(nostack, nomem, preserves_flags));
 }
diff --git a/tests/codegen/branch-protection.rs b/tests/codegen/branch-protection.rs
index 2f5ff9e98c2..945bad05625 100644
--- a/tests/codegen/branch-protection.rs
+++ b/tests/codegen/branch-protection.rs
@@ -1,11 +1,15 @@
 // Test that the correct module flags are emitted with different branch protection flags.
 
-//@ revisions: BTI PACRET LEAF BKEY NONE
+//@ revisions: BTI PACRET LEAF BKEY PAUTHLR PAUTHLR_BKEY PAUTHLR_LEAF PAUTHLR_BTI NONE
 //@ needs-llvm-components: aarch64
 //@ [BTI] compile-flags: -Z branch-protection=bti
 //@ [PACRET] compile-flags: -Z branch-protection=pac-ret
 //@ [LEAF] compile-flags: -Z branch-protection=pac-ret,leaf
 //@ [BKEY] compile-flags: -Z branch-protection=pac-ret,b-key
+//@ [PAUTHLR] compile-flags: -Z branch-protection=pac-ret,pc
+//@ [PAUTHLR_BKEY] compile-flags: -Z branch-protection=pac-ret,pc,b-key
+//@ [PAUTHLR_LEAF] compile-flags: -Z branch-protection=pac-ret,pc,leaf
+//@ [PAUTHLR_BTI] compile-flags: -Z branch-protection=bti,pac-ret,pc
 //@ compile-flags: --target aarch64-unknown-linux-gnu
 //@ min-llvm-version: 19
 
@@ -24,6 +28,7 @@ pub fn test() {}
 // BTI: attributes [[ATTR]] = {{.*}} "branch-target-enforcement"
 // BTI: !"branch-target-enforcement", i32 1
 // BTI: !"sign-return-address", i32 0
+// BTI: !"branch-protection-pauth-lr", i32 0
 // BTI: !"sign-return-address-all", i32 0
 // BTI: !"sign-return-address-with-bkey", i32 0
 
@@ -31,6 +36,7 @@ pub fn test() {}
 // PACRET-SAME: "sign-return-address-key"="a_key"
 // PACRET: !"branch-target-enforcement", i32 0
 // PACRET: !"sign-return-address", i32 1
+// PACRET: !"branch-protection-pauth-lr", i32 0
 // PACRET: !"sign-return-address-all", i32 0
 // PACRET: !"sign-return-address-with-bkey", i32 0
 
@@ -38,6 +44,7 @@ pub fn test() {}
 // LEAF-SAME: "sign-return-address-key"="a_key"
 // LEAF: !"branch-target-enforcement", i32 0
 // LEAF: !"sign-return-address", i32 1
+// LEAF: !"branch-protection-pauth-lr", i32 0
 // LEAF: !"sign-return-address-all", i32 1
 // LEAF: !"sign-return-address-with-bkey", i32 0
 
@@ -45,9 +52,42 @@ pub fn test() {}
 // BKEY-SAME: "sign-return-address-key"="b_key"
 // BKEY: !"branch-target-enforcement", i32 0
 // BKEY: !"sign-return-address", i32 1
+// BKEY: !"branch-protection-pauth-lr", i32 0
 // BKEY: !"sign-return-address-all", i32 0
 // BKEY: !"sign-return-address-with-bkey", i32 1
 
+// PAUTHLR: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
+// PAUTHLR-SAME: "sign-return-address-key"="a_key"
+// PAUTHLR: !"branch-target-enforcement", i32 0
+// PAUTHLR: !"sign-return-address", i32 1
+// PAUTHLR: !"branch-protection-pauth-lr", i32 1
+// PAUTHLR: !"sign-return-address-all", i32 0
+// PAUTHLR: !"sign-return-address-with-bkey", i32 0
+
+// PAUTHLR_BKEY: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
+// PAUTHLR_BKEY-SAME: "sign-return-address-key"="b_key"
+// PAUTHLR_BKEY: !"branch-target-enforcement", i32 0
+// PAUTHLR_BKEY: !"sign-return-address", i32 1
+// PAUTHLR_BKEY: !"branch-protection-pauth-lr", i32 1
+// PAUTHLR_BKEY: !"sign-return-address-all", i32 0
+// PAUTHLR_BKEY: !"sign-return-address-with-bkey", i32 1
+
+// PAUTHLR_LEAF: attributes [[ATTR]] = {{.*}} "sign-return-address"="all"
+// PAUTHLR_LEAF-SAME: "sign-return-address-key"="a_key"
+// PAUTHLR_LEAF: !"branch-target-enforcement", i32 0
+// PAUTHLR_LEAF: !"sign-return-address", i32 1
+// PAUTHLR_LEAF: !"branch-protection-pauth-lr", i32 1
+// PAUTHLR_LEAF: !"sign-return-address-all", i32 1
+// PAUTHLR_LEAF: !"sign-return-address-with-bkey", i32 0
+
+// PAUTHLR_BTI: attributes [[ATTR]] = {{.*}} "sign-return-address"="non-leaf"
+// PAUTHLR_BTI-SAME: "sign-return-address-key"="a_key"
+// PAUTHLR_BTI: !"branch-target-enforcement", i32 1
+// PAUTHLR_BTI: !"sign-return-address", i32 1
+// PAUTHLR_BTI: !"branch-protection-pauth-lr", i32 1
+// PAUTHLR_BTI: !"sign-return-address-all", i32 0
+// PAUTHLR_BTI: !"sign-return-address-with-bkey", i32 0
+
 // NONE-NOT: branch-target-enforcement
 // NONE-NOT: sign-return-address
 // NONE-NOT: sign-return-address-all
diff --git a/tests/codegen/repr/transparent-opaque-ptr.rs b/tests/codegen/repr/transparent-opaque-ptr.rs
index 4e7b38bca39..29c03f0d5d9 100644
--- a/tests/codegen/repr/transparent-opaque-ptr.rs
+++ b/tests/codegen/repr/transparent-opaque-ptr.rs
@@ -1,12 +1,12 @@
-//@ revisions: aarch64-linux aarch64-darwin wasm32-wasi
+//@ revisions: aarch64-linux aarch64-darwin wasm32-wasip1
 //@ compile-flags: -O -C no-prepopulate-passes
 
 //@[aarch64-linux] compile-flags: --target aarch64-unknown-linux-gnu
 //@[aarch64-linux] needs-llvm-components: aarch64
 //@[aarch64-darwin] compile-flags: --target aarch64-apple-darwin
 //@[aarch64-darwin] needs-llvm-components: aarch64
-//@[wasm32-wasi] compile-flags: --target wasm32-wasi
-//@[wasm32-wasi] needs-llvm-components: webassembly
+//@[wasm32-wasip1] compile-flags: --target wasm32-wasip1
+//@[wasm32-wasip1] needs-llvm-components: webassembly
 
 // See ./transparent.rs
 // Some platforms pass large aggregates using immediate arrays in LLVMIR
diff --git a/tests/crashes/132127.rs b/tests/crashes/132127.rs
new file mode 100644
index 00000000000..cca354b9876
--- /dev/null
+++ b/tests/crashes/132127.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #132127
+#![feature(dyn_star)]
+
+trait Trait {}
+
+fn main() {
+    let x: dyn* Trait + Send = 1usize;
+    x as dyn* Trait;
+}
diff --git a/tests/crashes/132142.rs b/tests/crashes/132142.rs
new file mode 100644
index 00000000000..9a026f3bca7
--- /dev/null
+++ b/tests/crashes/132142.rs
@@ -0,0 +1,3 @@
+//@ known-bug: #132142
+
+async extern "C-cmse-nonsecure-entry" fn fun(...) {}
diff --git a/tests/crashes/132320.rs b/tests/crashes/132320.rs
new file mode 100644
index 00000000000..79181c3a2c5
--- /dev/null
+++ b/tests/crashes/132320.rs
@@ -0,0 +1,15 @@
+//@ known-bug: #132320
+//@ compile-flags: -Znext-solver=globally
+
+trait Foo {
+    type Item;
+    fn foo(&mut self);
+}
+
+impl Foo for () {
+    type Item = Option<()>;
+
+    fn foo(&mut self) {
+        let _ = Self::Item::None;
+    }
+}
diff --git a/tests/crashes/132330.rs b/tests/crashes/132330.rs
new file mode 100644
index 00000000000..3432685749d
--- /dev/null
+++ b/tests/crashes/132330.rs
@@ -0,0 +1,28 @@
+//@ known-bug: #132330
+//@compile-flags: -Znext-solver=globally
+
+trait Service {
+    type S;
+}
+
+trait Framing {
+    type F;
+}
+
+impl Framing for () {
+    type F = ();
+}
+
+trait HttpService<F: Framing>: Service<S = F::F> {}
+
+type BoxService = Box<dyn HttpService<(), S = ()>>;
+
+fn build_server<F: FnOnce() -> BoxService>(_: F) {}
+
+fn make_server<F: Framing>() -> Box<dyn HttpService<F, S = F::F>> {
+    unimplemented!()
+}
+
+fn main() {
+    build_server(|| make_server())
+}
diff --git a/tests/crashes/132335.rs b/tests/crashes/132335.rs
new file mode 100644
index 00000000000..2294539cfcf
--- /dev/null
+++ b/tests/crashes/132335.rs
@@ -0,0 +1,13 @@
+//@ known-bug: #132335
+//@ compile-flags: -Znext-solver=globally --crate-type lib --edition=2018
+use core::future::Future;
+use core::pin::Pin;
+
+pub trait Unit {}
+impl Unit for () {}
+
+pub fn get_all_files_in_dir() -> Pin<Box<dyn Future<Output = impl Unit>>> {
+    Box::pin(async {
+        get_all_files_in_dir().await;
+    })
+}
diff --git a/tests/crashes/132391.rs b/tests/crashes/132391.rs
new file mode 100644
index 00000000000..6c8c2c3a878
--- /dev/null
+++ b/tests/crashes/132391.rs
@@ -0,0 +1,8 @@
+//@ known-bug: #123291
+
+trait MyTrait {
+    #[repr(align)]
+    fn myfun();
+}
+
+pub fn main() {}
diff --git a/tests/crashes/132430.rs b/tests/crashes/132430.rs
new file mode 100644
index 00000000000..995bdf06224
--- /dev/null
+++ b/tests/crashes/132430.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #132430
+
+//@compile-flags: --edition=2018 --crate-type=lib
+#![feature(cmse_nonsecure_entry)]
+struct Test;
+
+impl Test {
+    pub async unsafe extern "C-cmse-nonsecure-entry" fn test(val: &str) {}
+}
diff --git a/tests/crashes/132530.rs b/tests/crashes/132530.rs
new file mode 100644
index 00000000000..b43da62bfc1
--- /dev/null
+++ b/tests/crashes/132530.rs
@@ -0,0 +1,9 @@
+//@ known-bug: #132530
+
+#![feature(non_lifetime_binders)]
+
+trait Trait<'a, A> {
+    type Assoc<'a> = i32;
+}
+
+fn a() -> impl for<T> Trait<Assoc = impl Trait<T>> {}
diff --git a/tests/crashes/README.md b/tests/crashes/README.md
index 71ce9b2eca6..2dc81a115df 100644
--- a/tests/crashes/README.md
+++ b/tests/crashes/README.md
@@ -8,7 +8,7 @@ A test will "pass" if rustc exits with something other than 1 or 0.
 
 When adding crashes from https://github.com/rust-lang/rust/issues, the
 issue number should be noted in the file name (12345.rs should suffice)
-and perhaps also inside the file via `//@ known-bug #4321`
+and also inside the file via `//@ known-bug #4321` if possible.
 
 If you happen to fix one of the crashes, please move it to a fitting
 subdirectory in `tests/ui` and give it a meaningful name.
@@ -21,3 +21,5 @@ to the description of your pull request will ensure the
 corresponding tickets will be closed automatically upon merge.
 The ticket ids can be found in the file name or the `known-bug` annotation
 inside the testfile.
+
+Please do not re-report any crashes that you find here!
diff --git a/tests/run-make/pointer-auth-link-with-c/rmake.rs b/tests/run-make/pointer-auth-link-with-c/rmake.rs
index 960eafa546b..7b6dff10eae 100644
--- a/tests/run-make/pointer-auth-link-with-c/rmake.rs
+++ b/tests/run-make/pointer-auth-link-with-c/rmake.rs
@@ -1,7 +1,7 @@
 // `-Z branch protection` is an unstable compiler feature which adds pointer-authentication
 // code (PAC), a useful hashing measure for verifying that pointers have not been modified.
 // This test checks that compilation and execution is successful when this feature is activated,
-// with some of its possible extra arguments (bti, pac-ret, leaf).
+// with some of its possible extra arguments (bti, pac-ret, pc, leaf, b-key).
 // See https://github.com/rust-lang/rust/pull/88354
 
 //@ only-aarch64
@@ -25,4 +25,16 @@ fn main() {
     llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run();
     rustc().arg("-Zbranch-protection=bti,pac-ret,leaf").input("test.rs").run();
     run("test");
+
+    // FIXME: +pc was only recently added to LLVM
+    // cc().arg("-v")
+    //     .arg("-c")
+    //     .out_exe("test")
+    //     .input("test.c")
+    //     .arg("-mbranch-protection=bti+pac-ret+pc+leaf")
+    //     .run();
+    // let obj_file = if is_msvc() { "test.obj" } else { "test" };
+    // llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run();
+    // rustc().arg("-Zbranch-protection=bti,pac-ret,pc,leaf").input("test.rs").run();
+    // run("test");
 }
diff --git a/tests/run-make/target-specs/definitely-not-builtin-target.json b/tests/run-make/target-specs/definitely-not-builtin-target.json
deleted file mode 100644
index b36fa993d97..00000000000
--- a/tests/run-make/target-specs/definitely-not-builtin-target.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "arch": "x86_64",
-  "is-builtin": true,
-  "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
-  "llvm-target": "x86_64-unknown-unknown-gnu",
-  "target-pointer-width": "64"
-}
diff --git a/tests/run-make/target-specs/rmake.rs b/tests/run-make/target-specs/rmake.rs
index 499c6c2079a..79c888ab340 100644
--- a/tests/run-make/target-specs/rmake.rs
+++ b/tests/run-make/target-specs/rmake.rs
@@ -54,11 +54,6 @@ fn main() {
         .run();
     rustc()
         .input("foo.rs")
-        .target("definitely-not-builtin-target")
-        .run_fail()
-        .assert_stderr_contains("may not set is_builtin");
-    rustc()
-        .input("foo.rs")
         .target("endianness-mismatch")
         .run_fail()
         .assert_stderr_contains(r#""data-layout" claims architecture is little-endian"#);
diff --git a/tests/rustdoc-ui/show-coverage-json.rs b/tests/rustdoc-ui/show-coverage-json.rs
new file mode 100644
index 00000000000..3851e34fe35
--- /dev/null
+++ b/tests/rustdoc-ui/show-coverage-json.rs
@@ -0,0 +1,13 @@
+//@ compile-flags: -Z unstable-options --show-coverage --output-format=json
+//@ check-pass
+
+mod bar {
+    /// a
+    ///
+    /// ```
+    /// let x = 0;
+    /// ```
+    pub struct Foo;
+}
+
+pub use bar::Foo;
diff --git a/tests/rustdoc-ui/show-coverage-json.stdout b/tests/rustdoc-ui/show-coverage-json.stdout
new file mode 100644
index 00000000000..ed5b5a60212
--- /dev/null
+++ b/tests/rustdoc-ui/show-coverage-json.stdout
@@ -0,0 +1 @@
+{"$DIR/show-coverage-json.rs":{"total":2,"with_docs":1,"total_examples":2,"with_examples":1}}
diff --git a/tests/rustdoc-ui/show-coverage.rs b/tests/rustdoc-ui/show-coverage.rs
new file mode 100644
index 00000000000..00bb1606a82
--- /dev/null
+++ b/tests/rustdoc-ui/show-coverage.rs
@@ -0,0 +1,13 @@
+//@ compile-flags: -Z unstable-options --show-coverage
+//@ check-pass
+
+mod bar {
+    /// a
+    ///
+    /// ```
+    /// let x = 0;
+    /// ```
+    pub struct Foo;
+}
+
+pub use bar::Foo;
diff --git a/tests/rustdoc-ui/show-coverage.stdout b/tests/rustdoc-ui/show-coverage.stdout
new file mode 100644
index 00000000000..b3b7679771f
--- /dev/null
+++ b/tests/rustdoc-ui/show-coverage.stdout
@@ -0,0 +1,7 @@
++-------------------------------------+------------+------------+------------+------------+
+| File                                | Documented | Percentage |   Examples | Percentage |
++-------------------------------------+------------+------------+------------+------------+
+| ...ests/rustdoc-ui/show-coverage.rs |          1 |      50.0% |          1 |      50.0% |
++-------------------------------------+------------+------------+------------+------------+
+| Total                               |          1 |      50.0% |          1 |      50.0% |
++-------------------------------------+------------+------------+------------+------------+
diff --git a/tests/rustdoc/const-intrinsic.rs b/tests/rustdoc/const-intrinsic.rs
index 520e253469c..8444d4a3aa7 100644
--- a/tests/rustdoc/const-intrinsic.rs
+++ b/tests/rustdoc/const-intrinsic.rs
@@ -1,20 +1,26 @@
-#![feature(intrinsics)]
+#![feature(intrinsics, rustc_attrs)]
 #![feature(staged_api)]
 
 #![crate_name = "foo"]
 #![stable(since="1.0.0", feature="rust1")]
 
-extern "rust-intrinsic" {
-    //@ has 'foo/fn.transmute.html'
-    //@ has - '//pre[@class="rust item-decl"]' 'pub const unsafe extern "rust-intrinsic" fn transmute<T, U>(_: T) -> U'
-    #[stable(since="1.0.0", feature="rust1")]
-    #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
-    pub fn transmute<T, U>(_: T) -> U;
+//@ has 'foo/fn.transmute.html'
+//@ has - '//pre[@class="rust item-decl"]' 'pub const unsafe fn transmute<T, U>(_: T) -> U'
+#[stable(since="1.0.0", feature="rust1")]
+#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn transmute<T, U>(_: T) -> U {
+    loop {}
+}
 
-    //@ has 'foo/fn.unreachable.html'
-    //@ has - '//pre[@class="rust item-decl"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
-    #[stable(since="1.0.0", feature="rust1")]
-    pub fn unreachable() -> !;
+//@ has 'foo/fn.unreachable.html'
+//@ has - '//pre[@class="rust item-decl"]' 'pub unsafe fn unreachable() -> !'
+#[stable(since="1.0.0", feature="rust1")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub unsafe fn unreachable() -> ! {
+    loop {}
 }
 
 extern "C" {
diff --git a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs
index 346f7120b5b..d301c355994 100644
--- a/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs
+++ b/tests/rustdoc/inline_cross/assoc_item_trait_bounds.rs
@@ -22,6 +22,7 @@ extern crate assoc_item_trait_bounds as aux;
 //@ has - '//*[@id="associatedtype.Out12"]' "type Out12: for<'w> Helper<B<'w> = Cow<'w, str>, A<'w> = bool>"
 //@ has - '//*[@id="associatedtype.Out13"]' "type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>"
 //@ has - '//*[@id="associatedtype.Out14"]' "type Out14<P: Copy + Eq, Q: ?Sized>"
+//@ has - '//*[@id="associatedtype.Out15"]' "type Out15: AsyncFnMut(i32) -> bool"
 //
 // Snapshots:
 // Check that we don't render any where-clauses for the following associated types since
diff --git a/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
index 551e97a2fa9..56708ec9310 100644
--- a/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
+++ b/tests/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
@@ -1,3 +1,7 @@
+#![feature(async_closure)]
+
+use std::ops::AsyncFnMut;
+
 pub trait Main {
     type Item;
 
@@ -16,6 +20,7 @@ pub trait Main {
     type Out12: for<'w> Helper<B<'w> = std::borrow::Cow<'w, str>, A<'w> = bool>;
     type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>;
     type Out14<P: Copy + Eq, Q: ?Sized>;
+    type Out15: AsyncFnMut(i32) -> bool;
 
     fn make<F>(_: F, _: impl FnMut(&str) -> bool)
     where
diff --git a/tests/ui-fulldeps/hash-stable-is-unstable.rs b/tests/ui-fulldeps/hash-stable-is-unstable.rs
index e5d158a2661..dc778695287 100644
--- a/tests/ui-fulldeps/hash-stable-is-unstable.rs
+++ b/tests/ui-fulldeps/hash-stable-is-unstable.rs
@@ -1,24 +1,25 @@
+//@ ignore-stage1 FIXME: this line can be removed once these new error messages are in stage 0 rustc
 //@ compile-flags: -Zdeduplicate-diagnostics=yes
 extern crate rustc_data_structures;
-//~^ use of unstable library feature 'rustc_private'
+//~^ use of unstable library feature `rustc_private`
 //~| NOTE: issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information
 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 extern crate rustc_macros;
-//~^ use of unstable library feature 'rustc_private'
+//~^ use of unstable library feature `rustc_private`
 //~| NOTE: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information
 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 extern crate rustc_query_system;
-//~^ use of unstable library feature 'rustc_private'
+//~^ use of unstable library feature `rustc_private`
 //~| NOTE: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information
 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 use rustc_macros::HashStable;
-//~^ use of unstable library feature 'rustc_private'
+//~^ use of unstable library feature `rustc_private`
 //~| NOTE: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information
 //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 #[derive(HashStable)]
-//~^ use of unstable library feature 'rustc_private'
+//~^ use of unstable library feature `rustc_private`
 //~| NOTE: in this expansion of #[derive(HashStable)]
 //~| NOTE: in this expansion of #[derive(HashStable)]
 //~| NOTE: in this expansion of #[derive(HashStable)]
diff --git a/tests/ui-fulldeps/hash-stable-is-unstable.stderr b/tests/ui-fulldeps/hash-stable-is-unstable.stderr
index c9aac624cbb..8d809175875 100644
--- a/tests/ui-fulldeps/hash-stable-is-unstable.stderr
+++ b/tests/ui-fulldeps/hash-stable-is-unstable.stderr
@@ -1,5 +1,5 @@
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:2:1
+error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+  --> $DIR/hash-stable-is-unstable.rs:3:1
    |
 LL | extern crate rustc_data_structures;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,8 +8,8 @@ LL | extern crate rustc_data_structures;
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:6:1
+error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+  --> $DIR/hash-stable-is-unstable.rs:7:1
    |
 LL | extern crate rustc_macros;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -18,8 +18,8 @@ LL | extern crate rustc_macros;
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:10:1
+error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+  --> $DIR/hash-stable-is-unstable.rs:11:1
    |
 LL | extern crate rustc_query_system;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -28,8 +28,8 @@ LL | extern crate rustc_query_system;
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:15:5
+error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+  --> $DIR/hash-stable-is-unstable.rs:16:5
    |
 LL | use rustc_macros::HashStable;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -38,8 +38,8 @@ LL | use rustc_macros::HashStable;
    = help: add `#![feature(rustc_private)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/hash-stable-is-unstable.rs:20:10
+error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+  --> $DIR/hash-stable-is-unstable.rs:21:10
    |
 LL | #[derive(HashStable)]
    |          ^^^^^^^^^^
diff --git a/tests/ui-fulldeps/pathless-extern-unstable.rs b/tests/ui-fulldeps/pathless-extern-unstable.rs
index 2da1a7f0ddc..27272135696 100644
--- a/tests/ui-fulldeps/pathless-extern-unstable.rs
+++ b/tests/ui-fulldeps/pathless-extern-unstable.rs
@@ -1,9 +1,10 @@
+//@ ignore-stage1 FIXME: this line can be removed once these new error messages are in stage 0 rustc
 //@ edition:2018
 //@ compile-flags:--extern rustc_middle
 
 // Test that `--extern rustc_middle` fails with `rustc_private`.
 
 pub use rustc_middle;
-//~^ ERROR use of unstable library feature 'rustc_private'
+//~^ ERROR use of unstable library feature `rustc_private`
 
 fn main() {}
diff --git a/tests/ui-fulldeps/pathless-extern-unstable.stderr b/tests/ui-fulldeps/pathless-extern-unstable.stderr
index 36e56adfdbd..a78b69f4d20 100644
--- a/tests/ui-fulldeps/pathless-extern-unstable.stderr
+++ b/tests/ui-fulldeps/pathless-extern-unstable.stderr
@@ -1,5 +1,5 @@
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/pathless-extern-unstable.rs:6:9
+error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+  --> $DIR/pathless-extern-unstable.rs:7:9
    |
 LL | pub use rustc_middle;
    |         ^^^^^^^^^^^^
diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr
new file mode 100644
index 00000000000..34105ceac04
--- /dev/null
+++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr
@@ -0,0 +1,264 @@
+error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:32:18
+   |
+LL |         asm!("", out("sp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:34:18
+   |
+LL |         asm!("", out("r2") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:38:18
+   |
+LL |         asm!("", out("r29") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:40:18
+   |
+LL |         asm!("", out("r30") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:42:18
+   |
+LL |         asm!("", out("fp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `lr`: the link register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:44:18
+   |
+LL |         asm!("", out("lr") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:46:18
+   |
+LL |         asm!("", out("ctr") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:48:18
+   |
+LL |         asm!("", out("vrsave") _);
+   |                  ^^^^^^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:66:18
+   |
+LL |         asm!("", in("cr") x);
+   |                  ^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:69:18
+   |
+LL |         asm!("", out("cr") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:72:26
+   |
+LL |         asm!("/* {} */", in(cr) x);
+   |                          ^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:75:26
+   |
+LL |         asm!("/* {} */", out(cr) _);
+   |                          ^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:79:18
+   |
+LL |         asm!("", in("xer") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:82:18
+   |
+LL |         asm!("", out("xer") x);
+   |                  ^^^^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:85:26
+   |
+LL |         asm!("/* {} */", in(xer) x);
+   |                          ^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:88:26
+   |
+LL |         asm!("/* {} */", out(xer) _);
+   |                          ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:93:18
+   |
+LL |         asm!("", in("v0") x);
+   |                  ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:96:18
+   |
+LL |         asm!("", out("v0") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:99:26
+   |
+LL |         asm!("/* {} */", in(vreg) x);
+   |                          ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:102:26
+   |
+LL |         asm!("/* {} */", out(vreg) _);
+   |                          ^^^^^^^^^^^
+
+error: register `cr0` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:106:31
+   |
+LL |         asm!("", out("cr") _, out("cr0") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr0`
+   |                  |
+   |                  register `cr`
+
+error: register `cr1` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:108:31
+   |
+LL |         asm!("", out("cr") _, out("cr1") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr1`
+   |                  |
+   |                  register `cr`
+
+error: register `cr2` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:110:31
+   |
+LL |         asm!("", out("cr") _, out("cr2") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr2`
+   |                  |
+   |                  register `cr`
+
+error: register `cr3` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:112:31
+   |
+LL |         asm!("", out("cr") _, out("cr3") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr3`
+   |                  |
+   |                  register `cr`
+
+error: register `cr4` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:114:31
+   |
+LL |         asm!("", out("cr") _, out("cr4") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr4`
+   |                  |
+   |                  register `cr`
+
+error: register `cr5` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:116:31
+   |
+LL |         asm!("", out("cr") _, out("cr5") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr5`
+   |                  |
+   |                  register `cr`
+
+error: register `cr6` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:118:31
+   |
+LL |         asm!("", out("cr") _, out("cr6") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr6`
+   |                  |
+   |                  register `cr`
+
+error: register `cr7` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:120:31
+   |
+LL |         asm!("", out("cr") _, out("cr7") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr7`
+   |                  |
+   |                  register `cr`
+
+error: cannot use register `r13`: r13 is a reserved register on this target
+  --> $DIR/bad-reg.rs:36:18
+   |
+LL |         asm!("", out("r13") _);
+   |                  ^^^^^^^^^^^^
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:66:27
+   |
+LL |         asm!("", in("cr") x);
+   |                           ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:69:28
+   |
+LL |         asm!("", out("cr") x);
+   |                            ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:72:33
+   |
+LL |         asm!("/* {} */", in(cr) x);
+   |                                 ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:79:28
+   |
+LL |         asm!("", in("xer") x);
+   |                            ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:82:29
+   |
+LL |         asm!("", out("xer") x);
+   |                             ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:85:34
+   |
+LL |         asm!("/* {} */", in(xer) x);
+   |                                  ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:93:27
+   |
+LL |         asm!("", in("v0") x);
+   |                           ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:96:28
+   |
+LL |         asm!("", out("v0") x);
+   |                            ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:99:35
+   |
+LL |         asm!("/* {} */", in(vreg) x);
+   |                                   ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: aborting due to 38 previous errors
+
diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr
new file mode 100644
index 00000000000..34105ceac04
--- /dev/null
+++ b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr
@@ -0,0 +1,264 @@
+error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:32:18
+   |
+LL |         asm!("", out("sp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:34:18
+   |
+LL |         asm!("", out("r2") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:38:18
+   |
+LL |         asm!("", out("r29") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:40:18
+   |
+LL |         asm!("", out("r30") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:42:18
+   |
+LL |         asm!("", out("fp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `lr`: the link register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:44:18
+   |
+LL |         asm!("", out("lr") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:46:18
+   |
+LL |         asm!("", out("ctr") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:48:18
+   |
+LL |         asm!("", out("vrsave") _);
+   |                  ^^^^^^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:66:18
+   |
+LL |         asm!("", in("cr") x);
+   |                  ^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:69:18
+   |
+LL |         asm!("", out("cr") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:72:26
+   |
+LL |         asm!("/* {} */", in(cr) x);
+   |                          ^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:75:26
+   |
+LL |         asm!("/* {} */", out(cr) _);
+   |                          ^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:79:18
+   |
+LL |         asm!("", in("xer") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:82:18
+   |
+LL |         asm!("", out("xer") x);
+   |                  ^^^^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:85:26
+   |
+LL |         asm!("/* {} */", in(xer) x);
+   |                          ^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:88:26
+   |
+LL |         asm!("/* {} */", out(xer) _);
+   |                          ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:93:18
+   |
+LL |         asm!("", in("v0") x);
+   |                  ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:96:18
+   |
+LL |         asm!("", out("v0") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:99:26
+   |
+LL |         asm!("/* {} */", in(vreg) x);
+   |                          ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:102:26
+   |
+LL |         asm!("/* {} */", out(vreg) _);
+   |                          ^^^^^^^^^^^
+
+error: register `cr0` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:106:31
+   |
+LL |         asm!("", out("cr") _, out("cr0") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr0`
+   |                  |
+   |                  register `cr`
+
+error: register `cr1` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:108:31
+   |
+LL |         asm!("", out("cr") _, out("cr1") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr1`
+   |                  |
+   |                  register `cr`
+
+error: register `cr2` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:110:31
+   |
+LL |         asm!("", out("cr") _, out("cr2") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr2`
+   |                  |
+   |                  register `cr`
+
+error: register `cr3` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:112:31
+   |
+LL |         asm!("", out("cr") _, out("cr3") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr3`
+   |                  |
+   |                  register `cr`
+
+error: register `cr4` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:114:31
+   |
+LL |         asm!("", out("cr") _, out("cr4") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr4`
+   |                  |
+   |                  register `cr`
+
+error: register `cr5` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:116:31
+   |
+LL |         asm!("", out("cr") _, out("cr5") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr5`
+   |                  |
+   |                  register `cr`
+
+error: register `cr6` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:118:31
+   |
+LL |         asm!("", out("cr") _, out("cr6") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr6`
+   |                  |
+   |                  register `cr`
+
+error: register `cr7` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:120:31
+   |
+LL |         asm!("", out("cr") _, out("cr7") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr7`
+   |                  |
+   |                  register `cr`
+
+error: cannot use register `r13`: r13 is a reserved register on this target
+  --> $DIR/bad-reg.rs:36:18
+   |
+LL |         asm!("", out("r13") _);
+   |                  ^^^^^^^^^^^^
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:66:27
+   |
+LL |         asm!("", in("cr") x);
+   |                           ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:69:28
+   |
+LL |         asm!("", out("cr") x);
+   |                            ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:72:33
+   |
+LL |         asm!("/* {} */", in(cr) x);
+   |                                 ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:79:28
+   |
+LL |         asm!("", in("xer") x);
+   |                            ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:82:29
+   |
+LL |         asm!("", out("xer") x);
+   |                             ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:85:34
+   |
+LL |         asm!("/* {} */", in(xer) x);
+   |                                  ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:93:27
+   |
+LL |         asm!("", in("v0") x);
+   |                           ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:96:28
+   |
+LL |         asm!("", out("v0") x);
+   |                            ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:99:35
+   |
+LL |         asm!("/* {} */", in(vreg) x);
+   |                                   ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: aborting due to 38 previous errors
+
diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr
new file mode 100644
index 00000000000..34105ceac04
--- /dev/null
+++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr
@@ -0,0 +1,264 @@
+error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:32:18
+   |
+LL |         asm!("", out("sp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:34:18
+   |
+LL |         asm!("", out("r2") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:38:18
+   |
+LL |         asm!("", out("r29") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:40:18
+   |
+LL |         asm!("", out("r30") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:42:18
+   |
+LL |         asm!("", out("fp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `lr`: the link register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:44:18
+   |
+LL |         asm!("", out("lr") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:46:18
+   |
+LL |         asm!("", out("ctr") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:48:18
+   |
+LL |         asm!("", out("vrsave") _);
+   |                  ^^^^^^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:66:18
+   |
+LL |         asm!("", in("cr") x);
+   |                  ^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:69:18
+   |
+LL |         asm!("", out("cr") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:72:26
+   |
+LL |         asm!("/* {} */", in(cr) x);
+   |                          ^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:75:26
+   |
+LL |         asm!("/* {} */", out(cr) _);
+   |                          ^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:79:18
+   |
+LL |         asm!("", in("xer") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:82:18
+   |
+LL |         asm!("", out("xer") x);
+   |                  ^^^^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:85:26
+   |
+LL |         asm!("/* {} */", in(xer) x);
+   |                          ^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:88:26
+   |
+LL |         asm!("/* {} */", out(xer) _);
+   |                          ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:93:18
+   |
+LL |         asm!("", in("v0") x);
+   |                  ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:96:18
+   |
+LL |         asm!("", out("v0") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:99:26
+   |
+LL |         asm!("/* {} */", in(vreg) x);
+   |                          ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:102:26
+   |
+LL |         asm!("/* {} */", out(vreg) _);
+   |                          ^^^^^^^^^^^
+
+error: register `cr0` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:106:31
+   |
+LL |         asm!("", out("cr") _, out("cr0") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr0`
+   |                  |
+   |                  register `cr`
+
+error: register `cr1` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:108:31
+   |
+LL |         asm!("", out("cr") _, out("cr1") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr1`
+   |                  |
+   |                  register `cr`
+
+error: register `cr2` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:110:31
+   |
+LL |         asm!("", out("cr") _, out("cr2") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr2`
+   |                  |
+   |                  register `cr`
+
+error: register `cr3` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:112:31
+   |
+LL |         asm!("", out("cr") _, out("cr3") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr3`
+   |                  |
+   |                  register `cr`
+
+error: register `cr4` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:114:31
+   |
+LL |         asm!("", out("cr") _, out("cr4") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr4`
+   |                  |
+   |                  register `cr`
+
+error: register `cr5` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:116:31
+   |
+LL |         asm!("", out("cr") _, out("cr5") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr5`
+   |                  |
+   |                  register `cr`
+
+error: register `cr6` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:118:31
+   |
+LL |         asm!("", out("cr") _, out("cr6") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr6`
+   |                  |
+   |                  register `cr`
+
+error: register `cr7` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:120:31
+   |
+LL |         asm!("", out("cr") _, out("cr7") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr7`
+   |                  |
+   |                  register `cr`
+
+error: cannot use register `r13`: r13 is a reserved register on this target
+  --> $DIR/bad-reg.rs:36:18
+   |
+LL |         asm!("", out("r13") _);
+   |                  ^^^^^^^^^^^^
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:66:27
+   |
+LL |         asm!("", in("cr") x);
+   |                           ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:69:28
+   |
+LL |         asm!("", out("cr") x);
+   |                            ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:72:33
+   |
+LL |         asm!("/* {} */", in(cr) x);
+   |                                 ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:79:28
+   |
+LL |         asm!("", in("xer") x);
+   |                            ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:82:29
+   |
+LL |         asm!("", out("xer") x);
+   |                             ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:85:34
+   |
+LL |         asm!("/* {} */", in(xer) x);
+   |                                  ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:93:27
+   |
+LL |         asm!("", in("v0") x);
+   |                           ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:96:28
+   |
+LL |         asm!("", out("v0") x);
+   |                            ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:99:35
+   |
+LL |         asm!("/* {} */", in(vreg) x);
+   |                                   ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: aborting due to 38 previous errors
+
diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr
new file mode 100644
index 00000000000..34105ceac04
--- /dev/null
+++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr
@@ -0,0 +1,264 @@
+error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:32:18
+   |
+LL |         asm!("", out("sp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:34:18
+   |
+LL |         asm!("", out("r2") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:38:18
+   |
+LL |         asm!("", out("r29") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:40:18
+   |
+LL |         asm!("", out("r30") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:42:18
+   |
+LL |         asm!("", out("fp") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `lr`: the link register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:44:18
+   |
+LL |         asm!("", out("lr") _);
+   |                  ^^^^^^^^^^^
+
+error: invalid register `ctr`: the counter register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:46:18
+   |
+LL |         asm!("", out("ctr") _);
+   |                  ^^^^^^^^^^^^
+
+error: invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
+  --> $DIR/bad-reg.rs:48:18
+   |
+LL |         asm!("", out("vrsave") _);
+   |                  ^^^^^^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:66:18
+   |
+LL |         asm!("", in("cr") x);
+   |                  ^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:69:18
+   |
+LL |         asm!("", out("cr") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:72:26
+   |
+LL |         asm!("/* {} */", in(cr) x);
+   |                          ^^^^^^^^
+
+error: register class `cr` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:75:26
+   |
+LL |         asm!("/* {} */", out(cr) _);
+   |                          ^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:79:18
+   |
+LL |         asm!("", in("xer") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:82:18
+   |
+LL |         asm!("", out("xer") x);
+   |                  ^^^^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:85:26
+   |
+LL |         asm!("/* {} */", in(xer) x);
+   |                          ^^^^^^^^^
+
+error: register class `xer` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:88:26
+   |
+LL |         asm!("/* {} */", out(xer) _);
+   |                          ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:93:18
+   |
+LL |         asm!("", in("v0") x);
+   |                  ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:96:18
+   |
+LL |         asm!("", out("v0") x);
+   |                  ^^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:99:26
+   |
+LL |         asm!("/* {} */", in(vreg) x);
+   |                          ^^^^^^^^^^
+
+error: register class `vreg` can only be used as a clobber, not as an input or output
+  --> $DIR/bad-reg.rs:102:26
+   |
+LL |         asm!("/* {} */", out(vreg) _);
+   |                          ^^^^^^^^^^^
+
+error: register `cr0` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:106:31
+   |
+LL |         asm!("", out("cr") _, out("cr0") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr0`
+   |                  |
+   |                  register `cr`
+
+error: register `cr1` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:108:31
+   |
+LL |         asm!("", out("cr") _, out("cr1") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr1`
+   |                  |
+   |                  register `cr`
+
+error: register `cr2` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:110:31
+   |
+LL |         asm!("", out("cr") _, out("cr2") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr2`
+   |                  |
+   |                  register `cr`
+
+error: register `cr3` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:112:31
+   |
+LL |         asm!("", out("cr") _, out("cr3") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr3`
+   |                  |
+   |                  register `cr`
+
+error: register `cr4` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:114:31
+   |
+LL |         asm!("", out("cr") _, out("cr4") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr4`
+   |                  |
+   |                  register `cr`
+
+error: register `cr5` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:116:31
+   |
+LL |         asm!("", out("cr") _, out("cr5") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr5`
+   |                  |
+   |                  register `cr`
+
+error: register `cr6` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:118:31
+   |
+LL |         asm!("", out("cr") _, out("cr6") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr6`
+   |                  |
+   |                  register `cr`
+
+error: register `cr7` conflicts with register `cr`
+  --> $DIR/bad-reg.rs:120:31
+   |
+LL |         asm!("", out("cr") _, out("cr7") _);
+   |                  -----------  ^^^^^^^^^^^^ register `cr7`
+   |                  |
+   |                  register `cr`
+
+error: cannot use register `r13`: r13 is a reserved register on this target
+  --> $DIR/bad-reg.rs:36:18
+   |
+LL |         asm!("", out("r13") _);
+   |                  ^^^^^^^^^^^^
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:66:27
+   |
+LL |         asm!("", in("cr") x);
+   |                           ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:69:28
+   |
+LL |         asm!("", out("cr") x);
+   |                            ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:72:33
+   |
+LL |         asm!("/* {} */", in(cr) x);
+   |                                 ^
+   |
+   = note: register class `cr` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:79:28
+   |
+LL |         asm!("", in("xer") x);
+   |                            ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:82:29
+   |
+LL |         asm!("", out("xer") x);
+   |                             ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:85:34
+   |
+LL |         asm!("/* {} */", in(xer) x);
+   |                                  ^
+   |
+   = note: register class `xer` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:93:27
+   |
+LL |         asm!("", in("v0") x);
+   |                           ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:96:28
+   |
+LL |         asm!("", out("v0") x);
+   |                            ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: type `i32` cannot be used with this register class
+  --> $DIR/bad-reg.rs:99:35
+   |
+LL |         asm!("/* {} */", in(vreg) x);
+   |                                   ^
+   |
+   = note: register class `vreg` supports these types: 
+
+error: aborting due to 38 previous errors
+
diff --git a/tests/ui/asm/powerpc/bad-reg.rs b/tests/ui/asm/powerpc/bad-reg.rs
new file mode 100644
index 00000000000..5023ad51838
--- /dev/null
+++ b/tests/ui/asm/powerpc/bad-reg.rs
@@ -0,0 +1,124 @@
+//@ revisions: powerpc powerpc64 powerpc64le aix64
+//@[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
+//@[powerpc] needs-llvm-components: powerpc
+//@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
+//@[powerpc64] needs-llvm-components: powerpc
+//@[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
+//@[powerpc64le] needs-llvm-components: powerpc
+//@[aix64] compile-flags: --target powerpc64-ibm-aix
+//@[aix64] needs-llvm-components: powerpc
+//@ needs-asm-support
+
+#![crate_type = "rlib"]
+#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for i32 {}
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+
+fn f() {
+    let mut x = 0;
+    unsafe {
+        // Unsupported registers
+        asm!("", out("sp") _);
+        //~^ ERROR invalid register `sp`: the stack pointer cannot be used as an operand for inline asm
+        asm!("", out("r2") _);
+        //~^ ERROR invalid register `r2`: r2 is a system reserved register and cannot be used as an operand for inline asm
+        asm!("", out("r13") _);
+        //~^ ERROR cannot use register `r13`: r13 is a reserved register on this target
+        asm!("", out("r29") _);
+        //~^ ERROR invalid register `r29`: r29 is used internally by LLVM and cannot be used as an operand for inline asm
+        asm!("", out("r30") _);
+        //~^ ERROR invalid register `r30`: r30 is used internally by LLVM and cannot be used as an operand for inline asm
+        asm!("", out("fp") _);
+        //~^ ERROR invalid register `fp`: the frame pointer cannot be used as an operand for inline asm
+        asm!("", out("lr") _);
+        //~^ ERROR invalid register `lr`: the link register cannot be used as an operand for inline asm
+        asm!("", out("ctr") _);
+        //~^ ERROR invalid register `ctr`: the counter register cannot be used as an operand for inline asm
+        asm!("", out("vrsave") _);
+        //~^ ERROR invalid register `vrsave`: the vrsave register cannot be used as an operand for inline asm
+        asm!("", out("v20") _);
+        asm!("", out("v21") _);
+        asm!("", out("v22") _);
+        asm!("", out("v23") _);
+        asm!("", out("v24") _);
+        asm!("", out("v25") _);
+        asm!("", out("v26") _);
+        asm!("", out("v27") _);
+        asm!("", out("v28") _);
+        asm!("", out("v29") _);
+        asm!("", out("v30") _);
+        asm!("", out("v31") _);
+
+        // Clobber-only registers
+        // cr
+        asm!("", out("cr") _); // ok
+        asm!("", in("cr") x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("", out("cr") x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", in(cr) x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", out(cr) _);
+        //~^ ERROR can only be used as a clobber
+        // xer
+        asm!("", out("xer") _); // ok
+        asm!("", in("xer") x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("", out("xer") x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", in(xer) x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", out(xer) _);
+        //~^ ERROR can only be used as a clobber
+        // vreg
+        asm!("", out("v0") _); // ok
+        // FIXME: will be supported in the subsequent patch: https://github.com/rust-lang/rust/pull/131551
+        asm!("", in("v0") x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("", out("v0") x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", in(vreg) x);
+        //~^ ERROR can only be used as a clobber
+        //~| ERROR type `i32` cannot be used with this register class
+        asm!("/* {} */", out(vreg) _);
+        //~^ ERROR can only be used as a clobber
+
+        // Overlapping-only registers
+        asm!("", out("cr") _, out("cr0") _);
+        //~^ ERROR register `cr0` conflicts with register `cr`
+        asm!("", out("cr") _, out("cr1") _);
+        //~^ ERROR register `cr1` conflicts with register `cr`
+        asm!("", out("cr") _, out("cr2") _);
+        //~^ ERROR register `cr2` conflicts with register `cr`
+        asm!("", out("cr") _, out("cr3") _);
+        //~^ ERROR register `cr3` conflicts with register `cr`
+        asm!("", out("cr") _, out("cr4") _);
+        //~^ ERROR register `cr4` conflicts with register `cr`
+        asm!("", out("cr") _, out("cr5") _);
+        //~^ ERROR register `cr5` conflicts with register `cr`
+        asm!("", out("cr") _, out("cr6") _);
+        //~^ ERROR register `cr6` conflicts with register `cr`
+        asm!("", out("cr") _, out("cr7") _);
+        //~^ ERROR register `cr7` conflicts with register `cr`
+        asm!("", out("f0") _, out("v0") _); // ok
+    }
+}
diff --git a/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs b/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs
index ddb9278bafa..91641489cc9 100644
--- a/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs
+++ b/tests/ui/associated-inherent-types/assoc-inherent-unstable.rs
@@ -4,6 +4,6 @@
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
 
-type Data = aux::Owner::Data; //~ ERROR use of unstable library feature 'data'
+type Data = aux::Owner::Data; //~ ERROR use of unstable library feature `data`
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr b/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr
index ab8cdb6f80a..132d566fecd 100644
--- a/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr
+++ b/tests/ui/associated-inherent-types/assoc-inherent-unstable.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'data'
+error[E0658]: use of unstable library feature `data`
   --> $DIR/assoc-inherent-unstable.rs:7:13
    |
 LL | type Data = aux::Owner::Data;
diff --git a/tests/ui/async-await/async-fn/edition-2015.rs b/tests/ui/async-await/async-fn/edition-2015.rs
index 50448313b30..e38179758f6 100644
--- a/tests/ui/async-await/async-fn/edition-2015.rs
+++ b/tests/ui/async-await/async-fn/edition-2015.rs
@@ -3,7 +3,7 @@ fn foo(x: impl async Fn()) -> impl async Fn() { x }
 //~| ERROR `async` trait bounds are only allowed in Rust 2018 or later
 //~| ERROR async closures are unstable
 //~| ERROR async closures are unstable
-//~| ERROR use of unstable library feature 'async_closure'
-//~| ERROR use of unstable library feature 'async_closure'
+//~| ERROR use of unstable library feature `async_closure`
+//~| ERROR use of unstable library feature `async_closure`
 
 fn main() {}
diff --git a/tests/ui/async-await/async-fn/edition-2015.stderr b/tests/ui/async-await/async-fn/edition-2015.stderr
index 358bb3e112e..25101cb65df 100644
--- a/tests/ui/async-await/async-fn/edition-2015.stderr
+++ b/tests/ui/async-await/async-fn/edition-2015.stderr
@@ -38,7 +38,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: to use an async block, remove the `||`: `async {`
 
-error[E0658]: use of unstable library feature 'async_closure'
+error[E0658]: use of unstable library feature `async_closure`
   --> $DIR/edition-2015.rs:1:42
    |
 LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
@@ -48,7 +48,7 @@ LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
    = help: add `#![feature(async_closure)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'async_closure'
+error[E0658]: use of unstable library feature `async_closure`
   --> $DIR/edition-2015.rs:1:22
    |
 LL | fn foo(x: impl async Fn()) -> impl async Fn() { x }
diff --git a/tests/ui/box/alloc-unstable-fail.rs b/tests/ui/box/alloc-unstable-fail.rs
index 9427571648c..e209af97d7f 100644
--- a/tests/ui/box/alloc-unstable-fail.rs
+++ b/tests/ui/box/alloc-unstable-fail.rs
@@ -2,5 +2,5 @@ use std::boxed::Box;
 
 fn main() {
     let _boxed: Box<u32, _> = Box::new(10);
-    //~^ ERROR use of unstable library feature 'allocator_api'
+    //~^ ERROR use of unstable library feature `allocator_api`
 }
diff --git a/tests/ui/box/alloc-unstable-fail.stderr b/tests/ui/box/alloc-unstable-fail.stderr
index 9e1e12a2b6a..6ce63a79966 100644
--- a/tests/ui/box/alloc-unstable-fail.stderr
+++ b/tests/ui/box/alloc-unstable-fail.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'allocator_api'
+error[E0658]: use of unstable library feature `allocator_api`
   --> $DIR/alloc-unstable-fail.rs:4:26
    |
 LL |     let _boxed: Box<u32, _> = Box::new(10);
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index 7589551a87c..43766788de7 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra`
 LL |     cfg!(target_feature = "zebra");
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 246 more
+   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 247 more
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: 27 warnings emitted
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 37d2b0343c9..224313c6c8d 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -174,7 +174,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_feature = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt`
+   = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt`
    = 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/closures/2229_closure_analysis/arrays-completely-captured.rs b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs
index c194cea2e37..27b17a56f12 100644
--- a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs
+++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.rs
@@ -13,10 +13,10 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         m[0] += 10;
-        //~^ NOTE: Capturing m[] -> MutBorrow
-        //~| NOTE: Min Capture m[] -> MutBorrow
+        //~^ NOTE: Capturing m[] -> Mutable
+        //~| NOTE: Min Capture m[] -> Mutable
         m[1] += 40;
-        //~^ NOTE: Capturing m[] -> MutBorrow
+        //~^ NOTE: Capturing m[] -> Mutable
     };
 
     c();
diff --git a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr
index d7582dcfcc7..3c4f2de73a4 100644
--- a/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr
+++ b/tests/ui/closures/2229_closure_analysis/arrays-completely-captured.stderr
@@ -20,12 +20,12 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing m[] -> MutBorrow
+note: Capturing m[] -> Mutable
   --> $DIR/arrays-completely-captured.rs:15:9
    |
 LL |         m[0] += 10;
    |         ^
-note: Capturing m[] -> MutBorrow
+note: Capturing m[] -> Mutable
   --> $DIR/arrays-completely-captured.rs:18:9
    |
 LL |         m[1] += 40;
@@ -43,7 +43,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture m[] -> MutBorrow
+note: Min Capture m[] -> Mutable
   --> $DIR/arrays-completely-captured.rs:15:9
    |
 LL |         m[0] += 10;
diff --git a/tests/ui/closures/2229_closure_analysis/by_value.rs b/tests/ui/closures/2229_closure_analysis/by_value.rs
index 3fa28a1c6e9..2c9202fd617 100644
--- a/tests/ui/closures/2229_closure_analysis/by_value.rs
+++ b/tests/ui/closures/2229_closure_analysis/by_value.rs
@@ -26,8 +26,8 @@ fn big_box() {
         //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
         //~| NOTE: Min Capture t[(0, 0)] -> ByValue
         println!("{} {:?}", t.1, p);
-        //~^ NOTE: Capturing t[(1, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing t[(1, 0)] -> Immutable
+        //~| NOTE: Min Capture t[(1, 0)] -> Immutable
     };
 
     c();
diff --git a/tests/ui/closures/2229_closure_analysis/by_value.stderr b/tests/ui/closures/2229_closure_analysis/by_value.stderr
index 0dd9991cf84..f843b76d723 100644
--- a/tests/ui/closures/2229_closure_analysis/by_value.stderr
+++ b/tests/ui/closures/2229_closure_analysis/by_value.stderr
@@ -25,7 +25,7 @@ note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
    |
 LL |         let p = t.0.0;
    |                 ^^^^^
-note: Capturing t[(1, 0)] -> ImmBorrow
+note: Capturing t[(1, 0)] -> Immutable
   --> $DIR/by_value.rs:28:29
    |
 LL |         println!("{} {:?}", t.1, p);
@@ -48,7 +48,7 @@ note: Min Capture t[(0, 0)] -> ByValue
    |
 LL |         let p = t.0.0;
    |                 ^^^^^
-note: Min Capture t[(1, 0)] -> ImmBorrow
+note: Min Capture t[(1, 0)] -> Immutable
   --> $DIR/by_value.rs:28:29
    |
 LL |         println!("{} {:?}", t.1, p);
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs
index fa1ddeb0176..0c42e66a2fa 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs
@@ -20,15 +20,15 @@ fn main() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         println!("{:?}", p);
-        //~^ NOTE: Capturing p[] -> ImmBorrow
-        //~| NOTE: Min Capture p[] -> ImmBorrow
+        //~^ NOTE: Capturing p[] -> Immutable
+        //~| NOTE: Min Capture p[] -> Immutable
         println!("{:?}", p.x);
-        //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing p[(0, 0)] -> Immutable
 
         println!("{:?}", q.x);
-        //~^ NOTE: Capturing q[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing q[(0, 0)] -> Immutable
         println!("{:?}", q);
-        //~^ NOTE: Capturing q[] -> ImmBorrow
-        //~| NOTE: Min Capture q[] -> ImmBorrow
+        //~^ NOTE: Capturing q[] -> Immutable
+        //~| NOTE: Min Capture q[] -> Immutable
     };
 }
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr
index d2409c9367c..64ae704bc90 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr
@@ -20,22 +20,22 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing p[] -> ImmBorrow
+note: Capturing p[] -> Immutable
   --> $DIR/capture-analysis-1.rs:22:26
    |
 LL |         println!("{:?}", p);
    |                          ^
-note: Capturing p[(0, 0)] -> ImmBorrow
+note: Capturing p[(0, 0)] -> Immutable
   --> $DIR/capture-analysis-1.rs:25:26
    |
 LL |         println!("{:?}", p.x);
    |                          ^^^
-note: Capturing q[(0, 0)] -> ImmBorrow
+note: Capturing q[(0, 0)] -> Immutable
   --> $DIR/capture-analysis-1.rs:28:26
    |
 LL |         println!("{:?}", q.x);
    |                          ^^^
-note: Capturing q[] -> ImmBorrow
+note: Capturing q[] -> Immutable
   --> $DIR/capture-analysis-1.rs:30:26
    |
 LL |         println!("{:?}", q);
@@ -53,12 +53,12 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture p[] -> ImmBorrow
+note: Min Capture p[] -> Immutable
   --> $DIR/capture-analysis-1.rs:22:26
    |
 LL |         println!("{:?}", p);
    |                          ^
-note: Min Capture q[] -> ImmBorrow
+note: Min Capture q[] -> Immutable
   --> $DIR/capture-analysis-1.rs:30:26
    |
 LL |         println!("{:?}", q);
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs
index eb342b303f9..adb618d1771 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs
@@ -22,7 +22,7 @@ fn main() {
         //~^ NOTE: Capturing p[(0, 0)] -> ByValue
         //~| NOTE: p[] captured as ByValue here
         println!("{:?}", p);
-        //~^ NOTE: Capturing p[] -> ImmBorrow
+        //~^ NOTE: Capturing p[] -> Immutable
         //~| NOTE: Min Capture p[] -> ByValue
         //~| NOTE: p[] used here
     };
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr
index 7049c708bb8..40c075f3cc8 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-2.stderr
@@ -25,7 +25,7 @@ note: Capturing p[(0, 0)] -> ByValue
    |
 LL |         let _x = p.x;
    |                  ^^^
-note: Capturing p[] -> ImmBorrow
+note: Capturing p[] -> Immutable
   --> $DIR/capture-analysis-2.rs:24:26
    |
 LL |         println!("{:?}", p);
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs
index e1476e415d9..0a21eaaaa12 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.rs
@@ -27,7 +27,7 @@ fn main() {
         //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ByValue
         //~| NOTE: a[(0, 0)] captured as ByValue here
         println!("{:?}", a.b);
-        //~^ NOTE: Capturing a[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing a[(0, 0)] -> Immutable
         //~| NOTE: Min Capture a[(0, 0)] -> ByValue
         //~| NOTE: a[(0, 0)] used here
     };
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr
index 698b51a4fdb..a4689f2ea96 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-3.stderr
@@ -25,7 +25,7 @@ note: Capturing a[(0, 0),(0, 0)] -> ByValue
    |
 LL |         let _x = a.b.c;
    |                  ^^^^^
-note: Capturing a[(0, 0)] -> ImmBorrow
+note: Capturing a[(0, 0)] -> Immutable
   --> $DIR/capture-analysis-3.rs:29:26
    |
 LL |         println!("{:?}", a.b);
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs
index 6d53a0ac634..790dad0710b 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.rs
@@ -27,6 +27,6 @@ fn main() {
         //~^ NOTE: Capturing a[(0, 0)] -> ByValue
         //~| NOTE: Min Capture a[(0, 0)] -> ByValue
         println!("{:?}", a.b.c);
-        //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing a[(0, 0),(0, 0)] -> Immutable
     };
 }
diff --git a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr
index 9cd0dcf720e..9d3004dbbb0 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-analysis-4.stderr
@@ -25,7 +25,7 @@ note: Capturing a[(0, 0)] -> ByValue
    |
 LL |         let _x = a.b;
    |                  ^^^
-note: Capturing a[(0, 0),(0, 0)] -> ImmBorrow
+note: Capturing a[(0, 0),(0, 0)] -> Immutable
   --> $DIR/capture-analysis-4.rs:29:26
    |
 LL |         println!("{:?}", a.b.c);
diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs
index 68703333fa8..af12e0b259d 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs
+++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.rs
@@ -18,8 +18,8 @@ fn main() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         println!("{}", p.x);
-        //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing p[(0, 0)] -> Immutable
+        //~| NOTE: Min Capture p[(0, 0)] -> Immutable
     };
 
     // `c` should only capture `p.x`, therefore mutating `p.y` is allowed.
diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr
index 92a719d6098..48fbd682a5b 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-struct.stderr
@@ -20,7 +20,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing p[(0, 0)] -> ImmBorrow
+note: Capturing p[(0, 0)] -> Immutable
   --> $DIR/capture-disjoint-field-struct.rs:20:24
    |
 LL |         println!("{}", p.x);
@@ -38,7 +38,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture p[(0, 0)] -> ImmBorrow
+note: Min Capture p[(0, 0)] -> Immutable
   --> $DIR/capture-disjoint-field-struct.rs:20:24
    |
 LL |         println!("{}", p.x);
diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs
index 0c006ffdd72..ccd26049264 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs
+++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.rs
@@ -13,8 +13,8 @@ fn main() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         println!("{}", t.0);
-        //~^ NOTE: Capturing t[(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture t[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing t[(0, 0)] -> Immutable
+        //~| NOTE: Min Capture t[(0, 0)] -> Immutable
     };
 
     // `c` only captures t.0, therefore mutating t.1 is allowed.
diff --git a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr
index d5333bf71db..496511d6025 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-disjoint-field-tuple.stderr
@@ -20,7 +20,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0)] -> ImmBorrow
+note: Capturing t[(0, 0)] -> Immutable
   --> $DIR/capture-disjoint-field-tuple.rs:15:24
    |
 LL |         println!("{}", t.0);
@@ -38,7 +38,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0)] -> ImmBorrow
+note: Min Capture t[(0, 0)] -> Immutable
   --> $DIR/capture-disjoint-field-tuple.rs:15:24
    |
 LL |         println!("{}", t.0);
diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.rs b/tests/ui/closures/2229_closure_analysis/capture-enums.rs
index 6f973739e66..b1e21bd0f8d 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-enums.rs
+++ b/tests/ui/closures/2229_closure_analysis/capture-enums.rs
@@ -21,14 +21,14 @@ fn multi_variant_enum() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         if let Info::Point(_, _, str) = point {
-            //~^ NOTE: Capturing point[] -> ImmBorrow
+            //~^ NOTE: Capturing point[] -> Immutable
             //~| NOTE: Capturing point[(2, 0)] -> ByValue
             //~| NOTE: Min Capture point[] -> ByValue
             println!("{}", str);
         }
 
         if let Info::Meta(_, v) = meta {
-            //~^ NOTE: Capturing meta[] -> ImmBorrow
+            //~^ NOTE: Capturing meta[] -> Immutable
             //~| NOTE: Capturing meta[(1, 1)] -> ByValue
             //~| NOTE: Min Capture meta[] -> ByValue
             println!("{:?}", v);
diff --git a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr
index 8b258569d95..2d70b614858 100644
--- a/tests/ui/closures/2229_closure_analysis/capture-enums.stderr
+++ b/tests/ui/closures/2229_closure_analysis/capture-enums.stderr
@@ -30,7 +30,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Capturing point[] -> ImmBorrow
+note: Capturing point[] -> Immutable
   --> $DIR/capture-enums.rs:23:41
    |
 LL |         if let Info::Point(_, _, str) = point {
@@ -40,7 +40,7 @@ note: Capturing point[(2, 0)] -> ByValue
    |
 LL |         if let Info::Point(_, _, str) = point {
    |                                         ^^^^^
-note: Capturing meta[] -> ImmBorrow
+note: Capturing meta[] -> Immutable
   --> $DIR/capture-enums.rs:30:35
    |
 LL |         if let Info::Meta(_, v) = meta {
diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs
index 5143836ad6b..61b707605c2 100644
--- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs
+++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.rs
@@ -39,13 +39,13 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let x = &p.a.p.x;
-        //~^ NOTE: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing p[(0, 0),(0, 0),(0, 0)] -> Immutable
         p.b.q.y = 9;
-        //~^ NOTE: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow
-        //~| NOTE: p[] captured as MutBorrow here
+        //~^ NOTE: Capturing p[(1, 0),(1, 0),(1, 0)] -> Mutable
+        //~| NOTE: p[] captured as Mutable here
         println!("{:?}", p);
-        //~^ NOTE: Capturing p[] -> ImmBorrow
-        //~| NOTE: Min Capture p[] -> MutBorrow
+        //~^ NOTE: Capturing p[] -> Immutable
+        //~| NOTE: Min Capture p[] -> Mutable
         //~| NOTE: p[] used here
     };
 }
diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr
index 55ba416dfd9..d118f7573a4 100644
--- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr
+++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-struct.stderr
@@ -20,17 +20,17 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing p[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
+note: Capturing p[(0, 0),(0, 0),(0, 0)] -> Immutable
   --> $DIR/deep-multilevel-struct.rs:41:18
    |
 LL |         let x = &p.a.p.x;
    |                  ^^^^^^^
-note: Capturing p[(1, 0),(1, 0),(1, 0)] -> MutBorrow
+note: Capturing p[(1, 0),(1, 0),(1, 0)] -> Mutable
   --> $DIR/deep-multilevel-struct.rs:43:9
    |
 LL |         p.b.q.y = 9;
    |         ^^^^^^^
-note: Capturing p[] -> ImmBorrow
+note: Capturing p[] -> Immutable
   --> $DIR/deep-multilevel-struct.rs:46:26
    |
 LL |         println!("{:?}", p);
@@ -48,11 +48,11 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture p[] -> MutBorrow
+note: Min Capture p[] -> Mutable
   --> $DIR/deep-multilevel-struct.rs:43:9
    |
 LL |         p.b.q.y = 9;
-   |         ^^^^^^^ p[] captured as MutBorrow here
+   |         ^^^^^^^ p[] captured as Mutable here
 ...
 LL |         println!("{:?}", p);
    |                          ^ p[] used here
diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs
index 0cb0aeb824e..6c7eab1eeb7 100644
--- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs
+++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.rs
@@ -13,13 +13,13 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let x = &t.0.0.0;
-        //~^ NOTE: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing t[(0, 0),(0, 0),(0, 0)] -> Immutable
         t.1.1.1 = 9;
-        //~^ NOTE: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow
-        //~| NOTE: t[] captured as MutBorrow here
+        //~^ NOTE: Capturing t[(1, 0),(1, 0),(1, 0)] -> Mutable
+        //~| NOTE: t[] captured as Mutable here
         println!("{:?}", t);
-        //~^ NOTE: Min Capture t[] -> MutBorrow
-        //~| NOTE: Capturing t[] -> ImmBorrow
+        //~^ NOTE: Min Capture t[] -> Mutable
+        //~| NOTE: Capturing t[] -> Immutable
         //~| NOTE: t[] used here
     };
 }
diff --git a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr
index 5e45fe1ca8b..cc5f74613e4 100644
--- a/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr
+++ b/tests/ui/closures/2229_closure_analysis/deep-multilevel-tuple.stderr
@@ -20,17 +20,17 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),(0, 0),(0, 0)] -> ImmBorrow
+note: Capturing t[(0, 0),(0, 0),(0, 0)] -> Immutable
   --> $DIR/deep-multilevel-tuple.rs:15:18
    |
 LL |         let x = &t.0.0.0;
    |                  ^^^^^^^
-note: Capturing t[(1, 0),(1, 0),(1, 0)] -> MutBorrow
+note: Capturing t[(1, 0),(1, 0),(1, 0)] -> Mutable
   --> $DIR/deep-multilevel-tuple.rs:17:9
    |
 LL |         t.1.1.1 = 9;
    |         ^^^^^^^
-note: Capturing t[] -> ImmBorrow
+note: Capturing t[] -> Immutable
   --> $DIR/deep-multilevel-tuple.rs:20:26
    |
 LL |         println!("{:?}", t);
@@ -48,11 +48,11 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[] -> MutBorrow
+note: Min Capture t[] -> Mutable
   --> $DIR/deep-multilevel-tuple.rs:17:9
    |
 LL |         t.1.1.1 = 9;
-   |         ^^^^^^^ t[] captured as MutBorrow here
+   |         ^^^^^^^ t[] captured as Mutable here
 ...
 LL |         println!("{:?}", t);
    |                          ^ t[] used here
diff --git a/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs b/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs
index 3106c478d00..68e8d66762d 100644
--- a/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs
+++ b/tests/ui/closures/2229_closure_analysis/destructure_patterns.rs
@@ -44,9 +44,9 @@ fn structs() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let Point { x: ref mut x, y: _, id: moved_id } = p;
-        //~^ NOTE: Capturing p[(0, 0)] -> MutBorrow
+        //~^ NOTE: Capturing p[(0, 0)] -> Mutable
         //~| NOTE: Capturing p[(2, 0)] -> ByValue
-        //~| NOTE: Min Capture p[(0, 0)] -> MutBorrow
+        //~| NOTE: Min Capture p[(0, 0)] -> Mutable
         //~| NOTE: Min Capture p[(2, 0)] -> ByValue
 
         println!("{}, {}", x, moved_id);
@@ -65,11 +65,11 @@ fn tuples() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let (ref mut x, ref ref_str, (moved_s, _)) = t;
-        //~^ NOTE: Capturing t[(0, 0)] -> MutBorrow
-        //~| NOTE: Capturing t[(1, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing t[(0, 0)] -> Mutable
+        //~| NOTE: Capturing t[(1, 0)] -> Immutable
         //~| NOTE: Capturing t[(2, 0),(0, 0)] -> ByValue
-        //~| NOTE: Min Capture t[(0, 0)] -> MutBorrow
-        //~| NOTE: Min Capture t[(1, 0)] -> ImmBorrow
+        //~| NOTE: Min Capture t[(0, 0)] -> Mutable
+        //~| NOTE: Min Capture t[(1, 0)] -> Immutable
         //~| NOTE: Min Capture t[(2, 0),(0, 0)] -> ByValue
 
         println!("{}, {} {}", x, ref_str, moved_s);
diff --git a/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr b/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr
index 7fc85de499f..6f8295ac095 100644
--- a/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr
+++ b/tests/ui/closures/2229_closure_analysis/destructure_patterns.stderr
@@ -86,7 +86,7 @@ LL | |         println!("{}, {}", x, moved_id);
 LL | |     };
    | |_____^
    |
-note: Capturing p[(0, 0)] -> MutBorrow
+note: Capturing p[(0, 0)] -> Mutable
   --> $DIR/destructure_patterns.rs:46:58
    |
 LL |         let Point { x: ref mut x, y: _, id: moved_id } = p;
@@ -109,7 +109,7 @@ LL | |         println!("{}, {}", x, moved_id);
 LL | |     };
    | |_____^
    |
-note: Min Capture p[(0, 0)] -> MutBorrow
+note: Min Capture p[(0, 0)] -> Mutable
   --> $DIR/destructure_patterns.rs:46:58
    |
 LL |         let Point { x: ref mut x, y: _, id: moved_id } = p;
@@ -132,12 +132,12 @@ LL | |         println!("{}, {} {}", x, ref_str, moved_s);
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0)] -> MutBorrow
+note: Capturing t[(0, 0)] -> Mutable
   --> $DIR/destructure_patterns.rs:67:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
    |                                                      ^
-note: Capturing t[(1, 0)] -> ImmBorrow
+note: Capturing t[(1, 0)] -> Immutable
   --> $DIR/destructure_patterns.rs:67:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
@@ -160,12 +160,12 @@ LL | |         println!("{}, {} {}", x, ref_str, moved_s);
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0)] -> MutBorrow
+note: Min Capture t[(0, 0)] -> Mutable
   --> $DIR/destructure_patterns.rs:67:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
    |                                                      ^
-note: Min Capture t[(1, 0)] -> ImmBorrow
+note: Min Capture t[(1, 0)] -> Immutable
   --> $DIR/destructure_patterns.rs:67:54
    |
 LL |         let (ref mut x, ref ref_str, (moved_s, _)) = t;
diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs
index 059c248a3e8..7467c13b337 100644
--- a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs
+++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.rs
@@ -13,7 +13,7 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("This uses new capture analyysis to capture s={}", s);
-        //~^ NOTE: Capturing s[] -> ImmBorrow
-        //~| NOTE: Min Capture s[] -> ImmBorrow
+        //~^ NOTE: Capturing s[] -> Immutable
+        //~| NOTE: Min Capture s[] -> Immutable
     };
 }
diff --git a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
index 4e76070dcf7..6dbe8c153c0 100644
--- a/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
+++ b/tests/ui/closures/2229_closure_analysis/feature-gate-capture_disjoint_fields.stderr
@@ -20,7 +20,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing s[] -> ImmBorrow
+note: Capturing s[] -> Immutable
   --> $DIR/feature-gate-capture_disjoint_fields.rs:15:69
    |
 LL |         println!("This uses new capture analyysis to capture s={}", s);
@@ -38,7 +38,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture s[] -> ImmBorrow
+note: Min Capture s[] -> Immutable
   --> $DIR/feature-gate-capture_disjoint_fields.rs:15:69
    |
 LL |         println!("This uses new capture analyysis to capture s={}", s);
diff --git a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs
index 11ef92367ca..feef8cabb39 100644
--- a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs
+++ b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.rs
@@ -24,8 +24,8 @@ impl Data {
             |v| self.filter.allowed(*v),
             //~^ ERROR: First Pass analysis includes:
             //~| ERROR: Min Capture analysis includes:
-            //~| NOTE: Capturing self[Deref,(0, 0)] -> ImmBorrow
-            //~| NOTE: Min Capture self[Deref,(0, 0)] -> ImmBorrow
+            //~| NOTE: Capturing self[Deref,(0, 0)] -> Immutable
+            //~| NOTE: Min Capture self[Deref,(0, 0)] -> Immutable
         );
     }
 }
diff --git a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr
index 10e0d076b42..ffe7dd4d108 100644
--- a/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr
+++ b/tests/ui/closures/2229_closure_analysis/filter-on-struct-member.stderr
@@ -4,7 +4,7 @@ error: First Pass analysis includes:
 LL |             |v| self.filter.allowed(*v),
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: Capturing self[Deref,(0, 0)] -> ImmBorrow
+note: Capturing self[Deref,(0, 0)] -> Immutable
   --> $DIR/filter-on-struct-member.rs:24:17
    |
 LL |             |v| self.filter.allowed(*v),
@@ -16,7 +16,7 @@ error: Min Capture analysis includes:
 LL |             |v| self.filter.allowed(*v),
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: Min Capture self[Deref,(0, 0)] -> ImmBorrow
+note: Min Capture self[Deref,(0, 0)] -> Immutable
   --> $DIR/filter-on-struct-member.rs:24:17
    |
 LL |             |v| self.filter.allowed(*v),
diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.rs b/tests/ui/closures/2229_closure_analysis/issue-87378.rs
index 0a771466e1e..9c89a4538be 100644
--- a/tests/ui/closures/2229_closure_analysis/issue-87378.rs
+++ b/tests/ui/closures/2229_closure_analysis/issue-87378.rs
@@ -19,8 +19,8 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
        unsafe { u.value }
-        //~^ NOTE: Capturing u[(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture u[] -> ImmBorrow
+        //~^ NOTE: Capturing u[(0, 0)] -> Immutable
+        //~| NOTE: Min Capture u[] -> Immutable
     };
 
     c();
diff --git a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr
index 19c0c59170b..3273e92d9d1 100644
--- a/tests/ui/closures/2229_closure_analysis/issue-87378.stderr
+++ b/tests/ui/closures/2229_closure_analysis/issue-87378.stderr
@@ -20,7 +20,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing u[(0, 0)] -> ImmBorrow
+note: Capturing u[(0, 0)] -> Immutable
   --> $DIR/issue-87378.rs:21:17
    |
 LL |        unsafe { u.value }
@@ -38,7 +38,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture u[] -> ImmBorrow
+note: Min Capture u[] -> Immutable
   --> $DIR/issue-87378.rs:21:17
    |
 LL |        unsafe { u.value }
diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.rs b/tests/ui/closures/2229_closure_analysis/issue-88476.rs
index 7f833839d56..45fe73b76e2 100644
--- a/tests/ui/closures/2229_closure_analysis/issue-88476.rs
+++ b/tests/ui/closures/2229_closure_analysis/issue-88476.rs
@@ -24,7 +24,7 @@ pub fn test1() {
     //~| ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{:?}", f.0);
-        //~^ NOTE: Capturing f[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing f[(0, 0)] -> Immutable
         //~| NOTE: Min Capture f[] -> ByValue
     };
 
@@ -52,7 +52,7 @@ fn test2() {
     //~| ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{}", character.hp)
-        //~^ NOTE: Capturing character[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing character[(0, 0)] -> Immutable
         //~| NOTE: Min Capture character[(0, 0)] -> ByValue
     };
 
diff --git a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr
index d0201757157..1c0e254dbf7 100644
--- a/tests/ui/closures/2229_closure_analysis/issue-88476.stderr
+++ b/tests/ui/closures/2229_closure_analysis/issue-88476.stderr
@@ -31,7 +31,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing f[(0, 0)] -> ImmBorrow
+note: Capturing f[(0, 0)] -> Immutable
   --> $DIR/issue-88476.rs:26:26
    |
 LL |         println!("{:?}", f.0);
@@ -69,7 +69,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing character[(0, 0)] -> ImmBorrow
+note: Capturing character[(0, 0)] -> Immutable
   --> $DIR/issue-88476.rs:54:24
    |
 LL |         println!("{}", character.hp)
diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
index 8dd20fc2a74..9c7b70457d9 100644
--- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
+++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs
@@ -13,8 +13,8 @@ fn test_1_should_capture() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         match variant {
-        //~^ NOTE: Capturing variant[] -> ImmBorrow
-        //~| NOTE: Min Capture variant[] -> ImmBorrow
+        //~^ NOTE: Capturing variant[] -> Immutable
+        //~| NOTE: Min Capture variant[] -> Immutable
             Some(_) => {}
             _ => {}
         }
@@ -64,9 +64,9 @@ fn test_6_should_capture_single_variant() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         match variant {
-            //~^ NOTE: Capturing variant[] -> ImmBorrow
-            //~| NOTE: Capturing variant[(0, 0)] -> ImmBorrow
-            //~| NOTE: Min Capture variant[] -> ImmBorrow
+            //~^ NOTE: Capturing variant[] -> Immutable
+            //~| NOTE: Capturing variant[(0, 0)] -> Immutable
+            //~| NOTE: Min Capture variant[] -> Immutable
             SingleVariant::Points(a) => {
                 println!("{:?}", a);
             }
@@ -131,8 +131,8 @@ fn test_5_should_capture_multi_variant() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         match variant {
-        //~^ NOTE: Capturing variant[] -> ImmBorrow
-        //~| NOTE: Min Capture variant[] -> ImmBorrow
+        //~^ NOTE: Capturing variant[] -> Immutable
+        //~| NOTE: Min Capture variant[] -> Immutable
             MVariant::A => {}
             _ => {}
         }
@@ -149,8 +149,8 @@ fn test_7_should_capture_slice_len() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         match slice {
-            //~^ NOTE: Capturing slice[] -> ImmBorrow
-            //~| NOTE: Min Capture slice[] -> ImmBorrow
+            //~^ NOTE: Capturing slice[] -> Immutable
+            //~| NOTE: Min Capture slice[] -> Immutable
             [_,_,_] => {},
             _ => {}
         }
@@ -161,8 +161,8 @@ fn test_7_should_capture_slice_len() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         match slice {
-            //~^ NOTE: Capturing slice[] -> ImmBorrow
-            //~| NOTE: Min Capture slice[] -> ImmBorrow
+            //~^ NOTE: Capturing slice[] -> Immutable
+            //~| NOTE: Min Capture slice[] -> Immutable
             [] => {},
             _ => {}
         }
@@ -173,8 +173,8 @@ fn test_7_should_capture_slice_len() {
     //~^ First Pass analysis includes:
     //~| Min Capture analysis includes:
         match slice {
-            //~^ NOTE: Capturing slice[] -> ImmBorrow
-            //~| NOTE: Min Capture slice[] -> ImmBorrow
+            //~^ NOTE: Capturing slice[] -> Immutable
+            //~| NOTE: Min Capture slice[] -> Immutable
             [_, .. ,_] => {},
             _ => {}
         }
diff --git a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
index c3c3f8b8477..7125bfa3101 100644
--- a/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
+++ b/tests/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr
@@ -10,7 +10,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Capturing variant[] -> ImmBorrow
+note: Capturing variant[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:15:15
    |
 LL |         match variant {
@@ -28,7 +28,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Min Capture variant[] -> ImmBorrow
+note: Min Capture variant[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:15:15
    |
 LL |         match variant {
@@ -68,12 +68,12 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Capturing variant[] -> ImmBorrow
+note: Capturing variant[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:66:15
    |
 LL |         match variant {
    |               ^^^^^^^
-note: Capturing variant[(0, 0)] -> ImmBorrow
+note: Capturing variant[(0, 0)] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:66:15
    |
 LL |         match variant {
@@ -91,7 +91,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Min Capture variant[] -> ImmBorrow
+note: Min Capture variant[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:66:15
    |
 LL |         match variant {
@@ -142,7 +142,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Capturing variant[] -> ImmBorrow
+note: Capturing variant[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:133:15
    |
 LL |         match variant {
@@ -160,7 +160,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Min Capture variant[] -> ImmBorrow
+note: Min Capture variant[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:133:15
    |
 LL |         match variant {
@@ -178,7 +178,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Capturing slice[] -> ImmBorrow
+note: Capturing slice[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:151:15
    |
 LL |         match slice {
@@ -196,7 +196,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Min Capture slice[] -> ImmBorrow
+note: Min Capture slice[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:151:15
    |
 LL |         match slice {
@@ -214,7 +214,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Capturing slice[] -> ImmBorrow
+note: Capturing slice[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:163:15
    |
 LL |         match slice {
@@ -232,7 +232,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Min Capture slice[] -> ImmBorrow
+note: Min Capture slice[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:163:15
    |
 LL |         match slice {
@@ -250,7 +250,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Capturing slice[] -> ImmBorrow
+note: Capturing slice[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:175:15
    |
 LL |         match slice {
@@ -268,7 +268,7 @@ LL | |         }
 LL | |     };
    | |_____^
    |
-note: Min Capture slice[] -> ImmBorrow
+note: Min Capture slice[] -> Immutable
   --> $DIR/patterns-capture-analysis.rs:175:15
    |
 LL |         match slice {
diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.rs b/tests/ui/closures/2229_closure_analysis/move_closure.rs
index 3b7f036dfe7..b6690d06011 100644
--- a/tests/ui/closures/2229_closure_analysis/move_closure.rs
+++ b/tests/ui/closures/2229_closure_analysis/move_closure.rs
@@ -17,7 +17,7 @@ fn simple_move_closure() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         t.0.0 = "new S".into();
-        //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> MutBorrow
+        //~^ NOTE: Capturing t[(0, 0),(0, 0)] -> Mutable
         //~| NOTE: Min Capture t[(0, 0),(0, 0)] -> ByValue
     };
     c();
@@ -36,7 +36,7 @@ fn simple_ref() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         *ref_s += 10;
-        //~^ NOTE: Capturing ref_s[Deref] -> MutBorrow
+        //~^ NOTE: Capturing ref_s[Deref] -> Mutable
         //~| NOTE: Min Capture ref_s[] -> ByValue
     };
     c();
@@ -58,7 +58,7 @@ fn struct_contains_ref_to_another_struct_1() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         t.0.0 = "new s".into();
-        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow
+        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> Mutable
         //~| NOTE: Min Capture t[(0, 0)] -> ByValue
     };
 
@@ -82,7 +82,7 @@ fn struct_contains_ref_to_another_struct_2() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let _t = t.0.0;
-        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable
         //~| NOTE: Min Capture t[(0, 0)] -> ByValue
     };
 
@@ -127,7 +127,7 @@ fn truncate_box_derefs() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let _t = b.0;
-        //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing b[Deref,(0, 0)] -> Immutable
         //~| NOTE: Min Capture b[] -> ByValue
     };
 
@@ -144,7 +144,7 @@ fn truncate_box_derefs() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{}", b.0);
-        //~^ NOTE: Capturing b[Deref,(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing b[Deref,(0, 0)] -> Immutable
         //~| NOTE: Min Capture b[] -> ByValue
     };
 
@@ -162,7 +162,7 @@ fn truncate_box_derefs() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{}", t.1.0);
-        //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing t[(1, 0),Deref,(0, 0)] -> Immutable
         //~| NOTE: Min Capture t[(1, 0)] -> ByValue
     };
 }
@@ -182,7 +182,7 @@ fn box_mut_1() {
     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
     //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
     //~| First Pass analysis includes:
-    //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+    //~| NOTE: Capturing box_p_foo[Deref,Deref,(0, 0)] -> Mutable
     //~| Min Capture analysis includes:
     //~| NOTE: Min Capture box_p_foo[] -> ByValue
 }
@@ -200,7 +200,7 @@ fn box_mut_2() {
     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
     //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
     //~| First Pass analysis includes:
-    //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+    //~| NOTE: Capturing p_foo[Deref,Deref,(0, 0)] -> Mutable
     //~| Min Capture analysis includes:
     //~| NOTE: Min Capture p_foo[] -> ByValue
 }
@@ -214,7 +214,7 @@ fn returned_closure_owns_copy_type_data() -> impl Fn() -> i32 {
     //~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
     //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
     //~| First Pass analysis includes:
-    //~| NOTE: Capturing x[] -> ImmBorrow
+    //~| NOTE: Capturing x[] -> Immutable
     //~| Min Capture analysis includes:
     //~| NOTE: Min Capture x[] -> ByValue
 
diff --git a/tests/ui/closures/2229_closure_analysis/move_closure.stderr b/tests/ui/closures/2229_closure_analysis/move_closure.stderr
index 7e9e3c5fed3..68754b8f7be 100644
--- a/tests/ui/closures/2229_closure_analysis/move_closure.stderr
+++ b/tests/ui/closures/2229_closure_analysis/move_closure.stderr
@@ -114,7 +114,7 @@ error: First Pass analysis includes:
 LL |     let c = #[rustc_capture_analysis] move || x;
    |                                       ^^^^^^^^^
    |
-note: Capturing x[] -> ImmBorrow
+note: Capturing x[] -> Immutable
   --> $DIR/move_closure.rs:212:47
    |
 LL |     let c = #[rustc_capture_analysis] move || x;
@@ -144,7 +144,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),(0, 0)] -> MutBorrow
+note: Capturing t[(0, 0),(0, 0)] -> Mutable
   --> $DIR/move_closure.rs:19:9
    |
 LL |         t.0.0 = "new S".into();
@@ -180,7 +180,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing ref_s[Deref] -> MutBorrow
+note: Capturing ref_s[Deref] -> Mutable
   --> $DIR/move_closure.rs:38:9
    |
 LL |         *ref_s += 10;
@@ -216,7 +216,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),Deref,(0, 0)] -> MutBorrow
+note: Capturing t[(0, 0),Deref,(0, 0)] -> Mutable
   --> $DIR/move_closure.rs:60:9
    |
 LL |         t.0.0 = "new s".into();
@@ -252,7 +252,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+note: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable
   --> $DIR/move_closure.rs:84:18
    |
 LL |         let _t = t.0.0;
@@ -324,7 +324,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing b[Deref,(0, 0)] -> ImmBorrow
+note: Capturing b[Deref,(0, 0)] -> Immutable
   --> $DIR/move_closure.rs:129:18
    |
 LL |         let _t = b.0;
@@ -360,7 +360,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing b[Deref,(0, 0)] -> ImmBorrow
+note: Capturing b[Deref,(0, 0)] -> Immutable
   --> $DIR/move_closure.rs:146:24
    |
 LL |         println!("{}", b.0);
@@ -396,7 +396,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(1, 0),Deref,(0, 0)] -> ImmBorrow
+note: Capturing t[(1, 0),Deref,(0, 0)] -> Immutable
   --> $DIR/move_closure.rs:164:24
    |
 LL |         println!("{}", t.1.0);
@@ -426,7 +426,7 @@ error: First Pass analysis includes:
 LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+note: Capturing box_p_foo[Deref,Deref,(0, 0)] -> Mutable
   --> $DIR/move_closure.rs:180:47
    |
 LL |     let c = #[rustc_capture_analysis] move || box_p_foo.x += 10;
@@ -450,7 +450,7 @@ error: First Pass analysis includes:
 LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
    |                                       ^^^^^^^^^^^^^^^^^^^^^
    |
-note: Capturing p_foo[Deref,Deref,(0, 0)] -> MutBorrow
+note: Capturing p_foo[Deref,Deref,(0, 0)] -> Mutable
   --> $DIR/move_closure.rs:198:47
    |
 LL |     let c = #[rustc_capture_analysis] move || p_foo.x += 10;
diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs
index 2d7c26074cb..501aebe725a 100644
--- a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs
+++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.rs
@@ -27,8 +27,8 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let wp = &w.p;
-        //~^ NOTE: Capturing w[(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture w[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing w[(0, 0)] -> Immutable
+        //~| NOTE: Min Capture w[(0, 0)] -> Immutable
         println!("{}", wp.x);
     };
 
diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr
index 118a7dacec6..000d929f07f 100644
--- a/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr
+++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-1.stderr
@@ -20,7 +20,7 @@ LL | |         println!("{}", wp.x);
 LL | |     };
    | |_____^
    |
-note: Capturing w[(0, 0)] -> ImmBorrow
+note: Capturing w[(0, 0)] -> Immutable
   --> $DIR/multilevel-path-1.rs:29:19
    |
 LL |         let wp = &w.p;
@@ -38,7 +38,7 @@ LL | |         println!("{}", wp.x);
 LL | |     };
    | |_____^
    |
-note: Min Capture w[(0, 0)] -> ImmBorrow
+note: Min Capture w[(0, 0)] -> Immutable
   --> $DIR/multilevel-path-1.rs:29:19
    |
 LL |         let wp = &w.p;
diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs
index bcf0ed35137..f73627d14da 100644
--- a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs
+++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.rs
@@ -22,8 +22,8 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{}", w.p.x);
-        //~^ NOTE: Capturing w[(0, 0),(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture w[(0, 0),(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing w[(0, 0),(0, 0)] -> Immutable
+        //~| NOTE: Min Capture w[(0, 0),(0, 0)] -> Immutable
     };
 
     // `c` only captures `w.p.x`, therefore it's safe to mutate `w.p.y`.
diff --git a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr
index a7112531d9a..97f53e490e8 100644
--- a/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr
+++ b/tests/ui/closures/2229_closure_analysis/multilevel-path-2.stderr
@@ -20,7 +20,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing w[(0, 0),(0, 0)] -> ImmBorrow
+note: Capturing w[(0, 0),(0, 0)] -> Immutable
   --> $DIR/multilevel-path-2.rs:24:24
    |
 LL |         println!("{}", w.p.x);
@@ -38,7 +38,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture w[(0, 0),(0, 0)] -> ImmBorrow
+note: Min Capture w[(0, 0),(0, 0)] -> Immutable
   --> $DIR/multilevel-path-2.rs:24:24
    |
 LL |         println!("{}", w.p.x);
diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.rs b/tests/ui/closures/2229_closure_analysis/nested-closure.rs
index c481b3d853b..54166d068cb 100644
--- a/tests/ui/closures/2229_closure_analysis/nested-closure.rs
+++ b/tests/ui/closures/2229_closure_analysis/nested-closure.rs
@@ -24,8 +24,8 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{}", p.x);
-        //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing p[(0, 0)] -> Immutable
+        //~| NOTE: Min Capture p[(0, 0)] -> Immutable
         let incr = 10;
         let mut c2 = #[rustc_capture_analysis]
         //~^ ERROR: attributes on expressions are experimental
@@ -34,15 +34,15 @@ fn main() {
         || p.y += incr;
         //~^ ERROR: First Pass analysis includes:
         //~| ERROR: Min Capture analysis includes:
-        //~| NOTE: Capturing p[(1, 0)] -> MutBorrow
-        //~| NOTE: Capturing incr[] -> ImmBorrow
-        //~| NOTE: Min Capture p[(1, 0)] -> MutBorrow
-        //~| NOTE: Min Capture incr[] -> ImmBorrow
-        //~| NOTE: Capturing p[(1, 0)] -> MutBorrow
-        //~| NOTE: Min Capture p[(1, 0)] -> MutBorrow
+        //~| NOTE: Capturing p[(1, 0)] -> Mutable
+        //~| NOTE: Capturing incr[] -> Immutable
+        //~| NOTE: Min Capture p[(1, 0)] -> Mutable
+        //~| NOTE: Min Capture incr[] -> Immutable
+        //~| NOTE: Capturing p[(1, 0)] -> Mutable
+        //~| NOTE: Min Capture p[(1, 0)] -> Mutable
         c2();
         println!("{}", p.y);
-        //~^ NOTE: Capturing p[(1, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing p[(1, 0)] -> Immutable
     };
 
     c1();
diff --git a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr
index 256bfd58597..03550cb2d35 100644
--- a/tests/ui/closures/2229_closure_analysis/nested-closure.stderr
+++ b/tests/ui/closures/2229_closure_analysis/nested-closure.stderr
@@ -24,12 +24,12 @@ error: First Pass analysis includes:
 LL |         || p.y += incr;
    |         ^^^^^^^^^^^^^^
    |
-note: Capturing p[(1, 0)] -> MutBorrow
+note: Capturing p[(1, 0)] -> Mutable
   --> $DIR/nested-closure.rs:34:12
    |
 LL |         || p.y += incr;
    |            ^^^
-note: Capturing incr[] -> ImmBorrow
+note: Capturing incr[] -> Immutable
   --> $DIR/nested-closure.rs:34:19
    |
 LL |         || p.y += incr;
@@ -41,12 +41,12 @@ error: Min Capture analysis includes:
 LL |         || p.y += incr;
    |         ^^^^^^^^^^^^^^
    |
-note: Min Capture p[(1, 0)] -> MutBorrow
+note: Min Capture p[(1, 0)] -> Mutable
   --> $DIR/nested-closure.rs:34:12
    |
 LL |         || p.y += incr;
    |            ^^^
-note: Min Capture incr[] -> ImmBorrow
+note: Min Capture incr[] -> Immutable
   --> $DIR/nested-closure.rs:34:19
    |
 LL |         || p.y += incr;
@@ -64,17 +64,17 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing p[(0, 0)] -> ImmBorrow
+note: Capturing p[(0, 0)] -> Immutable
   --> $DIR/nested-closure.rs:26:24
    |
 LL |         println!("{}", p.x);
    |                        ^^^
-note: Capturing p[(1, 0)] -> MutBorrow
+note: Capturing p[(1, 0)] -> Mutable
   --> $DIR/nested-closure.rs:34:12
    |
 LL |         || p.y += incr;
    |            ^^^
-note: Capturing p[(1, 0)] -> ImmBorrow
+note: Capturing p[(1, 0)] -> Immutable
   --> $DIR/nested-closure.rs:44:24
    |
 LL |         println!("{}", p.y);
@@ -92,12 +92,12 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture p[(0, 0)] -> ImmBorrow
+note: Min Capture p[(0, 0)] -> Immutable
   --> $DIR/nested-closure.rs:26:24
    |
 LL |         println!("{}", p.x);
    |                        ^^^
-note: Min Capture p[(1, 0)] -> MutBorrow
+note: Min Capture p[(1, 0)] -> Mutable
   --> $DIR/nested-closure.rs:34:12
    |
 LL |         || p.y += incr;
diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs
index 8df0eeb0eb4..70c20cf5aef 100644
--- a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs
+++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.rs
@@ -23,8 +23,8 @@ fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
     //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
     //~| ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
-    //~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow
-    //~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow
+    //~| NOTE: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> Immutable
+    //~| NOTE: Min Capture m[Deref,(0, 0),Deref] -> Immutable
     c
 }
 
diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr
index 99159ab58a2..86f7a6a6bca 100644
--- a/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr
+++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case.stderr
@@ -14,7 +14,7 @@ error: First Pass analysis includes:
 LL |     let c = #[rustc_capture_analysis] || drop(&m.a.0);
    |                                       ^^^^^^^^^^^^^^^
    |
-note: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> ImmBorrow
+note: Capturing m[Deref,(0, 0),Deref,(0, 0)] -> Immutable
   --> $DIR/edge_case.rs:20:48
    |
 LL |     let c = #[rustc_capture_analysis] || drop(&m.a.0);
@@ -26,7 +26,7 @@ error: Min Capture analysis includes:
 LL |     let c = #[rustc_capture_analysis] || drop(&m.a.0);
    |                                       ^^^^^^^^^^^^^^^
    |
-note: Min Capture m[Deref,(0, 0),Deref] -> ImmBorrow
+note: Min Capture m[Deref,(0, 0),Deref] -> Immutable
   --> $DIR/edge_case.rs:20:48
    |
 LL |     let c = #[rustc_capture_analysis] || drop(&m.a.0);
diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs b/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs
index 2d3db4fde72..ed740f3a167 100644
--- a/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs
+++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.rs
@@ -28,7 +28,7 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{}", pent.points[5].x);
-        //~^ NOTE: Capturing pent[(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture pent[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing pent[(0, 0)] -> Immutable
+        //~| NOTE: Min Capture pent[(0, 0)] -> Immutable
     };
 }
diff --git a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr
index 22bd13617c1..e82295f047b 100644
--- a/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr
+++ b/tests/ui/closures/2229_closure_analysis/path-with-array-access.stderr
@@ -20,7 +20,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing pent[(0, 0)] -> ImmBorrow
+note: Capturing pent[(0, 0)] -> Immutable
   --> $DIR/path-with-array-access.rs:30:24
    |
 LL |         println!("{}", pent.points[5].x);
@@ -38,7 +38,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture pent[(0, 0)] -> ImmBorrow
+note: Min Capture pent[(0, 0)] -> Immutable
   --> $DIR/path-with-array-access.rs:30:24
    |
 LL |         println!("{}", pent.points[5].x);
diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs
index c30eaf8fb1b..159be843edb 100644
--- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs
+++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.rs
@@ -28,17 +28,17 @@ fn test_one() {
         //~^ ERROR: Min Capture analysis includes:
         //~| ERROR
         println!("{:?}", a.0);
-        //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture a[(0, 0)] -> Immutable
         //~| NOTE
         println!("{:?}", a.1);
-        //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture a[(1, 0)] -> Immutable
         //~| NOTE
 
         println!("{:?}", b.0);
-        //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture b[(0, 0)] -> Immutable
         //~| NOTE
         println!("{:?}", b.1);
-        //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture b[(1, 0)] -> Immutable
         //~| NOTE
     };
 }
@@ -55,17 +55,17 @@ fn test_two() {
         //~^ ERROR: Min Capture analysis includes:
         //~| ERROR
         println!("{:?}", a.1);
-        //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture a[(1, 0)] -> Immutable
         //~| NOTE
         println!("{:?}", a.0);
-        //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture a[(0, 0)] -> Immutable
         //~| NOTE
 
         println!("{:?}", b.1);
-        //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture b[(1, 0)] -> Immutable
         //~| NOTE
         println!("{:?}", b.0);
-        //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture b[(0, 0)] -> Immutable
         //~| NOTE
     };
 }
@@ -82,17 +82,17 @@ fn test_three() {
         //~^ ERROR: Min Capture analysis includes:
         //~| ERROR
         println!("{:?}", b.1);
-        //~^ NOTE: Min Capture b[(1, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture b[(1, 0)] -> Immutable
         //~| NOTE
         println!("{:?}", a.1);
-        //~^ NOTE: Min Capture a[(1, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture a[(1, 0)] -> Immutable
         //~| NOTE
         println!("{:?}", a.0);
-        //~^ NOTE: Min Capture a[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture a[(0, 0)] -> Immutable
         //~| NOTE
 
         println!("{:?}", b.0);
-        //~^ NOTE: Min Capture b[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Min Capture b[(0, 0)] -> Immutable
         //~| NOTE
     };
 }
diff --git a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr
index 82f770eafed..65a0a317ab6 100644
--- a/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr
+++ b/tests/ui/closures/2229_closure_analysis/preserve_field_drop_order.stderr
@@ -40,22 +40,22 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing a[(0, 0)] -> ImmBorrow
+note: Capturing a[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:30:26
    |
 LL |         println!("{:?}", a.0);
    |                          ^^^
-note: Capturing a[(1, 0)] -> ImmBorrow
+note: Capturing a[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:33:26
    |
 LL |         println!("{:?}", a.1);
    |                          ^^^
-note: Capturing b[(0, 0)] -> ImmBorrow
+note: Capturing b[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:37:26
    |
 LL |         println!("{:?}", b.0);
    |                          ^^^
-note: Capturing b[(1, 0)] -> ImmBorrow
+note: Capturing b[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:40:26
    |
 LL |         println!("{:?}", b.1);
@@ -73,22 +73,22 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture a[(0, 0)] -> ImmBorrow
+note: Min Capture a[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:30:26
    |
 LL |         println!("{:?}", a.0);
    |                          ^^^
-note: Min Capture a[(1, 0)] -> ImmBorrow
+note: Min Capture a[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:33:26
    |
 LL |         println!("{:?}", a.1);
    |                          ^^^
-note: Min Capture b[(0, 0)] -> ImmBorrow
+note: Min Capture b[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:37:26
    |
 LL |         println!("{:?}", b.0);
    |                          ^^^
-note: Min Capture b[(1, 0)] -> ImmBorrow
+note: Min Capture b[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:40:26
    |
 LL |         println!("{:?}", b.1);
@@ -106,22 +106,22 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing a[(1, 0)] -> ImmBorrow
+note: Capturing a[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:57:26
    |
 LL |         println!("{:?}", a.1);
    |                          ^^^
-note: Capturing a[(0, 0)] -> ImmBorrow
+note: Capturing a[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:60:26
    |
 LL |         println!("{:?}", a.0);
    |                          ^^^
-note: Capturing b[(1, 0)] -> ImmBorrow
+note: Capturing b[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:64:26
    |
 LL |         println!("{:?}", b.1);
    |                          ^^^
-note: Capturing b[(0, 0)] -> ImmBorrow
+note: Capturing b[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:67:26
    |
 LL |         println!("{:?}", b.0);
@@ -139,22 +139,22 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture a[(0, 0)] -> ImmBorrow
+note: Min Capture a[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:60:26
    |
 LL |         println!("{:?}", a.0);
    |                          ^^^
-note: Min Capture a[(1, 0)] -> ImmBorrow
+note: Min Capture a[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:57:26
    |
 LL |         println!("{:?}", a.1);
    |                          ^^^
-note: Min Capture b[(0, 0)] -> ImmBorrow
+note: Min Capture b[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:67:26
    |
 LL |         println!("{:?}", b.0);
    |                          ^^^
-note: Min Capture b[(1, 0)] -> ImmBorrow
+note: Min Capture b[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:64:26
    |
 LL |         println!("{:?}", b.1);
@@ -172,22 +172,22 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing b[(1, 0)] -> ImmBorrow
+note: Capturing b[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:84:26
    |
 LL |         println!("{:?}", b.1);
    |                          ^^^
-note: Capturing a[(1, 0)] -> ImmBorrow
+note: Capturing a[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:87:26
    |
 LL |         println!("{:?}", a.1);
    |                          ^^^
-note: Capturing a[(0, 0)] -> ImmBorrow
+note: Capturing a[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:90:26
    |
 LL |         println!("{:?}", a.0);
    |                          ^^^
-note: Capturing b[(0, 0)] -> ImmBorrow
+note: Capturing b[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:94:26
    |
 LL |         println!("{:?}", b.0);
@@ -205,22 +205,22 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture b[(0, 0)] -> ImmBorrow
+note: Min Capture b[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:94:26
    |
 LL |         println!("{:?}", b.0);
    |                          ^^^
-note: Min Capture b[(1, 0)] -> ImmBorrow
+note: Min Capture b[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:84:26
    |
 LL |         println!("{:?}", b.1);
    |                          ^^^
-note: Min Capture a[(0, 0)] -> ImmBorrow
+note: Min Capture a[(0, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:90:26
    |
 LL |         println!("{:?}", a.0);
    |                          ^^^
-note: Min Capture a[(1, 0)] -> ImmBorrow
+note: Min Capture a[(1, 0)] -> Immutable
   --> $DIR/preserve_field_drop_order.rs:87:26
    |
 LL |         println!("{:?}", a.1);
diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.rs b/tests/ui/closures/2229_closure_analysis/repr_packed.rs
index 0dde2b12b87..2525af37eaa 100644
--- a/tests/ui/closures/2229_closure_analysis/repr_packed.rs
+++ b/tests/ui/closures/2229_closure_analysis/repr_packed.rs
@@ -19,10 +19,10 @@ fn test_alignment_not_affected() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let z1: &u8 = &foo.x;
-        //~^ NOTE: Capturing foo[] -> ImmBorrow
+        //~^ NOTE: Capturing foo[] -> Immutable
         let z2: &mut u8 = &mut foo.y;
-        //~^ NOTE: Capturing foo[] -> MutBorrow
-        //~| NOTE: Min Capture foo[] -> MutBorrow
+        //~^ NOTE: Capturing foo[] -> Mutable
+        //~| NOTE: Min Capture foo[] -> Mutable
 
         *z2 = 42;
 
@@ -50,10 +50,10 @@ fn test_alignment_affected() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let z1: &String = &foo.x;
-        //~^ NOTE: Capturing foo[] -> ImmBorrow
+        //~^ NOTE: Capturing foo[] -> Immutable
         let z2: &mut u16 = &mut foo.y;
-        //~^ NOTE: Capturing foo[] -> MutBorrow
-        //~| NOTE: Min Capture foo[] -> MutBorrow
+        //~^ NOTE: Capturing foo[] -> Mutable
+        //~| NOTE: Min Capture foo[] -> Mutable
 
 
         *z2 = 42;
@@ -86,7 +86,7 @@ fn test_truncation_when_ref_and_move() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{}", foo.x);
-        //~^ NOTE: Capturing foo[] -> ImmBorrow
+        //~^ NOTE: Capturing foo[] -> Immutable
         //~| NOTE: Min Capture foo[] -> ByValue
         //~| NOTE: foo[] used here
         let _z = foo.x;
diff --git a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr
index 3bac41d60d5..d4b2f8bfeae 100644
--- a/tests/ui/closures/2229_closure_analysis/repr_packed.stderr
+++ b/tests/ui/closures/2229_closure_analysis/repr_packed.stderr
@@ -40,12 +40,12 @@ LL | |         println!("({}, {})", z1, z2);
 LL | |     };
    | |_____^
    |
-note: Capturing foo[] -> ImmBorrow
+note: Capturing foo[] -> Immutable
   --> $DIR/repr_packed.rs:21:24
    |
 LL |         let z1: &u8 = &foo.x;
    |                        ^^^^^
-note: Capturing foo[] -> MutBorrow
+note: Capturing foo[] -> Mutable
   --> $DIR/repr_packed.rs:23:32
    |
 LL |         let z2: &mut u8 = &mut foo.y;
@@ -63,7 +63,7 @@ LL | |         println!("({}, {})", z1, z2);
 LL | |     };
    | |_____^
    |
-note: Min Capture foo[] -> MutBorrow
+note: Min Capture foo[] -> Mutable
   --> $DIR/repr_packed.rs:23:32
    |
 LL |         let z2: &mut u8 = &mut foo.y;
@@ -81,12 +81,12 @@ LL | |         println!("({}, {})", z1, z2);
 LL | |     };
    | |_____^
    |
-note: Capturing foo[] -> ImmBorrow
+note: Capturing foo[] -> Immutable
   --> $DIR/repr_packed.rs:52:28
    |
 LL |         let z1: &String = &foo.x;
    |                            ^^^^^
-note: Capturing foo[] -> MutBorrow
+note: Capturing foo[] -> Mutable
   --> $DIR/repr_packed.rs:54:33
    |
 LL |         let z2: &mut u16 = &mut foo.y;
@@ -104,7 +104,7 @@ LL | |         println!("({}, {})", z1, z2);
 LL | |     };
    | |_____^
    |
-note: Min Capture foo[] -> MutBorrow
+note: Min Capture foo[] -> Mutable
   --> $DIR/repr_packed.rs:54:33
    |
 LL |         let z2: &mut u16 = &mut foo.y;
@@ -122,7 +122,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing foo[] -> ImmBorrow
+note: Capturing foo[] -> Immutable
   --> $DIR/repr_packed.rs:88:24
    |
 LL |         println!("{}", foo.x);
diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs
index 4b749a70577..38aa76999fb 100644
--- a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs
+++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.rs
@@ -16,7 +16,7 @@ fn main() {
     //
     // Requirements:
     // p.x -> MutBoorrow
-    // p   -> ImmBorrow
+    // p   -> Immutable
     //
     // Requirements met when p is captured via MutBorrow
     //
@@ -28,11 +28,11 @@ fn main() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         p.x += 10;
-        //~^ NOTE: Capturing p[(0, 0)] -> MutBorrow
-        //~| NOTE: p[] captured as MutBorrow here
+        //~^ NOTE: Capturing p[(0, 0)] -> Mutable
+        //~| NOTE: p[] captured as Mutable here
         println!("{:?}", p);
-        //~^ NOTE: Capturing p[] -> ImmBorrow
-        //~| NOTE: Min Capture p[] -> MutBorrow
+        //~^ NOTE: Capturing p[] -> Immutable
+        //~| NOTE: Min Capture p[] -> Mutable
         //~| NOTE: p[] used here
     };
 
diff --git a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr
index 247dcbe94bc..a88bd01093a 100644
--- a/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr
+++ b/tests/ui/closures/2229_closure_analysis/simple-struct-min-capture.stderr
@@ -20,12 +20,12 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing p[(0, 0)] -> MutBorrow
+note: Capturing p[(0, 0)] -> Mutable
   --> $DIR/simple-struct-min-capture.rs:30:9
    |
 LL |         p.x += 10;
    |         ^^^
-note: Capturing p[] -> ImmBorrow
+note: Capturing p[] -> Immutable
   --> $DIR/simple-struct-min-capture.rs:33:26
    |
 LL |         println!("{:?}", p);
@@ -43,11 +43,11 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture p[] -> MutBorrow
+note: Min Capture p[] -> Mutable
   --> $DIR/simple-struct-min-capture.rs:30:9
    |
 LL |         p.x += 10;
-   |         ^^^ p[] captured as MutBorrow here
+   |         ^^^ p[] captured as Mutable here
 ...
 LL |         println!("{:?}", p);
    |                          ^ p[] used here
diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs
index 33d43c5f526..667f244f612 100644
--- a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs
+++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.rs
@@ -30,8 +30,8 @@ fn unsafe_imm() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         println!("{:?}", (*t.0).s);
-        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture t[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable
+        //~| NOTE: Min Capture t[(0, 0)] -> Immutable
     };
 
     c();
@@ -51,8 +51,8 @@ fn unsafe_mut() {
     //~^ ERROR: First Pass analysis includes:
     //~| ERROR: Min Capture analysis includes:
         let x = unsafe { &mut (*p).s };
-        //~^ NOTE: Capturing p[Deref,(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture p[] -> ImmBorrow
+        //~^ NOTE: Capturing p[Deref,(0, 0)] -> Immutable
+        //~| NOTE: Min Capture p[] -> Immutable
         *x = "s".into();
     };
     c();
diff --git a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr
index 4f3de075054..54463c5277d 100644
--- a/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr
+++ b/tests/ui/closures/2229_closure_analysis/unsafe_ptr.stderr
@@ -30,7 +30,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing t[(0, 0),Deref,(0, 0)] -> ImmBorrow
+note: Capturing t[(0, 0),Deref,(0, 0)] -> Immutable
   --> $DIR/unsafe_ptr.rs:32:26
    |
 LL |         println!("{:?}", (*t.0).s);
@@ -48,7 +48,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture t[(0, 0)] -> ImmBorrow
+note: Min Capture t[(0, 0)] -> Immutable
   --> $DIR/unsafe_ptr.rs:32:26
    |
 LL |         println!("{:?}", (*t.0).s);
@@ -66,7 +66,7 @@ LL | |         *x = "s".into();
 LL | |     };
    | |_____^
    |
-note: Capturing p[Deref,(0, 0)] -> ImmBorrow
+note: Capturing p[Deref,(0, 0)] -> Immutable
   --> $DIR/unsafe_ptr.rs:53:31
    |
 LL |         let x = unsafe { &mut (*p).s };
@@ -84,7 +84,7 @@ LL | |         *x = "s".into();
 LL | |     };
    | |_____^
    |
-note: Min Capture p[] -> ImmBorrow
+note: Min Capture p[] -> Immutable
   --> $DIR/unsafe_ptr.rs:53:31
    |
 LL |         let x = unsafe { &mut (*p).s };
diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.rs b/tests/ui/closures/2229_closure_analysis/wild_patterns.rs
index 9adf20c21d5..d220cfce9ce 100644
--- a/tests/ui/closures/2229_closure_analysis/wild_patterns.rs
+++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.rs
@@ -28,8 +28,8 @@ fn wild_struct() {
     //~| ERROR: Min Capture analysis includes:
         // FIXME(arora-aman): Change `_x` to `_`
         let Point { x: _x, y: _ } = p;
-        //~^ NOTE: Capturing p[(0, 0)] -> ImmBorrow
-        //~| NOTE: Min Capture p[(0, 0)] -> ImmBorrow
+        //~^ NOTE: Capturing p[(0, 0)] -> Immutable
+        //~| NOTE: Min Capture p[(0, 0)] -> Immutable
     };
 
     c();
diff --git a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr
index 88b48aaaf8c..4d6d85649da 100644
--- a/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr
+++ b/tests/ui/closures/2229_closure_analysis/wild_patterns.stderr
@@ -40,7 +40,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Capturing p[(0, 0)] -> ImmBorrow
+note: Capturing p[(0, 0)] -> Immutable
   --> $DIR/wild_patterns.rs:30:37
    |
 LL |         let Point { x: _x, y: _ } = p;
@@ -58,7 +58,7 @@ LL | |
 LL | |     };
    | |_____^
    |
-note: Min Capture p[(0, 0)] -> ImmBorrow
+note: Min Capture p[(0, 0)] -> Immutable
   --> $DIR/wild_patterns.rs:30:37
    |
 LL |         let Point { x: _x, y: _ } = p;
diff --git a/tests/ui/closures/coerce-unsafe-to-closure.stderr b/tests/ui/closures/coerce-unsafe-to-closure.stderr
index 2538fc0361c..013b9009da4 100644
--- a/tests/ui/closures/coerce-unsafe-to-closure.stderr
+++ b/tests/ui/closures/coerce-unsafe-to-closure.stderr
@@ -1,4 +1,4 @@
-error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
+error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
   --> $DIR/coerce-unsafe-to-closure.rs:2:44
    |
 LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
@@ -6,7 +6,7 @@ LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
    |                                        |
    |                                        required by a bound introduced by this call
    |
-   = help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
+   = help: the trait `FnOnce(&str)` is not implemented for fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
diff --git a/tests/ui/conditional-compilation/cfg_accessible-unstable.rs b/tests/ui/conditional-compilation/cfg_accessible-unstable.rs
index e9247e67a2a..9ac98dbd6e7 100644
--- a/tests/ui/conditional-compilation/cfg_accessible-unstable.rs
+++ b/tests/ui/conditional-compilation/cfg_accessible-unstable.rs
@@ -1,2 +1,2 @@
-#[cfg_accessible(std)] //~ ERROR use of unstable library feature 'cfg_accessible'
+#[cfg_accessible(std)] //~ ERROR use of unstable library feature `cfg_accessible`
 fn main() {}
diff --git a/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr b/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr
index 201f6a13f1f..c994f4e67ac 100644
--- a/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr
+++ b/tests/ui/conditional-compilation/cfg_accessible-unstable.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'cfg_accessible': `cfg_accessible` is not fully implemented
+error[E0658]: use of unstable library feature `cfg_accessible`: `cfg_accessible` is not fully implemented
   --> $DIR/cfg_accessible-unstable.rs:1:3
    |
 LL | #[cfg_accessible(std)]
diff --git a/tests/ui/consts/auxiliary/unstable_intrinsic.rs b/tests/ui/consts/auxiliary/unstable_intrinsic.rs
index edef499dbb1..9e53a8feb5d 100644
--- a/tests/ui/consts/auxiliary/unstable_intrinsic.rs
+++ b/tests/ui/consts/auxiliary/unstable_intrinsic.rs
@@ -1,26 +1,13 @@
 #![feature(staged_api, rustc_attrs, intrinsics)]
 #![stable(since="1.0.0", feature = "stable")]
 
-#[stable(since="1.0.0", feature = "stable")]
-pub mod old_way {
-    extern "rust-intrinsic" {
-        #[unstable(feature = "unstable", issue = "42")]
-        pub fn size_of_val<T>(x: *const T) -> usize;
-
-        #[unstable(feature = "unstable", issue = "42")]
-        #[rustc_const_unstable(feature = "unstable", issue = "42")]
-        pub fn min_align_of_val<T>(x: *const T) -> usize;
-    }
-}
-
-#[stable(since="1.0.0", feature = "stable")]
-pub mod new_way {
-    #[unstable(feature = "unstable", issue = "42")]
-    #[rustc_intrinsic]
-    pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
-
-    #[unstable(feature = "unstable", issue = "42")]
-    #[rustc_const_unstable(feature = "unstable", issue = "42")]
-    #[rustc_intrinsic]
-    pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
-}
+#[unstable(feature = "unstable", issue = "42")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
+
+#[unstable(feature = "unstable", issue = "42")]
+#[rustc_const_unstable(feature = "unstable", issue = "42")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
diff --git a/tests/ui/consts/const-compare-bytes-ub.rs b/tests/ui/consts/const-compare-bytes-ub.rs
index 903ba15e622..9dafae1efd1 100644
--- a/tests/ui/consts/const-compare-bytes-ub.rs
+++ b/tests/ui/consts/const-compare-bytes-ub.rs
@@ -1,7 +1,6 @@
 //@ check-fail
 
 #![feature(core_intrinsics)]
-#![feature(const_intrinsic_compare_bytes)]
 use std::intrinsics::compare_bytes;
 use std::mem::MaybeUninit;
 
diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr
index 7f83dee6409..9ef5c8ad43a 100644
--- a/tests/ui/consts/const-compare-bytes-ub.stderr
+++ b/tests/ui/consts/const-compare-bytes-ub.stderr
@@ -1,47 +1,47 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-compare-bytes-ub.rs:10:9
+  --> $DIR/const-compare-bytes-ub.rs:9:9
    |
 LL |         compare_bytes(0 as *const u8, 2 as *const u8, 1)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got a null pointer
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-compare-bytes-ub.rs:14:9
+  --> $DIR/const-compare-bytes-ub.rs:13:9
    |
 LL |         compare_bytes(1 as *const u8, 0 as *const u8, 1)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-compare-bytes-ub.rs:18:9
+  --> $DIR/const-compare-bytes-ub.rs:17:9
    |
 LL |         compare_bytes(1 as *const u8, 2 as *const u8, 1)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 1 byte of memory, but got 0x1[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-compare-bytes-ub.rs:22:9
+  --> $DIR/const-compare-bytes-ub.rs:21:9
    |
 LL |         compare_bytes([1, 2, 3].as_ptr(), [1, 2, 3, 4].as_ptr(), 4)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0 which is only 3 bytes from the end of the allocation
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-compare-bytes-ub.rs:26:9
+  --> $DIR/const-compare-bytes-ub.rs:25:9
    |
 LL |         compare_bytes([1, 2, 3, 4].as_ptr(), [1, 2, 3].as_ptr(), 4)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC1 which is only 3 bytes from the end of the allocation
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-compare-bytes-ub.rs:30:9
+  --> $DIR/const-compare-bytes-ub.rs:29:9
    |
 LL |         compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-compare-bytes-ub.rs:34:9
+  --> $DIR/const-compare-bytes-ub.rs:33:9
    |
 LL |         compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-compare-bytes-ub.rs:38:9
+  --> $DIR/const-compare-bytes-ub.rs:37:9
    |
 LL |         compare_bytes([&1].as_ptr().cast(), [&2].as_ptr().cast(), std::mem::size_of::<usize>())
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
diff --git a/tests/ui/consts/const-compare-bytes.rs b/tests/ui/consts/const-compare-bytes.rs
index 8596a2d9df9..cd5cdfd0400 100644
--- a/tests/ui/consts/const-compare-bytes.rs
+++ b/tests/ui/consts/const-compare-bytes.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 
 #![feature(core_intrinsics)]
-#![feature(const_intrinsic_compare_bytes)]
 use std::intrinsics::compare_bytes;
 
 fn main() {
diff --git a/tests/ui/consts/const-eval/simd/insert_extract.rs b/tests/ui/consts/const-eval/simd/insert_extract.rs
index 57d4b4888ca..e5873ea26e8 100644
--- a/tests/ui/consts/const-eval/simd/insert_extract.rs
+++ b/tests/ui/consts/const-eval/simd/insert_extract.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![feature(repr_simd)]
-#![feature(intrinsics)]
+#![feature(intrinsics, rustc_attrs)]
 #![feature(staged_api)]
 #![stable(feature = "foo", since = "1.3.37")]
 #![allow(non_camel_case_types)]
@@ -10,14 +10,18 @@
 #[repr(simd)] struct u16x2([u16; 2]);
 #[repr(simd)] struct f32x4([f32; 4]);
 
-extern "rust-intrinsic" {
-    #[stable(feature = "foo", since = "1.3.37")]
-    #[rustc_const_stable(feature = "foo", since = "1.3.37")]
-    fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
+#[stable(feature = "foo", since = "1.3.37")]
+#[rustc_const_stable(feature = "foo", since = "1.3.37")]
+#[rustc_intrinsic]
+const unsafe fn simd_insert<T, U>(_x: T, _idx: u32, _val: U) -> T {
+    unimplemented!()
+}
 
-    #[stable(feature = "foo", since = "1.3.37")]
-    #[rustc_const_stable(feature = "foo", since = "1.3.37")]
-    fn simd_extract<T, U>(x: T, idx: u32) -> U;
+#[stable(feature = "foo", since = "1.3.37")]
+#[rustc_const_stable(feature = "foo", since = "1.3.37")]
+#[rustc_intrinsic]
+const unsafe fn simd_extract<T, U>(_x: T, _idx: u32) -> U {
+    unimplemented!()
 }
 
 fn main() {
diff --git a/tests/ui/consts/const-ptr-is-null.stderr b/tests/ui/consts/const-ptr-is-null.stderr
index 20e44a1401f..5fd35142818 100644
--- a/tests/ui/consts/const-ptr-is-null.stderr
+++ b/tests/ui/consts/const-ptr-is-null.stderr
@@ -3,7 +3,7 @@ error[E0080]: evaluation of constant value failed
    |
    = note: the evaluated program panicked at 'null-ness of this pointer cannot be determined in const context', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-note: inside `std::ptr::const_ptr::<impl *const T>::is_null::const_impl`
+note: inside `std::ptr::const_ptr::<impl *const T>::is_null::compiletime`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
 note: inside `std::ptr::const_ptr::<impl *const i32>::is_null`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -12,7 +12,7 @@ note: inside `MAYBE_NULL`
    |
 LL |     assert!(!ptr.wrapping_sub(512).is_null());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `const_eval_select` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const-unstable-intrinsic.rs b/tests/ui/consts/const-unstable-intrinsic.rs
index 050abc6dd46..56b552b6a3f 100644
--- a/tests/ui/consts/const-unstable-intrinsic.rs
+++ b/tests/ui/consts/const-unstable-intrinsic.rs
@@ -14,63 +14,51 @@ fn main() {
 const fn const_main() {
     let x = 42;
     unsafe {
-        unstable_intrinsic::old_way::size_of_val(&x);
-        //~^ERROR: unstable library feature 'unstable'
-        //~|ERROR: cannot call non-const intrinsic
-        unstable_intrinsic::old_way::min_align_of_val(&x);
-        //~^ERROR: unstable library feature 'unstable'
-        //~|ERROR: not yet stable as a const intrinsic
-        unstable_intrinsic::new_way::size_of_val(&x);
-        //~^ERROR: unstable library feature 'unstable'
+        unstable_intrinsic::size_of_val(&x);
+        //~^ERROR: unstable library feature `unstable`
         //~|ERROR: cannot be (indirectly) exposed to stable
-        unstable_intrinsic::new_way::min_align_of_val(&x);
-        //~^ERROR: unstable library feature 'unstable'
+        unstable_intrinsic::min_align_of_val(&x);
+        //~^ERROR: unstable library feature `unstable`
         //~|ERROR: not yet stable as a const intrinsic
 
-        old_way::size_of_val(&x);
-        //~^ERROR: cannot call non-const intrinsic
-        old_way::min_align_of_val(&x);
-        //~^ERROR: cannot use `#[feature(local)]`
-        new_way::size_of_val(&x);
+        size_of_val(&x);
         //~^ERROR: cannot be (indirectly) exposed to stable
-        new_way::min_align_of_val(&x);
+        min_align_of_val(&x);
         //~^ERROR: cannot use `#[feature(local)]`
     }
 }
 
-#[stable(since="1.0.0", feature = "stable")]
-pub mod old_way {
-    extern "rust-intrinsic" {
-        #[unstable(feature = "local", issue = "42")]
-        pub fn size_of_val<T>(x: *const T) -> usize;
-
-        #[unstable(feature = "local", issue = "42")]
-        #[rustc_const_unstable(feature = "local", issue = "42")]
-        pub fn min_align_of_val<T>(x: *const T) -> usize;
-    }
-}
-
-#[stable(since="1.0.0", feature = "stable")]
-pub mod new_way {
-    #[unstable(feature = "local", issue = "42")]
-    #[rustc_intrinsic]
-    pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
+#[unstable(feature = "local", issue = "42")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
 
-    #[unstable(feature = "local", issue = "42")]
-    #[rustc_const_unstable(feature = "local", issue = "42")]
-    #[rustc_intrinsic]
-    pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
-}
+#[unstable(feature = "local", issue = "42")]
+#[rustc_const_unstable(feature = "local", issue = "42")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+pub const unsafe fn min_align_of_val<T>(x: *const T) -> usize { 42 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
 #[inline]
 pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     // Const stability attributes are not inherited from parent items.
-    extern "rust-intrinsic" {
-        fn copy<T>(src: *const T, dst: *mut T, count: usize);
+    #[rustc_intrinsic]
+    #[rustc_intrinsic_must_be_overridden]
+    const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
+        unimplemented!()
     }
 
     unsafe { copy(src, dst, count) }
-    //~^ ERROR cannot call non-const intrinsic
+    //~^ ERROR cannot be (indirectly) exposed to stable
+}
+
+// Ensure that a fallback body is recursively-const-checked.
+mod fallback {
+    #[rustc_intrinsic]
+    const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
+        super::size_of_val(src);
+        //~^ ERROR cannot be (indirectly) exposed to stable
+    }
 }
diff --git a/tests/ui/consts/const-unstable-intrinsic.stderr b/tests/ui/consts/const-unstable-intrinsic.stderr
index 33a434c503d..3e605f3d003 100644
--- a/tests/ui/consts/const-unstable-intrinsic.stderr
+++ b/tests/ui/consts/const-unstable-intrinsic.stderr
@@ -1,84 +1,52 @@
-error[E0658]: use of unstable library feature 'unstable'
+error[E0658]: use of unstable library feature `unstable`
   --> $DIR/const-unstable-intrinsic.rs:17:9
    |
-LL |         unstable_intrinsic::old_way::size_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         unstable_intrinsic::size_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
    = help: add `#![feature(unstable)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable'
+error[E0658]: use of unstable library feature `unstable`
   --> $DIR/const-unstable-intrinsic.rs:20:9
    |
-LL |         unstable_intrinsic::old_way::min_align_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
-   = help: add `#![feature(unstable)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: use of unstable library feature 'unstable'
-  --> $DIR/const-unstable-intrinsic.rs:23:9
-   |
-LL |         unstable_intrinsic::new_way::size_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
-   = help: add `#![feature(unstable)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
-
-error[E0658]: use of unstable library feature 'unstable'
-  --> $DIR/const-unstable-intrinsic.rs:26:9
-   |
-LL |         unstable_intrinsic::new_way::min_align_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         unstable_intrinsic::min_align_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #42 <https://github.com/rust-lang/rust/issues/42> for more information
    = help: add `#![feature(unstable)]` 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: cannot call non-const intrinsic `size_of_val` in constant functions
+error: intrinsic `unstable_intrinsic::size_of_val` cannot be (indirectly) exposed to stable
   --> $DIR/const-unstable-intrinsic.rs:17:9
    |
-LL |         unstable_intrinsic::old_way::size_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         unstable_intrinsic::size_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
 
 error: `min_align_of_val` is not yet stable as a const intrinsic
   --> $DIR/const-unstable-intrinsic.rs:20:9
    |
-LL |         unstable_intrinsic::old_way::min_align_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         unstable_intrinsic::min_align_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add `#![feature(unstable)]` to the crate attributes to enable
 
-error: intrinsic `unstable_intrinsic::new_way::size_of_val` cannot be (indirectly) exposed to stable
-  --> $DIR/const-unstable-intrinsic.rs:23:9
+error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
+  --> $DIR/const-unstable-intrinsic.rs:24:9
    |
-LL |         unstable_intrinsic::new_way::size_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         size_of_val(&x);
+   |         ^^^^^^^^^^^^^^^
    |
-   = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
-
-error: `min_align_of_val` is not yet stable as a const intrinsic
-  --> $DIR/const-unstable-intrinsic.rs:26:9
-   |
-LL |         unstable_intrinsic::new_way::min_align_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(unstable)]` to the crate attributes to enable
-
-error: cannot call non-const intrinsic `size_of_val` in constant functions
-  --> $DIR/const-unstable-intrinsic.rs:30:9
-   |
-LL |         old_way::size_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
 
 error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
-  --> $DIR/const-unstable-intrinsic.rs:32:9
+  --> $DIR/const-unstable-intrinsic.rs:26:9
    |
-LL |         old_way::min_align_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         min_align_of_val(&x);
+   |         ^^^^^^^^^^^^^^^^^^^^
    |
 help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
    |
@@ -91,37 +59,22 @@ LL + #[rustc_allow_const_fn_unstable(local)]
 LL | const fn const_main() {
    |
 
-error: intrinsic `new_way::size_of_val` cannot be (indirectly) exposed to stable
-  --> $DIR/const-unstable-intrinsic.rs:34:9
+error: intrinsic `copy::copy` cannot be (indirectly) exposed to stable
+  --> $DIR/const-unstable-intrinsic.rs:53:14
    |
-LL |         new_way::size_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe { copy(src, dst, count) }
+   |              ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_indirect]` (but this requires team approval)
+   = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
 
-error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
-  --> $DIR/const-unstable-intrinsic.rs:36:9
-   |
-LL |         new_way::min_align_of_val(&x);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
+  --> $DIR/const-unstable-intrinsic.rs:61:9
    |
-help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
+LL |         super::size_of_val(src);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
    |
-LL + #[rustc_const_unstable(feature = "...", issue = "...")]
-LL | const fn const_main() {
-   |
-help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
-   |
-LL + #[rustc_allow_const_fn_unstable(local)]
-LL | const fn const_main() {
-   |
-
-error: cannot call non-const intrinsic `copy` in constant functions
-  --> $DIR/const-unstable-intrinsic.rs:74:14
-   |
-LL |     unsafe { copy(src, dst, count) }
-   |              ^^^^^^^^^^^^^^^^^^^^^
+   = help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
 
-error: aborting due to 13 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/consts/copy-intrinsic.rs b/tests/ui/consts/copy-intrinsic.rs
index 62917c0b98b..08fbcc107e7 100644
--- a/tests/ui/consts/copy-intrinsic.rs
+++ b/tests/ui/consts/copy-intrinsic.rs
@@ -1,17 +1,21 @@
 #![stable(feature = "dummy", since = "1.0.0")]
 
 // ignore-tidy-linelength
-#![feature(intrinsics, staged_api)]
+#![feature(intrinsics, staged_api, rustc_attrs)]
 use std::mem;
 
-extern "rust-intrinsic" {
-    #[stable(feature = "dummy", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
-    fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
+#[stable(feature = "dummy", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
+#[rustc_intrinsic]
+const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
+    unimplemented!()
+}
 
-    #[stable(feature = "dummy", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
-    fn copy<T>(src: *const T, dst: *mut T, count: usize);
+#[stable(feature = "dummy", since = "1.0.0")]
+#[rustc_const_stable(feature = "const_intrinsic_copy", since = "1.63.0")]
+#[rustc_intrinsic]
+const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
+    unimplemented!()
 }
 
 const COPY_ZERO: () = unsafe {
diff --git a/tests/ui/consts/copy-intrinsic.stderr b/tests/ui/consts/copy-intrinsic.stderr
index 29a88f6270b..41af3a2cd2d 100644
--- a/tests/ui/consts/copy-intrinsic.stderr
+++ b/tests/ui/consts/copy-intrinsic.stderr
@@ -1,23 +1,23 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:30:5
+  --> $DIR/copy-intrinsic.rs:34:5
    |
 LL |     copy_nonoverlapping(0x100 as *const i32, dangle, 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got 0x100[noalloc] which is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:39:5
+  --> $DIR/copy-intrinsic.rs:43:5
    |
 LL |     copy_nonoverlapping(dangle, 0x100 as *mut i32, 1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: expected a pointer to 4 bytes of memory, but got ALLOC0+0x28 which is at or beyond the end of the allocation of size 4 bytes
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:46:5
+  --> $DIR/copy-intrinsic.rs:50:5
    |
 LL |     copy(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy`
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/copy-intrinsic.rs:52:5
+  --> $DIR/copy-intrinsic.rs:56:5
    |
 LL |     copy_nonoverlapping(&x, &mut y, 1usize << (mem::size_of::<usize>() * 8 - 1));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflow computing total size of `copy_nonoverlapping`
diff --git a/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs
new file mode 100644
index 00000000000..c4fb620fea4
--- /dev/null
+++ b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.rs
@@ -0,0 +1,11 @@
+// Duplicate implementations of Copy/Clone should not trigger
+// borrow check warnings
+// See #131083
+
+#[derive(Copy, Clone)]
+#[derive(Copy, Clone)]
+//~^ ERROR conflicting implementations of trait `Clone` for type `E`
+//~| ERROR conflicting implementations of trait `Copy` for type `E`
+enum E {}
+
+fn main() {}
diff --git a/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr
new file mode 100644
index 00000000000..f8e1db33f53
--- /dev/null
+++ b/tests/ui/derives/duplicate-derive-copy-clone-diagnostics.stderr
@@ -0,0 +1,23 @@
+error[E0119]: conflicting implementations of trait `Copy` for type `E`
+  --> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:10
+   |
+LL | #[derive(Copy, Clone)]
+   |          ---- first implementation here
+LL | #[derive(Copy, Clone)]
+   |          ^^^^ conflicting implementation for `E`
+   |
+   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0119]: conflicting implementations of trait `Clone` for type `E`
+  --> $DIR/duplicate-derive-copy-clone-diagnostics.rs:6:16
+   |
+LL | #[derive(Copy, Clone)]
+   |                ----- first implementation here
+LL | #[derive(Copy, Clone)]
+   |                ^^^^^ conflicting implementation for `E`
+   |
+   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/derives/rustc-decodable-issue-123156.stderr b/tests/ui/derives/rustc-decodable-issue-123156.stderr
index ee7b33d59bb..93a993b90d8 100644
--- a/tests/ui/derives/rustc-decodable-issue-123156.stderr
+++ b/tests/ui/derives/rustc-decodable-issue-123156.stderr
@@ -1,5 +1,5 @@
 Future incompatibility report: Future breakage diagnostic:
-warning: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code
+warning: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code
   --> $DIR/rustc-decodable-issue-123156.rs:10:10
    |
 LL | #[derive(RustcDecodable)]
diff --git a/tests/ui/destructuring-assignment/struct_destructure_fail.stderr b/tests/ui/destructuring-assignment/struct_destructure_fail.stderr
index 57851ed417e..4c4f0663eeb 100644
--- a/tests/ui/destructuring-assignment/struct_destructure_fail.stderr
+++ b/tests/ui/destructuring-assignment/struct_destructure_fail.stderr
@@ -41,6 +41,10 @@ LL |     Struct { a, b } = Struct { a: 1, b: 2 };
    |               ~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     Struct { a, b: _ } = Struct { a: 1, b: 2 };
+   |               ~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     Struct { a, .. } = Struct { a: 1, b: 2 };
    |               ~~~~~~
 
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr
index e56af28f3fb..be17476524a 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/do_not_apply_attribute_without_feature_flag.stderr
@@ -15,6 +15,10 @@ note: required by a bound in `check`
    |
 LL | fn check(a: impl Foo) {}
    |                  ^^^ required by this bound in `check`
+help: use a unary tuple instead
+   |
+LL |     check(((),));
+   |           +  ++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr
index 629fc59361d..ca9a6ebc1c4 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.current.stderr
@@ -12,6 +12,10 @@ note: required by a bound in `check`
    |
 LL | fn check(a: impl Foo) {}
    |                  ^^^ required by this bound in `check`
+help: use a unary tuple instead
+   |
+LL |     check(((),));
+   |           +  ++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr
index 629fc59361d..ca9a6ebc1c4 100644
--- a/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr
+++ b/tests/ui/diagnostic_namespace/do_not_recommend/supress_suggestions_in_help.next.stderr
@@ -12,6 +12,10 @@ note: required by a bound in `check`
    |
 LL | fn check(a: impl Foo) {}
    |                  ^^^ required by this bound in `check`
+help: use a unary tuple instead
+   |
+LL |     check(((),));
+   |           +  ++
 
 error: aborting due to 1 previous error
 
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 43c1c775978..17b76b6c832 100644
--- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
+++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
@@ -21,6 +21,6 @@ enum FingerTree<T:'static> {
 }
 
 fn main() {
-    let ft = //~ ERROR overflow while adding drop-check rules for FingerTree
+    let ft = //~ ERROR overflow while adding drop-check rules for `FingerTree
         FingerTree::Single(1);
 }
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 8f4d301b5ca..9360f4a98e9 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,10 @@
-error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
+error[E0320]: overflow while adding drop-check rules for `FingerTree<i32>`
   --> $DIR/dropck_no_diverge_on_nonregular_1.rs:24: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<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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs
index edd07652e53..d731ab09e7e 100644
--- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs
+++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.rs
@@ -20,6 +20,6 @@ enum FingerTree<T:'static> {
 }
 
 fn main() {
-    let ft = //~ ERROR overflow while adding drop-check rules for FingerTree
+    let ft = //~ ERROR overflow while adding drop-check rules for `FingerTree
         FingerTree::Single(1);
 }
diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
index 4ef7aa61db7..88162989dee 100644
--- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
+++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
@@ -1,10 +1,10 @@
-error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
+error[E0320]: overflow while adding drop-check rules for `FingerTree<i32>`
   --> $DIR/dropck_no_diverge_on_nonregular_2.rs:23: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<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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs
index af7402ca4a1..d318bdcde92 100644
--- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs
+++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.rs
@@ -29,7 +29,7 @@ enum Wrapper<T:'static> {
 }
 
 fn main() {
-    let w = //~ ERROR overflow while adding drop-check rules for Option
+    let w = //~ ERROR overflow while adding drop-check rules for `Option
         Some(Wrapper::Simple::<u32>);
-    //~^ ERROR overflow while adding drop-check rules for Wrapper
+    //~^ ERROR overflow while adding drop-check rules for `Wrapper
 }
diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
index deaf116b647..54cf20a3520 100644
--- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
+++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
@@ -1,18 +1,18 @@
-error[E0320]: overflow while adding drop-check rules for Option<Wrapper<u32>>
+error[E0320]: overflow while adding drop-check rules for `Option<Wrapper<u32>>`
   --> $DIR/dropck_no_diverge_on_nonregular_3.rs:32:9
    |
 LL |     let w =
    |         ^
    |
-   = 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<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+   = 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<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
 
-error[E0320]: overflow while adding drop-check rules for Wrapper<u32>
+error[E0320]: overflow while adding drop-check rules for `Wrapper<u32>`
   --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:14
    |
 LL |         Some(Wrapper::Simple::<u32>);
    |              ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = 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<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+   = 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<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/enum/assoc-fn-call-on-variant.rs b/tests/ui/enum/assoc-fn-call-on-variant.rs
new file mode 100644
index 00000000000..7fa8eb2da41
--- /dev/null
+++ b/tests/ui/enum/assoc-fn-call-on-variant.rs
@@ -0,0 +1,15 @@
+#[derive(Default)]
+enum E {
+    A {},
+    B {},
+    #[default]
+    C,
+}
+
+impl E {
+    fn f() {}
+}
+
+fn main() {
+    E::A::f(); //~ ERROR failed to resolve: `A` is a variant, not a module
+}
diff --git a/tests/ui/enum/assoc-fn-call-on-variant.stderr b/tests/ui/enum/assoc-fn-call-on-variant.stderr
new file mode 100644
index 00000000000..47fc630c923
--- /dev/null
+++ b/tests/ui/enum/assoc-fn-call-on-variant.stderr
@@ -0,0 +1,14 @@
+error[E0433]: failed to resolve: `A` is a variant, not a module
+  --> $DIR/assoc-fn-call-on-variant.rs:14:8
+   |
+LL |     E::A::f();
+   |        ^ `A` is a variant, not a module
+   |
+help: there is an enum variant `E::A`; try using the variant's enum
+   |
+LL |     E::f();
+   |     ~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/error-codes/E0027.stderr b/tests/ui/error-codes/E0027.stderr
index 9ae97e4a994..7bbafcf0a27 100644
--- a/tests/ui/error-codes/E0027.stderr
+++ b/tests/ui/error-codes/E0027.stderr
@@ -10,6 +10,10 @@ LL |         Dog { age: x, name } => {}
    |                     ~~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |         Dog { age: x, name: _ } => {}
+   |                     ~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |         Dog { age: x, .. } => {}
    |                     ~~~~~~
 
@@ -25,6 +29,10 @@ LL |         Dog { name: x, age } => {}
    |                      ~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |         Dog { name: x, age: _ } => {}
+   |                      ~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |         Dog { name: x, .. } => {}
    |                      ~~~~~~
 
@@ -40,6 +48,10 @@ LL |         Dog { name: x, age } => {}
    |                      ~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |         Dog { name: x, age: _ } => {}
+   |                      ~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |         Dog { name: x, .. } => {}
    |                      ~~~~~~
 
@@ -55,6 +67,10 @@ LL |         Dog { name, age } => {}
    |             ~~~~~~~~~~~~~
 help: if you don't care about these missing fields, you can explicitly ignore them
    |
+LL |         Dog { name: _, age: _ } => {}
+   |             ~~~~~~~~~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |         Dog { .. } => {}
    |             ~~~~~~
 
diff --git a/tests/ui/error-festival.stderr b/tests/ui/error-festival.stderr
index 26393352b2b..f71fa7e685c 100644
--- a/tests/ui/error-festival.stderr
+++ b/tests/ui/error-festival.stderr
@@ -2,7 +2,16 @@ error[E0425]: cannot find value `y` in this scope
   --> $DIR/error-festival.rs:14:5
    |
 LL |     y = 2;
-   |     ^ help: a local variable with a similar name exists: `x`
+   |     ^
+   |
+help: a local variable with a similar name exists
+   |
+LL |     x = 2;
+   |     ~
+help: you might have meant to introduce a new binding
+   |
+LL |     let y = 2;
+   |     +++
 
 error[E0603]: constant `FOO` is private
   --> $DIR/error-festival.rs:22:10
diff --git a/tests/ui/explore-issue-38412.rs b/tests/ui/explore-issue-38412.rs
index 836cb98b5b3..e1295a96ba5 100644
--- a/tests/ui/explore-issue-38412.rs
+++ b/tests/ui/explore-issue-38412.rs
@@ -18,7 +18,7 @@ fn main() {
 
     let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } =
         Record::new();
-    //~^^ ERROR use of unstable library feature 'unstable_undeclared'
+    //~^^ ERROR use of unstable library feature `unstable_undeclared`
 
     let r = Record::new();
     let t = Tuple::new();
diff --git a/tests/ui/explore-issue-38412.stderr b/tests/ui/explore-issue-38412.stderr
index a45ec688855..884184ec16e 100644
--- a/tests/ui/explore-issue-38412.stderr
+++ b/tests/ui/explore-issue-38412.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_undeclared'
+error[E0658]: use of unstable library feature `unstable_undeclared`
   --> $DIR/explore-issue-38412.rs:19:63
    |
 LL |     let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_undeclared_pub: _, .. } =
@@ -8,7 +8,7 @@ LL |     let Record { a_stable_pub: _, a_unstable_declared_pub: _, a_unstable_un
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_undeclared'
+error[E0658]: use of unstable library feature `unstable_undeclared`
   --> $DIR/explore-issue-38412.rs:28:5
    |
 LL |     r.a_unstable_undeclared_pub;
@@ -36,7 +36,7 @@ error[E0616]: field `d_priv` of struct `Record` is private
 LL |     r.d_priv;
    |       ^^^^^^ private field
 
-error[E0658]: use of unstable library feature 'unstable_undeclared'
+error[E0658]: use of unstable library feature `unstable_undeclared`
   --> $DIR/explore-issue-38412.rs:35:5
    |
 LL |     t.2;
@@ -64,7 +64,7 @@ error[E0616]: field `5` of struct `pub_and_stability::Tuple` is private
 LL |     t.5;
    |       ^ private field
 
-error[E0658]: use of unstable library feature 'unstable_undeclared'
+error[E0658]: use of unstable library feature `unstable_undeclared`
   --> $DIR/explore-issue-38412.rs:42:7
    |
 LL |     r.unstable_undeclared_trait_method();
@@ -74,7 +74,7 @@ LL |     r.unstable_undeclared_trait_method();
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_undeclared'
+error[E0658]: use of unstable library feature `unstable_undeclared`
   --> $DIR/explore-issue-38412.rs:46:7
    |
 LL |     r.unstable_undeclared();
@@ -117,7 +117,7 @@ LL |     r.private();
 LL |         fn private(&self) -> i32 { self.d_priv }
    |         ------------------------ private method defined here
 
-error[E0658]: use of unstable library feature 'unstable_undeclared'
+error[E0658]: use of unstable library feature `unstable_undeclared`
   --> $DIR/explore-issue-38412.rs:55:7
    |
 LL |     t.unstable_undeclared_trait_method();
@@ -127,7 +127,7 @@ LL |     t.unstable_undeclared_trait_method();
    = help: add `#![feature(unstable_undeclared)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_undeclared'
+error[E0658]: use of unstable library feature `unstable_undeclared`
   --> $DIR/explore-issue-38412.rs:59:7
    |
 LL |     t.unstable_undeclared();
diff --git a/tests/ui/feature-gates/bench.rs b/tests/ui/feature-gates/bench.rs
index 2ce1d50fbb0..12e646f7a32 100644
--- a/tests/ui/feature-gates/bench.rs
+++ b/tests/ui/feature-gates/bench.rs
@@ -1,9 +1,9 @@
 //@ edition:2018
 
-#[bench] //~ ERROR use of unstable library feature 'test'
+#[bench] //~ ERROR use of unstable library feature `test`
          //~| WARN this was previously accepted
 fn bench() {}
 
-use bench as _; //~ ERROR use of unstable library feature 'test'
+use bench as _; //~ ERROR use of unstable library feature `test`
                 //~| WARN this was previously accepted
 fn main() {}
diff --git a/tests/ui/feature-gates/bench.stderr b/tests/ui/feature-gates/bench.stderr
index df935560fd6..de78e863012 100644
--- a/tests/ui/feature-gates/bench.stderr
+++ b/tests/ui/feature-gates/bench.stderr
@@ -1,4 +1,4 @@
-error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
+error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
   --> $DIR/bench.rs:3:3
    |
 LL | #[bench]
@@ -8,7 +8,7 @@ LL | #[bench]
    = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
    = note: `#[deny(soft_unstable)]` on by default
 
-error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
+error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
   --> $DIR/bench.rs:7:5
    |
 LL | use bench as _;
@@ -20,7 +20,7 @@ LL | use bench as _;
 error: aborting due to 2 previous errors
 
 Future incompatibility report: Future breakage diagnostic:
-error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
+error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
   --> $DIR/bench.rs:3:3
    |
 LL | #[bench]
@@ -31,7 +31,7 @@ LL | #[bench]
    = note: `#[deny(soft_unstable)]` on by default
 
 Future breakage diagnostic:
-error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
+error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
   --> $DIR/bench.rs:7:5
    |
 LL | use bench as _;
diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs b/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs
index 2d099e24db8..a2a4b3f19d9 100644
--- a/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs
+++ b/tests/ui/feature-gates/feature-gate-alloc-error-handler.rs
@@ -5,7 +5,7 @@
 
 use core::alloc::Layout;
 
-#[alloc_error_handler] //~ ERROR use of unstable library feature 'alloc_error_handler'
+#[alloc_error_handler] //~ ERROR use of unstable library feature `alloc_error_handler`
 fn oom(info: Layout) -> ! {
     loop {}
 }
diff --git a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr
index 2ebd7cd9b02..ae41ee55d3d 100644
--- a/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr
+++ b/tests/ui/feature-gates/feature-gate-alloc-error-handler.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'alloc_error_handler'
+error[E0658]: use of unstable library feature `alloc_error_handler`
   --> $DIR/feature-gate-alloc-error-handler.rs:8:3
    |
 LL | #[alloc_error_handler]
diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr
index 36a017dd53c..15ef257fbd8 100644
--- a/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr
+++ b/tests/ui/feature-gates/feature-gate-autodiff-use.has_support.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'autodiff'
+error[E0658]: use of unstable library feature `autodiff`
   --> $DIR/feature-gate-autodiff-use.rs:13:3
    |
 LL | #[autodiff(dfoo, Reverse)]
@@ -8,7 +8,7 @@ LL | #[autodiff(dfoo, Reverse)]
    = help: add `#![feature(autodiff)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'autodiff'
+error[E0658]: use of unstable library feature `autodiff`
   --> $DIR/feature-gate-autodiff-use.rs:9:5
    |
 LL | use std::autodiff::autodiff;
diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr
index 4b767f824c8..f59e4955452 100644
--- a/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr
+++ b/tests/ui/feature-gates/feature-gate-autodiff-use.no_support.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'autodiff'
+error[E0658]: use of unstable library feature `autodiff`
   --> $DIR/feature-gate-autodiff-use.rs:13:3
    |
 LL | #[autodiff(dfoo, Reverse)]
@@ -14,7 +14,7 @@ error: this rustc version does not support autodiff
 LL | #[autodiff(dfoo, Reverse)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0658]: use of unstable library feature 'autodiff'
+error[E0658]: use of unstable library feature `autodiff`
   --> $DIR/feature-gate-autodiff-use.rs:9:5
    |
 LL | use std::autodiff::autodiff;
diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.rs b/tests/ui/feature-gates/feature-gate-autodiff-use.rs
index 2276a79d6e2..602e830b0b2 100644
--- a/tests/ui/feature-gates/feature-gate-autodiff-use.rs
+++ b/tests/ui/feature-gates/feature-gate-autodiff-use.rs
@@ -7,11 +7,11 @@
 #![crate_type = "lib"]
 
 use std::autodiff::autodiff;
-//[has_support]~^ ERROR use of unstable library feature 'autodiff'
-//[no_support]~^^ ERROR use of unstable library feature 'autodiff'
+//[has_support]~^ ERROR use of unstable library feature `autodiff`
+//[no_support]~^^ ERROR use of unstable library feature `autodiff`
 
 #[autodiff(dfoo, Reverse)]
-//[has_support]~^ ERROR use of unstable library feature 'autodiff' [E0658]
-//[no_support]~^^ ERROR use of unstable library feature 'autodiff' [E0658]
+//[has_support]~^ ERROR use of unstable library feature `autodiff` [E0658]
+//[no_support]~^^ ERROR use of unstable library feature `autodiff` [E0658]
 //[no_support]~| ERROR this rustc version does not support autodiff
 fn foo() {}
diff --git a/tests/ui/feature-gates/feature-gate-concat_bytes.rs b/tests/ui/feature-gates/feature-gate-concat_bytes.rs
index 07d63cb11e0..abdaa725784 100644
--- a/tests/ui/feature-gates/feature-gate-concat_bytes.rs
+++ b/tests/ui/feature-gates/feature-gate-concat_bytes.rs
@@ -1,4 +1,4 @@
 fn main() {
-    let a = concat_bytes!(b'A', b"BC"); //~ ERROR use of unstable library feature 'concat_bytes'
+    let a = concat_bytes!(b'A', b"BC"); //~ ERROR use of unstable library feature `concat_bytes`
     assert_eq!(a, &[65, 66, 67]);
 }
diff --git a/tests/ui/feature-gates/feature-gate-concat_bytes.stderr b/tests/ui/feature-gates/feature-gate-concat_bytes.stderr
index ed9692d3693..4f75e143e9a 100644
--- a/tests/ui/feature-gates/feature-gate-concat_bytes.stderr
+++ b/tests/ui/feature-gates/feature-gate-concat_bytes.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'concat_bytes'
+error[E0658]: use of unstable library feature `concat_bytes`
   --> $DIR/feature-gate-concat_bytes.rs:2:13
    |
 LL |     let a = concat_bytes!(b'A', b"BC");
diff --git a/tests/ui/feature-gates/feature-gate-concat_idents.stderr b/tests/ui/feature-gates/feature-gate-concat_idents.stderr
index eaaef0f2539..d0f4fe62d04 100644
--- a/tests/ui/feature-gates/feature-gate-concat_idents.stderr
+++ b/tests/ui/feature-gates/feature-gate-concat_idents.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents.rs:5:13
    |
 LL |     let a = concat_idents!(X, Y_1);
@@ -8,7 +8,7 @@ LL |     let a = concat_idents!(X, Y_1);
    = help: add `#![feature(concat_idents)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents.rs:6:13
    |
 LL |     let b = concat_idents!(X, Y_2);
diff --git a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr
index 2fe786ff406..2052813ea4a 100644
--- a/tests/ui/feature-gates/feature-gate-concat_idents2.stderr
+++ b/tests/ui/feature-gates/feature-gate-concat_idents2.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents2.rs:2:5
    |
 LL |     concat_idents!(a, b);
diff --git a/tests/ui/feature-gates/feature-gate-concat_idents3.stderr b/tests/ui/feature-gates/feature-gate-concat_idents3.stderr
index a7daa1f949f..b186601d0ed 100644
--- a/tests/ui/feature-gates/feature-gate-concat_idents3.stderr
+++ b/tests/ui/feature-gates/feature-gate-concat_idents3.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents3.rs:5:20
    |
 LL |     assert_eq!(10, concat_idents!(X, Y_1));
@@ -8,7 +8,7 @@ LL |     assert_eq!(10, concat_idents!(X, Y_1));
    = help: add `#![feature(concat_idents)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'concat_idents': `concat_idents` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `concat_idents`: `concat_idents` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-concat_idents3.rs:6:20
    |
 LL |     assert_eq!(20, concat_idents!(X, Y_2));
diff --git a/tests/ui/feature-gates/feature-gate-custom_mir.stderr b/tests/ui/feature-gates/feature-gate-custom_mir.stderr
index 118eab144bf..eeceb0355ee 100644
--- a/tests/ui/feature-gates/feature-gate-custom_mir.stderr
+++ b/tests/ui/feature-gates/feature-gate-custom_mir.stderr
@@ -7,7 +7,7 @@ LL | #[custom_mir(dialect = "built")]
    = help: add `#![feature(custom_mir)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable
+error[E0658]: use of unstable library feature `custom_mir`: MIR is an implementation detail and extremely unstable
   --> $DIR/feature-gate-custom_mir.rs:4:5
    |
 LL | use core::intrinsics::mir::*;
@@ -16,7 +16,7 @@ LL | use core::intrinsics::mir::*;
    = help: add `#![feature(custom_mir)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'custom_mir': MIR is an implementation detail and extremely unstable
+error[E0658]: use of unstable library feature `custom_mir`: MIR is an implementation detail and extremely unstable
   --> $DIR/feature-gate-custom_mir.rs:10:13
    |
 LL |             Return()
diff --git a/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
index 016be980d4d..7744759be57 100644
--- a/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
+++ b/tests/ui/feature-gates/feature-gate-custom_test_frameworks.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'custom_test_frameworks': custom test frameworks are an unstable feature
+error[E0658]: use of unstable library feature `custom_test_frameworks`: custom test frameworks are an unstable feature
   --> $DIR/feature-gate-custom_test_frameworks.rs:3:3
    |
 LL | #[test_case]
diff --git a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.rs b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.rs
index 69bc70e8666..d730849dcf6 100644
--- a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.rs
+++ b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.rs
@@ -1,6 +1,6 @@
-use std::marker::CoercePointee; //~ ERROR use of unstable library feature 'derive_coerce_pointee'
+use std::marker::CoercePointee; //~ ERROR use of unstable library feature `derive_coerce_pointee`
 
-#[derive(CoercePointee)] //~ ERROR use of unstable library feature 'derive_coerce_pointee'
+#[derive(CoercePointee)] //~ ERROR use of unstable library feature `derive_coerce_pointee`
 #[repr(transparent)]
 struct MyPointer<'a, #[pointee] T: ?Sized> {
     ptr: &'a T,
diff --git a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr
index 0b52ceb782a..19babe149d9 100644
--- a/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr
+++ b/tests/ui/feature-gates/feature-gate-derive-coerce-pointee.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'derive_coerce_pointee'
+error[E0658]: use of unstable library feature `derive_coerce_pointee`
   --> $DIR/feature-gate-derive-coerce-pointee.rs:3:10
    |
 LL | #[derive(CoercePointee)]
@@ -8,7 +8,7 @@ LL | #[derive(CoercePointee)]
    = help: add `#![feature(derive_coerce_pointee)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'derive_coerce_pointee'
+error[E0658]: use of unstable library feature `derive_coerce_pointee`
   --> $DIR/feature-gate-derive-coerce-pointee.rs:1:5
    |
 LL | use std::marker::CoercePointee;
diff --git a/tests/ui/feature-gates/feature-gate-format_args_nl.stderr b/tests/ui/feature-gates/feature-gate-format_args_nl.stderr
index f72d34d9b0b..c7e8f8c686f 100644
--- a/tests/ui/feature-gates/feature-gate-format_args_nl.stderr
+++ b/tests/ui/feature-gates/feature-gate-format_args_nl.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'format_args_nl': `format_args_nl` is only for internal language use and is subject to change
+error[E0658]: use of unstable library feature `format_args_nl`: `format_args_nl` is only for internal language use and is subject to change
   --> $DIR/feature-gate-format_args_nl.rs:2:5
    |
 LL |     format_args_nl!("");
diff --git a/tests/ui/feature-gates/feature-gate-log_syntax.stderr b/tests/ui/feature-gates/feature-gate-log_syntax.stderr
index 0eba231a287..78152b50e89 100644
--- a/tests/ui/feature-gates/feature-gate-log_syntax.stderr
+++ b/tests/ui/feature-gates/feature-gate-log_syntax.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `log_syntax`: `log_syntax!` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-log_syntax.rs:2:5
    |
 LL |     log_syntax!()
diff --git a/tests/ui/feature-gates/feature-gate-log_syntax2.stderr b/tests/ui/feature-gates/feature-gate-log_syntax2.stderr
index e1f92dd60a3..8875de2281b 100644
--- a/tests/ui/feature-gates/feature-gate-log_syntax2.stderr
+++ b/tests/ui/feature-gates/feature-gate-log_syntax2.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'log_syntax': `log_syntax!` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `log_syntax`: `log_syntax!` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-log_syntax2.rs:2:22
    |
 LL |     println!("{:?}", log_syntax!());
diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.rs b/tests/ui/feature-gates/feature-gate-naked_functions.rs
index 5fe0bbdc774..abb55b9a557 100644
--- a/tests/ui/feature-gates/feature-gate-naked_functions.rs
+++ b/tests/ui/feature-gates/feature-gate-naked_functions.rs
@@ -1,13 +1,13 @@
 //@ needs-asm-support
 
 use std::arch::naked_asm;
-//~^ ERROR use of unstable library feature 'naked_functions'
+//~^ ERROR use of unstable library feature `naked_functions`
 
 #[naked]
 //~^ the `#[naked]` attribute is an experimental feature
 extern "C" fn naked() {
     naked_asm!("")
-    //~^ ERROR use of unstable library feature 'naked_functions'
+    //~^ ERROR use of unstable library feature `naked_functions`
     //~| ERROR: requires unsafe
 }
 
@@ -15,7 +15,7 @@ extern "C" fn naked() {
 //~^ the `#[naked]` attribute is an experimental feature
 extern "C" fn naked_2() -> isize {
     naked_asm!("")
-    //~^ ERROR use of unstable library feature 'naked_functions'
+    //~^ ERROR use of unstable library feature `naked_functions`
     //~| ERROR: requires unsafe
 }
 
diff --git a/tests/ui/feature-gates/feature-gate-naked_functions.stderr b/tests/ui/feature-gates/feature-gate-naked_functions.stderr
index 709234eb023..9bfb9275bb2 100644
--- a/tests/ui/feature-gates/feature-gate-naked_functions.stderr
+++ b/tests/ui/feature-gates/feature-gate-naked_functions.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'naked_functions'
+error[E0658]: use of unstable library feature `naked_functions`
   --> $DIR/feature-gate-naked_functions.rs:9:5
    |
 LL |     naked_asm!("")
@@ -8,7 +8,7 @@ LL |     naked_asm!("")
    = help: add `#![feature(naked_functions)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'naked_functions'
+error[E0658]: use of unstable library feature `naked_functions`
   --> $DIR/feature-gate-naked_functions.rs:17:5
    |
 LL |     naked_asm!("")
@@ -38,7 +38,7 @@ LL | #[naked]
    = help: add `#![feature(naked_functions)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'naked_functions'
+error[E0658]: use of unstable library feature `naked_functions`
   --> $DIR/feature-gate-naked_functions.rs:3:5
    |
 LL | use std::arch::naked_asm;
diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs
index 13f8fd5fe22..71caf43806d 100644
--- a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs
+++ b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.rs
@@ -5,11 +5,11 @@ extern crate rustc_serialize; //~ERROR can't find crate for `rustc_serialize`
 
 #[derive(
     RustcEncodable,
-    //~^   ERROR   use of unstable library feature 'rustc_encodable_decodable'
+    //~^   ERROR   use of unstable library feature `rustc_encodable_decodable`
     //~^^  WARNING this was previously accepted by the compiler
     //~^^^ WARNING use of deprecated macro `RustcEncodable`
     RustcDecodable,
-    //~^   ERROR   use of unstable library feature 'rustc_encodable_decodable'
+    //~^   ERROR   use of unstable library feature `rustc_encodable_decodable`
     //~^^  WARNING this was previously accepted by the compiler
     //~^^^ WARNING use of deprecated macro `RustcDecodable`
 )]
diff --git a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr
index 02b74dacf4d..b949dbb9da2 100644
--- a/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr
+++ b/tests/ui/feature-gates/feature-gate-rustc_encodable_decodable.stderr
@@ -6,7 +6,7 @@ LL | extern crate rustc_serialize;
    |
    = help: maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
 
-error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code
+error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code
   --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5
    |
 LL |     RustcEncodable,
@@ -24,7 +24,7 @@ LL |     RustcEncodable,
    |
    = note: `#[warn(deprecated)]` on by default
 
-error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code
+error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code
   --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5
    |
 LL |     RustcDecodable,
@@ -43,7 +43,7 @@ error: aborting due to 3 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0463`.
 Future incompatibility report: Future breakage diagnostic:
-error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code
+error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code
   --> $DIR/feature-gate-rustc_encodable_decodable.rs:7:5
    |
 LL |     RustcEncodable,
@@ -54,7 +54,7 @@ LL |     RustcEncodable,
    = note: `#[deny(soft_unstable)]` on by default
 
 Future breakage diagnostic:
-error: use of unstable library feature 'rustc_encodable_decodable': derive macro for `rustc-serialize`; should not be used in new code
+error: use of unstable library feature `rustc_encodable_decodable`: derive macro for `rustc-serialize`; should not be used in new code
   --> $DIR/feature-gate-rustc_encodable_decodable.rs:11:5
    |
 LL |     RustcDecodable,
diff --git a/tests/ui/feature-gates/feature-gate-trace_macros.stderr b/tests/ui/feature-gates/feature-gate-trace_macros.stderr
index 68d3f75e995..4c6cfce7d3d 100644
--- a/tests/ui/feature-gates/feature-gate-trace_macros.stderr
+++ b/tests/ui/feature-gates/feature-gate-trace_macros.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/feature-gate-trace_macros.rs:2:5
    |
 LL |     trace_macros!(true);
diff --git a/tests/ui/feature-gates/feature-gate-type_ascription.rs b/tests/ui/feature-gates/feature-gate-type_ascription.rs
index 5c3f0e37df6..ef3923b6ff2 100644
--- a/tests/ui/feature-gates/feature-gate-type_ascription.rs
+++ b/tests/ui/feature-gates/feature-gate-type_ascription.rs
@@ -1,5 +1,5 @@
 // Type ascription is unstable
 
 fn main() {
-    let a = type_ascribe!(10, u8); //~ ERROR use of unstable library feature 'type_ascription': placeholder syntax for type ascription
+    let a = type_ascribe!(10, u8); //~ ERROR use of unstable library feature `type_ascription`: placeholder syntax for type ascription
 }
diff --git a/tests/ui/feature-gates/feature-gate-type_ascription.stderr b/tests/ui/feature-gates/feature-gate-type_ascription.stderr
index 88da58d07e1..f59e6435c8e 100644
--- a/tests/ui/feature-gates/feature-gate-type_ascription.stderr
+++ b/tests/ui/feature-gates/feature-gate-type_ascription.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'type_ascription': placeholder syntax for type ascription
+error[E0658]: use of unstable library feature `type_ascription`: placeholder syntax for type ascription
   --> $DIR/feature-gate-type_ascription.rs:4:13
    |
 LL |     let a = type_ascribe!(10, u8);
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs
index 42f7c5f0fba..bc5b48741b0 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.rs
@@ -1,9 +1,9 @@
 #![allow(dead_code)]
 
 fn foo<F: Fn()>(mut f: F) {
-    f.call(()); //~ ERROR use of unstable library feature 'fn_traits'
-    f.call_mut(()); //~ ERROR use of unstable library feature 'fn_traits'
-    f.call_once(()); //~ ERROR use of unstable library feature 'fn_traits'
+    f.call(()); //~ ERROR use of unstable library feature `fn_traits`
+    f.call_mut(()); //~ ERROR use of unstable library feature `fn_traits`
+    f.call_once(()); //~ ERROR use of unstable library feature `fn_traits`
 }
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr
index 0ef732d391b..6a5f0c8e6a6 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-method-calls.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'fn_traits'
+error[E0658]: use of unstable library feature `fn_traits`
   --> $DIR/feature-gate-unboxed-closures-method-calls.rs:4:7
    |
 LL |     f.call(());
@@ -8,7 +8,7 @@ LL |     f.call(());
    = help: add `#![feature(fn_traits)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'fn_traits'
+error[E0658]: use of unstable library feature `fn_traits`
   --> $DIR/feature-gate-unboxed-closures-method-calls.rs:5:7
    |
 LL |     f.call_mut(());
@@ -18,7 +18,7 @@ LL |     f.call_mut(());
    = help: add `#![feature(fn_traits)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'fn_traits'
+error[E0658]: use of unstable library feature `fn_traits`
   --> $DIR/feature-gate-unboxed-closures-method-calls.rs:6:7
    |
 LL |     f.call_once(());
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs
index 25c90492eb8..137e7d71e91 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.rs
@@ -1,9 +1,9 @@
 #![allow(dead_code)]
 
 fn foo<F: Fn()>(mut f: F) {
-    Fn::call(&f, ()); //~ ERROR use of unstable library feature 'fn_traits'
-    FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature 'fn_traits'
-    FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature 'fn_traits'
+    Fn::call(&f, ()); //~ ERROR use of unstable library feature `fn_traits`
+    FnMut::call_mut(&mut f, ()); //~ ERROR use of unstable library feature `fn_traits`
+    FnOnce::call_once(f, ()); //~ ERROR use of unstable library feature `fn_traits`
 }
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr
index f4d75fc6a86..90695fa4c46 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-ufcs-calls.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'fn_traits'
+error[E0658]: use of unstable library feature `fn_traits`
   --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:4:5
    |
 LL |     Fn::call(&f, ());
@@ -8,7 +8,7 @@ LL |     Fn::call(&f, ());
    = help: add `#![feature(fn_traits)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'fn_traits'
+error[E0658]: use of unstable library feature `fn_traits`
   --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:5:5
    |
 LL |     FnMut::call_mut(&mut f, ());
@@ -18,7 +18,7 @@ LL |     FnMut::call_mut(&mut f, ());
    = help: add `#![feature(fn_traits)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'fn_traits'
+error[E0658]: use of unstable library feature `fn_traits`
   --> $DIR/feature-gate-unboxed-closures-ufcs-calls.rs:6:5
    |
 LL |     FnOnce::call_once(f, ());
diff --git a/tests/ui/feature-gates/issue-49983-see-issue-0.stderr b/tests/ui/feature-gates/issue-49983-see-issue-0.stderr
index 8f090c9eef9..29a2845852e 100644
--- a/tests/ui/feature-gates/issue-49983-see-issue-0.stderr
+++ b/tests/ui/feature-gates/issue-49983-see-issue-0.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'ptr_internals': use `NonNull` instead and consider `PhantomData<T>` (if you also use `#[may_dangle]`), `Send`, and/or `Sync`
+error[E0658]: use of unstable library feature `ptr_internals`: use `NonNull` instead and consider `PhantomData<T>` (if you also use `#[may_dangle]`), `Send`, and/or `Sync`
   --> $DIR/issue-49983-see-issue-0.rs:4:30
    |
 LL | #[allow(unused_imports)] use core::ptr::Unique;
diff --git a/tests/ui/feature-gates/rustc-private.rs b/tests/ui/feature-gates/rustc-private.rs
index aa44f790c8a..2605f595b6c 100644
--- a/tests/ui/feature-gates/rustc-private.rs
+++ b/tests/ui/feature-gates/rustc-private.rs
@@ -1,5 +1,5 @@
 // gate-test-rustc_private
 
-extern crate cfg_if; //~ ERROR  use of unstable library feature 'rustc_private'
+extern crate cfg_if; //~ ERROR  use of unstable library feature `rustc_private`
 
 fn main() {}
diff --git a/tests/ui/feature-gates/rustc-private.stderr b/tests/ui/feature-gates/rustc-private.stderr
index 96cc98619fd..74594c712f2 100644
--- a/tests/ui/feature-gates/rustc-private.stderr
+++ b/tests/ui/feature-gates/rustc-private.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+error[E0658]: use of unstable library feature `rustc_private`: this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
   --> $DIR/rustc-private.rs:3:1
    |
 LL | extern crate cfg_if;
diff --git a/tests/ui/feature-gates/trace_macros-gate.stderr b/tests/ui/feature-gates/trace_macros-gate.stderr
index 1313a0e8ae2..6ca9d1573d9 100644
--- a/tests/ui/feature-gates/trace_macros-gate.stderr
+++ b/tests/ui/feature-gates/trace_macros-gate.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/trace_macros-gate.rs:4:5
    |
 LL |     trace_macros!();
@@ -14,7 +14,7 @@ error: trace_macros! accepts only `true` or `false`
 LL |     trace_macros!();
    |     ^^^^^^^^^^^^^^^
 
-error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/trace_macros-gate.rs:6:5
    |
 LL |     trace_macros!(true);
@@ -24,7 +24,7 @@ LL |     trace_macros!(true);
    = help: add `#![feature(trace_macros)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/trace_macros-gate.rs:7:5
    |
 LL |     trace_macros!(false);
@@ -34,7 +34,7 @@ LL |     trace_macros!(false);
    = help: add `#![feature(trace_macros)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'trace_macros': `trace_macros` is not stable enough for use and is subject to change
+error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change
   --> $DIR/trace_macros-gate.rs:10:26
    |
 LL |         ($x: ident) => { trace_macros!($x) }
diff --git a/tests/ui/imports/issue-37887.stderr b/tests/ui/imports/issue-37887.stderr
index 02c2c803262..cc191a17c29 100644
--- a/tests/ui/imports/issue-37887.stderr
+++ b/tests/ui/imports/issue-37887.stderr
@@ -9,7 +9,7 @@ help: consider importing the `test` crate
 LL + extern crate test;
    |
 
-error[E0658]: use of unstable library feature 'test'
+error[E0658]: use of unstable library feature `test`
   --> $DIR/issue-37887.rs:2:5
    |
 LL |     extern crate test;
diff --git a/tests/ui/imports/resolve-other-libc.rs b/tests/ui/imports/resolve-other-libc.rs
index d848f8260aa..e23083276ce 100644
--- a/tests/ui/imports/resolve-other-libc.rs
+++ b/tests/ui/imports/resolve-other-libc.rs
@@ -6,7 +6,7 @@
 // indicates that `libc` was wrongly resolved to `libc` shipped with the
 // compiler:
 //
-//   error[E0658]: use of unstable library feature 'rustc_private': \
+//   error[E0658]: use of unstable library feature `rustc_private`: \
 //           this crate is being loaded from the sysroot
 //
 extern crate libc; //~ ERROR: extern location for libc does not exist: test.rlib
diff --git a/tests/ui/inference/inference_unstable_forced.stderr b/tests/ui/inference/inference_unstable_forced.stderr
index 26eaddd2707..e3b5b292cd4 100644
--- a/tests/ui/inference/inference_unstable_forced.stderr
+++ b/tests/ui/inference/inference_unstable_forced.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'ipu_flatten'
+error[E0658]: use of unstable library feature `ipu_flatten`
   --> $DIR/inference_unstable_forced.rs:11:20
    |
 LL |     assert_eq!('x'.ipu_flatten(), 0);
diff --git a/tests/ui/internal/internal-unstable-noallow.rs b/tests/ui/internal/internal-unstable-noallow.rs
index 9d925c86122..57ddb93d880 100644
--- a/tests/ui/internal/internal-unstable-noallow.rs
+++ b/tests/ui/internal/internal-unstable-noallow.rs
@@ -4,10 +4,10 @@
 // the // ~ form.
 
 //@ aux-build:internal_unstable.rs
-//@ error-pattern:use of unstable library feature 'function'
-//@ error-pattern:use of unstable library feature 'struct_field'
-//@ error-pattern:use of unstable library feature 'method'
-//@ error-pattern:use of unstable library feature 'struct2_field'
+//@ error-pattern:use of unstable library feature `function`
+//@ error-pattern:use of unstable library feature `struct_field`
+//@ error-pattern:use of unstable library feature `method`
+//@ error-pattern:use of unstable library feature `struct2_field`
 
 #[macro_use]
 extern crate internal_unstable;
diff --git a/tests/ui/internal/internal-unstable-noallow.stderr b/tests/ui/internal/internal-unstable-noallow.stderr
index b39456b1cae..22f42abbd11 100644
--- a/tests/ui/internal/internal-unstable-noallow.stderr
+++ b/tests/ui/internal/internal-unstable-noallow.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'function'
+error[E0658]: use of unstable library feature `function`
   --> $DIR/internal-unstable-noallow.rs:16:5
    |
 LL |     call_unstable_noallow!();
@@ -8,7 +8,7 @@ LL |     call_unstable_noallow!();
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: this error originates in the macro `call_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0658]: use of unstable library feature 'struct_field'
+error[E0658]: use of unstable library feature `struct_field`
   --> $DIR/internal-unstable-noallow.rs:18:5
    |
 LL |     construct_unstable_noallow!(0);
@@ -18,7 +18,7 @@ LL |     construct_unstable_noallow!(0);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: this error originates in the macro `construct_unstable_noallow` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0658]: use of unstable library feature 'method'
+error[E0658]: use of unstable library feature `method`
   --> $DIR/internal-unstable-noallow.rs:20:35
    |
 LL |     |x: internal_unstable::Foo| { call_method_noallow!(x) };
@@ -28,7 +28,7 @@ LL |     |x: internal_unstable::Foo| { call_method_noallow!(x) };
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: this error originates in the macro `call_method_noallow` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0658]: use of unstable library feature 'struct2_field'
+error[E0658]: use of unstable library feature `struct2_field`
   --> $DIR/internal-unstable-noallow.rs:22:35
    |
 LL |     |x: internal_unstable::Bar| { access_field_noallow!(x) };
diff --git a/tests/ui/internal/internal-unstable-thread-local.stderr b/tests/ui/internal/internal-unstable-thread-local.stderr
index 58c7b3f67eb..c0510b39e50 100644
--- a/tests/ui/internal/internal-unstable-thread-local.stderr
+++ b/tests/ui/internal/internal-unstable-thread-local.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'function'
+error[E0658]: use of unstable library feature `function`
   --> $DIR/internal-unstable-thread-local.rs:9:32
    |
 LL | thread_local!(static BAR: () = internal_unstable::unstable());
diff --git a/tests/ui/internal/internal-unstable.stderr b/tests/ui/internal/internal-unstable.stderr
index 78b9109d1c2..ea74175f09b 100644
--- a/tests/ui/internal/internal-unstable.stderr
+++ b/tests/ui/internal/internal-unstable.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'function'
+error[E0658]: use of unstable library feature `function`
   --> $DIR/internal-unstable.rs:48:25
    |
 LL |     pass_through_allow!(internal_unstable::unstable());
@@ -7,7 +7,7 @@ LL |     pass_through_allow!(internal_unstable::unstable());
    = help: add `#![feature(function)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'function'
+error[E0658]: use of unstable library feature `function`
   --> $DIR/internal-unstable.rs:50:27
    |
 LL |     pass_through_noallow!(internal_unstable::unstable());
@@ -16,7 +16,7 @@ LL |     pass_through_noallow!(internal_unstable::unstable());
    = help: add `#![feature(function)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'function'
+error[E0658]: use of unstable library feature `function`
   --> $DIR/internal-unstable.rs:54:22
    |
 LL |     println!("{:?}", internal_unstable::unstable());
@@ -25,7 +25,7 @@ LL |     println!("{:?}", internal_unstable::unstable());
    = help: add `#![feature(function)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'function'
+error[E0658]: use of unstable library feature `function`
   --> $DIR/internal-unstable.rs:56:10
    |
 LL |     bar!(internal_unstable::unstable());
@@ -34,7 +34,7 @@ LL |     bar!(internal_unstable::unstable());
    = help: add `#![feature(function)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'function'
+error[E0658]: use of unstable library feature `function`
   --> $DIR/internal-unstable.rs:18:9
    |
 LL |         internal_unstable::unstable();
diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs
index 99f98c3f27a..76b6a8c8395 100644
--- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs
+++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.rs
@@ -1,5 +1,4 @@
 #![feature(core_intrinsics)]
-#![feature(const_intrinsic_raw_eq)]
 
 const RAW_EQ_PADDING: bool = unsafe {
     std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr
index bedfc8283ea..b8fdfe7bef3 100644
--- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr
+++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr
@@ -1,11 +1,11 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/intrinsic-raw_eq-const-bad.rs:5:5
+  --> $DIR/intrinsic-raw_eq-const-bad.rs:4:5
    |
 LL |     std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/intrinsic-raw_eq-const-bad.rs:11:5
+  --> $DIR/intrinsic-raw_eq-const-bad.rs:10:5
    |
 LL |     std::intrinsics::raw_eq(&(&0), &(&1))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into integer
@@ -14,7 +14,7 @@ LL |     std::intrinsics::raw_eq(&(&0), &(&1))
    = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/intrinsic-raw_eq-const-bad.rs:19:5
+  --> $DIR/intrinsic-raw_eq-const-bad.rs:18:5
    |
 LL |     std::intrinsics::raw_eq(aref, aref)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required
diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const.rs b/tests/ui/intrinsics/intrinsic-raw_eq-const.rs
index 47b4e20dfbb..b37def85bb7 100644
--- a/tests/ui/intrinsics/intrinsic-raw_eq-const.rs
+++ b/tests/ui/intrinsics/intrinsic-raw_eq-const.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 
 #![feature(core_intrinsics)]
-#![feature(const_intrinsic_raw_eq)]
 
 pub fn main() {
     use std::intrinsics::raw_eq;
diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr
index 21b7bf4e1cb..7af17147f28 100644
--- a/tests/ui/intrinsics/reify-intrinsic.stderr
+++ b/tests/ui/intrinsics/reify-intrinsic.stderr
@@ -7,9 +7,9 @@ LL |     let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr
    |            expected due to this
    |
    = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize`
-                 found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
+                 found fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}`
 
-error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
+error[E0606]: casting `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid
   --> $DIR/reify-intrinsic.rs:11:13
    |
 LL |     let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize;
diff --git a/tests/ui/intrinsics/unchecked_math_unstable.stderr b/tests/ui/intrinsics/unchecked_math_unstable.stderr
index c2a116b6200..b284567f8af 100644
--- a/tests/ui/intrinsics/unchecked_math_unstable.stderr
+++ b/tests/ui/intrinsics/unchecked_math_unstable.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
   --> $DIR/unchecked_math_unstable.rs:4:19
    |
 LL |         let add = std::intrinsics::unchecked_add(x, y);
@@ -7,7 +7,7 @@ LL |         let add = std::intrinsics::unchecked_add(x, y);
    = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
   --> $DIR/unchecked_math_unstable.rs:5:19
    |
 LL |         let sub = std::intrinsics::unchecked_sub(x, y);
@@ -16,7 +16,7 @@ LL |         let sub = std::intrinsics::unchecked_sub(x, y);
    = help: add `#![feature(core_intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
   --> $DIR/unchecked_math_unstable.rs:6:19
    |
 LL |         let mul = std::intrinsics::unchecked_mul(x, y);
diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr
index d0e8d4719d3..dae08119dbc 100644
--- a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr
+++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGS.stderr
@@ -1,2 +1,2 @@
-error: incorrect value `leaf` for unstable option `branch-protection` - a `,` separated combination of `bti`, `b-key`, `pac-ret`, or `leaf` was expected
+error: incorrect value `leaf` for unstable option `branch-protection` - a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf` was expected
 
diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr
new file mode 100644
index 00000000000..13f79e94674
--- /dev/null
+++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.BADFLAGSPC.stderr
@@ -0,0 +1,2 @@
+error: incorrect value `pc` for unstable option `branch-protection` - a `,` separated combination of `bti`, `pac-ret`, followed by a combination of `pc`, `b-key`, or `leaf` was expected
+
diff --git a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs
index c0a4bcac11b..b4025080034 100644
--- a/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs
+++ b/tests/ui/invalid-compile-flags/branch-protection-missing-pac-ret.rs
@@ -1,7 +1,10 @@
-//@ revisions: BADFLAGS BADTARGET
+//@ revisions: BADFLAGS BADFLAGSPC BADTARGET
 //@ [BADFLAGS] compile-flags: --target=aarch64-unknown-linux-gnu -Zbranch-protection=leaf
 //@ [BADFLAGS] check-fail
 //@ [BADFLAGS] needs-llvm-components: aarch64
+//@ [BADFLAGSPC] compile-flags: --target=aarch64-unknown-linux-gnu -Zbranch-protection=pc
+//@ [BADFLAGSPC] check-fail
+//@ [BADFLAGSPC] needs-llvm-components: aarch64
 //@ [BADTARGET] compile-flags: --target=x86_64-unknown-linux-gnu -Zbranch-protection=bti
 //@ [BADTARGET] check-fail
 //@ [BADTARGET] needs-llvm-components: x86
@@ -10,5 +13,5 @@
 #![feature(no_core, lang_items)]
 #![no_core]
 
-#[lang="sized"]
-trait Sized { }
+#[lang = "sized"]
+trait Sized {}
diff --git a/tests/ui/issues/issue-52489.rs b/tests/ui/issues/issue-52489.rs
index 95a3d43105c..c1e1cb41c76 100644
--- a/tests/ui/issues/issue-52489.rs
+++ b/tests/ui/issues/issue-52489.rs
@@ -3,6 +3,6 @@
 //@ compile-flags:--extern issue_52489
 
 use issue_52489;
-//~^ ERROR use of unstable library feature 'issue_52489_unstable'
+//~^ ERROR use of unstable library feature `issue_52489_unstable`
 
 fn main() {}
diff --git a/tests/ui/issues/issue-52489.stderr b/tests/ui/issues/issue-52489.stderr
index fa88725bceb..8e5b87b7f0f 100644
--- a/tests/ui/issues/issue-52489.stderr
+++ b/tests/ui/issues/issue-52489.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'issue_52489_unstable'
+error[E0658]: use of unstable library feature `issue_52489_unstable`
   --> $DIR/issue-52489.rs:5:5
    |
 LL | use issue_52489;
diff --git a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
index cceaddf7803..206a6801065 100644
--- a/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
+++ b/tests/ui/layout/rust-call-abi-not-a-tuple-ice-81974.stderr
@@ -71,6 +71,10 @@ LL |     cachedcoso.call_once(1);
    |
 note: required by a bound in `call_once`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: use a unary tuple instead
+   |
+LL |     cachedcoso.call_once((1,));
+   |                          + ++
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.rs b/tests/ui/layout/thaw-transmute-invalid-enum.rs
index 835dcc04996..a7c2e1a86de 100644
--- a/tests/ui/layout/thaw-transmute-invalid-enum.rs
+++ b/tests/ui/layout/thaw-transmute-invalid-enum.rs
@@ -2,13 +2,13 @@
 
 mod assert {
     use std::mem::{Assume, TransmuteFrom};
-    //~^ ERROR: use of unstable library feature 'transmutability'
-    //~| ERROR: use of unstable library feature 'transmutability'
+    //~^ ERROR: use of unstable library feature `transmutability`
+    //~| ERROR: use of unstable library feature `transmutability`
 
     pub fn is_transmutable<Src, Dst>()
     where
         Dst: TransmuteFrom<Src>,
-        //~^ ERROR: use of unstable library feature 'transmutability'
+        //~^ ERROR: use of unstable library feature `transmutability`
     {
     }
 }
diff --git a/tests/ui/layout/thaw-transmute-invalid-enum.stderr b/tests/ui/layout/thaw-transmute-invalid-enum.stderr
index e6a5399c66b..d12fc4694e0 100644
--- a/tests/ui/layout/thaw-transmute-invalid-enum.stderr
+++ b/tests/ui/layout/thaw-transmute-invalid-enum.stderr
@@ -20,7 +20,7 @@ LL | |     V = 0xFF,
 LL | | }
    | |_- not a struct or union
 
-error[E0658]: use of unstable library feature 'transmutability'
+error[E0658]: use of unstable library feature `transmutability`
   --> $DIR/thaw-transmute-invalid-enum.rs:4:20
    |
 LL |     use std::mem::{Assume, TransmuteFrom};
@@ -30,7 +30,7 @@ LL |     use std::mem::{Assume, TransmuteFrom};
    = help: add `#![feature(transmutability)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'transmutability'
+error[E0658]: use of unstable library feature `transmutability`
   --> $DIR/thaw-transmute-invalid-enum.rs:4:28
    |
 LL |     use std::mem::{Assume, TransmuteFrom};
@@ -40,7 +40,7 @@ LL |     use std::mem::{Assume, TransmuteFrom};
    = help: add `#![feature(transmutability)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'transmutability'
+error[E0658]: use of unstable library feature `transmutability`
   --> $DIR/thaw-transmute-invalid-enum.rs:10:14
    |
 LL |         Dst: TransmuteFrom<Src>,
diff --git a/tests/ui/lint/expansion-time.rs b/tests/ui/lint/expansion-time.rs
index 1e1f8f9e1b6..d0f26a87385 100644
--- a/tests/ui/lint/expansion-time.rs
+++ b/tests/ui/lint/expansion-time.rs
@@ -11,7 +11,7 @@ macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier
 
 #[warn(soft_unstable)]
 mod benches {
-    #[bench] //~ WARN use of unstable library feature 'test'
+    #[bench] //~ WARN use of unstable library feature `test`
              //~| WARN this was previously accepted
     fn foo() {}
 }
diff --git a/tests/ui/lint/expansion-time.stderr b/tests/ui/lint/expansion-time.stderr
index e490ae91a48..f65627c2c08 100644
--- a/tests/ui/lint/expansion-time.stderr
+++ b/tests/ui/lint/expansion-time.stderr
@@ -26,7 +26,7 @@ note: the lint level is defined here
 LL | #[warn(missing_fragment_specifier)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
+warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
   --> $DIR/expansion-time.rs:14:7
    |
 LL |     #[bench]
@@ -70,7 +70,7 @@ LL | #[warn(missing_fragment_specifier)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Future breakage diagnostic:
-warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
+warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
   --> $DIR/expansion-time.rs:14:7
    |
 LL |     #[bench]
diff --git a/tests/ui/lint/lint-output-format.stderr b/tests/ui/lint/lint-output-format.stderr
index c399b6cdbc2..23a36eb4c87 100644
--- a/tests/ui/lint/lint-output-format.stderr
+++ b/tests/ui/lint/lint-output-format.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-output-format.rs:6:1
    |
 LL | extern crate lint_output_format;
@@ -7,7 +7,7 @@ LL | extern crate lint_output_format;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-output-format.rs:7:26
    |
 LL | use lint_output_format::{foo, bar};
@@ -16,7 +16,7 @@ LL | use lint_output_format::{foo, bar};
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-output-format.rs:7:31
    |
 LL | use lint_output_format::{foo, bar};
@@ -25,7 +25,7 @@ LL | use lint_output_format::{foo, bar};
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-output-format.rs:12:14
    |
 LL |     let _y = bar();
diff --git a/tests/ui/lint/lint-stability-2.rs b/tests/ui/lint/lint-stability-2.rs
index 644b12670a6..50e84a6f4a7 100644
--- a/tests/ui/lint/lint-stability-2.rs
+++ b/tests/ui/lint/lint-stability-2.rs
@@ -66,15 +66,15 @@ mod cross_crate {
         <Foo>::trait_unstable(&foo); //~ ERROR use of unstable library feature
 
         foo.method_unstable_text();
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         Foo::method_unstable_text(&foo);
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         <Foo>::method_unstable_text(&foo);
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         foo.trait_unstable_text();
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         <Foo>::trait_unstable_text(&foo);
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
 
         stable();
         foo.method_stable();
@@ -139,9 +139,9 @@ mod cross_crate {
         foo.trait_unstable(); //~ ERROR use of unstable library feature
         <Foo>::trait_unstable(&foo); //~ ERROR use of unstable library feature
         foo.trait_unstable_text();
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         <Foo>::trait_unstable_text(&foo);
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         foo.trait_stable();
         Trait::trait_stable(&foo);
         <Foo>::trait_stable(&foo);
@@ -157,7 +157,7 @@ mod cross_crate {
         //~^ ERROR use of unstable library feature
         foo.trait_unstable(); //~ ERROR use of unstable library feature
         foo.trait_unstable_text();
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         foo.trait_stable();
     }
 
diff --git a/tests/ui/lint/lint-stability-2.stderr b/tests/ui/lint/lint-stability-2.stderr
index 20d49780a91..b3357bfe232 100644
--- a/tests/ui/lint/lint-stability-2.stderr
+++ b/tests/ui/lint/lint-stability-2.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:40:13
    |
 LL |         foo.method_deprecated_unstable();
@@ -7,7 +7,7 @@ LL |         foo.method_deprecated_unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:42:9
    |
 LL |         Foo::method_deprecated_unstable(&foo);
@@ -16,7 +16,7 @@ LL |         Foo::method_deprecated_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:44:9
    |
 LL |         <Foo>::method_deprecated_unstable(&foo);
@@ -25,7 +25,7 @@ LL |         <Foo>::method_deprecated_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:46:13
    |
 LL |         foo.trait_deprecated_unstable();
@@ -34,7 +34,7 @@ LL |         foo.trait_deprecated_unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:48:9
    |
 LL |         <Foo>::trait_deprecated_unstable(&foo);
@@ -43,7 +43,7 @@ LL |         <Foo>::trait_deprecated_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:51:13
    |
 LL |         foo.method_deprecated_unstable_text();
@@ -52,7 +52,7 @@ LL |         foo.method_deprecated_unstable_text();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:53:9
    |
 LL |         Foo::method_deprecated_unstable_text(&foo);
@@ -61,7 +61,7 @@ LL |         Foo::method_deprecated_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:55:9
    |
 LL |         <Foo>::method_deprecated_unstable_text(&foo);
@@ -70,7 +70,7 @@ LL |         <Foo>::method_deprecated_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:57:13
    |
 LL |         foo.trait_deprecated_unstable_text();
@@ -79,7 +79,7 @@ LL |         foo.trait_deprecated_unstable_text();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:59:9
    |
 LL |         <Foo>::trait_deprecated_unstable_text(&foo);
@@ -88,7 +88,7 @@ LL |         <Foo>::trait_deprecated_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:62:13
    |
 LL |         foo.method_unstable();
@@ -97,7 +97,7 @@ LL |         foo.method_unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:63:9
    |
 LL |         Foo::method_unstable(&foo);
@@ -106,7 +106,7 @@ LL |         Foo::method_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:64:9
    |
 LL |         <Foo>::method_unstable(&foo);
@@ -115,7 +115,7 @@ LL |         <Foo>::method_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:65:13
    |
 LL |         foo.trait_unstable();
@@ -124,7 +124,7 @@ LL |         foo.trait_unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:66:9
    |
 LL |         <Foo>::trait_unstable(&foo);
@@ -133,7 +133,7 @@ LL |         <Foo>::trait_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability-2.rs:68:13
    |
 LL |         foo.method_unstable_text();
@@ -142,7 +142,7 @@ LL |         foo.method_unstable_text();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability-2.rs:70:9
    |
 LL |         Foo::method_unstable_text(&foo);
@@ -151,7 +151,7 @@ LL |         Foo::method_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability-2.rs:72:9
    |
 LL |         <Foo>::method_unstable_text(&foo);
@@ -160,7 +160,7 @@ LL |         <Foo>::method_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability-2.rs:74:13
    |
 LL |         foo.trait_unstable_text();
@@ -169,7 +169,7 @@ LL |         foo.trait_unstable_text();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability-2.rs:76:9
    |
 LL |         <Foo>::trait_unstable_text(&foo);
@@ -178,7 +178,7 @@ LL |         <Foo>::trait_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:131:13
    |
 LL |         foo.trait_deprecated_unstable();
@@ -187,7 +187,7 @@ LL |         foo.trait_deprecated_unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:133:9
    |
 LL |         <Foo>::trait_deprecated_unstable(&foo);
@@ -196,7 +196,7 @@ LL |         <Foo>::trait_deprecated_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:135:13
    |
 LL |         foo.trait_deprecated_unstable_text();
@@ -205,7 +205,7 @@ LL |         foo.trait_deprecated_unstable_text();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:137:9
    |
 LL |         <Foo>::trait_deprecated_unstable_text(&foo);
@@ -214,7 +214,7 @@ LL |         <Foo>::trait_deprecated_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:139:13
    |
 LL |         foo.trait_unstable();
@@ -223,7 +223,7 @@ LL |         foo.trait_unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:140:9
    |
 LL |         <Foo>::trait_unstable(&foo);
@@ -232,7 +232,7 @@ LL |         <Foo>::trait_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability-2.rs:141:13
    |
 LL |         foo.trait_unstable_text();
@@ -241,7 +241,7 @@ LL |         foo.trait_unstable_text();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability-2.rs:143:9
    |
 LL |         <Foo>::trait_unstable_text(&foo);
@@ -250,7 +250,7 @@ LL |         <Foo>::trait_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:154:13
    |
 LL |         foo.trait_deprecated_unstable();
@@ -259,7 +259,7 @@ LL |         foo.trait_deprecated_unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:156:13
    |
 LL |         foo.trait_deprecated_unstable_text();
@@ -268,7 +268,7 @@ LL |         foo.trait_deprecated_unstable_text();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-2.rs:158:13
    |
 LL |         foo.trait_unstable();
@@ -277,7 +277,7 @@ LL |         foo.trait_unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability-2.rs:159:13
    |
 LL |         foo.trait_unstable_text();
diff --git a/tests/ui/lint/lint-stability-fields.stderr b/tests/ui/lint/lint-stability-fields.stderr
index 9dffe94c12e..9cd3753cc3b 100644
--- a/tests/ui/lint/lint-stability-fields.stderr
+++ b/tests/ui/lint/lint-stability-fields.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:56:17
    |
 LL |         let x = Unstable {
@@ -7,7 +7,7 @@ LL |         let x = Unstable {
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:66:13
    |
 LL |         let Unstable {
@@ -16,7 +16,7 @@ LL |         let Unstable {
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:72:13
    |
 LL |         let Unstable
@@ -25,7 +25,7 @@ LL |         let Unstable
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:77:17
    |
 LL |         let x = reexport::Unstable2(1, 2, 3);
@@ -34,7 +34,7 @@ LL |         let x = reexport::Unstable2(1, 2, 3);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:79:17
    |
 LL |         let x = Unstable2(1, 2, 3);
@@ -43,7 +43,7 @@ LL |         let x = Unstable2(1, 2, 3);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:85:13
    |
 LL |         let Unstable2
@@ -52,7 +52,7 @@ LL |         let Unstable2
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:90:13
    |
 LL |         let Unstable2
@@ -61,7 +61,7 @@ LL |         let Unstable2
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:95:17
    |
 LL |         let x = Deprecated {
@@ -70,7 +70,7 @@ LL |         let x = Deprecated {
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:105:13
    |
 LL |         let Deprecated {
@@ -79,7 +79,7 @@ LL |         let Deprecated {
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:111:13
    |
 LL |         let Deprecated
@@ -88,7 +88,7 @@ LL |         let Deprecated
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:115:17
    |
 LL |         let x = Deprecated2(1, 2, 3);
@@ -97,7 +97,7 @@ LL |         let x = Deprecated2(1, 2, 3);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:121:13
    |
 LL |         let Deprecated2
@@ -106,7 +106,7 @@ LL |         let Deprecated2
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:126:13
    |
 LL |         let Deprecated2
@@ -115,7 +115,7 @@ LL |         let Deprecated2
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:21:13
    |
 LL |             override1: 2,
@@ -124,7 +124,7 @@ LL |             override1: 2,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:22:13
    |
 LL |             override2: 3,
@@ -133,7 +133,7 @@ LL |             override2: 3,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:27:17
    |
 LL |         let _ = x.override1;
@@ -142,7 +142,7 @@ LL |         let _ = x.override1;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:28:17
    |
 LL |         let _ = x.override2;
@@ -151,7 +151,7 @@ LL |         let _ = x.override2;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:33:13
    |
 LL |             override1: _,
@@ -160,7 +160,7 @@ LL |             override1: _,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:34:13
    |
 LL |             override2: _,
@@ -169,7 +169,7 @@ LL |             override2: _,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:43:17
    |
 LL |         let _ = x.1;
@@ -178,7 +178,7 @@ LL |         let _ = x.1;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:44:17
    |
 LL |         let _ = x.2;
@@ -187,7 +187,7 @@ LL |         let _ = x.2;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:48:20
    |
 LL |                    _,
@@ -196,7 +196,7 @@ LL |                    _,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:49:20
    |
 LL |                    _,
@@ -205,7 +205,7 @@ LL |                    _,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:57:13
    |
 LL |             inherit: 1,
@@ -214,7 +214,7 @@ LL |             inherit: 1,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:59:13
    |
 LL |             override2: 3,
@@ -223,7 +223,7 @@ LL |             override2: 3,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:62:17
    |
 LL |         let _ = x.inherit;
@@ -232,7 +232,7 @@ LL |         let _ = x.inherit;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:64:17
    |
 LL |         let _ = x.override2;
@@ -241,7 +241,7 @@ LL |         let _ = x.override2;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:67:13
    |
 LL |             inherit: _,
@@ -250,7 +250,7 @@ LL |             inherit: _,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:69:13
    |
 LL |             override2: _
@@ -259,7 +259,7 @@ LL |             override2: _
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:81:17
    |
 LL |         let _ = x.0;
@@ -268,7 +268,7 @@ LL |         let _ = x.0;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:83:17
    |
 LL |         let _ = x.2;
@@ -277,7 +277,7 @@ LL |         let _ = x.2;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:86:14
    |
 LL |             (_,
@@ -286,7 +286,7 @@ LL |             (_,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:88:14
    |
 LL |              _)
@@ -295,7 +295,7 @@ LL |              _)
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:96:13
    |
 LL |             inherit: 1,
@@ -304,7 +304,7 @@ LL |             inherit: 1,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:98:13
    |
 LL |             override2: 3,
@@ -313,7 +313,7 @@ LL |             override2: 3,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:101:17
    |
 LL |         let _ = x.inherit;
@@ -322,7 +322,7 @@ LL |         let _ = x.inherit;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:103:17
    |
 LL |         let _ = x.override2;
@@ -331,7 +331,7 @@ LL |         let _ = x.override2;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:106:13
    |
 LL |             inherit: _,
@@ -340,7 +340,7 @@ LL |             inherit: _,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:108:13
    |
 LL |             override2: _
@@ -349,7 +349,7 @@ LL |             override2: _
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:117:17
    |
 LL |         let _ = x.0;
@@ -358,7 +358,7 @@ LL |         let _ = x.0;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:119:17
    |
 LL |         let _ = x.2;
@@ -367,7 +367,7 @@ LL |         let _ = x.2;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:122:14
    |
 LL |             (_,
@@ -376,7 +376,7 @@ LL |             (_,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability-fields.rs:124:14
    |
 LL |              _)
diff --git a/tests/ui/lint/lint-stability.rs b/tests/ui/lint/lint-stability.rs
index eaf9796df6a..f080b5e4bbe 100644
--- a/tests/ui/lint/lint-stability.rs
+++ b/tests/ui/lint/lint-stability.rs
@@ -61,11 +61,11 @@ mod cross_crate {
         <Foo as Trait>::trait_unstable(&foo); //~ ERROR use of unstable library feature
 
         unstable_text();
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         Trait::trait_unstable_text(&foo);
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         <Foo as Trait>::trait_unstable_text(&foo);
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
 
         stable();
         foo.method_stable();
@@ -152,9 +152,9 @@ mod cross_crate {
         Trait::trait_unstable(&foo); //~ ERROR use of unstable library feature
         <Foo as Trait>::trait_unstable(&foo); //~ ERROR use of unstable library feature
         Trait::trait_unstable_text(&foo);
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         <Foo as Trait>::trait_unstable_text(&foo);
-        //~^ ERROR use of unstable library feature 'unstable_test_feature': text
+        //~^ ERROR use of unstable library feature `unstable_test_feature`: text
         foo.trait_stable();
         Trait::trait_stable(&foo);
         <Foo>::trait_stable(&foo);
diff --git a/tests/ui/lint/lint-stability.stderr b/tests/ui/lint/lint-stability.stderr
index af5816d4564..a22fce70a4a 100644
--- a/tests/ui/lint/lint-stability.stderr
+++ b/tests/ui/lint/lint-stability.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:17:5
    |
 LL |     extern crate stability_cfg2;
@@ -7,7 +7,7 @@ LL |     extern crate stability_cfg2;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:45:9
    |
 LL |         deprecated_unstable();
@@ -16,7 +16,7 @@ LL |         deprecated_unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:47:9
    |
 LL |         Trait::trait_deprecated_unstable(&foo);
@@ -25,7 +25,7 @@ LL |         Trait::trait_deprecated_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:49:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
@@ -34,7 +34,7 @@ LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:52:9
    |
 LL |         deprecated_unstable_text();
@@ -43,7 +43,7 @@ LL |         deprecated_unstable_text();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:54:9
    |
 LL |         Trait::trait_deprecated_unstable_text(&foo);
@@ -52,7 +52,7 @@ LL |         Trait::trait_deprecated_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:56:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
@@ -61,7 +61,7 @@ LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:59:9
    |
 LL |         unstable();
@@ -70,7 +70,7 @@ LL |         unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:60:9
    |
 LL |         Trait::trait_unstable(&foo);
@@ -79,7 +79,7 @@ LL |         Trait::trait_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:61:9
    |
 LL |         <Foo as Trait>::trait_unstable(&foo);
@@ -88,7 +88,7 @@ LL |         <Foo as Trait>::trait_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability.rs:63:9
    |
 LL |         unstable_text();
@@ -97,7 +97,7 @@ LL |         unstable_text();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability.rs:65:9
    |
 LL |         Trait::trait_unstable_text(&foo);
@@ -106,7 +106,7 @@ LL |         Trait::trait_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability.rs:67:9
    |
 LL |         <Foo as Trait>::trait_unstable_text(&foo);
@@ -115,7 +115,7 @@ LL |         <Foo as Trait>::trait_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:99:17
    |
 LL |         let _ = DeprecatedUnstableStruct {
@@ -124,7 +124,7 @@ LL |         let _ = DeprecatedUnstableStruct {
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:103:17
    |
 LL |         let _ = UnstableStruct { i: 0 };
@@ -133,7 +133,7 @@ LL |         let _ = UnstableStruct { i: 0 };
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:107:17
    |
 LL |         let _ = DeprecatedUnstableUnitStruct;
@@ -142,7 +142,7 @@ LL |         let _ = DeprecatedUnstableUnitStruct;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:109:17
    |
 LL |         let _ = UnstableUnitStruct;
@@ -151,7 +151,7 @@ LL |         let _ = UnstableUnitStruct;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:113:17
    |
 LL |         let _ = Enum::DeprecatedUnstableVariant;
@@ -160,7 +160,7 @@ LL |         let _ = Enum::DeprecatedUnstableVariant;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:115:17
    |
 LL |         let _ = Enum::UnstableVariant;
@@ -169,7 +169,7 @@ LL |         let _ = Enum::UnstableVariant;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:119:17
    |
 LL |         let _ = DeprecatedUnstableTupleStruct (1);
@@ -178,7 +178,7 @@ LL |         let _ = DeprecatedUnstableTupleStruct (1);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:121:17
    |
 LL |         let _ = UnstableTupleStruct (1);
@@ -187,7 +187,7 @@ LL |         let _ = UnstableTupleStruct (1);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:130:25
    |
 LL |         macro_test_arg!(deprecated_unstable_text());
@@ -196,7 +196,7 @@ LL |         macro_test_arg!(deprecated_unstable_text());
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:144:9
    |
 LL |         Trait::trait_deprecated_unstable(&foo);
@@ -205,7 +205,7 @@ LL |         Trait::trait_deprecated_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:146:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
@@ -214,7 +214,7 @@ LL |         <Foo as Trait>::trait_deprecated_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:148:9
    |
 LL |         Trait::trait_deprecated_unstable_text(&foo);
@@ -223,7 +223,7 @@ LL |         Trait::trait_deprecated_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:150:9
    |
 LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
@@ -232,7 +232,7 @@ LL |         <Foo as Trait>::trait_deprecated_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:152:9
    |
 LL |         Trait::trait_unstable(&foo);
@@ -241,7 +241,7 @@ LL |         Trait::trait_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:153:9
    |
 LL |         <Foo as Trait>::trait_unstable(&foo);
@@ -250,7 +250,7 @@ LL |         <Foo as Trait>::trait_unstable(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability.rs:154:9
    |
 LL |         Trait::trait_unstable_text(&foo);
@@ -259,7 +259,7 @@ LL |         Trait::trait_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/lint-stability.rs:156:9
    |
 LL |         <Foo as Trait>::trait_unstable_text(&foo);
@@ -268,7 +268,7 @@ LL |         <Foo as Trait>::trait_unstable_text(&foo);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:172:10
    |
 LL |     impl UnstableTrait for S { }
@@ -277,7 +277,7 @@ LL |     impl UnstableTrait for S { }
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:174:24
    |
 LL |     trait LocalTrait : UnstableTrait { }
@@ -286,7 +286,7 @@ LL |     trait LocalTrait : UnstableTrait { }
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:179:9
    |
 LL |         fn trait_unstable(&self) {}
@@ -295,7 +295,7 @@ LL |         fn trait_unstable(&self) {}
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:184:5
    |
 LL |     extern crate inherited_stability;
@@ -304,7 +304,7 @@ LL |     extern crate inherited_stability;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:185:9
    |
 LL |     use self::inherited_stability::*;
@@ -313,7 +313,7 @@ LL |     use self::inherited_stability::*;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:188:9
    |
 LL |         unstable();
@@ -322,7 +322,7 @@ LL |         unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:191:9
    |
 LL |         stable_mod::unstable();
@@ -331,7 +331,7 @@ LL |         stable_mod::unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:194:9
    |
 LL |         unstable_mod::deprecated();
@@ -340,7 +340,7 @@ LL |         unstable_mod::deprecated();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:195:9
    |
 LL |         unstable_mod::unstable();
@@ -349,7 +349,7 @@ LL |         unstable_mod::unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:197:17
    |
 LL |         let _ = Unstable::UnstableVariant;
@@ -358,7 +358,7 @@ LL |         let _ = Unstable::UnstableVariant;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:198:17
    |
 LL |         let _ = Unstable::StableVariant;
@@ -367,7 +367,7 @@ LL |         let _ = Unstable::StableVariant;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:88:48
    |
 LL |         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
@@ -376,7 +376,7 @@ LL |         struct S1<T: TraitWithAssociatedTypes>(T::TypeUnstable);
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/lint-stability.rs:92:13
    |
 LL |             TypeUnstable = u8,
diff --git a/tests/ui/macros/macro-stability.rs b/tests/ui/macros/macro-stability.rs
index a909b14f47b..cd419d51354 100644
--- a/tests/ui/macros/macro-stability.rs
+++ b/tests/ui/macros/macro-stability.rs
@@ -19,10 +19,10 @@ macro local_unstable_modern() {}
 macro_rules! local_deprecated{ () => () }
 
 fn main() {
-    local_unstable!(); //~ ERROR use of unstable library feature 'local_unstable'
-    local_unstable_modern!(); //~ ERROR use of unstable library feature 'local_unstable'
-    unstable_macro!(); //~ ERROR use of unstable library feature 'unstable_macros'
-    // unstable_macro_modern!(); // ERROR use of unstable library feature 'unstable_macros'
+    local_unstable!(); //~ ERROR use of unstable library feature `local_unstable`
+    local_unstable_modern!(); //~ ERROR use of unstable library feature `local_unstable`
+    unstable_macro!(); //~ ERROR use of unstable library feature `unstable_macros`
+    // unstable_macro_modern!(); // ERROR use of unstable library feature `unstable_macros`
 
     deprecated_macro!();
     //~^ WARN use of deprecated macro `deprecated_macro`: deprecation note
diff --git a/tests/ui/macros/macro-stability.stderr b/tests/ui/macros/macro-stability.stderr
index 21b6cef5c9c..fd8f029b4c4 100644
--- a/tests/ui/macros/macro-stability.stderr
+++ b/tests/ui/macros/macro-stability.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'local_unstable'
+error[E0658]: use of unstable library feature `local_unstable`
   --> $DIR/macro-stability.rs:22:5
    |
 LL |     local_unstable!();
@@ -7,7 +7,7 @@ LL |     local_unstable!();
    = help: add `#![feature(local_unstable)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'local_unstable'
+error[E0658]: use of unstable library feature `local_unstable`
   --> $DIR/macro-stability.rs:23:5
    |
 LL |     local_unstable_modern!();
@@ -16,7 +16,7 @@ LL |     local_unstable_modern!();
    = help: add `#![feature(local_unstable)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_macros'
+error[E0658]: use of unstable library feature `unstable_macros`
   --> $DIR/macro-stability.rs:24:5
    |
 LL |     unstable_macro!();
diff --git a/tests/ui/offset-of/offset-of-unstable.stderr b/tests/ui/offset-of/offset-of-unstable.stderr
index 44ccad3ff39..d249e1b176d 100644
--- a/tests/ui/offset-of/offset-of-unstable.stderr
+++ b/tests/ui/offset-of/offset-of-unstable.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/offset-of-unstable.rs:12:9
    |
 LL |         Unstable,
@@ -7,7 +7,7 @@ LL |         Unstable,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/offset-of-unstable.rs:21:9
    |
 LL |         UnstableWithStableFieldType,
@@ -16,7 +16,7 @@ LL |         UnstableWithStableFieldType,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/offset-of-unstable.rs:26:9
    |
 LL |         UnstableWithStableFieldType,
@@ -25,7 +25,7 @@ LL |         UnstableWithStableFieldType,
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/offset-of-unstable.rs:10:5
    |
 LL | /     offset_of!(
@@ -39,7 +39,7 @@ LL | |     );
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/offset-of-unstable.rs:16:5
    |
 LL |     offset_of!(StableWithUnstableField, unstable);
@@ -49,7 +49,7 @@ LL |     offset_of!(StableWithUnstableField, unstable);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/offset-of-unstable.rs:18:5
    |
 LL |     offset_of!(StableWithUnstableFieldType, stable.unstable);
@@ -59,7 +59,7 @@ LL |     offset_of!(StableWithUnstableFieldType, stable.unstable);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/offset-of-unstable.rs:19:5
    |
 LL | /     offset_of!(
@@ -73,7 +73,7 @@ LL | |     );
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/offset-of-unstable.rs:24:5
    |
 LL | /     offset_of!(
diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap.rs b/tests/ui/on-unimplemented/suggest_tuple_wrap.rs
new file mode 100644
index 00000000000..010a47aef62
--- /dev/null
+++ b/tests/ui/on-unimplemented/suggest_tuple_wrap.rs
@@ -0,0 +1,19 @@
+pub trait Argument {}
+impl Argument for u8 {}
+impl Argument for i8 {}
+impl Argument for String {}
+impl Argument for &str {}
+
+pub trait TupleArgs {}
+impl<A: Argument> TupleArgs for (A,) {}
+impl<A: Argument, B: Argument> TupleArgs for (A, B) {}
+impl<A: Argument, B: Argument, C: Argument> TupleArgs for (A, B, C) {}
+
+fn convert_into_tuple(_x: impl TupleArgs) {}
+
+fn main() {
+    convert_into_tuple(42_u8);
+    //~^ ERROR E0277
+    //~| HELP the following other types implement trait `TupleArgs`
+    //~| HELP use a unary tuple instead
+}
diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap.stderr b/tests/ui/on-unimplemented/suggest_tuple_wrap.stderr
new file mode 100644
index 00000000000..93dd43aafd9
--- /dev/null
+++ b/tests/ui/on-unimplemented/suggest_tuple_wrap.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `u8: TupleArgs` is not satisfied
+  --> $DIR/suggest_tuple_wrap.rs:15:24
+   |
+LL |     convert_into_tuple(42_u8);
+   |     ------------------ ^^^^^ the trait `TupleArgs` is not implemented for `u8`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the following other types implement trait `TupleArgs`:
+             (A, B)
+             (A, B, C)
+             (A,)
+note: required by a bound in `convert_into_tuple`
+  --> $DIR/suggest_tuple_wrap.rs:12:32
+   |
+LL | fn convert_into_tuple(_x: impl TupleArgs) {}
+   |                                ^^^^^^^^^ required by this bound in `convert_into_tuple`
+help: use a unary tuple instead
+   |
+LL |     convert_into_tuple((42_u8,));
+   |                        +     ++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs
new file mode 100644
index 00000000000..e0036d30187
--- /dev/null
+++ b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.rs
@@ -0,0 +1,26 @@
+struct Tuple;
+
+impl From<(u8,)> for Tuple {
+    fn from(_: (u8,)) -> Self {
+        todo!()
+    }
+}
+impl From<(u8, u8)> for Tuple {
+    fn from(_: (u8, u8)) -> Self {
+        todo!()
+    }
+}
+impl From<(u8, u8, u8)> for Tuple {
+    fn from(_: (u8, u8, u8)) -> Self {
+        todo!()
+    }
+}
+
+fn convert_into_tuple(_x: impl Into<Tuple>) {}
+
+fn main() {
+    convert_into_tuple(42_u8);
+    //~^ ERROR E0277
+    //~| HELP use a unary tuple instead
+    //~| HELP the following other types implement trait `From<T>`
+}
diff --git a/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr
new file mode 100644
index 00000000000..6ee08d2cd1b
--- /dev/null
+++ b/tests/ui/on-unimplemented/suggest_tuple_wrap_root_obligation.stderr
@@ -0,0 +1,26 @@
+error[E0277]: the trait bound `Tuple: From<u8>` is not satisfied
+  --> $DIR/suggest_tuple_wrap_root_obligation.rs:22:24
+   |
+LL |     convert_into_tuple(42_u8);
+   |     ------------------ ^^^^^ the trait `From<u8>` is not implemented for `Tuple`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the following other types implement trait `From<T>`:
+             `Tuple` implements `From<(u8, u8)>`
+             `Tuple` implements `From<(u8, u8, u8)>`
+             `Tuple` implements `From<(u8,)>`
+   = note: required for `u8` to implement `Into<Tuple>`
+note: required by a bound in `convert_into_tuple`
+  --> $DIR/suggest_tuple_wrap_root_obligation.rs:19:32
+   |
+LL | fn convert_into_tuple(_x: impl Into<Tuple>) {}
+   |                                ^^^^^^^^^^^ required by this bound in `convert_into_tuple`
+help: use a unary tuple instead
+   |
+LL |     convert_into_tuple((42_u8,));
+   |                        +     ++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/overloaded/overloaded-calls-nontuple.stderr b/tests/ui/overloaded/overloaded-calls-nontuple.stderr
index 45a84fc4d7b..22598f3a390 100644
--- a/tests/ui/overloaded/overloaded-calls-nontuple.stderr
+++ b/tests/ui/overloaded/overloaded-calls-nontuple.stderr
@@ -38,6 +38,10 @@ LL |         self.call_mut(z)
    |
 note: required by a bound in `call_mut`
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
+help: use a unary tuple instead
+   |
+LL |         self.call_mut((z,))
+   |                       + ++
 
 error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
   --> $DIR/overloaded-calls-nontuple.rs:29:10
diff --git a/tests/ui/pattern/usefulness/doc-hidden-fields.stderr b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr
index f277bfbc884..158eac9a1bd 100644
--- a/tests/ui/pattern/usefulness/doc-hidden-fields.stderr
+++ b/tests/ui/pattern/usefulness/doc-hidden-fields.stderr
@@ -21,6 +21,10 @@ LL |     let HiddenStruct { one, two, .. } = HiddenStruct::default();
    |                           ~~~~~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     let HiddenStruct { one, two: _, .. } = HiddenStruct::default();
+   |                           ~~~~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     let HiddenStruct { one, .. } = HiddenStruct::default();
    |                           ~~~~~~
 
@@ -36,6 +40,10 @@ LL |     let HiddenStruct { one, hide, two } = HiddenStruct::default();
    |                                 ~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     let HiddenStruct { one, hide, two: _ } = HiddenStruct::default();
+   |                                 ~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     let HiddenStruct { one, hide, .. } = HiddenStruct::default();
    |                                 ~~~~~~
 
@@ -51,6 +59,10 @@ LL |     let InCrate { a, b, im_hidden } = InCrate { a: 0, b: false, im_hidden:
    |                       ~~~~~~~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     let InCrate { a, b, im_hidden: _ } = InCrate { a: 0, b: false, im_hidden: 0 };
+   |                       ~~~~~~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     let InCrate { a, b, .. } = InCrate { a: 0, b: false, im_hidden: 0 };
    |                       ~~~~~~
 
diff --git a/tests/ui/pattern/usefulness/stable-gated-fields.stderr b/tests/ui/pattern/usefulness/stable-gated-fields.stderr
index cf98c51a2b4..d6e9bac7c13 100644
--- a/tests/ui/pattern/usefulness/stable-gated-fields.stderr
+++ b/tests/ui/pattern/usefulness/stable-gated-fields.stderr
@@ -10,6 +10,10 @@ LL |     let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
    |                                ~~~~~~~~~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     let UnstableStruct { stable, stable2: _, .. } = UnstableStruct::default();
+   |                                ~~~~~~~~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     let UnstableStruct { stable, .. } = UnstableStruct::default();
    |                                ~~~~~~
 
diff --git a/tests/ui/pattern/usefulness/unstable-gated-fields.stderr b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr
index e4f5fa06b3f..bb10e439ee2 100644
--- a/tests/ui/pattern/usefulness/unstable-gated-fields.stderr
+++ b/tests/ui/pattern/usefulness/unstable-gated-fields.stderr
@@ -10,6 +10,10 @@ LL |     let UnstableStruct { stable, stable2, unstable } = UnstableStruct::defa
    |                                         ~~~~~~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     let UnstableStruct { stable, stable2, unstable: _ } = UnstableStruct::default();
+   |                                         ~~~~~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
    |                                         ~~~~~~
 
@@ -25,6 +29,10 @@ LL |     let UnstableStruct { stable, unstable, stable2 } = UnstableStruct::defa
    |                                          ~~~~~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     let UnstableStruct { stable, unstable, stable2: _ } = UnstableStruct::default();
+   |                                          ~~~~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     let UnstableStruct { stable, unstable, .. } = UnstableStruct::default();
    |                                          ~~~~~~
 
diff --git a/tests/ui/pin-macro/cant_access_internals.rs b/tests/ui/pin-macro/cant_access_internals.rs
index 17fe7fa0738..36a47d0fdf9 100644
--- a/tests/ui/pin-macro/cant_access_internals.rs
+++ b/tests/ui/pin-macro/cant_access_internals.rs
@@ -8,5 +8,5 @@ use core::{
 
 fn main() {
     let mut phantom_pinned = pin!(PhantomPinned);
-    mem::take(phantom_pinned.__pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals'
+    mem::take(phantom_pinned.__pointer); //~ ERROR use of unstable library feature `unsafe_pin_internals`
 }
diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr
index 444314a9d8b..8ad897bbbb9 100644
--- a/tests/ui/pin-macro/cant_access_internals.stderr
+++ b/tests/ui/pin-macro/cant_access_internals.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unsafe_pin_internals'
+error[E0658]: use of unstable library feature `unsafe_pin_internals`
   --> $DIR/cant_access_internals.rs:11:15
    |
 LL |     mem::take(phantom_pinned.__pointer);
diff --git a/tests/ui/proc-macro/expand-to-unstable.stderr b/tests/ui/proc-macro/expand-to-unstable.stderr
index 9eb701d9702..563c7ae8f95 100644
--- a/tests/ui/proc-macro/expand-to-unstable.stderr
+++ b/tests/ui/proc-macro/expand-to-unstable.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+error[E0658]: use of unstable library feature `core_intrinsics`: intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
   --> $DIR/expand-to-unstable.rs:8:10
    |
 LL | #[derive(Unstable)]
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 c9e93174e20..5c6eef46103 100644
--- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
+++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
@@ -8,7 +8,7 @@ struct S<T> {
     s: Box<S<fn(u: T)>>,
 }
 
-fn f(x: S<u32>) {} //~ ERROR overflow while adding drop-check rules for S<u32>
+fn f(x: S<u32>) {} //~ ERROR overflow while adding drop-check rules for `S<u32>`
 
 fn main() {
     // Force instantiation.
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 a5bbc5499a8..409f63b91b6 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,10 @@
-error[E0320]: overflow while adding drop-check rules for S<u32>
+error[E0320]: overflow while adding drop-check rules for `S<u32>`
   --> $DIR/issue-38591-non-regular-dropck-recursion.rs:11: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(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)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs
index 2509416ad87..2b6bbf12650 100644
--- a/tests/ui/repr/16-bit-repr-c-enum.rs
+++ b/tests/ui/repr/16-bit-repr-c-enum.rs
@@ -21,11 +21,12 @@ enum Foo {
     Bar,
 }
 
-extern "rust-intrinsic" {
-    #[stable(feature = "intrinsics_for_test", since = "3.3.3")]
-    #[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")]
-    #[rustc_safe_intrinsic]
-    fn size_of<T>() -> usize;
+#[stable(feature = "intrinsics_for_test", since = "3.3.3")]
+#[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+const fn size_of<T>() -> usize {
+    loop {}
 }
 
 #[lang="sized"]
diff --git a/tests/ui/resolve/resolve-variant-assoc-item.stderr b/tests/ui/resolve/resolve-variant-assoc-item.stderr
index ed157197d17..9a5a605ac05 100644
--- a/tests/ui/resolve/resolve-variant-assoc-item.stderr
+++ b/tests/ui/resolve/resolve-variant-assoc-item.stderr
@@ -6,7 +6,7 @@ LL |     E::V::associated_item;
    |
 help: there is an enum variant `E::V`; try using the variant's enum
    |
-LL |     E;
+LL |     E::associated_item;
    |     ~
 
 error[E0433]: failed to resolve: `V` is a variant, not a module
@@ -17,10 +17,6 @@ LL |     V::associated_item;
    |
 help: there is an enum variant `E::V`; try using the variant's enum
    |
-LL |     E;
-   |     ~
-help: an enum with a similar name exists
-   |
 LL |     E::associated_item;
    |     ~
 
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
index af6d05c1f96..08584349626 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.no_gate.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'structural_match'
+error[E0658]: use of unstable library feature `structural_match`
   --> $DIR/feature-gate.rs:29:6
    |
 LL | impl std::marker::StructuralPartialEq for Foo { }
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
index 839e9085440..711b07fee3b 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/feature-gate.rs
@@ -27,7 +27,7 @@ fn main() { //[with_gate]~ ERROR fatal error triggered by #[rustc_error]
 }
 
 impl std::marker::StructuralPartialEq for Foo { }
-//[no_gate]~^ ERROR use of unstable library feature 'structural_match'
+//[no_gate]~^ ERROR use of unstable library feature `structural_match`
 
 impl PartialEq<Foo> for Foo {
     fn eq(&self, other: &Self) -> bool {
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
index 4dc5932feab..5d9a8cfcac1 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs
@@ -38,3 +38,9 @@ pub enum NonExhaustiveCLikeEnum {
     Four = 4,
     Five = 5,
 }
+
+#[repr(C)]
+pub struct NormalStructWithNonExhaustiveCLikeEnum {
+    one: u8,
+    two: NonExhaustiveCLikeEnum,
+}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
index c7f470fb787..858e3374eac 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs
@@ -8,7 +8,7 @@ extern crate types;
 
 use types::{
     NonExhaustiveCLikeEnum, NonExhaustiveEnum, NonExhaustiveVariants,
-    NormalStruct, TupleStruct, UnitStruct,
+    NormalStruct, TupleStruct, UnitStruct, NormalStructWithNonExhaustiveCLikeEnum
 };
 
 extern "C" {
@@ -27,6 +27,9 @@ extern "C" {
 // These should pass without remark, as they're C-compatible, despite being "non-exhaustive".
 extern "C" {
     pub fn non_exhaustive_c_compat_enum(_: NonExhaustiveCLikeEnum);
+    pub fn non_exhaustive_c_compat_enum_ret() -> *mut NonExhaustiveCLikeEnum;
+    pub fn struct_w_non_exhaustive_c_like_enum(_: NormalStructWithNonExhaustiveCLikeEnum);
+    pub fn struct_w_non_exhaustive_c_like_enum_ret() -> *mut NormalStructWithNonExhaustiveCLikeEnum;
 }
 
 fn main() {}
diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.rs b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs
index f8bbe90cfc5..86a9d2066eb 100644
--- a/tests/ui/stability-attribute/accidental-stable-in-unstable.rs
+++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs
@@ -3,7 +3,7 @@ extern crate core;
 
 // Known accidental stabilizations with no known users, slated for un-stabilization
 // fully stable @ core::char::UNICODE_VERSION
-use core::unicode::UNICODE_VERSION; //~ ERROR use of unstable library feature 'unicode_internals'
+use core::unicode::UNICODE_VERSION; //~ ERROR use of unstable library feature `unicode_internals`
 
 // Known accidental stabilizations with known users
 // fully stable @ core::mem::transmute
diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr
index 4abf8243d2f..9943e6d7ac6 100644
--- a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr
+++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unicode_internals'
+error[E0658]: use of unstable library feature `unicode_internals`
   --> $DIR/accidental-stable-in-unstable.rs:6:5
    |
 LL | use core::unicode::UNICODE_VERSION;
diff --git a/tests/ui/stability-attribute/allow-unstable-reexport.rs b/tests/ui/stability-attribute/allow-unstable-reexport.rs
index d2f1593c31a..b6ed2110918 100644
--- a/tests/ui/stability-attribute/allow-unstable-reexport.rs
+++ b/tests/ui/stability-attribute/allow-unstable-reexport.rs
@@ -20,11 +20,11 @@ pub use lint_stability_reexport::unstable_text;
 // Ensure items which aren't marked as unstable can't re-export unstable items
 #[stable(feature = "lint_stability", since = "1.0.0")]
 pub use lint_stability::unstable as unstable2;
-//~^ ERROR use of unstable library feature 'unstable_test_feature'
+//~^ ERROR use of unstable library feature `unstable_test_feature`
 
 fn main() {
     // Since we didn't enable the feature in this crate, we still can't
     // use these items, even though they're in scope from the `use`s which are now allowed.
-    unstable(); //~ ERROR use of unstable library feature 'unstable_test_feature'
-    unstable_text(); //~ ERROR use of unstable library feature 'unstable_test_feature'
+    unstable(); //~ ERROR use of unstable library feature `unstable_test_feature`
+    unstable_text(); //~ ERROR use of unstable library feature `unstable_test_feature`
 }
diff --git a/tests/ui/stability-attribute/allow-unstable-reexport.stderr b/tests/ui/stability-attribute/allow-unstable-reexport.stderr
index af75b6afb04..f869eeb790e 100644
--- a/tests/ui/stability-attribute/allow-unstable-reexport.stderr
+++ b/tests/ui/stability-attribute/allow-unstable-reexport.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/allow-unstable-reexport.rs:22:9
    |
 LL | pub use lint_stability::unstable as unstable2;
@@ -7,7 +7,7 @@ LL | pub use lint_stability::unstable as unstable2;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/allow-unstable-reexport.rs:28:5
    |
 LL |     unstable();
@@ -16,7 +16,7 @@ LL |     unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': text
+error[E0658]: use of unstable library feature `unstable_test_feature`: text
   --> $DIR/allow-unstable-reexport.rs:29:5
    |
 LL |     unstable_text();
diff --git a/tests/ui/stability-attribute/allowed-through-unstable.rs b/tests/ui/stability-attribute/allowed-through-unstable.rs
index 6bce5c87ddb..29911a70be9 100644
--- a/tests/ui/stability-attribute/allowed-through-unstable.rs
+++ b/tests/ui/stability-attribute/allowed-through-unstable.rs
@@ -6,4 +6,4 @@
 extern crate allowed_through_unstable_core;
 
 use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable;
-use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature 'unstable_test_feature'
+use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature `unstable_test_feature`
diff --git a/tests/ui/stability-attribute/allowed-through-unstable.stderr b/tests/ui/stability-attribute/allowed-through-unstable.stderr
index 5c8e6358b7c..00eea9f730d 100644
--- a/tests/ui/stability-attribute/allowed-through-unstable.stderr
+++ b/tests/ui/stability-attribute/allowed-through-unstable.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/allowed-through-unstable.rs:9:5
    |
 LL | use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable;
diff --git a/tests/ui/stability-attribute/default-body-stability-err.stderr b/tests/ui/stability-attribute/default-body-stability-err.stderr
index 9d8ad81f102..6173de5020b 100644
--- a/tests/ui/stability-attribute/default-body-stability-err.stderr
+++ b/tests/ui/stability-attribute/default-body-stability-err.stderr
@@ -5,7 +5,7 @@ LL | impl JustTrait for Type {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: default implementation of `CONSTANT` is unstable
-   = note: use of unstable library feature 'constant_default_body'
+   = note: use of unstable library feature `constant_default_body`
    = help: add `#![feature(constant_default_body)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -16,7 +16,7 @@ LL | impl JustTrait for Type {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: default implementation of `fun` is unstable
-   = note: use of unstable library feature 'fun_default_body'
+   = note: use of unstable library feature `fun_default_body`
    = help: add `#![feature(fun_default_body)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -27,7 +27,7 @@ LL | impl JustTrait for Type {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: default implementation of `fun2` is unstable
-   = note: use of unstable library feature 'fun_default_body': reason
+   = note: use of unstable library feature `fun_default_body`: reason
    = help: add `#![feature(fun_default_body)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -43,7 +43,7 @@ LL | | }
    | |_^
    |
    = note: default implementation of `eq` is unstable
-   = note: use of unstable library feature 'eq_default_body'
+   = note: use of unstable library feature `eq_default_body`
    = help: add `#![feature(eq_default_body)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
diff --git a/tests/ui/stability-attribute/generics-default-stability-trait.rs b/tests/ui/stability-attribute/generics-default-stability-trait.rs
index ba8ee143d4a..a2302959638 100644
--- a/tests/ui/stability-attribute/generics-default-stability-trait.rs
+++ b/tests/ui/stability-attribute/generics-default-stability-trait.rs
@@ -13,15 +13,15 @@ impl Trait1 for S {
 
 struct S;
 
-impl Trait1<usize> for S { //~ ERROR use of unstable library feature 'unstable_default'
+impl Trait1<usize> for S { //~ ERROR use of unstable library feature `unstable_default`
     fn foo() -> usize { 0 }
 }
 
-impl Trait1<isize> for S { //~ ERROR use of unstable library feature 'unstable_default'
+impl Trait1<isize> for S { //~ ERROR use of unstable library feature `unstable_default`
     fn foo() -> isize { 0 }
 }
 
-impl Trait2<usize> for S { //~ ERROR use of unstable library feature 'unstable_default'
+impl Trait2<usize> for S { //~ ERROR use of unstable library feature `unstable_default`
     fn foo() -> usize { 0 }
 }
 
diff --git a/tests/ui/stability-attribute/generics-default-stability-trait.stderr b/tests/ui/stability-attribute/generics-default-stability-trait.stderr
index 699e7c83c70..21b21fdb945 100644
--- a/tests/ui/stability-attribute/generics-default-stability-trait.stderr
+++ b/tests/ui/stability-attribute/generics-default-stability-trait.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability-trait.rs:16:13
    |
 LL | impl Trait1<usize> for S {
@@ -7,7 +7,7 @@ LL | impl Trait1<usize> for S {
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability-trait.rs:20:13
    |
 LL | impl Trait1<isize> for S {
@@ -16,7 +16,7 @@ LL | impl Trait1<isize> for S {
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability-trait.rs:24:13
    |
 LL | impl Trait2<usize> for S {
diff --git a/tests/ui/stability-attribute/generics-default-stability-where.rs b/tests/ui/stability-attribute/generics-default-stability-where.rs
index f8a2fb4873a..a7bc1756d78 100644
--- a/tests/ui/stability-attribute/generics-default-stability-where.rs
+++ b/tests/ui/stability-attribute/generics-default-stability-where.rs
@@ -4,7 +4,7 @@ extern crate unstable_generic_param;
 
 use unstable_generic_param::*;
 
-impl<T> Trait3<usize> for T where T: Trait2<usize> { //~ ERROR use of unstable library feature 'unstable_default'
+impl<T> Trait3<usize> for T where T: Trait2<usize> { //~ ERROR use of unstable library feature `unstable_default`
 //~^ ERROR `T` must be used as the type parameter for some local type
     fn foo() -> usize { T::foo() }
 }
diff --git a/tests/ui/stability-attribute/generics-default-stability-where.stderr b/tests/ui/stability-attribute/generics-default-stability-where.stderr
index 8e4089970f5..9437f5d65fa 100644
--- a/tests/ui/stability-attribute/generics-default-stability-where.stderr
+++ b/tests/ui/stability-attribute/generics-default-stability-where.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability-where.rs:7:45
    |
 LL | impl<T> Trait3<usize> for T where T: Trait2<usize> {
diff --git a/tests/ui/stability-attribute/generics-default-stability.rs b/tests/ui/stability-attribute/generics-default-stability.rs
index abd45b651ee..e1b3971f70c 100644
--- a/tests/ui/stability-attribute/generics-default-stability.rs
+++ b/tests/ui/stability-attribute/generics-default-stability.rs
@@ -20,12 +20,12 @@ impl Trait3<usize> for S {
 fn main() {
     let _ = S;
 
-    let _: Struct1<isize> = Struct1 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Struct1<isize> = Struct1 { field: 1 }; //~ ERROR use of unstable library feature `unstable_default`
 
     let _ = STRUCT1; // ok
     let _: Struct1 = STRUCT1; // ok
-    let _: Struct1<usize> = STRUCT1; //~ ERROR use of unstable library feature 'unstable_default'
-    let _: Struct1<isize> = Struct1 { field: 0 }; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Struct1<usize> = STRUCT1; //~ ERROR use of unstable library feature `unstable_default`
+    let _: Struct1<isize> = Struct1 { field: 0 }; //~ ERROR use of unstable library feature `unstable_default`
 
     // Instability is not enforced for generic type parameters used in public fields.
     // Note how the unstable type default `usize` leaks,
@@ -54,10 +54,10 @@ fn main() {
 
     let _ = STRUCT3;
     let _: Struct3 = STRUCT3; // ok
-    let _: Struct3<isize, usize> = STRUCT3; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Struct3<isize, usize> = STRUCT3; //~ ERROR use of unstable library feature `unstable_default`
     let _: Struct3<isize> = STRUCT3; // ok
-    let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature 'unstable_default'
-    let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature `unstable_default`
+    let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 }; //~ ERROR use of unstable library feature `unstable_default`
     let _ = STRUCT3.field1; // ok
     let _: isize = STRUCT3.field1; // ok
     let _ = STRUCT3.field1 + 1; // ok
@@ -81,15 +81,15 @@ fn main() {
     //~^^^ use of deprecated field `unstable_generic_param::Struct4::field`: test [deprecated]
 
     let _ = STRUCT5;
-    let _: Struct5<isize> = Struct5 { field: 1 }; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Struct5<isize> = Struct5 { field: 1 }; //~ ERROR use of unstable library feature `unstable_default`
     //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated]
     //~^^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated]
     //~^^^ use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated]
     let _ = STRUCT5;
     let _: Struct5 = STRUCT5; //~ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated]
-    let _: Struct5<usize> = STRUCT5; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Struct5<usize> = STRUCT5; //~ ERROR use of unstable library feature `unstable_default`
     //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated]
-    let _: Struct5<isize> = Struct5 { field: 0 }; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Struct5<isize> = Struct5 { field: 0 }; //~ ERROR use of unstable library feature `unstable_default`
     //~^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated]
     //~^^ use of deprecated struct `unstable_generic_param::Struct5`: test [deprecated]
     //~^^^ use of deprecated field `unstable_generic_param::Struct5::field`: test [deprecated]
@@ -97,12 +97,12 @@ fn main() {
     let _: Struct6<isize> = Struct6 { field: 1 }; // ok
     let _: Struct6<isize> = Struct6 { field: 0 }; // ok
 
-    let _: Alias1<isize> = Alias1::Some(1); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Alias1<isize> = Alias1::Some(1); //~ ERROR use of unstable library feature `unstable_default`
 
     let _ = ALIAS1; // ok
     let _: Alias1 = ALIAS1; // ok
-    let _: Alias1<usize> = ALIAS1; //~ ERROR use of unstable library feature 'unstable_default'
-    let _: Alias1<isize> = Alias1::Some(0); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Alias1<usize> = ALIAS1; //~ ERROR use of unstable library feature `unstable_default`
+    let _: Alias1<isize> = Alias1::Some(0); //~ ERROR use of unstable library feature `unstable_default`
 
     // Instability is not enforced for generic type parameters used in public fields.
     // Note how the unstable type default `usize` leaks,
@@ -130,10 +130,10 @@ fn main() {
 
     let _ = ALIAS3;
     let _: Alias3 = ALIAS3; // ok
-    let _: Alias3<isize, usize> = ALIAS3; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Alias3<isize, usize> = ALIAS3; //~ ERROR use of unstable library feature `unstable_default`
     let _: Alias3<isize> = ALIAS3; // ok
-    let _: Alias3<isize, isize> = Alias3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default'
-    let _: Alias3<usize, usize> = Alias3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Alias3<isize, isize> = Alias3::Ok(0); //~ ERROR use of unstable library feature `unstable_default`
+    let _: Alias3<usize, usize> = Alias3::Ok(0); //~ ERROR use of unstable library feature `unstable_default`
     let _ = ALIAS3.unwrap(); // ok
     let _: isize = ALIAS3.unwrap(); // ok
     let _ = ALIAS3.unwrap() + 1; // ok
@@ -155,26 +155,26 @@ fn main() {
     //~^^ use of deprecated type alias `unstable_generic_param::Alias4`: test [deprecated]
 
     let _ = ALIAS5;
-    let _: Alias5<isize> = Alias5::Some(1); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Alias5<isize> = Alias5::Some(1); //~ ERROR use of unstable library feature `unstable_default`
     //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated]
     //~^^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated]
     let _ = ALIAS5;
     let _: Alias5 = ALIAS5; //~ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated]
-    let _: Alias5<usize> = ALIAS5; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Alias5<usize> = ALIAS5; //~ ERROR use of unstable library feature `unstable_default`
     //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated]
-    let _: Alias5<isize> = Alias5::Some(0); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Alias5<isize> = Alias5::Some(0); //~ ERROR use of unstable library feature `unstable_default`
     //~^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated]
     //~^^ use of deprecated type alias `unstable_generic_param::Alias5`: test [deprecated]
 
     let _: Alias6<isize> = Alias6::Some(1); // ok
     let _: Alias6<isize> = Alias6::Some(0); // ok
 
-    let _: Enum1<isize> = Enum1::Some(1); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Enum1<isize> = Enum1::Some(1); //~ ERROR use of unstable library feature `unstable_default`
 
     let _ = ENUM1; // ok
     let _: Enum1 = ENUM1; // ok
-    let _: Enum1<usize> = ENUM1; //~ ERROR use of unstable library feature 'unstable_default'
-    let _: Enum1<isize> = Enum1::Some(0); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Enum1<usize> = ENUM1; //~ ERROR use of unstable library feature `unstable_default`
+    let _: Enum1<isize> = Enum1::Some(0); //~ ERROR use of unstable library feature `unstable_default`
 
     // Instability is not enforced for generic type parameters used in public fields.
     // Note how the unstable type default `usize` leaks,
@@ -202,10 +202,10 @@ fn main() {
 
     let _ = ENUM3;
     let _: Enum3 = ENUM3; // ok
-    let _: Enum3<isize, usize> = ENUM3; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Enum3<isize, usize> = ENUM3; //~ ERROR use of unstable library feature `unstable_default`
     let _: Enum3<isize> = ENUM3; // ok
-    let _: Enum3<isize, isize> = Enum3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default'
-    let _: Enum3<usize, usize> = Enum3::Ok(0); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Enum3<isize, isize> = Enum3::Ok(0); //~ ERROR use of unstable library feature `unstable_default`
+    let _: Enum3<usize, usize> = Enum3::Ok(0); //~ ERROR use of unstable library feature `unstable_default`
     if let Enum3::Ok(x) = ENUM3 {let _ = x;} // ok
     if let Enum3::Ok(x) = ENUM3 {let _: isize = x;} // ok
     if let Enum3::Ok(x) = ENUM3 {let _ = x + 1;} // ok
@@ -227,21 +227,21 @@ fn main() {
     //~^^ use of deprecated enum `unstable_generic_param::Enum4`: test [deprecated]
 
     let _ = ENUM5;
-    let _: Enum5<isize> = Enum5::Some(1); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Enum5<isize> = Enum5::Some(1); //~ ERROR use of unstable library feature `unstable_default`
     //~^ use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated]
     //~^^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated]
     let _ = ENUM5;
     let _: Enum5 = ENUM5; //~ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated]
-    let _: Enum5<usize> = ENUM5; //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Enum5<usize> = ENUM5; //~ ERROR use of unstable library feature `unstable_default`
     //~^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated]
-    let _: Enum5<isize> = Enum5::Some(0); //~ ERROR use of unstable library feature 'unstable_default'
+    let _: Enum5<isize> = Enum5::Some(0); //~ ERROR use of unstable library feature `unstable_default`
     //~^ use of deprecated tuple variant `unstable_generic_param::Enum5::Some`: test [deprecated]
     //~^^ use of deprecated enum `unstable_generic_param::Enum5`: test [deprecated]
 
     let _: Enum6<isize> = Enum6::Some(1); // ok
     let _: Enum6<isize> = Enum6::Some(0); // ok
 
-    let _: Box1<isize, System> = Box1::new(1); //~ ERROR use of unstable library feature 'box_alloc_param'
+    let _: Box1<isize, System> = Box1::new(1); //~ ERROR use of unstable library feature `box_alloc_param`
     let _: Box1<isize> = Box1::new(1); // ok
 
     let _: Box2<isize, System> = Box2::new(1); // ok
diff --git a/tests/ui/stability-attribute/generics-default-stability.stderr b/tests/ui/stability-attribute/generics-default-stability.stderr
index b1b91a850e9..f4f51a14248 100644
--- a/tests/ui/stability-attribute/generics-default-stability.stderr
+++ b/tests/ui/stability-attribute/generics-default-stability.stderr
@@ -216,7 +216,7 @@ warning: use of deprecated enum `unstable_generic_param::Enum5`: test
 LL |     let _: Enum5<isize> = Enum5::Some(0);
    |            ^^^^^
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:23:20
    |
 LL |     let _: Struct1<isize> = Struct1 { field: 1 };
@@ -225,7 +225,7 @@ LL |     let _: Struct1<isize> = Struct1 { field: 1 };
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:27:20
    |
 LL |     let _: Struct1<usize> = STRUCT1;
@@ -234,7 +234,7 @@ LL |     let _: Struct1<usize> = STRUCT1;
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:28:20
    |
 LL |     let _: Struct1<isize> = Struct1 { field: 0 };
@@ -243,7 +243,7 @@ LL |     let _: Struct1<isize> = Struct1 { field: 0 };
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:57:27
    |
 LL |     let _: Struct3<isize, usize> = STRUCT3;
@@ -252,7 +252,7 @@ LL |     let _: Struct3<isize, usize> = STRUCT3;
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:59:27
    |
 LL |     let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 };
@@ -261,7 +261,7 @@ LL |     let _: Struct3<isize, isize> = Struct3 { field1: 0, field2: 0 };
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:60:27
    |
 LL |     let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 };
@@ -270,7 +270,7 @@ LL |     let _: Struct3<usize, usize> = Struct3 { field1: 0, field2: 0 };
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:84:20
    |
 LL |     let _: Struct5<isize> = Struct5 { field: 1 };
@@ -279,7 +279,7 @@ LL |     let _: Struct5<isize> = Struct5 { field: 1 };
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:90:20
    |
 LL |     let _: Struct5<usize> = STRUCT5;
@@ -288,7 +288,7 @@ LL |     let _: Struct5<usize> = STRUCT5;
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:92:20
    |
 LL |     let _: Struct5<isize> = Struct5 { field: 0 };
@@ -297,7 +297,7 @@ LL |     let _: Struct5<isize> = Struct5 { field: 0 };
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:100:19
    |
 LL |     let _: Alias1<isize> = Alias1::Some(1);
@@ -306,7 +306,7 @@ LL |     let _: Alias1<isize> = Alias1::Some(1);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:104:19
    |
 LL |     let _: Alias1<usize> = ALIAS1;
@@ -315,7 +315,7 @@ LL |     let _: Alias1<usize> = ALIAS1;
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:105:19
    |
 LL |     let _: Alias1<isize> = Alias1::Some(0);
@@ -324,7 +324,7 @@ LL |     let _: Alias1<isize> = Alias1::Some(0);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:133:26
    |
 LL |     let _: Alias3<isize, usize> = ALIAS3;
@@ -333,7 +333,7 @@ LL |     let _: Alias3<isize, usize> = ALIAS3;
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:135:26
    |
 LL |     let _: Alias3<isize, isize> = Alias3::Ok(0);
@@ -342,7 +342,7 @@ LL |     let _: Alias3<isize, isize> = Alias3::Ok(0);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:136:26
    |
 LL |     let _: Alias3<usize, usize> = Alias3::Ok(0);
@@ -351,7 +351,7 @@ LL |     let _: Alias3<usize, usize> = Alias3::Ok(0);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:158:19
    |
 LL |     let _: Alias5<isize> = Alias5::Some(1);
@@ -360,7 +360,7 @@ LL |     let _: Alias5<isize> = Alias5::Some(1);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:163:19
    |
 LL |     let _: Alias5<usize> = ALIAS5;
@@ -369,7 +369,7 @@ LL |     let _: Alias5<usize> = ALIAS5;
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:165:19
    |
 LL |     let _: Alias5<isize> = Alias5::Some(0);
@@ -378,7 +378,7 @@ LL |     let _: Alias5<isize> = Alias5::Some(0);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:172:18
    |
 LL |     let _: Enum1<isize> = Enum1::Some(1);
@@ -387,7 +387,7 @@ LL |     let _: Enum1<isize> = Enum1::Some(1);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:176:18
    |
 LL |     let _: Enum1<usize> = ENUM1;
@@ -396,7 +396,7 @@ LL |     let _: Enum1<usize> = ENUM1;
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:177:18
    |
 LL |     let _: Enum1<isize> = Enum1::Some(0);
@@ -405,7 +405,7 @@ LL |     let _: Enum1<isize> = Enum1::Some(0);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:205:25
    |
 LL |     let _: Enum3<isize, usize> = ENUM3;
@@ -414,7 +414,7 @@ LL |     let _: Enum3<isize, usize> = ENUM3;
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:207:25
    |
 LL |     let _: Enum3<isize, isize> = Enum3::Ok(0);
@@ -423,7 +423,7 @@ LL |     let _: Enum3<isize, isize> = Enum3::Ok(0);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:208:25
    |
 LL |     let _: Enum3<usize, usize> = Enum3::Ok(0);
@@ -432,7 +432,7 @@ LL |     let _: Enum3<usize, usize> = Enum3::Ok(0);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:230:18
    |
 LL |     let _: Enum5<isize> = Enum5::Some(1);
@@ -441,7 +441,7 @@ LL |     let _: Enum5<isize> = Enum5::Some(1);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:235:18
    |
 LL |     let _: Enum5<usize> = ENUM5;
@@ -450,7 +450,7 @@ LL |     let _: Enum5<usize> = ENUM5;
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_default'
+error[E0658]: use of unstable library feature `unstable_default`
   --> $DIR/generics-default-stability.rs:237:18
    |
 LL |     let _: Enum5<isize> = Enum5::Some(0);
@@ -459,7 +459,7 @@ LL |     let _: Enum5<isize> = Enum5::Some(0);
    = help: add `#![feature(unstable_default)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'box_alloc_param'
+error[E0658]: use of unstable library feature `box_alloc_param`
   --> $DIR/generics-default-stability.rs:244:24
    |
 LL |     let _: Box1<isize, System> = Box1::new(1);
diff --git a/tests/ui/stability-attribute/issue-28075.rs b/tests/ui/stability-attribute/issue-28075.rs
index 8fc2ffe3dc9..b6b231d4afa 100644
--- a/tests/ui/stability-attribute/issue-28075.rs
+++ b/tests/ui/stability-attribute/issue-28075.rs
@@ -7,7 +7,7 @@
 extern crate lint_stability;
 
 use lint_stability::{unstable, deprecated};
-//~^ ERROR use of unstable library feature 'unstable_test_feature'
+//~^ ERROR use of unstable library feature `unstable_test_feature`
 
 fn main() {
 }
diff --git a/tests/ui/stability-attribute/issue-28075.stderr b/tests/ui/stability-attribute/issue-28075.stderr
index 282686d82bb..d10a27b874e 100644
--- a/tests/ui/stability-attribute/issue-28075.stderr
+++ b/tests/ui/stability-attribute/issue-28075.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/issue-28075.rs:9:22
    |
 LL | use lint_stability::{unstable, deprecated};
diff --git a/tests/ui/stability-attribute/issue-28388-3.rs b/tests/ui/stability-attribute/issue-28388-3.rs
index 2f61146f6e3..7b6b6ce7f4b 100644
--- a/tests/ui/stability-attribute/issue-28388-3.rs
+++ b/tests/ui/stability-attribute/issue-28388-3.rs
@@ -5,7 +5,7 @@
 extern crate lint_stability;
 
 use lint_stability::UnstableEnum::{};
-//~^ ERROR use of unstable library feature 'unstable_test_feature'
+//~^ ERROR use of unstable library feature `unstable_test_feature`
 use lint_stability::StableEnum::{}; // OK
 
 fn main() {}
diff --git a/tests/ui/stability-attribute/issue-28388-3.stderr b/tests/ui/stability-attribute/issue-28388-3.stderr
index 56ca57591ce..def27c0b44d 100644
--- a/tests/ui/stability-attribute/issue-28388-3.stderr
+++ b/tests/ui/stability-attribute/issue-28388-3.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/issue-28388-3.rs:7:5
    |
 LL | use lint_stability::UnstableEnum::{};
diff --git a/tests/ui/stability-attribute/missing-const-stability.rs b/tests/ui/stability-attribute/missing-const-stability.rs
index 6d49996c3b5..10c31d79438 100644
--- a/tests/ui/stability-attribute/missing-const-stability.rs
+++ b/tests/ui/stability-attribute/missing-const-stability.rs
@@ -36,10 +36,4 @@ impl const Bar for Foo {
 pub const unsafe fn size_of_val<T>(x: *const T) -> usize { 42 }
 //~^ ERROR function has missing const stability attribute
 
-extern "rust-intrinsic" {
-    #[stable(feature = "stable", since = "1.0.0")]
-    #[rustc_const_stable_indirect]
-    pub fn min_align_of_val<T>(x: *const T) -> usize;
-}
-
 fn main() {}
diff --git a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs
index 47f885a43d6..0cc1dd20fd8 100644
--- a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs
+++ b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.rs
@@ -5,9 +5,9 @@
 
 extern crate stability_attribute_implies;
 use stability_attribute_implies::{foo, foobar};
-//~^ ERROR use of unstable library feature 'foobar'
+//~^ ERROR use of unstable library feature `foobar`
 
 fn main() {
     foo(); // no error - stable
-    foobar(); //~ ERROR use of unstable library feature 'foobar'
+    foobar(); //~ ERROR use of unstable library feature `foobar`
 }
diff --git a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr
index b35ee6c1291..a625ef504b1 100644
--- a/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr
+++ b/tests/ui/stability-attribute/stability-attribute-implies-no-feature.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'foobar'
+error[E0658]: use of unstable library feature `foobar`
   --> $DIR/stability-attribute-implies-no-feature.rs:7:40
    |
 LL | use stability_attribute_implies::{foo, foobar};
@@ -8,7 +8,7 @@ LL | use stability_attribute_implies::{foo, foobar};
    = help: add `#![feature(foobar)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'foobar'
+error[E0658]: use of unstable library feature `foobar`
   --> $DIR/stability-attribute-implies-no-feature.rs:12:5
    |
 LL |     foobar();
diff --git a/tests/ui/stability-attribute/stability-attribute-issue.rs b/tests/ui/stability-attribute/stability-attribute-issue.rs
index 2d25c0c8bd7..e9d1f144e6b 100644
--- a/tests/ui/stability-attribute/stability-attribute-issue.rs
+++ b/tests/ui/stability-attribute/stability-attribute-issue.rs
@@ -6,7 +6,7 @@ use stability_attribute_issue::*;
 
 fn main() {
     unstable();
-    //~^ ERROR use of unstable library feature 'unstable_test_feature'
+    //~^ ERROR use of unstable library feature `unstable_test_feature`
     unstable_msg();
-    //~^ ERROR use of unstable library feature 'unstable_test_feature': message
+    //~^ ERROR use of unstable library feature `unstable_test_feature`: message
 }
diff --git a/tests/ui/stability-attribute/stability-attribute-issue.stderr b/tests/ui/stability-attribute/stability-attribute-issue.stderr
index 336e0f1718f..9dc6f441987 100644
--- a/tests/ui/stability-attribute/stability-attribute-issue.stderr
+++ b/tests/ui/stability-attribute/stability-attribute-issue.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/stability-attribute-issue.rs:8:5
    |
 LL |     unstable();
@@ -8,7 +8,7 @@ LL |     unstable();
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature': message
+error[E0658]: use of unstable library feature `unstable_test_feature`: message
   --> $DIR/stability-attribute-issue.rs:10:5
    |
 LL |     unstable_msg();
diff --git a/tests/ui/stability-attribute/stable-in-unstable.rs b/tests/ui/stability-attribute/stable-in-unstable.rs
index d10845d49a3..1fe084f6e59 100644
--- a/tests/ui/stability-attribute/stable-in-unstable.rs
+++ b/tests/ui/stability-attribute/stable-in-unstable.rs
@@ -13,8 +13,8 @@ extern crate stable_in_unstable_core;
 extern crate stable_in_unstable_std;
 
 mod isolated1 {
-    use stable_in_unstable_core::new_unstable_module; //~ ERROR use of unstable library feature 'unstable_test_feature'
-    use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature'
+    use stable_in_unstable_core::new_unstable_module; //~ ERROR use of unstable library feature `unstable_test_feature`
+    use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature `unstable_test_feature`
 }
 
 mod isolated2 {
@@ -26,7 +26,7 @@ mod isolated2 {
 }
 
 mod isolated3 {
-    use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature 'unstable_test_feature'
+    use stable_in_unstable_core::new_unstable_module::OldTrait; //~ ERROR use of unstable library feature `unstable_test_feature`
 
     struct LocalType;
 
@@ -36,7 +36,7 @@ mod isolated3 {
 mod isolated4 {
     struct LocalType;
 
-    impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {} //~ ERROR use of unstable library feature 'unstable_test_feature'
+    impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {} //~ ERROR use of unstable library feature `unstable_test_feature`
 }
 
 mod isolated5 {
@@ -46,9 +46,9 @@ mod isolated5 {
 }
 
 mod isolated6 {
-    use stable_in_unstable_core::new_unstable_module::{OldTrait}; //~ ERROR use of unstable library feature 'unstable_test_feature'
+    use stable_in_unstable_core::new_unstable_module::{OldTrait}; //~ ERROR use of unstable library feature `unstable_test_feature`
 }
 
 mod isolated7 {
-    use stable_in_unstable_core::new_unstable_module::*; //~ ERROR use of unstable library feature 'unstable_test_feature'
+    use stable_in_unstable_core::new_unstable_module::*; //~ ERROR use of unstable library feature `unstable_test_feature`
 }
diff --git a/tests/ui/stability-attribute/stable-in-unstable.stderr b/tests/ui/stability-attribute/stable-in-unstable.stderr
index eb73f047acd..b37b4dfd586 100644
--- a/tests/ui/stability-attribute/stable-in-unstable.stderr
+++ b/tests/ui/stability-attribute/stable-in-unstable.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/stable-in-unstable.rs:16:9
    |
 LL |     use stable_in_unstable_core::new_unstable_module;
@@ -8,7 +8,7 @@ LL |     use stable_in_unstable_core::new_unstable_module;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/stable-in-unstable.rs:17:9
    |
 LL |     use stable_in_unstable_core::new_unstable_module::OldTrait;
@@ -18,7 +18,7 @@ LL |     use stable_in_unstable_core::new_unstable_module::OldTrait;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/stable-in-unstable.rs:29:9
    |
 LL |     use stable_in_unstable_core::new_unstable_module::OldTrait;
@@ -28,7 +28,7 @@ LL |     use stable_in_unstable_core::new_unstable_module::OldTrait;
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/stable-in-unstable.rs:39:10
    |
 LL |     impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalType {}
@@ -38,7 +38,7 @@ LL |     impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalTy
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/stable-in-unstable.rs:49:56
    |
 LL |     use stable_in_unstable_core::new_unstable_module::{OldTrait};
@@ -48,7 +48,7 @@ LL |     use stable_in_unstable_core::new_unstable_module::{OldTrait};
    = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'unstable_test_feature'
+error[E0658]: use of unstable library feature `unstable_test_feature`
   --> $DIR/stable-in-unstable.rs:53:9
    |
 LL |     use stable_in_unstable_core::new_unstable_module::*;
diff --git a/tests/ui/stability-attribute/suggest-vec-allocator-api.rs b/tests/ui/stability-attribute/suggest-vec-allocator-api.rs
index fac52ab77c6..61a48c19e72 100644
--- a/tests/ui/stability-attribute/suggest-vec-allocator-api.rs
+++ b/tests/ui/stability-attribute/suggest-vec-allocator-api.rs
@@ -1,9 +1,9 @@
 fn main() {
-    let _: Vec<u8, _> = vec![]; //~ ERROR use of unstable library feature 'allocator_api'
+    let _: Vec<u8, _> = vec![]; //~ ERROR use of unstable library feature `allocator_api`
     #[rustfmt::skip]
     let _: Vec<
         String,
-        _> = vec![]; //~ ERROR use of unstable library feature 'allocator_api'
-    let _ = Vec::<u16, _>::new(); //~ ERROR use of unstable library feature 'allocator_api'
-    let _boxed: Box<u32, _> = Box::new(10); //~ ERROR use of unstable library feature 'allocator_api'
+        _> = vec![]; //~ ERROR use of unstable library feature `allocator_api`
+    let _ = Vec::<u16, _>::new(); //~ ERROR use of unstable library feature `allocator_api`
+    let _boxed: Box<u32, _> = Box::new(10); //~ ERROR use of unstable library feature `allocator_api`
 }
diff --git a/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr b/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr
index d7fcba4ced5..6662ceda90b 100644
--- a/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr
+++ b/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'allocator_api'
+error[E0658]: use of unstable library feature `allocator_api`
   --> $DIR/suggest-vec-allocator-api.rs:2:20
    |
 LL |     let _: Vec<u8, _> = vec![];
@@ -10,7 +10,7 @@ LL |     let _: Vec<u8, _> = vec![];
    = help: add `#![feature(allocator_api)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'allocator_api'
+error[E0658]: use of unstable library feature `allocator_api`
   --> $DIR/suggest-vec-allocator-api.rs:6:9
    |
 LL |         _> = vec![];
@@ -26,7 +26,7 @@ LL +         String,
 LL ~         _)> = vec![];
    |
 
-error[E0658]: use of unstable library feature 'allocator_api'
+error[E0658]: use of unstable library feature `allocator_api`
   --> $DIR/suggest-vec-allocator-api.rs:8:26
    |
 LL |     let _boxed: Box<u32, _> = Box::new(10);
@@ -36,7 +36,7 @@ LL |     let _boxed: Box<u32, _> = Box::new(10);
    = help: add `#![feature(allocator_api)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'allocator_api'
+error[E0658]: use of unstable library feature `allocator_api`
   --> $DIR/suggest-vec-allocator-api.rs:7:24
    |
 LL |     let _ = Vec::<u16, _>::new();
diff --git a/tests/ui/structs/struct-field-cfg.stderr b/tests/ui/structs/struct-field-cfg.stderr
index 2b9ba85ddcb..f30d343d582 100644
--- a/tests/ui/structs/struct-field-cfg.stderr
+++ b/tests/ui/structs/struct-field-cfg.stderr
@@ -24,6 +24,10 @@ LL |     let Foo { present } = foo;
    |             ~~~~~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     let Foo { present: _ } = foo;
+   |             ~~~~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     let Foo { .. } = foo;
    |             ~~~~~~
 
diff --git a/tests/ui/structs/struct-pat-derived-error.stderr b/tests/ui/structs/struct-pat-derived-error.stderr
index 78bb018cb4b..d1d68121cf1 100644
--- a/tests/ui/structs/struct-pat-derived-error.stderr
+++ b/tests/ui/structs/struct-pat-derived-error.stderr
@@ -27,6 +27,10 @@ LL |         let A { x, y, b, c } = self.d;
    |                     ~~~~~~~~
 help: if you don't care about these missing fields, you can explicitly ignore them
    |
+LL |         let A { x, y, b: _, c: _ } = self.d;
+   |                     ~~~~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |         let A { x, y, .. } = self.d;
    |                     ~~~~~~
 
diff --git a/tests/ui/structs/struct-tuple-field-names.stderr b/tests/ui/structs/struct-tuple-field-names.stderr
index 0b837a47a82..5f1ab2f9d68 100644
--- a/tests/ui/structs/struct-tuple-field-names.stderr
+++ b/tests/ui/structs/struct-tuple-field-names.stderr
@@ -32,6 +32,10 @@ LL |     if let E::S { 0: a, 1: _ } = x {
    |                       ~~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     if let E::S { 0: a, 1: _ } = x {
+   |                       ~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     if let E::S { 0: a, .. } = x {
    |                       ~~~~~~
 
diff --git a/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr
index e8503f540c2..af530e2b759 100644
--- a/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr
+++ b/tests/ui/structs/suggest-replacing-field-when-specifying-same-type.stderr
@@ -19,6 +19,10 @@ LL |         Foo::Bar { a, aa: 1, c, b } => (),
    |                               ~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |         Foo::Bar { a, aa: 1, c, b: _ } => (),
+   |                               ~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |         Foo::Bar { a, aa: 1, c, .. } => (),
    |                               ~~~~~~
 
@@ -43,6 +47,10 @@ LL |         Foo::Baz { bb: 1.0, a } => (),
    |                           ~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |         Foo::Baz { bb: 1.0, a: _ } => (),
+   |                           ~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |         Foo::Baz { bb: 1.0, .. } => (),
    |                           ~~~~~~
 
@@ -64,6 +72,10 @@ LL |         Foo::Bar { a, aa: "", c, b } => (),
    |                                ~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |         Foo::Bar { a, aa: "", c, b: _ } => (),
+   |                                ~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |         Foo::Bar { a, aa: "", c, .. } => (),
    |                                ~~~~~~
 
@@ -85,6 +97,10 @@ LL |         Foo::Baz { bb: "", a } => (),
    |                          ~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |         Foo::Baz { bb: "", a: _ } => (),
+   |                          ~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |         Foo::Baz { bb: "", .. } => (),
    |                          ~~~~~~
 
diff --git a/tests/ui/suggestions/partialeq_suggest_swap.rs b/tests/ui/suggestions/partialeq_suggest_swap.rs
new file mode 100644
index 00000000000..ee5583a5488
--- /dev/null
+++ b/tests/ui/suggestions/partialeq_suggest_swap.rs
@@ -0,0 +1,11 @@
+struct T(i32);
+
+impl PartialEq<i32> for T {
+    fn eq(&self, other: &i32) -> bool {
+        &self.0 == other
+    }
+}
+
+fn main() {
+    4i32 == T(4); //~ mismatched types [E0308]
+}
diff --git a/tests/ui/suggestions/partialeq_suggest_swap.stderr b/tests/ui/suggestions/partialeq_suggest_swap.stderr
new file mode 100644
index 00000000000..2cadc5a16d5
--- /dev/null
+++ b/tests/ui/suggestions/partialeq_suggest_swap.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/partialeq_suggest_swap.rs:10:13
+   |
+LL |     4i32 == T(4);
+   |     ----    ^^^^ expected `i32`, found `T`
+   |     |
+   |     expected because this is `i32`
+   |
+   = note: `T` implements `PartialEq<i32>`
+help: consider swapping the equality
+   |
+LL |     T(4) == 4i32;
+   |     ~~~~    ~~~~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/suggest-let-and-typo-issue-132483.rs b/tests/ui/suggestions/suggest-let-and-typo-issue-132483.rs
new file mode 100644
index 00000000000..d56a6b78d37
--- /dev/null
+++ b/tests/ui/suggestions/suggest-let-and-typo-issue-132483.rs
@@ -0,0 +1,7 @@
+fn main() {
+    let x1 = 0;
+    x2 = 1;
+    //~^ ERROR E0425
+    other_val = 2;
+    //~^ ERROR E0425
+}
diff --git a/tests/ui/suggestions/suggest-let-and-typo-issue-132483.stderr b/tests/ui/suggestions/suggest-let-and-typo-issue-132483.stderr
new file mode 100644
index 00000000000..c84f9363f03
--- /dev/null
+++ b/tests/ui/suggestions/suggest-let-and-typo-issue-132483.stderr
@@ -0,0 +1,29 @@
+error[E0425]: cannot find value `x2` in this scope
+  --> $DIR/suggest-let-and-typo-issue-132483.rs:3:5
+   |
+LL |     x2 = 1;
+   |     ^^
+   |
+help: a local variable with a similar name exists
+   |
+LL |     x1 = 1;
+   |     ~~
+help: you might have meant to introduce a new binding
+   |
+LL |     let x2 = 1;
+   |     +++
+
+error[E0425]: cannot find value `other_val` in this scope
+  --> $DIR/suggest-let-and-typo-issue-132483.rs:5:5
+   |
+LL |     other_val = 2;
+   |     ^^^^^^^^^
+   |
+help: you might have meant to introduce a new binding
+   |
+LL |     let other_val = 2;
+   |     +++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/auxiliary/using-target-feature-unstable.rs b/tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs
index 2682028936c..2682028936c 100644
--- a/tests/ui/auxiliary/using-target-feature-unstable.rs
+++ b/tests/ui/target-feature/auxiliary/using-target-feature-unstable.rs
diff --git a/tests/ui/target-feature/feature-hierarchy.rs b/tests/ui/target-feature/feature-hierarchy.rs
index 7f14d700ecb..d62b86693c2 100644
--- a/tests/ui/target-feature/feature-hierarchy.rs
+++ b/tests/ui/target-feature/feature-hierarchy.rs
@@ -18,10 +18,12 @@ trait Sized {}
 trait Copy {}
 impl Copy for bool {}
 
-extern "rust-intrinsic" {
-    #[stable(feature = "test", since = "1.0.0")]
-    #[rustc_const_stable(feature = "test", since = "1.0.0")]
-    fn unreachable() -> !;
+#[stable(feature = "test", since = "1.0.0")]
+#[rustc_const_stable(feature = "test", since = "1.0.0")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+const unsafe fn unreachable() -> ! {
+    loop {}
 }
 
 #[rustc_builtin_macro]
diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.rs b/tests/ui/target-feature/forbidden-target-feature-attribute.rs
new file mode 100644
index 00000000000..91c56b43689
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-target-feature-attribute.rs
@@ -0,0 +1,12 @@
+//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
+//@ needs-llvm-components: x86
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[target_feature(enable = "soft-float")]
+//~^ERROR: cannot be toggled with
+pub unsafe fn my_fun() {}
diff --git a/tests/ui/target-feature/forbidden-target-feature-attribute.stderr b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr
new file mode 100644
index 00000000000..fb318531f7e
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-target-feature-attribute.stderr
@@ -0,0 +1,8 @@
+error: target feature `soft-float` cannot be toggled with `#[target_feature]`: unsound because it changes float ABI
+  --> $DIR/forbidden-target-feature-attribute.rs:10:18
+   |
+LL | #[target_feature(enable = "soft-float")]
+   |                  ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/target-feature/forbidden-target-feature-cfg.rs b/tests/ui/target-feature/forbidden-target-feature-cfg.rs
new file mode 100644
index 00000000000..5df26e26793
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-target-feature-cfg.rs
@@ -0,0 +1,15 @@
+//@ compile-flags: --target=x86_64-unknown-none --crate-type=lib
+//@ needs-llvm-components: x86
+//@ check-pass
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![allow(unexpected_cfgs)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+// The compile_error macro does not exist, so if the `cfg` evaluates to `true` this
+// complains about the missing macro rather than showing the error... but that's good enough.
+#[cfg(target_feature = "soft-float")]
+compile_error!("the soft-float feature should not be exposed in `cfg`");
diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs
new file mode 100644
index 00000000000..b27e8a10afe
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.rs
@@ -0,0 +1,11 @@
+//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
+//@ needs-llvm-components: x86
+//@ compile-flags: -Ctarget-feature=-soft-float
+// For now this is just a warning.
+//@ build-pass
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
diff --git a/tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr b/tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr
new file mode 100644
index 00000000000..508e1fe0cf4
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-target-feature-flag-disable.stderr
@@ -0,0 +1,7 @@
+warning: target feature `soft-float` cannot be toggled with `-Ctarget-feature`: unsound because it changes float ABI
+   |
+   = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.rs b/tests/ui/target-feature/forbidden-target-feature-flag.rs
new file mode 100644
index 00000000000..93cebc6b536
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-target-feature-flag.rs
@@ -0,0 +1,11 @@
+//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
+//@ needs-llvm-components: x86
+//@ compile-flags: -Ctarget-feature=+soft-float
+// For now this is just a warning.
+//@ build-pass
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
diff --git a/tests/ui/target-feature/forbidden-target-feature-flag.stderr b/tests/ui/target-feature/forbidden-target-feature-flag.stderr
new file mode 100644
index 00000000000..508e1fe0cf4
--- /dev/null
+++ b/tests/ui/target-feature/forbidden-target-feature-flag.stderr
@@ -0,0 +1,7 @@
+warning: target feature `soft-float` cannot be toggled with `-Ctarget-feature`: unsound because it changes float ABI
+   |
+   = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/target-feature/no-llvm-leaks.rs b/tests/ui/target-feature/no-llvm-leaks.rs
index f0c887bc1e0..10268686405 100644
--- a/tests/ui/target-feature/no-llvm-leaks.rs
+++ b/tests/ui/target-feature/no-llvm-leaks.rs
@@ -16,10 +16,12 @@ trait Sized {}
 trait Copy {}
 impl Copy for bool {}
 
-extern "rust-intrinsic" {
-    #[stable(feature = "test", since = "1.0.0")]
-    #[rustc_const_stable(feature = "test", since = "1.0.0")]
-    fn unreachable() -> !;
+#[stable(feature = "test", since = "1.0.0")]
+#[rustc_const_stable(feature = "test", since = "1.0.0")]
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+const unsafe fn unreachable() -> ! {
+    loop {}
 }
 
 #[rustc_builtin_macro]
diff --git a/tests/ui/using-target-feature-unstable.rs b/tests/ui/target-feature/using-target-feature-unstable.rs
index 5ec0bda5eef..5ec0bda5eef 100644
--- a/tests/ui/using-target-feature-unstable.rs
+++ b/tests/ui/target-feature/using-target-feature-unstable.rs
diff --git a/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs b/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs
new file mode 100644
index 00000000000..48a98efea5e
--- /dev/null
+++ b/tests/ui/traits/bound/unknown-assoc-with-const-arg.rs
@@ -0,0 +1,20 @@
+// issue#132534
+
+trait X {
+    fn a<T>() -> T::unknown<{}> {}
+    //~^ ERROR: associated type `unknown` not found for `T`
+    //~| ERROR: associated type `unknown` not found for `T`
+}
+
+trait Y {
+    fn a() -> NOT_EXIST::unknown<{}> {}
+    //~^ ERROR: failed to resolve: use of undeclared type `NOT_EXIST`
+}
+
+trait Z<T> {
+    fn a() -> T::unknown<{}> {}
+    //~^ ERROR: associated type `unknown` not found for `T`
+    //~| ERROR: associated type `unknown` not found for `T`
+}
+
+fn main() {}
diff --git a/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr b/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr
new file mode 100644
index 00000000000..9598c373e6e
--- /dev/null
+++ b/tests/ui/traits/bound/unknown-assoc-with-const-arg.stderr
@@ -0,0 +1,38 @@
+error[E0220]: associated type `unknown` not found for `T`
+  --> $DIR/unknown-assoc-with-const-arg.rs:4:21
+   |
+LL |     fn a<T>() -> T::unknown<{}> {}
+   |                     ^^^^^^^ associated type `unknown` not found
+
+error[E0220]: associated type `unknown` not found for `T`
+  --> $DIR/unknown-assoc-with-const-arg.rs:15:18
+   |
+LL |     fn a() -> T::unknown<{}> {}
+   |                  ^^^^^^^ associated type `unknown` not found
+
+error[E0220]: associated type `unknown` not found for `T`
+  --> $DIR/unknown-assoc-with-const-arg.rs:4:21
+   |
+LL |     fn a<T>() -> T::unknown<{}> {}
+   |                     ^^^^^^^ associated type `unknown` not found
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0220]: associated type `unknown` not found for `T`
+  --> $DIR/unknown-assoc-with-const-arg.rs:15:18
+   |
+LL |     fn a() -> T::unknown<{}> {}
+   |                  ^^^^^^^ associated type `unknown` not found
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0433]: failed to resolve: use of undeclared type `NOT_EXIST`
+  --> $DIR/unknown-assoc-with-const-arg.rs:10:15
+   |
+LL |     fn a() -> NOT_EXIST::unknown<{}> {}
+   |               ^^^^^^^^^ use of undeclared type `NOT_EXIST`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0220, E0433.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr
index 3ccae5a83e6..95f6f32f21d 100644
--- a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr
+++ b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'derive_const'
+error[E0658]: use of unstable library feature `derive_const`
   --> $DIR/derive-const-gate.rs:1:3
    |
 LL | #[derive_const(Default)]
diff --git a/tests/ui/traits/const-traits/effects/minicore.rs b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs
index 50badcd2e87..209a111c243 100644
--- a/tests/ui/traits/const-traits/effects/minicore.rs
+++ b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs
@@ -1,12 +1,7 @@
-//@ known-bug: #110395
-//@ failure-status: 101
-//@ normalize-stderr-test: ".*note: .*\n\n" -> ""
-//@ normalize-stderr-test: "thread 'rustc' panicked.*:\n.*\n" -> ""
-//@ rustc-env:RUST_BACKTRACE=0
-// FIXME(const_trait_impl) check-pass
-//@ compile-flags: -Znext-solver
-
-#![crate_type = "lib"]
+//@ compile-flags: -Znext-solver -Cpanic=abort
+//@ no-prefer-dynamic
+
+#![crate_type = "rlib"]
 #![feature(
     no_core,
     lang_items,
@@ -23,13 +18,17 @@
 #![no_core]
 
 #[lang = "sized"]
-trait Sized {}
+pub trait Sized {}
 #[lang = "copy"]
-trait Copy {}
+pub trait Copy {}
+
+impl Copy for bool {}
+impl Copy for u8 {}
+impl<T: ?Sized> Copy for &T {}
 
 #[lang = "add"]
 #[const_trait]
-trait Add<Rhs = Self> {
+pub trait Add<Rhs = Self> {
     type Output;
 
     fn add(self, rhs: Rhs) -> Self::Output;
@@ -50,10 +49,9 @@ const fn bar() {
     let x = 42_i32 + 43_i32;
 }
 
-
 #[lang = "Try"]
 #[const_trait]
-trait Try: FromResidual<Self::Residual> {
+pub trait Try: FromResidual<Self::Residual> {
     type Output;
     type Residual;
 
@@ -64,9 +62,8 @@ trait Try: FromResidual<Self::Residual> {
     fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
 }
 
-// FIXME
-// #[const_trait]
-trait FromResidual<R = <Self as /* FIXME: ~const */ Try>::Residual> {
+#[const_trait]
+pub trait FromResidual<R = <Self as Try>::Residual> {
     #[lang = "from_residual"]
     fn from_residual(residual: R) -> Self;
 }
@@ -81,71 +78,32 @@ enum ControlFlow<B, C = ()> {
 #[const_trait]
 #[lang = "fn"]
 #[rustc_paren_sugar]
-trait Fn<Args: Tuple>: ~const FnMut<Args> {
+pub trait Fn<Args: Tuple>: ~const FnMut<Args> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
 }
 
 #[const_trait]
 #[lang = "fn_mut"]
 #[rustc_paren_sugar]
-trait FnMut<Args: Tuple>: ~const FnOnce<Args> {
+pub trait FnMut<Args: Tuple>: ~const FnOnce<Args> {
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
 }
 
 #[const_trait]
 #[lang = "fn_once"]
 #[rustc_paren_sugar]
-trait FnOnce<Args: Tuple> {
+pub trait FnOnce<Args: Tuple> {
     #[lang = "fn_once_output"]
     type Output;
 
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 }
 
-struct ConstFnMutClosure<CapturedData, Function> {
-    data: CapturedData,
-    func: Function,
-}
-
 #[lang = "tuple_trait"]
-trait Tuple {}
-
-macro_rules! impl_fn_mut_tuple {
-    ($($var:ident)*) => {
-        impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
-            FnOnce<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
-        where
-            Function: ~const Fn(($(&mut $var),*), ClosureArguments) -> ClosureReturnValue,
-            Function: ~const Destruct,
-        {
-            type Output = ClosureReturnValue;
-
-            extern "rust-call" fn call_once(mut self, args: ClosureArguments) -> Self::Output {
-            self.call_mut(args)
-            }
-        }
-        impl<'a, $($var,)* ClosureArguments: Tuple, Function, ClosureReturnValue> const
-            FnMut<ClosureArguments> for ConstFnMutClosure<($(&'a mut $var),*), Function>
-        where
-            Function: ~const Fn(($(&mut $var),*), ClosureArguments)-> ClosureReturnValue,
-            Function: ~const Destruct,
-        {
-            extern "rust-call" fn call_mut(&mut self, args: ClosureArguments) -> Self::Output {
-                #[allow(non_snake_case)]
-                let ($($var),*) = &mut self.data;
-                (self.func)(($($var),*), args)
-            }
-        }
-    };
-}
-//impl_fn_mut_tuple!(A);
-//impl_fn_mut_tuple!(A B);
-//impl_fn_mut_tuple!(A B C);
-//impl_fn_mut_tuple!(A B C D);
-//impl_fn_mut_tuple!(A B C D E);
+pub trait Tuple {}
 
 #[lang = "legacy_receiver"]
-trait LegacyReceiver {}
+pub trait LegacyReceiver {}
 
 impl<T: ?Sized> LegacyReceiver for &T {}
 
@@ -153,30 +111,26 @@ impl<T: ?Sized> LegacyReceiver for &mut T {}
 
 #[lang = "destruct"]
 #[const_trait]
-trait Destruct {}
+pub trait Destruct {}
 
 #[lang = "freeze"]
-unsafe auto trait Freeze {}
+pub unsafe auto trait Freeze {}
 
 #[lang = "drop"]
 #[const_trait]
-trait Drop {
+pub trait Drop {
     fn drop(&mut self);
 }
 
-/*
 #[const_trait]
-trait Residual<O> {
+pub trait Residual<O> {
     type TryType: ~const Try<Output = O, Residual = Self> + Try<Output = O, Residual = Self>;
 }
-*/
 
 const fn size_of<T>() -> usize {
     42
 }
 
-impl Copy for u8 {}
-
 impl usize {
     #[rustc_allow_incoherent_impl]
     const fn repeat_u8(x: u8) -> usize {
@@ -197,15 +151,14 @@ fn panic_fmt() {}
 
 #[lang = "index"]
 #[const_trait]
-trait Index<Idx: ?Sized> {
+pub trait Index<Idx: ?Sized> {
     type Output: ?Sized;
 
     fn index(&self, index: Idx) -> &Self::Output;
 }
 
-
 #[const_trait]
-unsafe trait SliceIndex<T: ?Sized> {
+pub unsafe trait SliceIndex<T: ?Sized> {
     type Output: ?Sized;
     fn index(self, slice: &T) -> &Self::Output;
 }
@@ -221,7 +174,7 @@ where
         index.index(self)
     }
 }
-/* FIXME
+
 impl<T, I, const N: usize> const Index<I> for [T; N]
 where
     [T]: ~const Index<I>,
@@ -229,35 +182,29 @@ where
     type Output = <[T] as Index<I>>::Output;
 
     #[inline]
-    // FIXME: make `Self::Output` act like `<Self as ~const Index<I>>::Output`
     fn index(&self, index: I) -> &<[T] as Index<I>>::Output {
         Index::index(self as &[T], index)
     }
 }
-*/
 
 #[lang = "unsize"]
-trait Unsize<T: ?Sized> {
-}
+pub trait Unsize<T: ?Sized> {}
 
 #[lang = "coerce_unsized"]
-trait CoerceUnsized<T: ?Sized> {
-}
+pub trait CoerceUnsized<T: ?Sized> {}
 
 impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
 
-
 #[lang = "deref"]
-// #[const_trait] FIXME
-trait Deref {
+#[const_trait]
+pub trait Deref {
     #[lang = "deref_target"]
     type Target: ?Sized;
 
     fn deref(&self) -> &Self::Target;
 }
 
-
-impl<T: ?Sized> /* const */ Deref for &T {
+impl<T: ?Sized> const Deref for &T {
     type Target = T;
 
     fn deref(&self) -> &T {
@@ -265,7 +212,7 @@ impl<T: ?Sized> /* const */ Deref for &T {
     }
 }
 
-impl<T: ?Sized> /* const */ Deref for &mut T {
+impl<T: ?Sized> const Deref for &mut T {
     type Target = T;
 
     fn deref(&self) -> &T {
@@ -298,7 +245,6 @@ impl<T> Option<T> {
 
 use Option::*;
 
-/*
 const fn as_deref<T>(opt: &Option<T>) -> Option<&T::Target>
 where
     T: ~const Deref,
@@ -308,15 +254,14 @@ where
         Option::None => Option::None,
     }
 }
-*/
 
 #[const_trait]
-trait Into<T>: Sized {
+pub trait Into<T>: Sized {
     fn into(self) -> T;
 }
 
 #[const_trait]
-trait From<T>: Sized {
+pub trait From<T>: Sized {
     fn from(value: T) -> Self;
 }
 
@@ -351,7 +296,7 @@ fn from_str(s: &str) -> Result<bool, ()> {
 
 #[lang = "eq"]
 #[const_trait]
-trait PartialEq<Rhs: ?Sized = Self> {
+pub trait PartialEq<Rhs: ?Sized = Self> {
     fn eq(&self, other: &Rhs) -> bool;
     fn ne(&self, other: &Rhs) -> bool {
         !self.eq(other)
@@ -373,10 +318,9 @@ impl PartialEq for str {
     }
 }
 
-
 #[lang = "not"]
 #[const_trait]
-trait Not {
+pub trait Not {
     type Output;
     fn not(self) -> Self::Output;
 }
@@ -388,9 +332,6 @@ impl const Not for bool {
     }
 }
 
-impl Copy for bool {}
-impl<'a> Copy for &'a str {}
-
 #[lang = "pin"]
 #[fundamental]
 #[repr(transparent)]
@@ -411,23 +352,21 @@ impl<'a, T: ?Sized> Pin<&'a T> {
     }
 }
 
-
 impl<P: Deref> Pin<P> {
-    /* const */ fn as_ref(&self) -> Pin<&P::Target>
+    const fn as_ref(&self) -> Pin<&P::Target>
     where
-        P: /* ~const */ Deref,
+        P: ~const Deref,
     {
         unsafe { Pin::new_unchecked(&*self.pointer) }
     }
 }
 
-
 impl<'a, T: ?Sized> Pin<&'a mut T> {
     const unsafe fn get_unchecked_mut(self) -> &'a mut T {
         self.pointer
     }
 }
-/* FIXME lol
+
 impl<T> Option<T> {
     const fn as_pin_ref(self: Pin<&Self>) -> Option<Pin<&T>> {
         match Pin::get_ref(self).as_ref() {
@@ -445,16 +384,15 @@ impl<T> Option<T> {
         }
     }
 }
-*/
 
-impl<P: /* ~const */ Deref> /* const */ Deref for Pin<P> {
+impl<P: ~const Deref> const Deref for Pin<P> {
     type Target = P::Target;
     fn deref(&self) -> &P::Target {
         Pin::get_ref(Pin::as_ref(self))
     }
 }
 
-impl<T> /* const */ Deref for Option<T> {
+impl<T> const Deref for Option<T> {
     type Target = T;
     fn deref(&self) -> &T {
         loop {}
@@ -506,23 +444,22 @@ impl<T: ?Sized> Deref for Ref<'_, T> {
 
 #[lang = "clone"]
 #[rustc_trivial_field_reads]
-#[const_trait]
-trait Clone: Sized {
+// FIXME: #[const_trait]
+pub trait Clone: Sized {
     fn clone(&self) -> Self;
     fn clone_from(&mut self, source: &Self)
     where
-        Self: ~const Destruct,
+    // FIXME: Self: ~const Destruct,
     {
         *self = source.clone()
     }
 }
 
 #[lang = "structural_peq"]
-trait StructuralPartialEq {}
+pub trait StructuralPartialEq {}
 
-const fn drop<T: ~const Destruct>(_: T) {}
+// FIXME: const fn drop<T: ~const Destruct>(_: T) {}
 
-#[rustc_const_stable_indirect]
 #[rustc_intrinsic_must_be_overridden]
 #[rustc_intrinsic]
 const fn const_eval_select<ARG: Tuple, F, G, RET>(
@@ -536,10 +473,3 @@ where
 {
     loop {}
 }
-
-fn test_const_eval_select() {
-    const fn const_fn() {}
-    fn rt_fn() {}
-
-    const_eval_select((), const_fn, rt_fn);
-}
diff --git a/tests/ui/traits/const-traits/effects/minicore-deref-fail.rs b/tests/ui/traits/const-traits/effects/minicore-deref-fail.rs
new file mode 100644
index 00000000000..f4a7678a009
--- /dev/null
+++ b/tests/ui/traits/const-traits/effects/minicore-deref-fail.rs
@@ -0,0 +1,20 @@
+//@ aux-build:minicore.rs
+//@ compile-flags: --crate-type=lib -Znext-solver -Cpanic=abort
+
+#![feature(no_core, const_trait_impl)]
+#![no_std]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+struct Ty;
+impl Deref for Ty {
+    type Target = ();
+    fn deref(&self) -> &Self::Target { &() }
+}
+
+const fn foo() {
+    *Ty;
+    //~^ ERROR the trait bound `Ty: ~const minicore::Deref` is not satisfied
+}
diff --git a/tests/ui/traits/const-traits/effects/minicore-deref-fail.stderr b/tests/ui/traits/const-traits/effects/minicore-deref-fail.stderr
new file mode 100644
index 00000000000..a1f840114fc
--- /dev/null
+++ b/tests/ui/traits/const-traits/effects/minicore-deref-fail.stderr
@@ -0,0 +1,9 @@
+error[E0277]: the trait bound `Ty: ~const minicore::Deref` is not satisfied
+  --> $DIR/minicore-deref-fail.rs:18:5
+   |
+LL |     *Ty;
+   |     ^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/effects/minicore-works.rs b/tests/ui/traits/const-traits/effects/minicore-works.rs
new file mode 100644
index 00000000000..bfbfa8b2d05
--- /dev/null
+++ b/tests/ui/traits/const-traits/effects/minicore-works.rs
@@ -0,0 +1,22 @@
+//@ aux-build:minicore.rs
+//@ compile-flags: --crate-type=lib -Znext-solver -Cpanic=abort
+//@ check-pass
+
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+#![feature(const_trait_impl)]
+
+extern crate minicore;
+use minicore::*;
+
+struct Custom;
+impl const Add for Custom {
+    type Output = ();
+    fn add(self, _other: Self) {}
+}
+
+const fn test_op() {
+    let _x = Add::add(1, 2);
+    let _y = Custom + Custom;
+}
diff --git a/tests/ui/traits/const-traits/effects/minicore.stderr b/tests/ui/traits/const-traits/effects/minicore.stderr
deleted file mode 100644
index 568d98cfe87..00000000000
--- a/tests/ui/traits/const-traits/effects/minicore.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-error: the compiler unexpectedly panicked. this is a bug.
-
-query stack during panic:
-#0 [typeck] type-checking `Clone::clone_from`
-#1 [analysis] running analysis passes on this crate
-end of query stack
-
-error: the compiler unexpectedly panicked. this is a bug.
-
-query stack during panic:
-#0 [typeck] type-checking `test_const_eval_select`
-#1 [analysis] running analysis passes on this crate
-end of query stack
diff --git a/tests/ui/traits/issue-78372.rs b/tests/ui/traits/issue-78372.rs
index b97835bbc57..82b13cc0b62 100644
--- a/tests/ui/traits/issue-78372.rs
+++ b/tests/ui/traits/issue-78372.rs
@@ -1,8 +1,8 @@
-use std::ops::DispatchFromDyn; //~ ERROR use of unstable library feature 'dispatch_from_dyn'
+use std::ops::DispatchFromDyn; //~ ERROR use of unstable library feature `dispatch_from_dyn`
 struct Smaht<T, MISC>(PhantomData); //~ ERROR cannot find type `PhantomData` in this scope
 impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {} //~ ERROR cannot find type `U` in this scope
 //~^ ERROR cannot find type `MISC` in this scope
-//~| ERROR use of unstable library feature 'dispatch_from_dyn'
+//~| ERROR use of unstable library feature `dispatch_from_dyn`
 //~| ERROR the trait `DispatchFromDyn` may only be implemented for a coercion between structures
 trait Foo: X<u32> {}
 trait X<T> {
diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr
index 9b93ffe8efb..4cc2c59fd8d 100644
--- a/tests/ui/traits/issue-78372.stderr
+++ b/tests/ui/traits/issue-78372.stderr
@@ -37,7 +37,7 @@ help: you might be missing a type parameter
 LL | impl<T, MISC> DispatchFromDyn<Smaht<U, MISC>> for T {}
    |       ++++++
 
-error[E0658]: use of unstable library feature 'dispatch_from_dyn'
+error[E0658]: use of unstable library feature `dispatch_from_dyn`
   --> $DIR/issue-78372.rs:1:5
    |
 LL | use std::ops::DispatchFromDyn;
@@ -46,7 +46,7 @@ LL | use std::ops::DispatchFromDyn;
    = help: add `#![feature(dispatch_from_dyn)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'dispatch_from_dyn'
+error[E0658]: use of unstable library feature `dispatch_from_dyn`
   --> $DIR/issue-78372.rs:3:9
    |
 LL | impl<T> DispatchFromDyn<Smaht<U, MISC>> for T {}
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs
index 07133aa5614..7fe2324698e 100644
--- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs
+++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.rs
@@ -3,7 +3,7 @@
 #![crate_type = "lib"]
 
 use std::mem::TransmuteFrom;
-//~^ ERROR use of unstable library feature 'transmutability' [E0658]
+//~^ ERROR use of unstable library feature `transmutability` [E0658]
 
 use std::mem::Assume;
-//~^ ERROR use of unstable library feature 'transmutability' [E0658]
+//~^ ERROR use of unstable library feature `transmutability` [E0658]
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr
index a2096cd53e5..e4ad720ff69 100644
--- a/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr
+++ b/tests/ui/transmutability/malformed-program-gracefulness/feature-missing.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'transmutability'
+error[E0658]: use of unstable library feature `transmutability`
   --> $DIR/feature-missing.rs:5:5
    |
 LL | use std::mem::TransmuteFrom;
@@ -8,7 +8,7 @@ LL | use std::mem::TransmuteFrom;
    = help: add `#![feature(transmutability)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'transmutability'
+error[E0658]: use of unstable library feature `transmutability`
   --> $DIR/feature-missing.rs:8:5
    |
 LL | use std::mem::Assume;
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs
index 3c507a9669d..e638f3c6c40 100644
--- a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs
@@ -3,12 +3,12 @@
 use std::pat::pattern_type;
 
 type NonNullU32 = pattern_type!(u32 is 1..);
-//~^ use of unstable library feature 'core_pattern_type'
+//~^ use of unstable library feature `core_pattern_type`
 type Percent = pattern_type!(u32 is 0..=100);
-//~^ use of unstable library feature 'core_pattern_type'
+//~^ use of unstable library feature `core_pattern_type`
 type Negative = pattern_type!(i32 is ..=0);
-//~^ use of unstable library feature 'core_pattern_type'
+//~^ use of unstable library feature `core_pattern_type`
 type Positive = pattern_type!(i32 is 0..);
-//~^ use of unstable library feature 'core_pattern_type'
+//~^ use of unstable library feature `core_pattern_type`
 type Always = pattern_type!(Option<u32> is Some(_));
-//~^ use of unstable library feature 'core_pattern_type'
+//~^ use of unstable library feature `core_pattern_type`
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
index 03e91b52a2a..6cbadf370a7 100644
--- a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
@@ -1,4 +1,4 @@
-error[E0658]: use of unstable library feature 'core_pattern_type'
+error[E0658]: use of unstable library feature `core_pattern_type`
   --> $DIR/feature-gate-pattern_types.rs:5:19
    |
 LL | type NonNullU32 = pattern_type!(u32 is 1..);
@@ -8,7 +8,7 @@ LL | type NonNullU32 = pattern_type!(u32 is 1..);
    = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'core_pattern_type'
+error[E0658]: use of unstable library feature `core_pattern_type`
   --> $DIR/feature-gate-pattern_types.rs:7:16
    |
 LL | type Percent = pattern_type!(u32 is 0..=100);
@@ -18,7 +18,7 @@ LL | type Percent = pattern_type!(u32 is 0..=100);
    = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'core_pattern_type'
+error[E0658]: use of unstable library feature `core_pattern_type`
   --> $DIR/feature-gate-pattern_types.rs:9:17
    |
 LL | type Negative = pattern_type!(i32 is ..=0);
@@ -28,7 +28,7 @@ LL | type Negative = pattern_type!(i32 is ..=0);
    = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'core_pattern_type'
+error[E0658]: use of unstable library feature `core_pattern_type`
   --> $DIR/feature-gate-pattern_types.rs:11:17
    |
 LL | type Positive = pattern_type!(i32 is 0..);
@@ -38,7 +38,7 @@ LL | type Positive = pattern_type!(i32 is 0..);
    = help: add `#![feature(core_pattern_type)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: use of unstable library feature 'core_pattern_type'
+error[E0658]: use of unstable library feature `core_pattern_type`
   --> $DIR/feature-gate-pattern_types.rs:13:15
    |
 LL | type Always = pattern_type!(Option<u32> is Some(_));
diff --git a/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr
index 96ac481438f..b9bdf6f9a39 100644
--- a/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr
+++ b/tests/ui/typeck/issue-87872-missing-inaccessible-field-pattern.stderr
@@ -10,6 +10,10 @@ LL |     let foo::Foo { visible, .. } = foo::Foo::default();
    |                  ~~~~~~~~~~~~~~~
 help: if you don't care about this missing field, you can explicitly ignore it
    |
+LL |     let foo::Foo { visible: _, .. } = foo::Foo::default();
+   |                  ~~~~~~~~~~~~~~~~~~
+help: or always ignore missing fields here
+   |
 LL |     let foo::Foo { .. } = foo::Foo::default();
    |                  ~~~~~~
 
diff --git a/triagebot.toml b/triagebot.toml
index 7f4def6a11b..45b580787d1 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -611,6 +611,10 @@ cc = ["@bjorn3"]
 [mentions."compiler/rustc_codegen_gcc"]
 cc = ["@antoyo", "@GuillaumeGomez"]
 
+[mentions."compiler/rustc_const_eval/src/"]
+message = "Some changes occurred to the CTFE machinery"
+cc = ["@rust-lang/wg-const-eval"]
+
 [mentions."compiler/rustc_const_eval/src/interpret"]
 message = "Some changes occurred to the CTFE / Miri interpreter"
 cc = ["@rust-lang/miri"]
@@ -633,7 +637,7 @@ cc = ["@compiler-errors", "@lcnr"]
 
 [mentions."compiler/rustc_middle/src/mir/interpret"]
 message = "Some changes occurred to the CTFE / Miri interpreter"
-cc = ["@rust-lang/miri"]
+cc = ["@rust-lang/miri", "@rust-lang/wg-const-eval"]
 
 [mentions."compiler/rustc_mir_transform/src/"]
 message = "Some changes occurred to MIR optimizations"
@@ -706,7 +710,7 @@ message = """
 Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
 gets adapted for the changes, if necessary.
 """
-cc = ["@rust-lang/miri"]
+cc = ["@rust-lang/miri", "@rust-lang/wg-const-eval"]
 
 [mentions."library/portable-simd"]
 message = """