about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml3
-rw-r--r--Cargo.lock109
-rw-r--r--compiler/rustc_abi/src/layout.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs3
-rw-r--r--compiler/rustc_attr/src/builtin.rs3
-rw-r--r--compiler/rustc_borrowck/src/nll.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs23
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/src/pretty_clif.rs2
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs49
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs166
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs24
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs8
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs3
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs5
-rw-r--r--compiler/rustc_const_eval/src/util/type_name.rs3
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs16
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/tests.rs27
-rw-r--r--compiler/rustc_data_structures/src/owned_slice.rs43
-rw-r--r--compiler/rustc_data_structures/src/owned_slice/tests.rs12
-rw-r--r--compiler/rustc_data_structures/src/sync.rs6
-rw-r--r--compiler/rustc_data_structures/src/sync/worker_local.rs7
-rw-r--r--compiler/rustc_driver_impl/src/args.rs2
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs19
-rw-r--r--compiler/rustc_errors/src/emitter.rs35
-rw-r--r--compiler/rustc_errors/src/lib.rs15
-rw-r--r--compiler/rustc_expand/src/base.rs11
-rw-r--r--compiler/rustc_expand/src/expand.rs8
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs13
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs2
-rw-r--r--compiler/rustc_hir/src/errors.rs10
-rw-r--r--compiler/rustc_hir/src/lang_items.rs8
-rw-r--r--compiler/rustc_hir/src/lib.rs1
-rw-r--r--compiler/rustc_hir/src/tests.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs76
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs21
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl11
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs55
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs27
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs89
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs92
-rw-r--r--compiler/rustc_incremental/src/persist/file_format.rs35
-rw-r--r--compiler/rustc_incremental/src/persist/load.rs32
-rw-r--r--compiler/rustc_incremental/src/persist/save.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs28
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs13
-rw-r--r--compiler/rustc_interface/src/interface.rs7
-rw-r--r--compiler/rustc_interface/src/passes.rs6
-rw-r--r--compiler/rustc_interface/src/queries.rs2
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_interface/src/util.rs15
-rw-r--r--compiler/rustc_lint/messages.ftl8
-rw-r--r--compiler/rustc_lint/src/drop_forget_useless.rs26
-rw-r--r--compiler/rustc_lint/src/lints.rs10
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp57
-rw-r--r--compiler/rustc_macros/src/query.rs6
-rw-r--r--compiler/rustc_metadata/src/creader.rs12
-rw-r--r--compiler/rustc_metadata/src/locator.rs24
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs18
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs7
-rw-r--r--compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs22
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs8
-rw-r--r--compiler/rustc_middle/messages.ftl2
-rw-r--r--compiler/rustc_middle/src/error.rs10
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs16
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs7
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs2
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/middle/debugger_visualizer.rs38
-rw-r--r--compiler/rustc_middle/src/middle/lang_items.rs8
-rw-r--r--compiler/rustc_middle/src/middle/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs3
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs3
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs23
-rw-r--r--compiler/rustc_middle/src/query/erase.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs45
-rw-r--r--compiler/rustc_middle/src/query/plumbing.rs (renamed from compiler/rustc_middle/src/ty/query.rs)191
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs23
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs24
-rw-r--r--compiler/rustc_middle/src/ty/context.rs18
-rw-r--r--compiler/rustc_middle/src/ty/context/tls.rs4
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs11
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs45
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs24
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs12
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs101
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs27
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs27
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs3
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs11
-rw-r--r--compiler/rustc_mir_transform/src/dump_mir.rs2
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs42
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs13
-rw-r--r--compiler/rustc_mir_transform/src/pass_manager.rs8
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs2
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs3
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/mod.rs30
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs2
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs1
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs3
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs2
-rw-r--r--compiler/rustc_passes/src/check_attr.rs53
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs124
-rw-r--r--compiler/rustc_query_impl/src/lib.rs12
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs365
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs6
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs26
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs18
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs19
-rw-r--r--compiler/rustc_resolve/src/ident.rs8
-rw-r--r--compiler/rustc_resolve/src/imports.rs15
-rw-r--r--compiler/rustc_resolve/src/late.rs20
-rw-r--r--compiler/rustc_resolve/src/lib.rs13
-rw-r--r--compiler/rustc_session/src/config.rs63
-rw-r--r--compiler/rustc_session/src/cstore.rs7
-rw-r--r--compiler/rustc_session/src/options.rs6
-rw-r--r--compiler/rustc_session/src/parse.rs4
-rw-r--r--compiler/rustc_session/src/session.rs35
-rw-r--r--compiler/rustc_span/src/def_id.rs9
-rw-r--r--compiler/rustc_span/src/lib.rs23
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/legacy.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs74
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs277
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs43
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs7
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs55
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs35
-rw-r--r--library/alloc/src/string.rs9
-rw-r--r--library/alloc/src/sync.rs25
-rw-r--r--library/alloc/src/vec/in_place_collect.rs9
-rw-r--r--library/core/benches/iter.rs46
-rw-r--r--library/core/src/ascii.rs2
-rw-r--r--library/core/src/cell.rs21
-rw-r--r--library/core/src/char/methods.rs24
-rw-r--r--library/core/src/char/mod.rs23
-rw-r--r--library/core/src/escape.rs65
-rw-r--r--library/core/src/ffi/c_str.rs5
-rw-r--r--library/core/src/fmt/float.rs12
-rw-r--r--library/core/src/fmt/mod.rs42
-rw-r--r--library/core/src/fmt/num.rs15
-rw-r--r--library/core/src/future/join.rs6
-rw-r--r--library/core/src/iter/adapters/filter.rs55
-rw-r--r--library/core/src/iter/adapters/filter_map.rs62
-rw-r--r--library/core/src/iter/traits/collect.rs10
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/marker.rs36
-rw-r--r--library/core/src/mem/mod.rs2
-rw-r--r--library/core/src/panic.rs24
-rw-r--r--library/core/src/pin.rs2
-rw-r--r--library/core/src/ptr/mod.rs16
-rw-r--r--library/core/src/slice/mod.rs12
-rw-r--r--library/core/src/slice/sort.rs38
-rw-r--r--library/core/src/task/mod.rs2
-rw-r--r--library/core/src/task/poll.rs33
-rw-r--r--library/core/src/task/ready.rs57
-rw-r--r--library/core/tests/mem.rs20
-rw-r--r--library/std/src/fs.rs11
-rw-r--r--library/std/src/fs/tests.rs54
-rw-r--r--library/std/src/net/tcp.rs9
-rw-r--r--library/std/src/net/udp.rs9
-rw-r--r--library/std/src/os/ios/fs.rs22
-rw-r--r--library/std/src/os/macos/fs.rs22
-rw-r--r--library/std/src/os/watchos/fs.rs22
-rw-r--r--library/std/src/os/windows/fs.rs19
-rw-r--r--library/std/src/panic.rs4
-rw-r--r--library/std/src/path.rs11
-rw-r--r--library/std/src/sys/unix/fs.rs52
-rw-r--r--library/std/src/sys/windows/fs.rs22
-rw-r--r--library/std/src/sys_common/backtrace.rs11
-rw-r--r--src/bootstrap/Cargo.lock20
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/bootstrap.py2
-rw-r--r--src/bootstrap/builder.rs1
-rw-r--r--src/bootstrap/builder/tests.rs16
-rw-r--r--src/bootstrap/config.rs150
-rw-r--r--src/bootstrap/config/tests.rs77
-rw-r--r--src/bootstrap/download.rs2
-rw-r--r--src/bootstrap/flags.rs5
-rw-r--r--src/bootstrap/lib.rs33
-rw-r--r--src/bootstrap/llvm.rs1
-rw-r--r--src/bootstrap/render_tests.rs9
-rw-r--r--src/bootstrap/test.rs2
-rw-r--r--src/ci/docker/README.md16
-rw-r--r--src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile30
-rw-r--r--src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig14
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rw-r--r--src/ci/docker/scripts/cross-apt-packages.sh1
-rw-r--r--src/ci/docker/scripts/crosstool-ng-git.sh17
-rw-r--r--src/ci/github-actions/ci.yml3
-rw-r--r--src/ci/stage-build.py92
m---------src/doc/embedded-book0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/exploit-mitigations.md17
-rw-r--r--src/doc/rustc/src/images/image3.pngbin72412 -> 19069 bytes
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustc/src/platform-support/loongarch-linux.md2
-rw-r--r--src/etc/completions/x.py.fish17
-rw-r--r--src/etc/completions/x.py.ps117
-rw-r--r--src/etc/completions/x.py.sh90
-rw-r--r--src/librustdoc/html/markdown.rs14
-rw-r--r--src/librustdoc/html/render/mod.rs2
-rw-r--r--src/librustdoc/html/static/css/settings.css9
-rw-r--r--src/librustdoc/lib.rs8
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs27
m---------src/llvm-project0
-rw-r--r--src/rustdoc-json-types/Cargo.toml1
-rw-r--r--src/rustdoc-json-types/lib.rs6
-rw-r--r--src/rustdoc-json-types/tests.rs16
-rw-r--r--src/tools/build-manifest/src/main.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/.github/workflows/clippy.yml2
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml10
-rw-r--r--src/tools/clippy/.github/workflows/clippy_dev.yml2
-rw-r--r--src/tools/clippy/.github/workflows/deploy.yml4
-rw-r--r--src/tools/clippy/.github/workflows/remark.yml4
-rw-r--r--src/tools/clippy/CHANGELOG.md4
-rw-r--r--src/tools/clippy/README.md2
-rw-r--r--src/tools/clippy/book/src/development/type_checking.md6
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs144
-rw-r--r--src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/dbg_macro.rs57
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/fn_null_check.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs61
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs224
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/needless_collect.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/repeat_once.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_bool.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/bit_mask.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/float_cmp.rs57
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/ref_patterns.rs44
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs59
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs111
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs140
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs110
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs206
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs50
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs52
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.rs1
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.stderr8
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs8
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.fixed15
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.rs15
-rw-r--r--src/tools/clippy/tests/ui/borrow_deref_ref.stderr6
-rw-r--r--src/tools/clippy/tests/ui/box_default.fixed7
-rw-r--r--src/tools/clippy/tests/ui/box_default.rs7
-rw-r--r--src/tools/clippy/tests/ui/box_default.stderr8
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.fixed7
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.rs7
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.stderr18
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.rs27
-rw-r--r--src/tools/clippy/tests/ui/dbg_macro.stderr82
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed18
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.rs18
-rw-r--r--src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr10
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs132
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr36
-rw-r--r--src/tools/clippy/tests/ui/float_arithmetic.rs2
-rw-r--r--src/tools/clippy/tests/ui/integer_arithmetic.rs109
-rw-r--r--src/tools/clippy/tests/ui/integer_arithmetic.stderr169
-rw-r--r--src/tools/clippy/tests/ui/issue-111399.rs13
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.rs15
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.stderr20
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.rs15
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.stderr82
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.stderr4
-rw-r--r--src/tools/clippy/tests/ui/manual_next_back.fixed36
-rw-r--r--src/tools/clippy/tests/ui/manual_next_back.rs36
-rw-r--r--src/tools/clippy/tests/ui/manual_next_back.stderr16
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr8
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms.rs82
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.rs6
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.stderr17
-rw-r--r--src/tools/clippy/tests/ui/mem_forget.rs2
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.fixed7
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.rs7
-rw-r--r--src/tools/clippy/tests/ui/needless_bool/fixable.stderr24
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.fixed12
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.rs12
-rw-r--r--src/tools/clippy/tests/ui/needless_collect.stderr26
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed5
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs5
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr26
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg.fixed17
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg.rs17
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg.stderr28
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg2.rs6
-rw-r--r--src/tools/clippy/tests/ui/non_minimal_cfg2.stderr10
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed10
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs10
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr39
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.fixed1
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.rs1
-rw-r--r--src/tools/clippy/tests/ui/partialeq_to_none.stderr30
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed19
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs31
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr60
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed26
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs38
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr62
-rw-r--r--src/tools/clippy/tests/ui/ref_patterns.rs19
-rw-r--r--src/tools/clippy/tests/ui/ref_patterns.stderr27
-rw-r--r--src/tools/clippy/tests/ui/regex.rs2
-rw-r--r--src/tools/clippy/tests/ui/regex.stderr40
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed18
-rw-r--r--src/tools/clippy/tests/ui/rename.rs10
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr118
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed10
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs10
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr24
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.fixed6
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.rs6
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.stderr32
-rw-r--r--src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs19
-rw-r--r--src/tools/clippy/triagebot.toml2
-rw-r--r--src/tools/compiletest/Cargo.toml1
-rw-r--r--src/tools/compiletest/src/runtest.rs7
-rw-r--r--src/tools/miri/Cargo.lock29
-rw-r--r--src/tools/miri/Cargo.toml1
-rw-r--r--src/tools/miri/cargo-miri/src/arg.rs8
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs52
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/concurrency/thread.rs17
-rw-r--r--src/tools/miri/src/machine.rs9
-rw-r--r--src/tools/miri/src/shims/backtrace.rs2
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs8
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs13
-rw-r--r--src/tools/miri/src/shims/mod.rs2
-rw-r--r--src/tools/miri/src/shims/time.rs2
-rw-r--r--src/tools/miri/src/shims/tls.rs2
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs2
-rw-r--r--src/tools/miri/src/shims/unix/linux/sync.rs2
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs2
-rw-r--r--src/tools/miri/src/shims/windows/handle.rs8
-rwxr-xr-xsrc/tools/miri/test-cargo-miri/run-test.py3
-rw-r--r--src/tools/miri/tests/fail/never_say_never.rs6
-rw-r--r--src/tools/miri/tests/fail/never_say_never.stderr4
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs2
-rw-r--r--src/tools/miri/tests/fail/uninit_buffer.rs2
-rw-r--r--src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs2
-rw-r--r--src/tools/miri/tests/pass/portable-simd.rs33
-rw-r--r--src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs2
-rw-r--r--src/tools/replace-version-placeholder/src/main.rs6
-rw-r--r--src/tools/tidy/src/deps.rs2
-rw-r--r--src/tools/tidy/src/ui_tests.rs1
-rw-r--r--tests/assembly/option-nonzero-eq.rs28
-rw-r--r--tests/codegen/drop-in-place-noalias.rs38
-rw-r--r--tests/codegen/issues/issue-111603.rs28
-rw-r--r--tests/codegen/noalias-box-off.rs5
-rw-r--r--tests/codegen/option-nonzero-eq.rs12
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs26
-rw-r--r--tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs112
-rw-r--r--tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs109
-rw-r--r--tests/codegen/tied-features-strength.rs29
-rw-r--r--tests/incremental/const-generic-type-cycle.rs17
-rw-r--r--tests/mir-opt/building/enum_cast.bar.built.after.mir9
-rw-r--r--tests/mir-opt/building/enum_cast.boo.built.after.mir9
-rw-r--r--tests/mir-opt/building/enum_cast.droppy.built.after.mir9
-rw-r--r--tests/mir-opt/building/enum_cast.far.built.after.mir22
-rw-r--r--tests/mir-opt/building/enum_cast.offsetty.built.after.mir26
-rw-r--r--tests/mir-opt/building/enum_cast.rs42
-rw-r--r--tests/mir-opt/building/enum_cast.signy.built.after.mir26
-rw-r--r--tests/mir-opt/building/enum_cast.unsigny.built.after.mir17
-rw-r--r--tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff166
-rw-r--r--tests/mir-opt/combine_transmutes.rs22
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff14
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff14
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff17
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff17
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff22
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff22
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff14
-rw-r--r--tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff14
-rw-r--r--tests/mir-opt/inline/unsized_argument.caller.Inline.diff50
-rw-r--r--tests/mir-opt/inline/unsized_argument.rs15
-rw-r--r--tests/mir-opt/issue_72181_1.f.built.after.mir14
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff14
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff14
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff14
-rw-r--r--tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff11
-rw-r--r--tests/run-make-fulldeps/obtain-borrowck/driver.rs4
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/Makefile6
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/main.rs4
-rw-r--r--tests/run-make/CURRENT_RUSTC_VERSION/stable.rs5
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/Makefile9
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/foo.py1
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/main.rs12
-rw-r--r--tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis1
-rw-r--r--tests/run-make/incremental-debugger-visualizer/Makefile49
-rw-r--r--tests/run-make/incremental-debugger-visualizer/foo.rs6
-rw-r--r--tests/run-make/issue-83045/Makefile2
-rw-r--r--tests/run-make/print-native-static-libs/Makefile15
-rw-r--r--tests/run-make/print-native-static-libs/bar.rs13
-rw-r--r--tests/run-make/print-native-static-libs/foo.rs15
-rw-r--r--tests/run-make/short-ice/Makefile9
-rw-r--r--tests/run-make/short-ice/check.sh36
-rw-r--r--tests/run-make/short-ice/src/lib.rs7
-rw-r--r--tests/rustdoc-gui/anchors.goml36
-rw-r--r--tests/rustdoc-gui/codeblock-tooltip.goml18
-rw-r--r--tests/rustdoc-gui/jump-to-def-background.goml6
-rw-r--r--tests/rustdoc-gui/scrape-examples-color.goml42
-rw-r--r--tests/rustdoc-gui/settings.goml4
-rw-r--r--tests/rustdoc-gui/source-code-page.goml22
-rw-r--r--tests/rustdoc-json/assoc_items.rs27
-rw-r--r--tests/rustdoc-json/blanket_impls.rs6
-rw-r--r--tests/rustdoc-json/enums/discriminant/basic.rs12
-rw-r--r--tests/rustdoc-json/enums/discriminant/expr.rs36
-rw-r--r--tests/rustdoc-json/enums/discriminant/limits.rs32
-rw-r--r--tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs18
-rw-r--r--tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs10
-rw-r--r--tests/rustdoc-json/enums/discriminant/struct.rs12
-rw-r--r--tests/rustdoc-json/enums/discriminant/tuple.rs12
-rw-r--r--tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs2
-rw-r--r--tests/rustdoc-json/enums/field_hidden.rs4
-rw-r--r--tests/rustdoc-json/enums/kind.rs28
-rw-r--r--tests/rustdoc-json/enums/struct_field_hidden.rs8
-rw-r--r--tests/rustdoc-json/enums/tuple_fields_hidden.rs80
-rw-r--r--tests/rustdoc-json/enums/use_glob.rs8
-rw-r--r--tests/rustdoc-json/enums/use_variant.rs8
-rw-r--r--tests/rustdoc-json/enums/use_variant_foreign.rs2
-rw-r--r--tests/rustdoc-json/enums/variant_struct.rs8
-rw-r--r--tests/rustdoc-json/enums/variant_tuple_struct.rs8
-rw-r--r--tests/rustdoc-json/fn_pointer/abi.rs14
-rw-r--r--tests/rustdoc-json/fn_pointer/generics.rs15
-rw-r--r--tests/rustdoc-json/fn_pointer/qualifiers.rs14
-rw-r--r--tests/rustdoc-json/fns/abi.rs14
-rw-r--r--tests/rustdoc-json/fns/async_return.rs26
-rw-r--r--tests/rustdoc-json/fns/extern_c_variadic.rs4
-rw-r--r--tests/rustdoc-json/fns/generic_args.rs88
-rw-r--r--tests/rustdoc-json/fns/generic_returns.rs9
-rw-r--r--tests/rustdoc-json/fns/generics.rs29
-rw-r--r--tests/rustdoc-json/fns/pattern_arg.rs4
-rw-r--r--tests/rustdoc-json/fns/qualifiers.rs36
-rw-r--r--tests/rustdoc-json/fns/return_type_alias.rs3
-rw-r--r--tests/rustdoc-json/generic-associated-types/gats.rs36
-rw-r--r--tests/rustdoc-json/glob_import.rs2
-rw-r--r--tests/rustdoc-json/impls/auto.rs3
-rw-r--r--tests/rustdoc-json/impls/foreign_for_local.rs8
-rw-r--r--tests/rustdoc-json/impls/impl_item_visibility.rs26
-rw-r--r--tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs28
-rw-r--r--tests/rustdoc-json/impls/impl_item_visibility_show_private.rs27
-rw-r--r--tests/rustdoc-json/impls/import_from_private.rs16
-rw-r--r--tests/rustdoc-json/impls/local_for_foreign.rs8
-rw-r--r--tests/rustdoc-json/impls/local_for_local.rs8
-rw-r--r--tests/rustdoc-json/impls/local_for_local_primitive.rs7
-rw-r--r--tests/rustdoc-json/impls/local_for_primitive.rs2
-rw-r--r--tests/rustdoc-json/lifetime/longest.rs37
-rw-r--r--tests/rustdoc-json/lifetime/outlives.rs32
-rw-r--r--tests/rustdoc-json/methods/abi.rs28
-rw-r--r--tests/rustdoc-json/methods/qualifiers.rs36
-rw-r--r--tests/rustdoc-json/nested.rs31
-rw-r--r--tests/rustdoc-json/non_lifetime_binders.rs10
-rw-r--r--tests/rustdoc-json/primitives/local_primitive.rs2
-rw-r--r--tests/rustdoc-json/primitives/primitive_impls.rs6
-rw-r--r--tests/rustdoc-json/primitives/primitive_type.rs15
-rw-r--r--tests/rustdoc-json/primitives/use_primitive.rs4
-rw-r--r--tests/rustdoc-json/reexport/doc_inline_external_crate.rs5
-rw-r--r--tests/rustdoc-json/reexport/export_extern_crate_as_self.rs2
-rw-r--r--tests/rustdoc-json/reexport/extern_crate_glob.rs5
-rw-r--r--tests/rustdoc-json/reexport/glob_collision.rs28
-rw-r--r--tests/rustdoc-json/reexport/glob_empty_mod.rs4
-rw-r--r--tests/rustdoc-json/reexport/glob_extern.rs13
-rw-r--r--tests/rustdoc-json/reexport/glob_private.rs20
-rw-r--r--tests/rustdoc-json/reexport/in_root_and_mod.rs4
-rw-r--r--tests/rustdoc-json/reexport/in_root_and_mod_pub.rs16
-rw-r--r--tests/rustdoc-json/reexport/macro.rs5
-rw-r--r--tests/rustdoc-json/reexport/mod_not_included.rs4
-rw-r--r--tests/rustdoc-json/reexport/private_twice_one_inline.rs10
-rw-r--r--tests/rustdoc-json/reexport/private_two_names.rs16
-rw-r--r--tests/rustdoc-json/reexport/reexport_method_from_private_module.rs4
-rw-r--r--tests/rustdoc-json/reexport/rename_private.rs4
-rw-r--r--tests/rustdoc-json/reexport/rename_public.rs11
-rw-r--r--tests/rustdoc-json/reexport/same_name_different_types.rs8
-rw-r--r--tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs12
-rw-r--r--tests/rustdoc-json/reexport/simple_private.rs8
-rw-r--r--tests/rustdoc-json/reexport/simple_public.rs9
-rw-r--r--tests/rustdoc-json/return_private.rs4
-rw-r--r--tests/rustdoc-json/structs/plain_all_pub.rs8
-rw-r--r--tests/rustdoc-json/structs/plain_doc_hidden.rs6
-rw-r--r--tests/rustdoc-json/structs/plain_empty.rs6
-rw-r--r--tests/rustdoc-json/structs/plain_pub_priv.rs6
-rw-r--r--tests/rustdoc-json/structs/tuple.rs4
-rw-r--r--tests/rustdoc-json/structs/tuple_empty.rs2
-rw-r--r--tests/rustdoc-json/structs/tuple_pub_priv.rs8
-rw-r--r--tests/rustdoc-json/structs/unit.rs4
-rw-r--r--tests/rustdoc-json/structs/with_generics.rs14
-rw-r--r--tests/rustdoc-json/structs/with_primitives.rs12
-rw-r--r--tests/rustdoc-json/traits/has_body.rs14
-rw-r--r--tests/rustdoc-json/traits/implementors.rs10
-rw-r--r--tests/rustdoc-json/traits/supertrait.rs16
-rw-r--r--tests/rustdoc-json/traits/trait_alias.rs18
-rw-r--r--tests/rustdoc-json/type/dyn.rs68
-rw-r--r--tests/rustdoc-json/type/extern.rs3
-rw-r--r--tests/rustdoc-json/type/fn_lifetime.rs39
-rw-r--r--tests/rustdoc-json/type/generic_default.rs42
-rw-r--r--tests/rustdoc-json/type/hrtb.rs18
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type.rs13
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_bound.rs14
-rw-r--r--tests/rustdoc-json/type/inherent_associated_type_projections.rs13
-rw-r--r--tests/rustdoc-json/unions/impl.rs6
-rw-r--r--tests/rustdoc-json/unions/union.rs8
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs10
-rw-r--r--tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr21
-rw-r--r--tests/rustdoc/strikethrough-in-summary.rs6
-rw-r--r--tests/ui/associated-inherent-types/inference.rs2
-rw-r--r--tests/ui/associated-inherent-types/issue-111879-0.rs14
-rw-r--r--tests/ui/associated-inherent-types/issue-111879-0.stderr8
-rw-r--r--tests/ui/associated-inherent-types/issue-111879-1.rs12
-rw-r--r--tests/ui/associated-inherent-types/issue-111879-1.stderr12
-rw-r--r--tests/ui/async-await/return-type-notation/supertrait-bound.rs11
-rw-r--r--tests/ui/async-await/return-type-notation/supertrait-bound.stderr11
-rw-r--r--tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs2
-rw-r--r--tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs2
-rw-r--r--tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs2
-rw-r--r--tests/ui/cfg/cfg-stmt-recovery.rs13
-rw-r--r--tests/ui/cfg/cfg-stmt-recovery.stderr20
-rw-r--r--tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs2
-rw-r--r--tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs2
-rw-r--r--tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs2
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_good.rs10
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr13
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs4
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr12
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs33
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr8
-rw-r--r--tests/ui/consts/const_forget.rs2
-rw-r--r--tests/ui/consts/issue-104155.rs2
-rw-r--r--tests/ui/crate-leading-sep.rs2
-rw-r--r--tests/ui/drop/issue-110682.rs92
-rw-r--r--tests/ui/drop/repeat-drop.rs2
-rw-r--r--tests/ui/dyn-star/param-env-infer.current.stderr18
-rw-r--r--tests/ui/dyn-star/param-env-infer.next.stderr18
-rw-r--r--tests/ui/dyn-star/param-env-infer.rs16
-rw-r--r--tests/ui/error-codes/E0746.fixed18
-rw-r--r--tests/ui/error-codes/E0746.rs2
-rw-r--r--tests/ui/error-codes/E0746.stderr22
-rw-r--r--tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed2
-rw-r--r--tests/ui/explicit/explicit-call-to-supertrait-dtor.rs2
-rw-r--r--tests/ui/generator/drop-env.rs2
-rw-r--r--tests/ui/generator/issue-57017.rs2
-rw-r--r--tests/ui/generator/non-static-is-unpin.rs2
-rw-r--r--tests/ui/generator/resume-arg-size.rs2
-rw-r--r--tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs2
-rw-r--r--tests/ui/illegal-ufcs-drop.fixed2
-rw-r--r--tests/ui/illegal-ufcs-drop.rs2
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs2
-rw-r--r--tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr110
-rw-r--r--tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs4
-rw-r--r--tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr108
-rw-r--r--tests/ui/imports/issue-109148.rs15
-rw-r--r--tests/ui/imports/issue-109148.stderr13
-rw-r--r--tests/ui/imports/issue-109343.rs10
-rw-r--r--tests/ui/imports/issue-109343.stderr11
-rw-r--r--tests/ui/invalid/foo.natvis.xml1
-rw-r--r--tests/ui/invalid/invalid-debugger-visualizer-target.rs2
-rw-r--r--tests/ui/invalid/invalid-debugger-visualizer-target.stderr4
-rw-r--r--tests/ui/issues/issue-18107.stderr12
-rw-r--r--tests/ui/iterators/collect-into-slice.rs6
-rw-r--r--tests/ui/iterators/collect-into-slice.stderr12
-rw-r--r--tests/ui/lint/dropping_copy_types.rs (renamed from tests/ui/lint/drop_copy.rs)2
-rw-r--r--tests/ui/lint/dropping_copy_types.stderr (renamed from tests/ui/lint/drop_copy.stderr)28
-rw-r--r--tests/ui/lint/dropping_references.rs (renamed from tests/ui/lint/drop_ref.rs)2
-rw-r--r--tests/ui/lint/dropping_references.stderr (renamed from tests/ui/lint/drop_ref.stderr)30
-rw-r--r--tests/ui/lint/forgetting_copy_types.rs (renamed from tests/ui/lint/forget_copy.rs)2
-rw-r--r--tests/ui/lint/forgetting_copy_types.stderr (renamed from tests/ui/lint/forget_copy.stderr)24
-rw-r--r--tests/ui/lint/forgetting_references.rs (renamed from tests/ui/lint/forget_ref.rs)2
-rw-r--r--tests/ui/lint/forgetting_references.stderr (renamed from tests/ui/lint/forget_ref.stderr)24
-rw-r--r--tests/ui/lint/unused/auxiliary/must-use-foreign.rs12
-rw-r--r--tests/ui/lint/unused/must-use-foreign.rs15
-rw-r--r--tests/ui/lint/unused/unused-async.rs2
-rw-r--r--tests/ui/lint/unused/unused-async.stderr13
-rw-r--r--tests/ui/liveness/liveness-unused.rs2
-rw-r--r--tests/ui/macros/issue-111749.rs12
-rw-r--r--tests/ui/macros/issue-111749.stderr18
-rw-r--r--tests/ui/macros/panic-temporaries-2018.rs55
-rw-r--r--tests/ui/macros/panic-temporaries.rs32
-rw-r--r--tests/ui/macros/parse-complex-macro-invoc-op.rs2
-rw-r--r--tests/ui/never_type/never-assign-dead-code.rs2
-rw-r--r--tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs2
-rw-r--r--tests/ui/nll/ty-outlives/projection-body.rs2
-rw-r--r--tests/ui/offset-of/offset-of-arg-count.rs5
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.rs16
-rw-r--r--tests/ui/offset-of/offset-of-dst-field.stderr55
-rw-r--r--tests/ui/offset-of/offset-of-inference.rs11
-rw-r--r--tests/ui/offset-of/offset-of-inference.stderr9
-rw-r--r--tests/ui/offset-of/offset-of-output-type.rs20
-rw-r--r--tests/ui/offset-of/offset-of-output-type.stderr64
-rw-r--r--tests/ui/offset-of/offset-of-private.rs12
-rw-r--r--tests/ui/offset-of/offset-of-private.stderr43
-rw-r--r--tests/ui/offset-of/offset-of-self.rs58
-rw-r--r--tests/ui/offset-of/offset-of-self.stderr79
-rw-r--r--tests/ui/or-patterns/or-patterns-default-binding-modes.rs4
-rw-r--r--tests/ui/panics/default-backtrace-ice.stderr2
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames-2.rs61
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr11
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames.rs57
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames.run.stderr12
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs4
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs2
-rw-r--r--tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs2
-rw-r--r--tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs2
-rw-r--r--tests/ui/print_type_sizes/async.rs2
-rw-r--r--tests/ui/print_type_sizes/generator_discr_placement.rs2
-rw-r--r--tests/ui/regions/type-param-outlives-reempty-issue-74429.rs2
-rw-r--r--tests/ui/resolve/issue-111312.rs11
-rw-r--r--tests/ui/resolve/issue-111312.stderr15
-rw-r--r--tests/ui/resolve/issue-111727.rs5
-rw-r--r--tests/ui/resolve/issue-111727.stderr9
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs2
-rw-r--r--tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs2
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.fixed2
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.rs2
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.rs16
-rw-r--r--tests/ui/self/arbitrary-self-from-method-substs.stderr9
-rw-r--r--tests/ui/self/self-ctor-inner-const.rs17
-rw-r--r--tests/ui/self/self-ctor-inner-const.stderr33
-rw-r--r--tests/ui/self/self-ctor-nongeneric.rs15
-rw-r--r--tests/ui/statics/issue-91050-1.rs2
-rw-r--r--tests/ui/suggestions/issue-109854.rs12
-rw-r--r--tests/ui/suggestions/issue-109854.stderr31
-rw-r--r--tests/ui/suggestions/issue-94171.rs5
-rw-r--r--tests/ui/suggestions/issue-94171.stderr36
-rw-r--r--tests/ui/traits/copy-guessing.rs5
-rw-r--r--tests/ui/traits/copy-guessing.stderr14
-rw-r--r--tests/ui/traits/cycle-cache-err-60010.stderr18
-rw-r--r--tests/ui/traits/impl-evaluation-order.rs2
-rw-r--r--tests/ui/traits/issue-106072.rs1
-rw-r--r--tests/ui/traits/issue-106072.stderr12
-rw-r--r--tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs2
-rw-r--r--tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs25
-rw-r--r--tests/ui/traits/new-solver/structural-resolve-field.rs13
-rw-r--r--tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs34
-rw-r--r--tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr24
-rw-r--r--tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs15
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs15
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr11
-rw-r--r--tests/ui/underscore-imports/issue-110164.rs19
-rw-r--r--tests/ui/underscore-imports/issue-110164.stderr71
-rw-r--r--tests/ui/unsized-locals/issue-67981.rs9
-rw-r--r--tests/ui/unsized-locals/issue-67981.stderr15
-rw-r--r--tests/ui/unsized/box-instead-of-dyn-fn.rs1
-rw-r--r--tests/ui/unsized/box-instead-of-dyn-fn.stderr43
-rw-r--r--tests/ui/unsized/issue-91801.stderr7
-rw-r--r--tests/ui/unsized/issue-91803.stderr9
-rw-r--r--tests/ui/use/use-self-type.stderr2
-rw-r--r--triagebot.toml27
750 files changed, 9666 insertions, 4858 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2d8980fcd1a..b12a0b855e2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -201,6 +201,9 @@ jobs:
           - name: dist-i686-linux
             os: ubuntu-20.04-8core-32gb
             env: {}
+          - name: dist-loongarch64-linux
+            os: ubuntu-20.04-8core-32gb
+            env: {}
           - name: dist-mips-linux
             os: ubuntu-20.04-8core-32gb
             env: {}
diff --git a/Cargo.lock b/Cargo.lock
index be95e63eb76..d5840513083 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -154,11 +154,11 @@ checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
 
 [[package]]
 name = "ar_archive_writer"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0639441fd17a3197d1cbca8dc8768cc172a63b64b4bb6c372e8f41ed0acc9bb"
+checksum = "74cfb39880a59e122232cb5fb06b20b4382d58c12fa9747d16f846d38a7b094c"
 dependencies = [
- "object",
+ "object 0.31.1",
 ]
 
 [[package]]
@@ -233,7 +233,7 @@ dependencies = [
  "cfg-if",
  "libc",
  "miniz_oxide",
- "object",
+ "object 0.30.1",
  "rustc-demangle",
 ]
 
@@ -247,6 +247,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "bincode"
+version = "1.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+dependencies = [
+ "serde",
+]
+
+[[package]]
 name = "bitflags"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -332,6 +341,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
 name = "bytes"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -629,7 +644,7 @@ dependencies = [
  "itertools",
  "pulldown-cmark",
  "quine-mc_cluskey",
- "regex-syntax",
+ "regex-syntax 0.7.1",
  "rustc-semver",
  "semver",
  "serde",
@@ -723,6 +738,7 @@ dependencies = [
 name = "compiletest"
 version = "0.0.0"
 dependencies = [
+ "anyhow",
  "build_helper",
  "colored",
  "diff",
@@ -888,6 +904,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "ctrlc"
+version = "3.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7394a21d012ce5c850497fb774b167d81b99f060025fbf06ee92b9848bd97eb2"
+dependencies = [
+ "nix",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "curl"
 version = "0.4.44"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2288,6 +2314,7 @@ name = "miri"
 version = "0.1.0"
 dependencies = [
  "colored",
+ "ctrlc",
  "env_logger 0.9.0",
  "getrandom",
  "lazy_static",
@@ -2318,6 +2345,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
 
 [[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "static_assertions",
+]
+
+[[package]]
 name = "nom"
 version = "7.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2364,13 +2403,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a"
 dependencies = [
  "compiler_builtins",
+ "memchr",
+ "rustc-std-workspace-alloc",
+ "rustc-std-workspace-core",
+]
+
+[[package]]
+name = "object"
+version = "0.31.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
+dependencies = [
  "crc32fast",
  "flate2",
  "hashbrown 0.13.1",
  "indexmap",
  "memchr",
- "rustc-std-workspace-alloc",
- "rustc-std-workspace-core",
+ "ruzstd",
 ]
 
 [[package]]
@@ -2695,9 +2744,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.53"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
 dependencies = [
  "unicode-ident",
 ]
@@ -2865,7 +2914,7 @@ checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-syntax",
+ "regex-syntax 0.6.26",
 ]
 
 [[package]]
@@ -2874,7 +2923,7 @@ version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
 dependencies = [
- "regex-syntax",
+ "regex-syntax 0.6.26",
 ]
 
 [[package]]
@@ -2893,6 +2942,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
 
 [[package]]
+name = "regex-syntax"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
+
+[[package]]
 name = "remote-test-client"
 version = "0.1.0"
 
@@ -3222,7 +3277,7 @@ dependencies = [
  "cstr",
  "libc",
  "measureme",
- "object",
+ "object 0.31.1",
  "rustc-demangle",
  "rustc_ast",
  "rustc_attr",
@@ -3258,7 +3313,7 @@ dependencies = [
  "itertools",
  "jobserver",
  "libc",
- "object",
+ "object 0.31.1",
  "pathdiff",
  "regex",
  "rustc_arena",
@@ -4328,6 +4383,7 @@ dependencies = [
 name = "rustdoc-json-types"
 version = "0.1.0"
 dependencies = [
+ "bincode",
  "rustc-hash",
  "serde",
  "serde_json",
@@ -4418,6 +4474,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
 
 [[package]]
+name = "ruzstd"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a15e661f0f9dac21f3494fe5d23a6338c0ac116a2d22c2b63010acd89467ffe"
+dependencies = [
+ "byteorder",
+ "thiserror",
+ "twox-hash",
+]
+
+[[package]]
 name = "ryu"
 version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4477,18 +4544,18 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.159"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.159"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4653,7 +4720,7 @@ dependencies = [
  "hermit-abi 0.3.0",
  "libc",
  "miniz_oxide",
- "object",
+ "object 0.30.1",
  "panic_abort",
  "panic_unwind",
  "profiler_builtins",
@@ -4925,13 +4992,13 @@ dependencies = [
 
 [[package]]
 name = "thorin-dwp"
-version = "0.4.0"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da8fbf660a019b6bf11ea95762041464aa9099cc293b6a66d77cea5107619671"
+checksum = "98c040e1340b889d4180c64e1d787efa9c32cb1617757e101480b61238b0d927"
 dependencies = [
  "gimli 0.26.2",
  "hashbrown 0.12.3",
- "object",
+ "object 0.31.1",
  "tracing",
 ]
 
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 3d97d9b4895..f11c1c77f9c 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -12,7 +12,7 @@ use tracing::debug;
 pub trait LayoutCalculator {
     type TargetDataLayoutRef: Borrow<TargetDataLayout>;
 
-    fn delay_bug(&self, txt: &str);
+    fn delay_bug(&self, txt: String);
     fn current_data_layout(&self) -> Self::TargetDataLayoutRef;
 
     fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS {
@@ -969,7 +969,7 @@ fn univariant(
     for &i in &inverse_memory_index {
         let field = &fields[i];
         if !sized {
-            this.delay_bug(&format!(
+            this.delay_bug(format!(
                 "univariant: field #{} comes after unsized field",
                 offsets.len(),
             ));
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index cd6614a54a4..211f5cb0a2a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -58,7 +58,7 @@ use rustc_errors::{
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::{ConstArg, GenericArg, ItemLocalId, ParamName, TraitCandidate};
 use rustc_index::{Idx, IndexSlice, IndexVec};
@@ -435,6 +435,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> {
     // Queries that borrow `resolver_for_lowering`.
     tcx.ensure_with_value().output_filenames(());
     tcx.ensure_with_value().early_lint_checks(());
+    tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE);
     let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal();
 
     let ast_index = index_crate(&resolver.node_id_to_def_id, &krate);
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 2a3092d3c7b..372a58857f3 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -23,8 +23,7 @@ use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
 pub const VERSION_PLACEHOLDER: &str = "CURRENT_RUSTC_VERSION";
 
 pub fn rust_version_symbol() -> Symbol {
-    let version = option_env!("CFG_VERSION").unwrap_or("<current>");
-    let version = version.split(' ').next().unwrap();
+    let version = option_env!("CFG_RELEASE").unwrap_or("<current>");
     Symbol::intern(&version)
 }
 
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index a4394ddc01c..b6ccf924a5c 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -430,7 +430,7 @@ pub(super) fn dump_annotation<'tcx>(
 fn for_each_region_constraint<'tcx>(
     tcx: TyCtxt<'tcx>,
     closure_region_requirements: &ClosureRegionRequirements<'tcx>,
-    with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
+    with_msg: &mut dyn FnMut(String) -> io::Result<()>,
 ) -> io::Result<()> {
     for req in &closure_region_requirements.outlives_requirements {
         let subject = match req.subject {
@@ -439,7 +439,7 @@ fn for_each_region_constraint<'tcx>(
                 format!("{:?}", ty.instantiate(tcx, |vid| tcx.mk_re_var(vid)))
             }
         };
-        with_msg(&format!("where {}: {:?}", subject, req.outlived_free_region,))?;
+        with_msg(format!("where {}: {:?}", subject, req.outlived_free_region,))?;
     }
     Ok(())
 }
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 309f23d9226..e9b5c47ce23 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -152,8 +152,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                     let guar = ty.error_reported().err().unwrap_or_else(|| {
                         prev.report_mismatch(
                             &OpaqueHiddenType { ty, span: concrete_type.span },
+                            opaque_type_key.def_id,
                             infcx.tcx,
                         )
+                        .emit()
                     });
                     prev.ty = infcx.tcx.ty_error(guar);
                 }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 33b24b68f7c..fa4bc926f27 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -71,7 +71,7 @@ macro_rules! span_mirbug {
         $crate::type_check::mirbug(
             $context.tcx(),
             $context.last_span,
-            &format!(
+            format!(
                 "broken MIR in {:?} ({:?}): {}",
                 $context.body().source.def_id(),
                 $elem,
@@ -274,7 +274,7 @@ fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
 }
 
 #[track_caller]
-fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: &str) {
+fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
     // We sometimes see MIR failures (notably predicate failures) due to
     // the fact that we check rvalue sized predicates here. So use `delay_span_bug`
     // to avoid reporting bugs in those cases.
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index bb059a120df..5217e317adf 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -550,7 +550,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
         if !parser.errors.is_empty() {
             let err = parser.errors.remove(0);
             let err_sp = template_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
-            let msg = &format!("invalid asm template string: {}", err.description);
+            let msg = format!("invalid asm template string: {}", err.description);
             let mut e = ecx.struct_span_err(err_sp, msg);
             e.span_label(err_sp, err.label + " in asm template string");
             if let Some(note) = err.note {
@@ -585,7 +585,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
                                 || args.reg_args.contains(idx)
                             {
                                 let msg = format!("invalid reference to argument at index {}", idx);
-                                let mut err = ecx.struct_span_err(span, &msg);
+                                let mut err = ecx.struct_span_err(span, msg);
                                 err.span_label(span, "from here");
 
                                 let positional_args = args.operands.len()
@@ -638,7 +638,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
                                     ecx.struct_span_err(
                                         template_span
                                             .from_inner(InnerSpan::new(span.start, span.end)),
-                                        &msg,
+                                        msg,
                                     )
                                     .emit();
                                     None
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 750f1fe121f..ed91cea4ae2 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -166,7 +166,9 @@ impl CfgEval<'_, '_> {
                     ))
                 },
                 Annotatable::Stmt(_) => |parser| {
-                    Ok(Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes)?.unwrap())))
+                    Ok(Annotatable::Stmt(P(parser
+                        .parse_stmt_without_recovery(false, ForceCollect::Yes)?
+                        .unwrap())))
                 },
                 Annotatable::Expr(_) => {
                     |parser| Ok(Annotatable::Expr(parser.parse_expr_force_collect()?))
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 0481a118906..2c8e6f99c67 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -27,3 +27,26 @@ pub fn expand_deriving_copy(
 
     trait_def.expand(cx, mitem, item, push);
 }
+
+pub fn expand_deriving_const_param_ty(
+    cx: &mut ExtCtxt<'_>,
+    span: Span,
+    mitem: &MetaItem,
+    item: &Annotatable,
+    push: &mut dyn FnMut(Annotatable),
+    is_const: bool,
+) {
+    let trait_def = TraitDef {
+        span,
+        path: path_std!(marker::ConstParamTy),
+        skip_path_as_bound: false,
+        needs_copy_as_bound_if_packed: false,
+        additional_bounds: Vec::new(),
+        supports_unions: false,
+        methods: Vec::new(),
+        associated_types: Vec::new(),
+        is_const,
+    };
+
+    trait_def.expand(cx, mitem, item, push);
+}
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index dfee2d3ce77..9883563746e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -145,7 +145,7 @@ fn cs_clone_simple(
             }
             _ => cx.span_bug(
                 trait_span,
-                &format!("unexpected substructure in simple `derive({})`", name),
+                format!("unexpected substructure in simple `derive({})`", name),
             ),
         }
     }
@@ -179,10 +179,10 @@ fn cs_clone(
             vdata = &variant.data;
         }
         EnumTag(..) | AllFieldlessEnum(..) => {
-            cx.span_bug(trait_span, &format!("enum tags in `derive({})`", name,))
+            cx.span_bug(trait_span, format!("enum tags in `derive({})`", name,))
         }
         StaticEnum(..) | StaticStruct(..) => {
-            cx.span_bug(trait_span, &format!("associated function in `derive({})`", name))
+            cx.span_bug(trait_span, format!("associated function in `derive({})`", name))
         }
     }
 
@@ -194,7 +194,7 @@ fn cs_clone(
                     let Some(ident) = field.name else {
                         cx.span_bug(
                             trait_span,
-                            &format!("unnamed field in normal struct in `derive({})`", name,),
+                            format!("unnamed field in normal struct in `derive({})`", name,),
                         );
                     };
                     let call = subcall(cx, field);
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index caced3d6447..4ba09335cb7 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1591,7 +1591,7 @@ impl<'a> TraitDef<'a> {
                                 BYTE_SLICE_IN_PACKED_STRUCT_WITH_DERIVE,
                                 sp,
                                 ast::CRATE_NODE_ID,
-                                &format!(
+                                format!(
                                     "{} slice in a packed struct that derives a built-in trait",
                                     ty
                                 ),
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index adc12ec84f5..c59a733c055 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -814,7 +814,7 @@ fn report_invalid_references(
         };
         e = ecx.struct_span_err(
             span,
-            &format!("invalid reference to positional {} ({})", arg_list, num_args_desc),
+            format!("invalid reference to positional {} ({})", arg_list, num_args_desc),
         );
         e.note("positional arguments are zero-based");
     }
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 4e5edb4d6b1..ebf1448f55c 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -115,6 +115,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
     register_derive! {
         Clone: clone::expand_deriving_clone,
         Copy: bounds::expand_deriving_copy,
+        ConstParamTy: bounds::expand_deriving_const_param_ty,
         Debug: debug::expand_deriving_debug,
         Default: default::expand_deriving_default,
         Eq: eq::expand_deriving_eq,
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index b8a24f1102d..e613b904d2e 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -188,12 +188,12 @@ pub fn expand_include_str(
                 base::MacEager::expr(cx.expr_str(sp, interned_src))
             }
             Err(_) => {
-                cx.span_err(sp, &format!("{} wasn't a utf-8 file", file.display()));
+                cx.span_err(sp, format!("{} wasn't a utf-8 file", file.display()));
                 DummyResult::any(sp)
             }
         },
         Err(e) => {
-            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
+            cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
             DummyResult::any(sp)
         }
     }
@@ -221,7 +221,7 @@ pub fn expand_include_bytes(
             base::MacEager::expr(expr)
         }
         Err(e) => {
-            cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), e));
+            cx.span_err(sp, format!("couldn't read {}: {}", file.display(), e));
             DummyResult::any(sp)
         }
     }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index e9dbea1be67..25fd5ca3ae8 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -966,11 +966,7 @@ fn codegen_panic_inner<'tcx>(
     args: &[Value],
     span: Span,
 ) {
-    let def_id = fx
-        .tcx
-        .lang_items()
-        .require(lang_item)
-        .unwrap_or_else(|e| fx.tcx.sess.span_fatal(span, e.to_string()));
+    let def_id = fx.tcx.require_lang_item(lang_item, Some(span));
 
     let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
     let symbol_name = fx.tcx.symbol_name(instance).name;
diff --git a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
index 27e21183c55..1007b33eca4 100644
--- a/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
+++ b/compiler/rustc_codegen_cranelift/src/pretty_clif.rs
@@ -227,7 +227,7 @@ pub(crate) fn write_ir_file(
         // Using early_warn as no Session is available here
         rustc_session::early_warn(
             rustc_session::config::ErrorOutputType::default(),
-            &format!("error writing ir file: {}", err),
+            format!("error writing ir file: {}", err),
         );
     }
 }
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 5e750d91b82..ad51f2d0958 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -11,7 +11,7 @@ bitflags = "1.0"
 cstr = "0.2"
 libc = "0.2"
 measureme = "10.0.0"
-object = { version = "0.30.1", default-features = false, features = [
+object = { version = "0.31.1", default-features = false, features = [
     "std",
     "read",
 ] }
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index d2e01708a37..604f68eb6a4 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -25,7 +25,6 @@ use std::fs::File;
 use std::io;
 use std::iter;
 use std::path::Path;
-use std::ptr;
 use std::slice;
 use std::sync::Arc;
 
@@ -709,17 +708,6 @@ pub unsafe fn optimize_thin_module(
         let llmod = module.module_llvm.llmod();
         save_temp_bitcode(cgcx, &module, "thin-lto-input");
 
-        // Before we do much else find the "main" `DICompileUnit` that we'll be
-        // using below. If we find more than one though then rustc has changed
-        // in a way we're not ready for, so generate an ICE by returning
-        // an error.
-        let mut cu1 = ptr::null_mut();
-        let mut cu2 = ptr::null_mut();
-        llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
-        if !cu2.is_null() {
-            return Err(write::llvm_err(&diag_handler, LlvmError::MultipleSourceDiCompileUnit));
-        }
-
         // Up next comes the per-module local analyses that we do for Thin LTO.
         // Each of these functions is basically copied from the LLVM
         // implementation and then tailored to suit this implementation. Ideally
@@ -766,43 +754,6 @@ pub unsafe fn optimize_thin_module(
             save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
         }
 
-        // Ok now this is a bit unfortunate. This is also something you won't
-        // find upstream in LLVM's ThinLTO passes! This is a hack for now to
-        // work around bugs in LLVM.
-        //
-        // First discovered in #45511 it was found that as part of ThinLTO
-        // importing passes LLVM will import `DICompileUnit` metadata
-        // information across modules. This means that we'll be working with one
-        // LLVM module that has multiple `DICompileUnit` instances in it (a
-        // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of
-        // bugs in LLVM's backend which generates invalid DWARF in a situation
-        // like this:
-        //
-        //  https://bugs.llvm.org/show_bug.cgi?id=35212
-        //  https://bugs.llvm.org/show_bug.cgi?id=35562
-        //
-        // While the first bug there is fixed the second ended up causing #46346
-        // which was basically a resurgence of #45511 after LLVM's bug 35212 was
-        // fixed.
-        //
-        // This function below is a huge hack around this problem. The function
-        // below is defined in `PassWrapper.cpp` and will basically "merge"
-        // all `DICompileUnit` instances in a module. Basically it'll take all
-        // the objects, rewrite all pointers of `DISubprogram` to point to the
-        // first `DICompileUnit`, and then delete all the other units.
-        //
-        // This is probably mangling to the debug info slightly (but hopefully
-        // not too much) but for now at least gets LLVM to emit valid DWARF (or
-        // so it appears). Hopefully we can remove this once upstream bugs are
-        // fixed in LLVM.
-        {
-            let _timer = cgcx
-                .prof
-                .generic_activity_with_arg("LLVM_thin_lto_patch_debuginfo", thin_module.name());
-            llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1);
-            save_temp_bitcode(cgcx, &module, "thin-lto-after-patch");
-        }
-
         // Alright now that we've done everything related to the ThinLTO
         // analysis it's time to run some optimizations! Here we use the same
         // `run_pass_manager` as the "fat" LTO above except that we tell it to
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index aaf5dbd9930..37f30917609 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -9,10 +9,9 @@ use rustc_ast::attr;
 use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir::def_id::LOCAL_CRATE;
-use rustc_middle::bug;
+use rustc_middle::{bug, middle::debugger_visualizer::DebuggerVisualizerType};
 use rustc_session::config::{CrateType, DebugInfo};
 use rustc_span::symbol::sym;
-use rustc_span::DebuggerVisualizerType;
 
 /// Inserts a side-effect free instruction sequence that makes sure that the
 /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 25fe3cb265d..bd2fba12602 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -806,8 +806,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
     name_in_debuginfo.push(codegen_unit_name);
 
     debug!("build_compile_unit_di_node: {:?}", name_in_debuginfo);
-    let rustc_producer =
-        format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"),);
+    let rustc_producer = format!("rustc version {}", tcx.sess.cfg_version);
     // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
     let producer = format!("clang LLVM ({})", rustc_producer);
 
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 6a86237d79e..805843e5863 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -10,6 +10,7 @@
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
 #![feature(never_type)]
+#![feature(impl_trait_in_assoc_type)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index aefd5b2a13c..de93a64c0d6 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2484,12 +2484,6 @@ extern "C" {
         len: usize,
         out_len: &mut usize,
     ) -> *const u8;
-    pub fn LLVMRustThinLTOGetDICompileUnit(
-        M: &Module,
-        CU1: &mut *mut c_void,
-        CU2: &mut *mut c_void,
-    );
-    pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void);
 
     pub fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
     pub fn LLVMRustLinkerAdd(
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 994addf12eb..03be0654b50 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -16,7 +16,6 @@ use rustc_session::config::PrintRequest;
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
-use smallvec::{smallvec, SmallVec};
 use std::ffi::{CStr, CString};
 
 use std::path::Path;
@@ -132,6 +131,60 @@ pub fn time_trace_profiler_finish(file_name: &Path) {
     }
 }
 
+pub enum TargetFeatureFoldStrength<'a> {
+    // The feature is only tied when enabling the feature, disabling
+    // this feature shouldn't disable the tied feature.
+    EnableOnly(&'a str),
+    // The feature is tied for both enabling and disabling this feature.
+    Both(&'a str),
+}
+
+impl<'a> TargetFeatureFoldStrength<'a> {
+    fn as_str(&self) -> &'a str {
+        match self {
+            TargetFeatureFoldStrength::EnableOnly(feat) => feat,
+            TargetFeatureFoldStrength::Both(feat) => feat,
+        }
+    }
+}
+
+pub struct LLVMFeature<'a> {
+    pub llvm_feature_name: &'a str,
+    pub dependency: Option<TargetFeatureFoldStrength<'a>>,
+}
+
+impl<'a> LLVMFeature<'a> {
+    pub fn new(llvm_feature_name: &'a str) -> Self {
+        Self { llvm_feature_name, dependency: None }
+    }
+
+    pub fn with_dependency(
+        llvm_feature_name: &'a str,
+        dependency: TargetFeatureFoldStrength<'a>,
+    ) -> Self {
+        Self { llvm_feature_name, dependency: Some(dependency) }
+    }
+
+    pub fn contains(&self, feat: &str) -> bool {
+        self.iter().any(|dep| dep == feat)
+    }
+
+    pub fn iter(&'a self) -> impl Iterator<Item = &'a str> {
+        let dependencies = self.dependency.iter().map(|feat| feat.as_str());
+        std::iter::once(self.llvm_feature_name).chain(dependencies)
+    }
+}
+
+impl<'a> IntoIterator for LLVMFeature<'a> {
+    type Item = &'a str;
+    type IntoIter = impl Iterator<Item = &'a str>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        let dependencies = self.dependency.into_iter().map(|feat| feat.as_str());
+        std::iter::once(self.llvm_feature_name).chain(dependencies)
+    }
+}
+
 // WARNING: the features after applying `to_llvm_features` must be known
 // to LLVM or the feature detection code will walk past the end of the feature
 // array, leading to crashes.
@@ -147,36 +200,65 @@ pub fn time_trace_profiler_finish(file_name: &Path) {
 // Though note that Rust can also be build with an external precompiled version of LLVM
 // which might lead to failures if the oldest tested / supported LLVM version
 // doesn't yet support the relevant intrinsics
-pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> {
+pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> {
     let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
     match (arch, s) {
-        ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"],
-        ("x86", "pclmulqdq") => smallvec!["pclmul"],
-        ("x86", "rdrand") => smallvec!["rdrnd"],
-        ("x86", "bmi1") => smallvec!["bmi"],
-        ("x86", "cmpxchg16b") => smallvec!["cx16"],
-        ("aarch64", "rcpc2") => smallvec!["rcpc-immo"],
-        ("aarch64", "dpb") => smallvec!["ccpp"],
-        ("aarch64", "dpb2") => smallvec!["ccdp"],
-        ("aarch64", "frintts") => smallvec!["fptoint"],
-        ("aarch64", "fcma") => smallvec!["complxnum"],
-        ("aarch64", "pmuv3") => smallvec!["perfmon"],
-        ("aarch64", "paca") => smallvec!["pauth"],
-        ("aarch64", "pacg") => smallvec!["pauth"],
-        // Rust ties fp and neon together. In LLVM neon implicitly enables fp,
-        // but we manually enable neon when a feature only implicitly enables fp
-        ("aarch64", "f32mm") => smallvec!["f32mm", "neon"],
-        ("aarch64", "f64mm") => smallvec!["f64mm", "neon"],
-        ("aarch64", "fhm") => smallvec!["fp16fml", "neon"],
-        ("aarch64", "fp16") => smallvec!["fullfp16", "neon"],
-        ("aarch64", "jsconv") => smallvec!["jsconv", "neon"],
-        ("aarch64", "sve") => smallvec!["sve", "neon"],
-        ("aarch64", "sve2") => smallvec!["sve2", "neon"],
-        ("aarch64", "sve2-aes") => smallvec!["sve2-aes", "neon"],
-        ("aarch64", "sve2-sm4") => smallvec!["sve2-sm4", "neon"],
-        ("aarch64", "sve2-sha3") => smallvec!["sve2-sha3", "neon"],
-        ("aarch64", "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"],
-        (_, s) => smallvec![s],
+        ("x86", "sse4.2") => {
+            LLVMFeature::with_dependency("sse4.2", TargetFeatureFoldStrength::EnableOnly("crc32"))
+        }
+        ("x86", "pclmulqdq") => LLVMFeature::new("pclmul"),
+        ("x86", "rdrand") => LLVMFeature::new("rdrnd"),
+        ("x86", "bmi1") => LLVMFeature::new("bmi"),
+        ("x86", "cmpxchg16b") => LLVMFeature::new("cx16"),
+        ("aarch64", "rcpc2") => LLVMFeature::new("rcpc-immo"),
+        ("aarch64", "dpb") => LLVMFeature::new("ccpp"),
+        ("aarch64", "dpb2") => LLVMFeature::new("ccdp"),
+        ("aarch64", "frintts") => LLVMFeature::new("fptoint"),
+        ("aarch64", "fcma") => LLVMFeature::new("complxnum"),
+        ("aarch64", "pmuv3") => LLVMFeature::new("perfmon"),
+        ("aarch64", "paca") => LLVMFeature::new("pauth"),
+        ("aarch64", "pacg") => LLVMFeature::new("pauth"),
+        // Rust ties fp and neon together.
+        ("aarch64", "neon") => {
+            LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8"))
+        }
+        // In LLVM neon implicitly enables fp, but we manually enable
+        // neon when a feature only implicitly enables fp
+        ("aarch64", "f32mm") => {
+            LLVMFeature::with_dependency("f32mm", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "f64mm") => {
+            LLVMFeature::with_dependency("f64mm", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "fhm") => {
+            LLVMFeature::with_dependency("fp16fml", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "fp16") => {
+            LLVMFeature::with_dependency("fullfp16", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "jsconv") => {
+            LLVMFeature::with_dependency("jsconv", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve") => {
+            LLVMFeature::with_dependency("sve", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2") => {
+            LLVMFeature::with_dependency("sve2", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2-aes") => {
+            LLVMFeature::with_dependency("sve2-aes", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2-sm4") => {
+            LLVMFeature::with_dependency("sve2-sm4", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2-sha3") => {
+            LLVMFeature::with_dependency("sve2-sha3", TargetFeatureFoldStrength::EnableOnly("neon"))
+        }
+        ("aarch64", "sve2-bitperm") => LLVMFeature::with_dependency(
+            "sve2-bitperm",
+            TargetFeatureFoldStrength::EnableOnly("neon"),
+        ),
+        (_, s) => LLVMFeature::new(s),
     }
 }
 
@@ -274,18 +356,17 @@ fn print_target_features(sess: &Session, tm: &llvm::TargetMachine) {
     let mut rustc_target_features = supported_target_features(sess)
         .iter()
         .map(|(feature, _gate)| {
-            let desc = if let Some(llvm_feature) = to_llvm_features(sess, *feature).first() {
-                // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
+            // 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;
+            let desc =
                 match llvm_target_features.binary_search_by_key(&llvm_feature, |(f, _d)| f).ok() {
                     Some(index) => {
                         known_llvm_target_features.insert(llvm_feature);
                         llvm_target_features[index].1
                     }
                     None => "",
-                }
-            } else {
-                ""
-            };
+                };
+
             (*feature, desc)
         })
         .collect::<Vec<_>>();
@@ -469,10 +550,19 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
             // 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.
+            let llvm_feature = to_llvm_features(sess, feature);
+
             Some(
-                to_llvm_features(sess, feature)
-                    .into_iter()
-                    .map(move |f| format!("{}{}", enable_disable, f)),
+                std::iter::once(format!("{}{}", enable_disable, llvm_feature.llvm_feature_name))
+                    .chain(llvm_feature.dependency.into_iter().filter_map(move |feat| {
+                        match (enable_disable, feat) {
+                            ('-' | '+', TargetFeatureFoldStrength::Both(f))
+                            | ('+', TargetFeatureFoldStrength::EnableOnly(f)) => {
+                                Some(format!("{}{}", enable_disable, f))
+                            }
+                            _ => None,
+                        }
+                    })),
             )
         })
         .flatten();
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 02be88df103..0ac12d32be5 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -14,7 +14,7 @@ itertools = "0.10.1"
 tracing = "0.1"
 jobserver = "0.1.22"
 tempfile = "3.2"
-thorin-dwp = "0.4"
+thorin-dwp = "0.6"
 pathdiff = "0.2.0"
 serde_json = "1.0.59"
 snap = "1"
@@ -46,7 +46,7 @@ rustc_session = { path = "../rustc_session" }
 libc = "0.2.50"
 
 [dependencies.object]
-version = "0.30.1"
+version = "0.31.1"
 default-features = false
 features = ["read_core", "elf", "macho", "pe", "unaligned", "archive", "write"]
 
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index ea06cb02d8b..8a00c42a0e8 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -9,6 +9,7 @@ use rustc_fs_util::fix_windows_verbatim_for_gcc;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_metadata::find_native_static_library;
 use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME};
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
@@ -21,7 +22,6 @@ use rustc_session::utils::NativeLibKind;
 /// need out of the shared crate context before we get rid of it.
 use rustc_session::{filesearch, Session};
 use rustc_span::symbol::Symbol;
-use rustc_span::DebuggerVisualizerFile;
 use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
 use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy};
 use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};
@@ -574,6 +574,8 @@ fn link_staticlib<'a>(
         }
     }
 
+    all_native_libs.extend_from_slice(&codegen_results.crate_info.used_libraries);
+
     if sess.opts.prints.contains(&PrintRequest::NativeStaticLibs) {
         print_native_static_libs(sess, &all_native_libs, &all_rust_dylibs);
     }
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index 1e57f4248d2..cd56f85cccd 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -144,7 +144,7 @@ pub fn get_linker<'a>(
             cmd,
             sess,
             target_cpu,
-            hinted_static: false,
+            hinted_static: None,
             is_ld: cc == Cc::No,
             is_gnu: flavor.is_gnu(),
         }) as Box<dyn Linker>,
@@ -214,7 +214,7 @@ pub struct GccLinker<'a> {
     cmd: Command,
     sess: &'a Session,
     target_cpu: &'a str,
-    hinted_static: bool, // Keeps track of the current hinting mode.
+    hinted_static: Option<bool>, // Keeps track of the current hinting mode.
     // Link as ld
     is_ld: bool,
     is_gnu: bool,
@@ -275,9 +275,9 @@ impl<'a> GccLinker<'a> {
         if !self.takes_hints() {
             return;
         }
-        if !self.hinted_static {
+        if self.hinted_static != Some(true) {
             self.linker_arg("-Bstatic");
-            self.hinted_static = true;
+            self.hinted_static = Some(true);
         }
     }
 
@@ -285,9 +285,9 @@ impl<'a> GccLinker<'a> {
         if !self.takes_hints() {
             return;
         }
-        if self.hinted_static {
+        if self.hinted_static != Some(false) {
             self.linker_arg("-Bdynamic");
-            self.hinted_static = false;
+            self.hinted_static = Some(false);
         }
     }
 
@@ -1484,25 +1484,25 @@ impl<'a> L4Bender<'a> {
 pub struct AixLinker<'a> {
     cmd: Command,
     sess: &'a Session,
-    hinted_static: bool,
+    hinted_static: Option<bool>,
 }
 
 impl<'a> AixLinker<'a> {
     pub fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> {
-        AixLinker { cmd: cmd, sess: sess, hinted_static: false }
+        AixLinker { cmd: cmd, sess: sess, hinted_static: None }
     }
 
     fn hint_static(&mut self) {
-        if !self.hinted_static {
+        if self.hinted_static != Some(true) {
             self.cmd.arg("-bstatic");
-            self.hinted_static = true;
+            self.hinted_static = Some(true);
         }
     }
 
     fn hint_dynamic(&mut self) {
-        if self.hinted_static {
+        if self.hinted_static != Some(false) {
             self.cmd.arg("-bdynamic");
-            self.hinted_static = false;
+            self.hinted_static = Some(false);
         }
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 8968133bac5..8bf84772f08 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -14,8 +14,7 @@ use snap::write::FrameEncoder;
 
 use object::elf::NT_GNU_PROPERTY_TYPE_0;
 use rustc_data_structures::memmap::Mmap;
-use rustc_data_structures::owned_slice::try_slice_owned;
-use rustc_data_structures::sync::MetadataRef;
+use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
 use rustc_metadata::fs::METADATA_FILENAME;
 use rustc_metadata::EncodedMetadata;
 use rustc_session::cstore::MetadataLoader;
@@ -39,7 +38,7 @@ pub struct DefaultMetadataLoader;
 fn load_metadata_with(
     path: &Path,
     f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>,
-) -> Result<MetadataRef, String> {
+) -> Result<OwnedSlice, String> {
     let file =
         File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?;
 
@@ -49,7 +48,7 @@ fn load_metadata_with(
 }
 
 impl MetadataLoader for DefaultMetadataLoader {
-    fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
+    fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
         load_metadata_with(path, |data| {
             let archive = object::read::archive::ArchiveFile::parse(&*data)
                 .map_err(|e| format!("failed to parse rlib '{}': {}", path.display(), e))?;
@@ -69,7 +68,7 @@ impl MetadataLoader for DefaultMetadataLoader {
         })
     }
 
-    fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
+    fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<OwnedSlice, String> {
         load_metadata_with(path, |data| search_for_section(path, data, ".rustc"))
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index d9b0a152594..15c7847155d 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -23,6 +23,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
+use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
 use rustc_middle::middle::exported_symbols;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_middle::middle::lang_items;
@@ -35,7 +36,6 @@ use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
 use rustc_session::Session;
 use rustc_span::symbol::sym;
 use rustc_span::Symbol;
-use rustc_span::{DebuggerVisualizerFile, DebuggerVisualizerType};
 use rustc_target::abi::{Align, FIRST_VARIANT};
 
 use std::collections::BTreeSet;
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index f4b9d1dea58..31854c7f4c4 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -28,6 +28,7 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir::def_id::CrateNum;
 use rustc_middle::dep_graph::WorkProduct;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Dependencies;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_middle::query::{ExternProviders, Providers};
@@ -36,8 +37,8 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::cstore::{self, CrateSource};
 use rustc_session::utils::NativeLibKind;
+use rustc_session::Session;
 use rustc_span::symbol::Symbol;
-use rustc_span::DebuggerVisualizerFile;
 use std::collections::BTreeSet;
 use std::io;
 use std::path::{Path, PathBuf};
@@ -175,11 +176,11 @@ pub struct CodegenResults {
     pub crate_info: CrateInfo,
 }
 
-pub enum CodegenErrors<'a> {
+pub enum CodegenErrors {
     WrongFileType,
     EmptyVersionNumber,
     EncodingVersionMismatch { version_array: String, rlink_version: u32 },
-    RustcVersionMismatch { rustc_version: String, current_version: &'a str },
+    RustcVersionMismatch { rustc_version: String },
 }
 
 pub fn provide(providers: &mut Providers) {
@@ -213,10 +214,9 @@ pub fn looks_like_rust_object_file(filename: &str) -> bool {
 const RLINK_VERSION: u32 = 1;
 const RLINK_MAGIC: &[u8] = b"rustlink";
 
-const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
-
 impl CodegenResults {
     pub fn serialize_rlink(
+        sess: &Session,
         rlink_file: &Path,
         codegen_results: &CodegenResults,
     ) -> Result<usize, io::Error> {
@@ -225,12 +225,12 @@ impl CodegenResults {
         // `emit_raw_bytes` is used to make sure that the version representation does not depend on
         // Encoder's inner representation of `u32`.
         encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
-        encoder.emit_str(RUSTC_VERSION.unwrap());
+        encoder.emit_str(sess.cfg_version);
         Encodable::encode(codegen_results, &mut encoder);
         encoder.finish()
     }
 
-    pub fn deserialize_rlink<'a>(data: Vec<u8>) -> Result<Self, CodegenErrors<'a>> {
+    pub fn deserialize_rlink(sess: &Session, data: Vec<u8>) -> Result<Self, CodegenErrors> {
         // The Decodable machinery is not used here because it panics if the input data is invalid
         // and because its internal representation may change.
         if !data.starts_with(RLINK_MAGIC) {
@@ -252,11 +252,9 @@ impl CodegenResults {
 
         let mut decoder = MemDecoder::new(&data[4..], 0);
         let rustc_version = decoder.read_str();
-        let current_version = RUSTC_VERSION.unwrap();
-        if rustc_version != current_version {
+        if rustc_version != sess.cfg_version {
             return Err(CodegenErrors::RustcVersionMismatch {
                 rustc_version: rustc_version.to_string(),
-                current_version,
             });
         }
 
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 3719283cccc..c5976a65411 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -250,6 +250,7 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("f", Some(sym::riscv_target_feature)),
     ("m", Some(sym::riscv_target_feature)),
     ("relax", Some(sym::riscv_target_feature)),
+    ("unaligned-scalar-mem", Some(sym::riscv_target_feature)),
     ("v", Some(sym::riscv_target_feature)),
     ("zba", Some(sym::riscv_target_feature)),
     ("zbb", Some(sym::riscv_target_feature)),
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 5c88368bc87..d83bfc74082 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -1,3 +1,5 @@
+use std::any::Any;
+
 use super::write::WriteBackendMethods;
 use super::CodegenObject;
 use crate::back::write::TargetMachineFactoryFn;
@@ -5,6 +7,7 @@ use crate::{CodegenResults, ModuleCodegen};
 
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::sync::{DynSend, DynSync};
 use rustc_errors::ErrorGuaranteed;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
@@ -20,11 +23,6 @@ use rustc_span::symbol::Symbol;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::spec::Target;
 
-pub use rustc_data_structures::sync::MetadataRef;
-
-use rustc_data_structures::sync::{DynSend, DynSync};
-use std::any::Any;
-
 pub trait BackendTypes {
     type Value: CodegenObject;
     type Function: CodegenObject;
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 5037c210e7d..c591ff75ab8 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -3,7 +3,8 @@ use std::fmt;
 
 use rustc_errors::Diagnostic;
 use rustc_middle::mir::AssertKind;
-use rustc_middle::ty::{layout::LayoutError, query::TyCtxtAt, ConstInt};
+use rustc_middle::query::TyCtxtAt;
+use rustc_middle::ty::{layout::LayoutError, ConstInt};
 use rustc_span::{Span, Symbol};
 
 use super::InterpCx;
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 2fa63dc8c93..040eba10eb4 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -8,13 +8,12 @@ use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
 use rustc_index::IndexVec;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{ErrorHandled, InterpError, ReportedErrorInfo};
+use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{
     self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
     TyAndLayout,
 };
-use rustc_middle::ty::{
-    self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
-};
+use rustc_middle::ty::{self, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable};
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_session::Limit;
 use rustc_span::Span;
diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs
index 4e80a285186..11ad5b49df2 100644
--- a/compiler/rustc_const_eval/src/util/type_name.rs
+++ b/compiler/rustc_const_eval/src/util/type_name.rs
@@ -58,11 +58,12 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
             // Types with identity (print the module path).
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
             ty::Foreign(def_id) => self.print_def_path(def_id, &[]),
 
+            ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"),
             ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"),
             ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"),
         }
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 4868f49d8d5..a5db14d9102 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -109,28 +109,27 @@ pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
         // they have been placed in the bucket.
         //
         // We compute a partial set of immediate dominators here.
-        let z = parent[w];
-        for &v in bucket[z].iter() {
+        for &v in bucket[w].iter() {
             // This uses the result of Lemma 5 from section 2 from the original
             // 1979 paper, to compute either the immediate or relative dominator
             // for a given vertex v.
             //
             // eval returns a vertex y, for which semi[y] is minimum among
-            // vertices semi[v] +> y *> v. Note that semi[v] = z as we're in the
-            // z bucket.
+            // vertices semi[v] +> y *> v. Note that semi[v] = w as we're in the
+            // w bucket.
             //
             // Given such a vertex y, semi[y] <= semi[v] and idom[y] = idom[v].
             // If semi[y] = semi[v], though, idom[v] = semi[v].
             //
             // Using this, we can either set idom[v] to be:
-            //  * semi[v] (i.e. z), if semi[y] is z
+            //  * semi[v] (i.e. w), if semi[y] is w
             //  * idom[y], otherwise
             //
             // We don't directly set to idom[y] though as it's not necessarily
             // known yet. The second preorder traversal will cleanup by updating
             // the idom for any that were missed in this pass.
             let y = eval(&mut parent, lastlinked, &semi, &mut label, v);
-            idom[v] = if semi[y] < z { y } else { z };
+            idom[v] = if semi[y] < w { y } else { w };
         }
 
         // This loop computes the semi[w] for w.
@@ -213,10 +212,11 @@ pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
         // If we don't yet know the idom directly, then push this vertex into
         // our semidominator's bucket, where it will get processed at a later
         // stage to compute its immediate dominator.
-        if parent[w] != semi[w] {
+        let z = parent[w];
+        if z != semi[w] {
             bucket[semi[w]].push(w);
         } else {
-            idom[w] = parent[w];
+            idom[w] = z;
         }
 
         // Optimization: We share the parent array between processed and not
diff --git a/compiler/rustc_data_structures/src/graph/dominators/tests.rs b/compiler/rustc_data_structures/src/graph/dominators/tests.rs
index 8b124516623..5472bb8087e 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/tests.rs
@@ -53,3 +53,30 @@ fn immediate_dominator() {
     assert_eq!(dominators.immediate_dominator(2), Some(1));
     assert_eq!(dominators.immediate_dominator(3), Some(2));
 }
+
+#[test]
+fn transitive_dominator() {
+    let graph = TestGraph::new(
+        0,
+        &[
+            // First tree branch.
+            (0, 1),
+            (1, 2),
+            (2, 3),
+            (3, 4),
+            // Second tree branch.
+            (1, 5),
+            (5, 6),
+            // Third tree branch.
+            (0, 7),
+            // These links make 0 the dominator for 2 and 3.
+            (7, 2),
+            (5, 3),
+        ],
+    );
+
+    let dom_tree = dominators(&graph);
+    let immediate_dominators = &dom_tree.immediate_dominators;
+    assert_eq!(immediate_dominators[2], Some(0));
+    assert_eq!(immediate_dominators[3], Some(0)); // This used to return Some(1).
+}
diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs
index 311a42aa42a..cbb3047d884 100644
--- a/compiler/rustc_data_structures/src/owned_slice.rs
+++ b/compiler/rustc_data_structures/src/owned_slice.rs
@@ -1,5 +1,6 @@
 use std::{borrow::Borrow, ops::Deref};
 
+use crate::sync::Lrc;
 // Use our fake Send/Sync traits when on not parallel compiler,
 // so that `OwnedSlice` only implements/requires Send/Sync
 // for parallel compiler builds.
@@ -7,7 +8,7 @@ use crate::sync::{Send, Sync};
 
 /// An owned slice.
 ///
-/// This is similar to `Box<[u8]>` but allows slicing and using anything as the
+/// This is similar to `Lrc<[u8]>` but allows slicing and using anything as the
 /// backing buffer.
 ///
 /// See [`slice_owned`] for `OwnedSlice` construction and examples.
@@ -16,6 +17,7 @@ use crate::sync::{Send, Sync};
 ///
 /// This is essentially a replacement for `owning_ref` which is a lot simpler
 /// and even sound! 🌸
+#[derive(Clone)]
 pub struct OwnedSlice {
     /// This is conceptually a `&'self.owner [u8]`.
     bytes: *const [u8],
@@ -31,7 +33,7 @@ pub struct OwnedSlice {
     //       \/
     //      ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
     #[expect(dead_code)]
-    owner: Box<dyn Send + Sync>,
+    owner: Lrc<dyn Send + Sync>,
 }
 
 /// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
@@ -72,10 +74,10 @@ where
     O: Send + Sync + 'static,
     F: FnOnce(&O) -> Result<&[u8], E>,
 {
-    // We box the owner of the bytes, so it doesn't move.
+    // We wrap the owner of the bytes in, so it doesn't move.
     //
     // Since the owner does not move and we don't access it in any way
-    // before drop, there is nothing that can invalidate the bytes pointer.
+    // before dropping, there is nothing that can invalidate the bytes pointer.
     //
     // Thus, "extending" the lifetime of the reference returned from `F` is fine.
     // We pretend that we pass it a reference that lives as long as the returned slice.
@@ -83,12 +85,39 @@ where
     // N.B. the HRTB on the `slicer` is important — without it the caller could provide
     // a short lived slice, unrelated to the owner.
 
-    let owner = Box::new(owner);
+    let owner = Lrc::new(owner);
     let bytes = slicer(&*owner)?;
 
     Ok(OwnedSlice { bytes, owner })
 }
 
+impl OwnedSlice {
+    /// Slice this slice by `slicer`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
+    /// let vec = vec![1, 2, 3, 4];
+    ///
+    /// // Identical to slicing via `&v[1..3]` but produces an owned slice
+    /// let slice: OwnedSlice = slice_owned(vec, |v| &v[..]);
+    /// assert_eq!(&*slice, [1, 2, 3, 4]);
+    ///
+    /// let slice = slice.slice(|slice| &slice[1..][..2]);
+    /// assert_eq!(&*slice, [2, 3]);
+    /// ```
+    ///
+    pub fn slice(self, slicer: impl FnOnce(&[u8]) -> &[u8]) -> OwnedSlice {
+        // This is basically identical to `try_slice_owned`,
+        // `slicer` can only return slices of its argument or some static data,
+        // both of which are valid while `owner` is alive.
+
+        let bytes = slicer(&self);
+        OwnedSlice { bytes, ..self }
+    }
+}
+
 impl Deref for OwnedSlice {
     type Target = [u8];
 
@@ -108,11 +137,11 @@ impl Borrow<[u8]> for OwnedSlice {
     }
 }
 
-// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Send`
+// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Send`
 #[cfg(parallel_compiler)]
 unsafe impl Send for OwnedSlice {}
 
-// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Sync`
+// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Arc<dyn Send + Sync>)`, which is `Sync`
 #[cfg(parallel_compiler)]
 unsafe impl Sync for OwnedSlice {}
 
diff --git a/compiler/rustc_data_structures/src/owned_slice/tests.rs b/compiler/rustc_data_structures/src/owned_slice/tests.rs
index e151b8c2de0..1eb5378cd1a 100644
--- a/compiler/rustc_data_structures/src/owned_slice/tests.rs
+++ b/compiler/rustc_data_structures/src/owned_slice/tests.rs
@@ -26,7 +26,7 @@ fn static_storage() {
 }
 
 #[test]
-fn slice_the_slice() {
+fn slice_owned_the_slice() {
     let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
     let slice = slice_owned(slice, |s| &s[1..][..4]);
     let slice = slice_owned(slice, |s| s);
@@ -36,6 +36,16 @@ fn slice_the_slice() {
 }
 
 #[test]
+fn slice_the_slice() {
+    let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice)
+        .slice(|s| &s[1..][..4])
+        .slice(|s| s)
+        .slice(|s| &s[1..]);
+
+    assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
+}
+
+#[test]
 fn try_and_fail() {
     let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(()));
 
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 8a778866a77..6c3197d8ec2 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -40,7 +40,6 @@
 //! [^2] `MTLockRef` is a typedef.
 
 pub use crate::marker::*;
-use crate::owned_slice::OwnedSlice;
 use std::collections::HashMap;
 use std::hash::{BuildHasher, Hash};
 use std::ops::{Deref, DerefMut};
@@ -92,6 +91,7 @@ mod mode {
 }
 
 pub use mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
+
 cfg_if! {
     if #[cfg(not(parallel_compiler))] {
         pub unsafe auto trait Send {}
@@ -244,8 +244,6 @@ cfg_if! {
             r
         }
 
-        pub type MetadataRef = OwnedSlice;
-
         pub use std::rc::Rc as Lrc;
         pub use std::rc::Weak as Weak;
         pub use std::cell::Ref as ReadGuard;
@@ -517,8 +515,6 @@ cfg_if! {
             }
         }
 
-        pub type MetadataRef = OwnedSlice;
-
         /// This makes locks panic if they are already held.
         /// It is only useful when you are running in a single thread
         const ERROR_CHECKING: bool = false;
diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs
index bfb04ba8a73..d61bb55be68 100644
--- a/compiler/rustc_data_structures/src/sync/worker_local.rs
+++ b/compiler/rustc_data_structures/src/sync/worker_local.rs
@@ -154,13 +154,6 @@ impl<T> WorkerLocal<T> {
     }
 }
 
-impl<T> WorkerLocal<Vec<T>> {
-    /// Joins the elements of all the worker locals into one Vec
-    pub fn join(self) -> Vec<T> {
-        self.into_inner().into_iter().flat_map(|v| v).collect()
-    }
-}
-
 impl<T> Deref for WorkerLocal<T> {
     type Target = T;
 
diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs
index 42c97cc6a9d..a713affa099 100644
--- a/compiler/rustc_driver_impl/src/args.rs
+++ b/compiler/rustc_driver_impl/src/args.rs
@@ -25,7 +25,7 @@ pub fn arg_expand_all(at_args: &[String]) -> Vec<String> {
             Ok(arg) => args.extend(arg),
             Err(err) => rustc_session::early_error(
                 rustc_session::config::ErrorOutputType::default(),
-                &format!("Failed to load argument file: {err}"),
+                format!("Failed to load argument file: {err}"),
             ),
         }
     }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 80a9dfd251a..6c204b894a6 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -322,7 +322,7 @@ fn run_compiler(
             1 => panic!("make_input should have provided valid inputs"),
             _ => early_error(
                 config.opts.error_format,
-                &format!(
+                format!(
                     "multiple input filenames provided (first two filenames are `{}` and `{}`)",
                     matches.free[0], matches.free[1],
                 ),
@@ -527,7 +527,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
             }
         }
         Err(InvalidErrorCode) => {
-            early_error(output, &format!("{code} is not a valid error code"));
+            early_error(output, format!("{code} is not a valid error code"));
         }
     }
 }
@@ -572,7 +572,7 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp
             let rlink_data = fs::read(file).unwrap_or_else(|err| {
                 sess.emit_fatal(RlinkUnableToRead { err });
             });
-            let codegen_results = match CodegenResults::deserialize_rlink(rlink_data) {
+            let codegen_results = match CodegenResults::deserialize_rlink(sess, rlink_data) {
                 Ok(codegen) => codegen,
                 Err(err) => {
                     match err {
@@ -586,10 +586,10 @@ pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Comp
                                 rlink_version,
                             })
                         }
-                        CodegenErrors::RustcVersionMismatch { rustc_version, current_version } => {
+                        CodegenErrors::RustcVersionMismatch { rustc_version } => {
                             sess.emit_fatal(RLinkRustcVersionMismatch {
                                 rustc_version,
-                                current_version,
+                                current_version: sess.cfg_version,
                             })
                         }
                     };
@@ -1102,7 +1102,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
                 .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")),
             _ => None,
         };
-        early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string()));
+        early_error(ErrorOutputType::default(), msg.unwrap_or_else(|| e.to_string()));
     });
 
     // For all options we just parsed, we check a few aspects:
@@ -1250,7 +1250,8 @@ pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&Handler))
         #[cfg(windows)]
         if let Some(msg) = info.payload().downcast_ref::<String>() {
             if msg.starts_with("failed printing to stdout: ") && msg.ends_with("(os error 232)") {
-                early_error_no_abort(ErrorOutputType::default(), &msg);
+                // the error code is already going to be reported when the panic unwinds up the stack
+                let _ = early_error_no_abort(ErrorOutputType::default(), msg.as_str());
                 return;
             }
         };
@@ -1342,7 +1343,7 @@ pub fn init_rustc_env_logger() {
 /// other than `RUSTC_LOG`.
 pub fn init_env_logger(env: &str) {
     if let Err(error) = rustc_log::init_env_logger(env) {
-        early_error(ErrorOutputType::default(), &error.to_string());
+        early_error(ErrorOutputType::default(), error.to_string());
     }
 }
 
@@ -1409,7 +1410,7 @@ pub fn main() -> ! {
                 arg.into_string().unwrap_or_else(|arg| {
                     early_error(
                         ErrorOutputType::default(),
-                        &format!("argument {i} is not valid Unicode: {arg:?}"),
+                        format!("argument {i} is not valid Unicode: {arg:?}"),
                     )
                 })
             })
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 68e57de5e08..3e38d6afb0b 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -2303,22 +2303,25 @@ impl EmitterWriter {
 
         // Colorize addition/replacements with green.
         for &SubstitutionHighlight { start, end } in highlight_parts {
-            // Account for tabs when highlighting (#87972).
-            let tabs: usize = line_to_add
-                .chars()
-                .take(start)
-                .map(|ch| match ch {
-                    '\t' => 3,
-                    _ => 0,
-                })
-                .sum();
-            buffer.set_style_range(
-                *row_num,
-                max_line_num_len + 3 + start + tabs,
-                max_line_num_len + 3 + end + tabs,
-                Style::Addition,
-                true,
-            );
+            // This is a no-op for empty ranges
+            if start != end {
+                // Account for tabs when highlighting (#87972).
+                let tabs: usize = line_to_add
+                    .chars()
+                    .take(start)
+                    .map(|ch| match ch {
+                        '\t' => 3,
+                        _ => 0,
+                    })
+                    .sum();
+                buffer.set_style_range(
+                    *row_num,
+                    max_line_num_len + 3 + start + tabs,
+                    max_line_num_len + 3 + end + tabs,
+                    Style::Addition,
+                    true,
+                );
+            }
         }
         *row_num += 1;
     }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 22c41f7b93f..074fbb1322c 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -330,12 +330,11 @@ impl CodeSuggestion {
                     });
                     buf.push_str(&part.snippet);
                     let cur_hi = sm.lookup_char_pos(part.span.hi());
-                    if cur_hi.line == cur_lo.line && !part.snippet.is_empty() {
-                        // Account for the difference between the width of the current code and the
-                        // snippet being suggested, so that the *later* suggestions are correctly
-                        // aligned on the screen.
-                        acc += len - (cur_hi.col.0 - cur_lo.col.0) as isize;
-                    }
+                    // Account for the difference between the width of the current code and the
+                    // snippet being suggested, so that the *later* suggestions are correctly
+                    // aligned on the screen. Note that cur_hi and cur_lo can be on different
+                    // lines, so cur_hi.col can be smaller than cur_lo.col
+                    acc += len - (cur_hi.col.0 as isize - cur_lo.col.0 as isize);
                     prev_hi = cur_hi;
                     prev_line = sf.get_line(prev_hi.line - 1);
                     for line in part.snippet.split('\n').skip(1) {
@@ -478,6 +477,8 @@ pub enum StashKey {
     /// FRU syntax
     MaybeFruTypo,
     CallAssocMethod,
+    TraitMissingMethod,
+    OpaqueHiddenTypeMismatch,
 }
 
 fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) {
@@ -1739,7 +1740,7 @@ impl DelayedDiagnostic {
     }
 
     fn decorate(mut self) -> Diagnostic {
-        self.inner.note(format!("delayed at {}", self.note));
+        self.inner.note(format!("delayed at {}\n{}", self.inner.emitted_at, self.note));
         self.inner
     }
 }
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index e03576c55f4..fd721749066 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -15,7 +15,8 @@ use rustc_attr::{self as attr, Deprecation, Stability};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{
-    Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, PResult,
+    Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic,
+    MultiSpan, PResult,
 };
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
 use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools};
@@ -1110,7 +1111,7 @@ impl<'a> ExtCtxt<'a> {
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
     ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
         self.sess.parse_sess.span_diagnostic.struct_span_err(sp, msg)
     }
@@ -1132,14 +1133,14 @@ impl<'a> ExtCtxt<'a> {
     /// Compilation will be stopped in the near future (at the end of
     /// the macro expansion phase).
     #[rustc_lint_diagnostics]
-    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
+    pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
         self.sess.parse_sess.span_diagnostic.span_err(sp, msg);
     }
     #[rustc_lint_diagnostics]
-    pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
+    pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) {
         self.sess.parse_sess.span_diagnostic.span_warn(sp, msg);
     }
-    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
+    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
         self.sess.parse_sess.span_diagnostic.span_bug(sp, msg);
     }
     pub fn trace_macros_diag(&mut self) {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 7c78970345a..5d369a1879a 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -722,7 +722,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                     });
                                 }
                             };
-                            if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
+                            if matches!(
+                                fragment_kind,
+                                AstFragmentKind::Expr | AstFragmentKind::MethodReceiverExpr
+                            ) && items.is_empty()
+                            {
                                 self.cx.emit_err(RemoveExprNotSupported { span });
                                 fragment_kind.dummy(span)
                             } else {
@@ -1664,7 +1668,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                         &UNUSED_ATTRIBUTES,
                         attr.span,
                         self.cx.current_expansion.lint_node_id,
-                        &format!("unused attribute `{}`", attr_name),
+                        format!("unused attribute `{}`", attr_name),
                         BuiltinLintDiagnostics::UnusedBuiltinAttribute {
                             attr_name,
                             macro_name: pprust::path_to_string(&call.path),
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 35572292271..cb8b4899e48 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -48,7 +48,7 @@ pub(super) fn failed_to_match_macro<'cx>(
 
     let span = token.span.substitute_dummy(sp);
 
-    let mut err = cx.struct_span_err(span, &parse_failure_msg(&token));
+    let mut err = cx.struct_span_err(span, parse_failure_msg(&token));
     err.span_label(span, label);
     if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) {
         err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
@@ -170,7 +170,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx,
             }
             Error(err_sp, msg) => {
                 let span = err_sp.substitute_dummy(self.root_span);
-                self.cx.struct_span_err(span, msg).emit();
+                self.cx.struct_span_err(span, msg.as_str()).emit();
                 self.result = Some(DummyResult::any(span));
             }
             ErrorReported(_) => self.result = Some(DummyResult::any(self.root_span)),
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 75b6396f0be..34f998274e9 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -110,7 +110,7 @@ use crate::mbe::{KleeneToken, TokenTree};
 use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::MultiSpan;
+use rustc_errors::{DiagnosticMessage, MultiSpan};
 use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
 use rustc_session::parse::ParseSess;
 use rustc_span::symbol::kw;
@@ -593,7 +593,7 @@ fn check_ops_is_prefix(
             return;
         }
     }
-    buffer_lint(sess, span.into(), node_id, &format!("unknown macro variable `{}`", name));
+    buffer_lint(sess, span.into(), node_id, format!("unknown macro variable `{}`", name));
 }
 
 /// Returns whether `binder_ops` is a prefix of `occurrence_ops`.
@@ -626,7 +626,7 @@ fn ops_is_prefix(
         if i >= occurrence_ops.len() {
             let mut span = MultiSpan::from_span(span);
             span.push_span_label(binder.span, "expected repetition");
-            let message = &format!("variable '{}' is still repeating at this depth", name);
+            let message = format!("variable '{}' is still repeating at this depth", name);
             buffer_lint(sess, span, node_id, message);
             return;
         }
@@ -642,7 +642,12 @@ fn ops_is_prefix(
     }
 }
 
-fn buffer_lint(sess: &ParseSess, span: MultiSpan, node_id: NodeId, message: &str) {
+fn buffer_lint(
+    sess: &ParseSess,
+    span: MultiSpan,
+    node_id: NodeId,
+    message: impl Into<DiagnosticMessage>,
+) {
     // Macros loaded from other crates have dummy node ids.
     if node_id != DUMMY_NODE_ID {
         sess.buffer_lint(&META_VARIABLE_MISUSE, span, node_id, message);
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index a07cb65170d..d523d3eacbe 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -510,7 +510,7 @@ fn out_of_bounds_err<'a>(
              must be less than {max}"
         )
     };
-    cx.struct_span_err(span, &msg)
+    cx.struct_span_err(span, msg)
 }
 
 fn transcribe_metavar_expr<'a>(
diff --git a/compiler/rustc_hir/src/errors.rs b/compiler/rustc_hir/src/errors.rs
deleted file mode 100644
index e593ed1044a..00000000000
--- a/compiler/rustc_hir/src/errors.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use crate::LangItem;
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
-pub struct LangItemError(pub LangItem);
-
-impl ToString for LangItemError {
-    fn to_string(&self) -> String {
-        format!("requires `{}` lang_item", self.0.name())
-    }
-}
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 1f08befb180..4b3bc816b95 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -8,7 +8,6 @@
 //! * Functions called by the compiler itself.
 
 use crate::def_id::DefId;
-use crate::errors::LangItemError;
 use crate::{MethodKind, Target};
 
 use rustc_ast as ast;
@@ -42,13 +41,6 @@ impl LanguageItems {
         self.items[item as usize] = Some(def_id);
     }
 
-    /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
-    /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
-    /// returns an error encapsulating the `LangItem`.
-    pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
-        self.get(it).ok_or_else(|| LangItemError(it))
-    }
-
     pub fn iter(&self) -> impl Iterator<Item = (LangItem, DefId)> + '_ {
         self.items
             .iter()
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 98d967cc0b8..616de57dc63 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -30,7 +30,6 @@ pub mod def;
 pub mod def_path_hash_map;
 pub mod definitions;
 pub mod diagnostic_items;
-pub mod errors;
 pub use rustc_span::def_id;
 mod hir;
 pub mod hir_id;
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index c7ac01b3334..a40a0178710 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -10,13 +10,13 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate-id of the defining crate. This is a desirable property
     // because the crate-id can be more easily changed than the DefPath
     // of an item, so, in the case of a crate-local DefPathHash collision,
-    // the user can simply "role the dice again" for all DefPathHashes in
+    // the user can simply "roll the dice again" for all DefPathHashes in
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
     create_session_if_not_set_then(Edition::Edition2024, |_| {
-        let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
-        let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
+        let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()], "");
+        let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()], "");
 
         let h0 = mk_test_hash(id0);
         let h1 = mk_test_hash(id1);
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index ed011b9086a..39d1d1f2de5 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -24,7 +24,7 @@ fn generic_arg_mismatch_err(
     arg: &GenericArg<'_>,
     param: &GenericParamDef,
     possible_ordering_error: bool,
-    help: Option<&str>,
+    help: Option<String>,
 ) -> ErrorGuaranteed {
     let sess = tcx.sess;
     let mut err = struct_span_err!(
@@ -300,7 +300,7 @@ pub fn create_substs_for_generic_args<'tcx, 'a>(
                                     arg,
                                     param,
                                     !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
-                                    Some(&format!(
+                                    Some(format!(
                                         "reorder the arguments: {}: `<{}>`",
                                         param_types_present
                                             .into_iter()
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 7e591fd25bf..cf082f1ffaa 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -19,7 +19,7 @@ use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{
     struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError,
-    MultiSpan,
+    MultiSpan, StashKey,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -38,7 +38,6 @@ use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}
 use rustc_middle::ty::{DynKind, ToPredicate};
 use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
 use rustc_span::edit_distance::find_best_match_for_name;
-use rustc_span::edition::Edition;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::{sym, Span, DUMMY_SP};
 use rustc_target::spec::abi;
@@ -3718,7 +3717,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 ));
             }
 
-            if self_ty.span.edition() >= Edition::Edition2021 {
+            if self_ty.span.edition().rust_2021() {
                 let msg = "trait objects must include the `dyn` keyword";
                 let label = "add `dyn` keyword before this trait";
                 let mut diag =
@@ -3732,7 +3731,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 }
                 // check if the impl trait that we are considering is a impl of a local trait
                 self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
-                diag.emit();
+                diag.stash(self_ty.span, StashKey::TraitMissingMethod);
             } else {
                 let msg = "trait objects without an explicit `dyn` are deprecated";
                 tcx.struct_span_lint_hir(
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 1cf93c86f4f..d6d1498d708 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -1,6 +1,5 @@
 use crate::errors::AutoDerefReachedRecursionLimit;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::NormalizeExt;
 use crate::traits::{self, TraitEngine, TraitEngineExt};
 use rustc_infer::infer::InferCtxt;
 use rustc_middle::ty::TypeVisitableExt;
@@ -9,6 +8,7 @@ use rustc_session::Limit;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::Span;
+use rustc_trait_selection::traits::StructurallyNormalizeExt;
 
 #[derive(Copy, Clone, Debug)]
 pub enum AutoderefKind {
@@ -66,14 +66,27 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
         }
 
         // Otherwise, deref if type is derefable:
-        let (kind, new_ty) =
-            if let Some(mt) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
-                (AutoderefKind::Builtin, mt.ty)
-            } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
-                (AutoderefKind::Overloaded, ty)
+        let (kind, new_ty) = if let Some(ty::TypeAndMut { ty, .. }) =
+            self.state.cur_ty.builtin_deref(self.include_raw_pointers)
+        {
+            debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
+            // NOTE: we may still need to normalize the built-in deref in case
+            // we have some type like `&<Ty as Trait>::Assoc`, since users of
+            // autoderef expect this type to have been structurally normalized.
+            if self.infcx.tcx.trait_solver_next()
+                && let ty::Alias(ty::Projection, _) = ty.kind()
+            {
+                let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
+                self.state.obligations.extend(obligations);
+                (AutoderefKind::Builtin, normalized_ty)
             } else {
-                return None;
-            };
+                (AutoderefKind::Builtin, ty)
+            }
+        } else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
+            (AutoderefKind::Overloaded, ty)
+        } else {
+            return None;
+        };
 
         if new_ty.references_error() {
             return None;
@@ -119,14 +132,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
 
     fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         debug!("overloaded_deref_ty({:?})", ty);
-
         let tcx = self.infcx.tcx;
 
         // <ty as Deref>
         let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
-
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
-
         let obligation = traits::Obligation::new(
             tcx,
             cause.clone(),
@@ -138,26 +148,48 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
             return None;
         }
 
-        let normalized_ty = self
+        let (normalized_ty, obligations) =
+            self.structurally_normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, [ty]))?;
+        debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
+        self.state.obligations.extend(obligations);
+
+        Some(self.infcx.resolve_vars_if_possible(normalized_ty))
+    }
+
+    #[instrument(level = "debug", skip(self), ret)]
+    pub fn structurally_normalize(
+        &self,
+        ty: Ty<'tcx>,
+    ) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
+        let tcx = self.infcx.tcx;
+        let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
+
+        let cause = traits::ObligationCause::misc(self.span, self.body_id);
+        let normalized_ty = match self
             .infcx
             .at(&cause, self.param_env)
-            .normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
-        let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
-        let normalized_ty =
-            normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfillcx);
-        let errors = fulfillcx.select_where_possible(&self.infcx);
+            .structurally_normalize(ty, &mut *fulfill_cx)
+        {
+            Ok(normalized_ty) => normalized_ty,
+            Err(errors) => {
+                // This shouldn't happen, except for evaluate/fulfill mismatches,
+                // but that's not a reason for an ICE (`predicate_may_hold` is conservative
+                // by design).
+                debug!(?errors, "encountered errors while fulfilling");
+                return None;
+            }
+        };
+
+        let errors = fulfill_cx.select_where_possible(&self.infcx);
         if !errors.is_empty() {
             // This shouldn't happen, except for evaluate/fulfill mismatches,
             // but that's not a reason for an ICE (`predicate_may_hold` is conservative
             // by design).
-            debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
+            debug!(?errors, "encountered errors while fulfilling");
             return None;
         }
-        let obligations = fulfillcx.pending_obligations();
-        debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
-        self.state.obligations.extend(obligations);
 
-        Some(self.infcx.resolve_vars_if_possible(normalized_ty))
+        Some((normalized_ty, fulfill_cx.pending_obligations()))
     }
 
     /// Returns the final type we ended up with, which may be an inference
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index d05d8508408..a98d8e17153 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -298,9 +298,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
 
     let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
 
-    let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
-        tcx.sess.fatal(format!("`CoerceUnsized` implementation {}", err.to_string()));
-    });
+    let unsize_trait = tcx.require_lang_item(LangItem::Unsize, Some(span));
 
     let source = tcx.type_of(impl_did).subst_identity();
     let trait_ref = tcx.impl_trait_ref(impl_did).unwrap().subst_identity();
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 9f00dc418ee..22502bd4fdb 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -73,7 +73,6 @@ pub fn provide(providers: &mut Providers) {
         fn_sig,
         impl_trait_ref,
         impl_polarity,
-        is_foreign_item,
         generator_kind,
         collect_mod_item_types,
         is_type_alias_impl_trait,
@@ -1466,10 +1465,6 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
     fty
 }
 
-fn is_foreign_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
-    matches!(tcx.hir().get_by_def_id(def_id), Node::ForeignItem(..))
-}
-
 fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorKind> {
     match tcx.hir().get_by_def_id(def_id) {
         Node::Expr(&rustc_hir::Expr {
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index a33990813b8..e5b5dae551e 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -427,6 +427,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
             //   supertrait).
             if let ty::Alias(ty::Projection, projection) = ty.kind() {
                 projection.substs == trait_identity_substs
+                    // FIXME(return_type_notation): This check should be more robust
+                    && !tcx.is_impl_trait_in_trait(projection.def_id)
                     && tcx.associated_item(projection.def_id).container_id(tcx)
                         == def_id.to_def_id()
             } else {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 6c7c2b9eea2..97c6cb491d1 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -164,7 +164,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
             let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
                 return tcx.ty_error_with_message(
                     tcx.def_span(def_id),
-                    &format!("unable to find type-dependent def for {:?}", parent_node_id),
+                    format!("unable to find type-dependent def for {:?}", parent_node_id),
                 );
             };
             let idx = segment
@@ -205,14 +205,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                     } else {
                         return tcx.ty_error_with_message(
                             tcx.def_span(def_id),
-                            &format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
+                            format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
                         );
                     }
                 }
                 _ => {
                     return tcx.ty_error_with_message(
                         tcx.def_span(def_id),
-                        &format!("unexpected const parent path {:?}", parent_node),
+                        format!("unexpected const parent path {:?}", parent_node),
                     );
                 }
             };
@@ -243,7 +243,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                 None => {
                     return tcx.ty_error_with_message(
                         tcx.def_span(def_id),
-                        &format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
+                        format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
                     );
                 }
             };
@@ -253,7 +253,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
 
         _ => return tcx.ty_error_with_message(
             tcx.def_span(def_id),
-            &format!("unexpected const parent in type_of(): {parent_node:?}"),
+            format!("unexpected const parent in type_of(): {parent_node:?}"),
         ),
     };
 
@@ -279,7 +279,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
     } else {
         return tcx.ty_error_with_message(
             tcx.def_span(def_id),
-            &format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
+            format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
         );
     }
 }
@@ -584,7 +584,8 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
                 debug!(?concrete_type, "found constraint");
                 if let Some(prev) = &mut self.found {
                     if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
-                        let guar = prev.report_mismatch(&concrete_type, self.tcx);
+                        let guar =
+                            prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
                         prev.ty = self.tcx.ty_error(guar);
                     }
                 } else {
@@ -678,10 +679,10 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
     // Only check against typeck if we didn't already error
     if !hidden.ty.references_error() {
         for concrete_type in locator.typeck_types {
-            if tcx.erase_regions(concrete_type.ty) != tcx.erase_regions(hidden.ty)
+            if concrete_type.ty != tcx.erase_regions(hidden.ty)
                 && !(concrete_type, hidden).references_error()
             {
-                hidden.report_mismatch(&concrete_type, tcx);
+                hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
             }
         }
     }
@@ -722,7 +723,7 @@ fn find_opaque_ty_constraints_for_rpit(
                 if concrete_type.ty != self.found.ty
                     && !(concrete_type, self.found).references_error()
                 {
-                    self.found.report_mismatch(&concrete_type, self.tcx);
+                    self.found.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
                 }
             }
         }
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index aa664031a87..4a669e3f8b8 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -79,3 +79,14 @@ hir_typeck_arg_mismatch_indeterminate = argument type mismatch was detected, but
 hir_typeck_suggest_boxing_note = for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
 
 hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new`
+
+hir_typeck_no_associated_item = no {$item_kind} named `{$item_name}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
+    [true] {""}
+    *[other] {" "}in the current scope
+}
+
+hir_typeck_candidate_trait_note = `{$trait_name}` defines an item `{$item_name}`{$action_or_ty ->
+    [NONE] {""}
+    [implement] , perhaps you need to implement it
+    *[other] , perhaps you need to restrict type parameter `{$action_or_ty}` with it
+}
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index bf8259ff70f..bfabd44bb57 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -32,6 +32,7 @@ pub(super) fn check_fn<'a, 'tcx>(
     fn_def_id: LocalDefId,
     body: &'tcx hir::Body<'tcx>,
     can_be_generator: Option<hir::Movability>,
+    params_can_be_unsized: bool,
 ) -> Option<GeneratorTypes<'tcx>> {
     let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
 
@@ -94,7 +95,7 @@ pub(super) fn check_fn<'a, 'tcx>(
         // The check for a non-trivial pattern is a hack to avoid duplicate warnings
         // for simple cases like `fn foo(x: Trait)`,
         // where we would error once on the parameter as a whole, and once on the binding `x`.
-        if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params {
+        if param.pat.simple_ident().is_none() && !params_can_be_unsized {
             fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span));
         }
 
@@ -103,24 +104,8 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     fcx.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
 
-    if let ty::Dynamic(_, _, ty::Dyn) = declared_ret_ty.kind() {
-        // FIXME: We need to verify that the return type is `Sized` after the return expression has
-        // been evaluated so that we have types available for all the nodes being returned, but that
-        // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
-        // causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
-        // while keeping the current ordering we will ignore the tail expression's type because we
-        // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
-        // because we will trigger "unreachable expression" lints unconditionally.
-        // Because of all of this, we perform a crude check to know whether the simplest `!Sized`
-        // case that a newcomer might make, returning a bare trait, and in that case we populate
-        // the tail expression's type so that the suggestion will be correct, but ignore all other
-        // possible cases.
-        fcx.check_expr(&body.value);
-        fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
-    } else {
-        fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
-        fcx.check_return_expr(&body.value, false);
-    }
+    fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
+    fcx.check_return_expr(&body.value, false);
 
     // We insert the deferred_generator_interiors entry after visiting the body.
     // This ensures that all nested generators appear before the entry of this generator.
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 7046269c2de..9659a0ec13d 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -89,6 +89,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             expr_def_id,
             body,
             closure.movability,
+            // Closure "rust-call" ABI doesn't support unsized params
+            false,
         );
 
         let parent_substs = InternalSubsts::identity_for_item(
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index ce30bbeca0b..102a313067f 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -1,4 +1,6 @@
 //! Errors emitted by `rustc_hir_typeck`.
+use std::borrow::Cow;
+
 use crate::fluent_generated as fluent;
 use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, MultiSpan, SubdiagnosticMessage};
 use rustc_macros::{Diagnostic, Subdiagnostic};
@@ -295,3 +297,25 @@ pub enum SuggestBoxing {
         end: Span,
     },
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_typeck_no_associated_item, code = "E0599")]
+pub struct NoAssociatedItem {
+    #[primary_span]
+    pub span: Span,
+    pub item_kind: &'static str,
+    pub item_name: Ident,
+    pub ty_prefix: Cow<'static, str>,
+    pub ty_str: String,
+    pub trait_missing_method: bool,
+}
+
+#[derive(Subdiagnostic)]
+#[note(hir_typeck_candidate_trait_note)]
+pub struct CandidateTraitNote {
+    #[primary_span]
+    pub span: Span,
+    pub trait_name: String,
+    pub item_name: Ident,
+    pub action_or_ty: String,
+}
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index bba049c3819..adc1b090af6 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -721,7 +721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // ICE this expression in particular (see #43162).
                 if let ExprKind::Path(QPath::Resolved(_, path)) = e.kind {
                     if path.segments.len() == 1 && path.segments[0].ident.name == sym::rust {
-                        fatally_break_rust(self.tcx.sess);
+                        fatally_break_rust(self.tcx);
                     }
                 }
             }
@@ -1245,6 +1245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         error,
                         Some((rcvr, args)),
                         expected,
+                        false,
                     ) {
                         err.emit();
                     }
@@ -2468,7 +2469,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             self.suggest_method_call(
                 &mut err,
-                &format!("a method `{field}` also exists, call it with parentheses"),
+                format!("a method `{field}` also exists, call it with parentheses"),
                 field,
                 expr_t,
                 expr,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 9e78e6acba5..9721e3b427d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -4,7 +4,7 @@ use crate::rvalue_scopes;
 use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, RawTy};
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -35,7 +35,9 @@ use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
 use rustc_target::abi::FieldIdx;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCauseCode, ObligationCtxt};
+use rustc_trait_selection::traits::{
+    self, NormalizeExt, ObligationCauseCode, ObligationCtxt, StructurallyNormalizeExt,
+};
 
 use std::collections::hash_map::Entry;
 use std::slice;
@@ -853,6 +855,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let item_name = item_segment.ident;
         let result = self
             .resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id)
+            .and_then(|r| {
+                // lint bare trait if the method is found in the trait
+                if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
+                    diag.emit();
+                }
+                Ok(r)
+            })
             .or_else(|error| {
                 let guar = self
                     .tcx
@@ -863,17 +872,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     _ => Err(guar),
                 };
 
+                let trait_missing_method =
+                    matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
                 // If we have a path like `MyTrait::missing_method`, then don't register
                 // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
                 // register a WF obligation so that we can detect any additional
                 // errors in the self type.
-                if !(matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait()) {
+                if !trait_missing_method {
                     self.register_wf_obligation(
                         ty.raw.into(),
                         qself.span,
                         traits::WellFormed(None),
                     );
                 }
+
+                // emit or cancel the diagnostic for bare traits
+                if span.edition().rust_2021() && let Some(mut diag) = self.tcx.sess.diagnostic().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) {
+                    if trait_missing_method {
+                        // cancel the diag for bare traits when meeting `MyTrait::missing_method`
+                        diag.cancel();
+                    } else {
+                        diag.emit();
+                    }
+                }
+
                 if item_name.name != kw::Empty {
                     if let Some(mut e) = self.report_method_error(
                         span,
@@ -883,10 +905,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         error,
                         None,
                         Expectation::NoExpectation,
+                        trait_missing_method && span.edition().rust_2021(), // emits missing method for trait only after edition 2021
                     ) {
                         e.emit();
                     }
                 }
+
                 result
             });
 
@@ -1438,10 +1462,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Resolves `typ` by a single level if `typ` is a type variable.
+    ///
+    /// When the new solver is enabled, this will also attempt to normalize
+    /// the type if it's a projection (note that it will not deeply normalize
+    /// projections within the type, just the outermost layer of the type).
+    ///
     /// If no resolution is possible, then an error is reported.
     /// Numeric inference variables may be left unresolved.
     pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
-        let ty = self.resolve_vars_with_obligations(ty);
+        let mut ty = self.resolve_vars_with_obligations(ty);
+
+        if self.tcx.trait_solver_next()
+            && let ty::Alias(ty::Projection, _) = ty.kind()
+        {
+            match self
+                .at(&self.misc(sp), self.param_env)
+                .structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut())
+            {
+                Ok(normalized_ty) => {
+                    ty = normalized_ty;
+                },
+                Err(errors) => {
+                    let guar = self.err_ctxt().report_fulfillment_errors(&errors);
+                    return self.tcx.ty_error(guar);
+                }
+            }
+        }
+
         if !ty.is_ty_var() {
             ty
         } else {
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 54b222ade03..b97b55d8f7e 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -72,7 +72,6 @@ use rustc_middle::query::Providers;
 use rustc_middle::traits;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::config;
-use rustc_session::Session;
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::{sym, Span};
 
@@ -213,7 +212,7 @@ fn typeck_with_fallback<'tcx>(
         let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
         let fn_sig = fcx.normalize(body.value.span, fn_sig);
 
-        check_fn(&mut fcx, fn_sig, decl, def_id, body, None);
+        check_fn(&mut fcx, fn_sig, decl, def_id, body, None, tcx.features().unsized_fn_params);
     } else {
         let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = body_ty {
             Some(fcx.next_ty_var(TypeVariableOrigin {
@@ -438,8 +437,8 @@ enum TupleArgumentsFlag {
     TupleArguments,
 }
 
-fn fatally_break_rust(sess: &Session) {
-    let handler = sess.diagnostic();
+fn fatally_break_rust(tcx: TyCtxt<'_>) {
+    let handler = tcx.sess.diagnostic();
     handler.span_bug_no_panic(
         MultiSpan::new(),
         "It looks like you're trying to break rust; would you like some ICE?",
@@ -451,7 +450,7 @@ fn fatally_break_rust(sess: &Session) {
     );
     handler.note_without_error(format!(
         "rustc {} running on {}",
-        option_env!("CFG_VERSION").unwrap_or("unknown_version"),
+        tcx.sess.cfg_version,
         config::host_triple(),
     ));
 }
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 9155a3d8daa..98529b66602 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -158,7 +158,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
             return self.tcx.ty_error_with_message(
                 rustc_span::DUMMY_SP,
-                &format!("failed autoderef {}", pick.autoderefs),
+                format!("failed autoderef {}", pick.autoderefs),
             );
         };
         assert_eq!(n, pick.autoderefs);
@@ -471,7 +471,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             self_ty, method_self_ty, self.span, pick
         );
         let cause = self.cause(
-            self.span,
+            self.self_expr.span,
             ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext {
                 assoc_item: pick.item,
                 param_env: self.param_env,
@@ -482,13 +482,22 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             Ok(InferOk { obligations, value: () }) => {
                 self.register_predicates(obligations);
             }
-            Err(_) => {
-                span_bug!(
-                    self.span,
-                    "{} was a subtype of {} but now is not?",
-                    self_ty,
-                    method_self_ty
-                );
+            Err(terr) => {
+                // FIXME(arbitrary_self_types): We probably should limit the
+                // situations where this can occur by adding additional restrictions
+                // to the feature, like the self type can't reference method substs.
+                if self.tcx.features().arbitrary_self_types {
+                    self.err_ctxt()
+                        .report_mismatched_types(&cause, method_self_ty, self_ty, terr)
+                        .emit();
+                } else {
+                    span_bug!(
+                        self.span,
+                        "{} was a subtype of {} but now is not?",
+                        self_ty,
+                        method_self_ty
+                    );
+                }
             }
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index cf9290c1a48..6f4d674ba10 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -13,7 +13,7 @@ pub use self::MethodError::*;
 use crate::errors::OpMethodGenericParams;
 use crate::FnCtxt;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_errors::{Applicability, Diagnostic, SubdiagnosticMessage};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
 use rustc_hir::def_id::DefId;
@@ -130,7 +130,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(crate) fn suggest_method_call(
         &self,
         err: &mut Diagnostic,
-        msg: &str,
+        msg: impl Into<SubdiagnosticMessage> + std::fmt::Debug,
         method_name: Ident,
         self_ty: Ty<'tcx>,
         call_expr: &hir::Expr<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 550a87e6102..17364509844 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -2,6 +2,8 @@
 //! found or is otherwise invalid.
 
 use crate::errors;
+use crate::errors::CandidateTraitNote;
+use crate::errors::NoAssociatedItem;
 use crate::Expectation;
 use crate::FnCtxt;
 use rustc_ast::ast::Mutability;
@@ -38,6 +40,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
 use rustc_trait_selection::traits::{
     FulfillmentError, Obligation, ObligationCause, ObligationCauseCode,
 };
+use std::borrow::Cow;
 
 use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
 use super::{CandidateSource, MethodError, NoMatchData};
@@ -112,6 +115,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: MethodError<'tcx>,
         args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>,
         expected: Expectation<'tcx>,
+        trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
         // Avoid suggestions when we don't know what's going on.
         if rcvr_ty.references_error() {
@@ -136,6 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     sugg_span,
                     &mut no_match_data,
                     expected,
+                    trait_missing_method,
                 );
             }
 
@@ -278,12 +283,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         sugg_span: Span,
         no_match_data: &mut NoMatchData<'tcx>,
         expected: Expectation<'tcx>,
+        trait_missing_method: bool,
     ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
         let mode = no_match_data.mode;
         let tcx = self.tcx;
         let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
-        let (ty_str, ty_file) = tcx.short_ty_string(rcvr_ty);
-        let short_ty_str = with_forced_trimmed_paths!(rcvr_ty.to_string());
+        let ((mut ty_str, ty_file), short_ty_str) = if trait_missing_method
+            && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() {
+                ((predicates.to_string(), None), with_forced_trimmed_paths!(predicates.to_string()))
+            } else {
+                (tcx.short_ty_string(rcvr_ty), with_forced_trimmed_paths!(rcvr_ty.to_string()))
+            };
         let is_method = mode == Mode::MethodCall;
         let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
         let similar_candidate = no_match_data.similar_candidate;
@@ -355,25 +365,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             self.suggest_missing_writer(rcvr_ty, args)
         } else {
-            struct_span_err!(
-                tcx.sess,
+            tcx.sess.create_err(NoAssociatedItem {
                 span,
-                E0599,
-                "no {} named `{}` found for {} `{}` in the current scope",
                 item_kind,
                 item_name,
-                rcvr_ty.prefix_string(self.tcx),
-                ty_str_reported,
-            )
+                ty_prefix: if trait_missing_method {
+                    // FIXME(mu001999) E0599 maybe not suitable here because it is for types
+                    Cow::from("trait")
+                } else {
+                    rcvr_ty.prefix_string(self.tcx)
+                },
+                ty_str: ty_str_reported,
+                trait_missing_method,
+            })
         };
         if tcx.sess.source_map().is_multiline(sugg_span) {
             err.span_label(sugg_span.with_hi(span.lo()), "");
         }
-        let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
-            short_ty_str
-        } else {
-            ty_str
-        };
+
+        if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
+            ty_str = short_ty_str;
+        }
+
         if let Some(file) = ty_file {
             err.note(format!("the full type name has been written to '{}'", file.display(),));
         }
@@ -1067,6 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 &static_candidates,
                 unsatisfied_bounds,
                 expected.only_has_type(self),
+                trait_missing_method,
             );
         }
 
@@ -2375,6 +2389,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         static_candidates: &[CandidateSource],
         unsatisfied_bounds: bool,
         return_type: Option<Ty<'tcx>>,
+        trait_missing_method: bool,
     ) {
         let mut alt_rcvr_sugg = false;
         if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
@@ -2598,11 +2613,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 },
                 _ => None,
             };
-            err.help(if param_type.is_some() {
-                "items from traits can only be used if the type parameter is bounded by the trait"
-            } else {
-                "items from traits can only be used if the trait is implemented and in scope"
-            });
+            if !trait_missing_method {
+                err.help(if param_type.is_some() {
+                    "items from traits can only be used if the type parameter is bounded by the trait"
+                } else {
+                    "items from traits can only be used if the trait is implemented and in scope"
+                });
+            }
+
             let candidates_len = candidates.len();
             let message = |action| {
                 format!(
@@ -2751,27 +2769,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 (candidates, Vec::new())
             };
 
-            let action = if let Some(param) = param_type {
-                format!("restrict type parameter `{}` with", param)
-            } else {
-                // FIXME: it might only need to be imported into scope, not implemented.
-                "implement".to_string()
-            };
             match &potential_candidates[..] {
                 [] => {}
                 [trait_info] if trait_info.def_id.is_local() => {
-                    err.span_note(
-                        self.tcx.def_span(trait_info.def_id),
-                        format!(
-                            "`{}` defines an item `{}`, perhaps you need to {} it",
-                            self.tcx.def_path_str(trait_info.def_id),
-                            item_name,
-                            action
-                        ),
-                    );
+                    err.subdiagnostic(CandidateTraitNote {
+                        span: self.tcx.def_span(trait_info.def_id),
+                        trait_name: self.tcx.def_path_str(trait_info.def_id),
+                        item_name,
+                        action_or_ty: if trait_missing_method {
+                            "NONE".to_string()
+                        } else {
+                            param_type.map_or_else(
+                                || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
+                                ToString::to_string,
+                            )
+                        },
+                    });
                 }
                 trait_infos => {
-                    let mut msg = message(action);
+                    let mut msg = message(param_type.map_or_else(
+                        || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
+                        |param| format!("restrict type parameter `{}` with", param),
+                    ));
                     for (i, trait_info) in trait_infos.iter().enumerate() {
                         msg.push_str(&format!(
                             "\ncandidate #{}: `{}`",
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 59bee69cfff..0f21fc1e662 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -5,11 +5,10 @@
 use crate::FnCtxt;
 use hir::def_id::LocalDefId;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::ErrorGuaranteed;
+use rustc_errors::{ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
-use rustc_infer::infer::InferCtxt;
 use rustc_middle::hir::place::Place as HirPlace;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
@@ -83,10 +82,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.typeck_results.treat_byte_string_as_slice =
             mem::take(&mut self.typeck_results.borrow_mut().treat_byte_string_as_slice);
 
-        if let Some(e) = self.tainted_by_errors() {
-            wbcx.typeck_results.tainted_by_errors = Some(e);
-        }
-
         debug!("writeback: typeck results for {:?} are {:#?}", item_def_id, wbcx.typeck_results);
 
         self.tcx.arena.alloc(wbcx.typeck_results)
@@ -119,12 +114,21 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     ) -> WritebackCx<'cx, 'tcx> {
         let owner = body.id().hir_id.owner;
 
-        WritebackCx {
+        let mut wbcx = WritebackCx {
             fcx,
             typeck_results: ty::TypeckResults::new(owner),
             body,
             rustc_dump_user_substs,
+        };
+
+        // HACK: We specifically don't want the (opaque) error from tainting our
+        // inference context. That'll prevent us from doing opaque type inference
+        // later on in borrowck, which affects diagnostic spans pretty negatively.
+        if let Some(e) = fcx.tainted_by_errors() {
+            wbcx.typeck_results.tainted_by_errors = Some(e);
         }
+
+        wbcx
     }
 
     fn tcx(&self) -> TyCtxt<'tcx> {
@@ -237,7 +241,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                     // error has been emitted. (#64638)
                     self.fcx.tcx.ty_error_with_message(
                         e.span,
-                        &format!("bad index {:?} for base: `{:?}`", index, base),
+                        format!("bad index {:?} for base: `{:?}`", index, base),
                     )
                 });
                 let index_ty = self.fcx.resolve_vars_if_possible(index_ty);
@@ -579,13 +583,26 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 continue;
             }
 
-            let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
-                opaque_type_key,
-                self.fcx.infcx.tcx,
-                true,
-            );
-
-            self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type);
+            let hidden_type =
+                self.tcx().erase_regions(hidden_type.remap_generic_params_to_declaration_params(
+                    opaque_type_key,
+                    self.tcx(),
+                    true,
+                ));
+
+            if let Some(last_opaque_ty) = self
+                .typeck_results
+                .concrete_opaque_types
+                .insert(opaque_type_key.def_id, hidden_type)
+                && last_opaque_ty.ty != hidden_type.ty
+            {
+                hidden_type
+                    .report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
+                    .stash(
+                        self.tcx().def_span(opaque_type_key.def_id),
+                        StashKey::OpaqueHiddenTypeMismatch,
+                    );
+            }
         }
     }
 
@@ -692,15 +709,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             fcx_typeck_results.offset_of_data().items_in_stable_order()
         {
             let hir_id = hir::HirId { owner: common_hir_owner, local_id };
-
-            if cfg!(debug_assertions) && container.has_infer() {
-                span_bug!(
-                    hir_id.to_span(self.fcx.tcx),
-                    "writeback: `{:?}` has inference variables",
-                    container
-                );
-            };
-
+            let container = self.resolve(container, &hir_id);
             self.typeck_results.offset_of_data_mut().insert(hir_id, (container, indices.clone()));
         }
     }
@@ -745,8 +754,7 @@ impl Locatable for hir::HirId {
 /// The Resolver. This is the type folding engine that detects
 /// unresolved types and so forth.
 struct Resolver<'cx, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    infcx: &'cx InferCtxt<'tcx>,
+    fcx: &'cx FnCtxt<'cx, 'tcx>,
     span: &'cx dyn Locatable,
     body: &'tcx hir::Body<'tcx>,
 
@@ -760,18 +768,18 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         span: &'cx dyn Locatable,
         body: &'tcx hir::Body<'tcx>,
     ) -> Resolver<'cx, 'tcx> {
-        Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: None }
+        Resolver { fcx, span, body, replaced_with_error: None }
     }
 
     fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) -> ErrorGuaranteed {
-        match self.tcx.sess.has_errors() {
+        match self.fcx.tcx.sess.has_errors() {
             Some(e) => e,
             None => self
-                .infcx
+                .fcx
                 .err_ctxt()
                 .emit_inference_failure_err(
-                    self.tcx.hir().body_owner_def_id(self.body.id()),
-                    self.span.to_span(self.tcx),
+                    self.fcx.tcx.hir().body_owner_def_id(self.body.id()),
+                    self.span.to_span(self.fcx.tcx),
                     p.into(),
                     E0282,
                     false,
@@ -803,40 +811,46 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEarlyRegions<'tcx> {
 
 impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
     fn interner(&self) -> TyCtxt<'tcx> {
-        self.tcx
+        self.fcx.tcx
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        match self.infcx.fully_resolve(t) {
+        match self.fcx.fully_resolve(t) {
+            Ok(t) if self.fcx.tcx.trait_solver_next() => {
+                // We must normalize erasing regions here, since later lints
+                // expect that types that show up in the typeck are fully
+                // normalized.
+                self.fcx.tcx.try_normalize_erasing_regions(self.fcx.param_env, t).unwrap_or(t)
+            }
             Ok(t) => {
                 // Do not anonymize late-bound regions
                 // (e.g. keep `for<'a>` named `for<'a>`).
                 // This allows NLL to generate error messages that
                 // refer to the higher-ranked lifetime names written by the user.
-                EraseEarlyRegions { tcx: self.tcx }.fold_ty(t)
+                EraseEarlyRegions { tcx: self.fcx.tcx }.fold_ty(t)
             }
             Err(_) => {
                 debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
                 let e = self.report_error(t);
                 self.replaced_with_error = Some(e);
-                self.interner().ty_error(e)
+                self.fcx.tcx.ty_error(e)
             }
         }
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         debug_assert!(!r.is_late_bound(), "Should not be resolving bound region.");
-        self.tcx.lifetimes.re_erased
+        self.fcx.tcx.lifetimes.re_erased
     }
 
     fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
-        match self.infcx.fully_resolve(ct) {
-            Ok(ct) => self.tcx.erase_regions(ct),
+        match self.fcx.fully_resolve(ct) {
+            Ok(ct) => self.fcx.tcx.erase_regions(ct),
             Err(_) => {
                 debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
                 let e = self.report_error(ct);
                 self.replaced_with_error = Some(e);
-                self.interner().const_error(ct.ty(), e)
+                self.fcx.tcx.const_error(ct.ty(), e)
             }
         }
     }
diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs
index dc981c6179e..25bf83f64a0 100644
--- a/compiler/rustc_incremental/src/persist/file_format.rs
+++ b/compiler/rustc_incremental/src/persist/file_format.rs
@@ -14,6 +14,7 @@ use rustc_data_structures::memmap::Mmap;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_serialize::Encoder;
 use rustc_session::Session;
+use std::borrow::Cow;
 use std::env;
 use std::fs;
 use std::io::{self, Read};
@@ -25,17 +26,12 @@ const FILE_MAGIC: &[u8] = b"RSIC";
 /// Change this if the header format changes.
 const HEADER_FORMAT_VERSION: u16 = 0;
 
-/// A version string that hopefully is always different for compiler versions
-/// with different encodings of incremental compilation artifacts. Contains
-/// the Git commit hash.
-const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
-
-pub(crate) fn write_file_header(stream: &mut FileEncoder, nightly_build: bool) {
+pub(crate) fn write_file_header(stream: &mut FileEncoder, sess: &Session) {
     stream.emit_raw_bytes(FILE_MAGIC);
     stream
         .emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8]);
 
-    let rustc_version = rustc_version(nightly_build);
+    let rustc_version = rustc_version(sess.is_nightly_build(), sess.cfg_version);
     assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
     stream.emit_raw_bytes(&[rustc_version.len() as u8]);
     stream.emit_raw_bytes(rustc_version.as_bytes());
@@ -73,7 +69,7 @@ where
         }
     };
 
-    write_file_header(&mut encoder, sess.is_nightly_build());
+    write_file_header(&mut encoder, sess);
 
     match encode(encoder) {
         Ok(position) => {
@@ -100,9 +96,10 @@ where
 /// - Returns `Err(..)` if some kind of IO error occurred while reading the
 ///   file.
 pub fn read_file(
-    report_incremental_info: bool,
     path: &Path,
-    nightly_build: bool,
+    report_incremental_info: bool,
+    is_nightly_build: bool,
+    cfg_version: &'static str,
 ) -> io::Result<Option<(Mmap, usize)>> {
     let file = match fs::File::open(path) {
         Ok(file) => file,
@@ -152,7 +149,7 @@ pub fn read_file(
         let mut buffer = vec![0; rustc_version_str_len];
         file.read_exact(&mut buffer)?;
 
-        if buffer != rustc_version(nightly_build).as_bytes() {
+        if buffer != rustc_version(is_nightly_build, cfg_version).as_bytes() {
             report_format_mismatch(report_incremental_info, path, "Different compiler version");
             return Ok(None);
         }
@@ -174,17 +171,15 @@ fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: &
     }
 }
 
-fn rustc_version(nightly_build: bool) -> String {
+/// A version string that hopefully is always different for compiler versions
+/// with different encodings of incremental compilation artifacts. Contains
+/// the Git commit hash.
+fn rustc_version(nightly_build: bool, cfg_version: &'static str) -> Cow<'static, str> {
     if nightly_build {
-        if let Some(val) = env::var_os("RUSTC_FORCE_RUSTC_VERSION") {
-            return val.to_string_lossy().into_owned();
+        if let Ok(val) = env::var("RUSTC_FORCE_RUSTC_VERSION") {
+            return val.into();
         }
     }
 
-    RUSTC_VERSION
-        .expect(
-            "Cannot use rustc without explicit version for \
-                          incremental compilation",
-        )
-        .to_string()
+    cfg_version.into()
 }
diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs
index ec7fcbdf884..a4407a93ff3 100644
--- a/compiler/rustc_incremental/src/persist/load.rs
+++ b/compiler/rustc_incremental/src/persist/load.rs
@@ -73,12 +73,22 @@ impl<T: Default> LoadResult<T> {
     }
 }
 
-fn load_data(
-    report_incremental_info: bool,
+fn load_data(path: &Path, sess: &Session) -> LoadResult<(Mmap, usize)> {
+    load_data_no_sess(
+        path,
+        sess.opts.unstable_opts.incremental_info,
+        sess.is_nightly_build(),
+        sess.cfg_version,
+    )
+}
+
+fn load_data_no_sess(
     path: &Path,
-    nightly_build: bool,
+    report_incremental_info: bool,
+    is_nightly_build: bool,
+    cfg_version: &'static str,
 ) -> LoadResult<(Mmap, usize)> {
-    match file_format::read_file(report_incremental_info, path, nightly_build) {
+    match file_format::read_file(path, report_incremental_info, is_nightly_build, cfg_version) {
         Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos },
         Ok(None) => {
             // The file either didn't exist or was produced by an incompatible
@@ -138,14 +148,13 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
     let expected_hash = sess.opts.dep_tracking_hash(false);
 
     let mut prev_work_products = FxHashMap::default();
-    let nightly_build = sess.is_nightly_build();
 
     // If we are only building with -Zquery-dep-graph but without an actual
     // incr. comp. session directory, we skip this. Otherwise we'd fail
     // when trying to load work products.
     if sess.incr_comp_session_dir_opt().is_some() {
         let work_products_path = work_products_path(sess);
-        let load_result = load_data(report_incremental_info, &work_products_path, nightly_build);
+        let load_result = load_data(&work_products_path, sess);
 
         if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
             // Decode the list of work_products
@@ -173,10 +182,13 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
         }
     }
 
+    let is_nightly_build = sess.is_nightly_build();
+    let cfg_version = sess.cfg_version;
+
     MaybeAsync::Async(std::thread::spawn(move || {
         let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
 
-        match load_data(report_incremental_info, &path, nightly_build) {
+        match load_data_no_sess(&path, report_incremental_info, is_nightly_build, cfg_version) {
             LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
             LoadResult::LoadDepGraph(path, err) => LoadResult::LoadDepGraph(path, err),
             LoadResult::DecodeIncrCache(err) => LoadResult::DecodeIncrCache(err),
@@ -218,11 +230,7 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache<'_>> {
 
     let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache");
 
-    match load_data(
-        sess.opts.unstable_opts.incremental_info,
-        &query_cache_path(sess),
-        sess.is_nightly_build(),
-    ) {
+    match load_data(&query_cache_path(sess), sess) {
         LoadResult::Ok { data: (bytes, start_pos) } => {
             Some(OnDiskCache::new(sess, bytes, start_pos))
         }
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 1441e64e41f..7376be6be8b 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -164,7 +164,7 @@ pub fn build_dep_graph(
         }
     };
 
-    file_format::write_file_header(&mut encoder, sess.is_nightly_build());
+    file_format::write_file_header(&mut encoder, sess);
 
     // First encode the commandline arguments hash
     sess.opts.dep_tracking_hash(false).encode(&mut encoder);
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 3605e10fecd..de9afbbcaab 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -153,20 +153,22 @@ impl<'tcx> InferCtxt<'tcx> {
 
     /// Used by the new solver as that one takes the opaque types at the end of a probe
     /// to deal with multiple candidates without having to recompute them.
-    pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+    pub fn clone_opaque_types_for_query_response(
+        &self,
+    ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
         self.inner
             .borrow()
             .opaque_type_storage
             .opaque_types
             .iter()
-            .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
+            .map(|(k, v)| (*k, v.hidden_type.ty))
             .collect()
     }
 
-    fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+    fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
         std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
             .into_iter()
-            .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
+            .map(|(k, v)| (k, v.hidden_type.ty))
             .collect()
     }
 
@@ -507,8 +509,22 @@ impl<'tcx> InferCtxt<'tcx> {
             let a = substitute_value(self.tcx, &result_subst, a);
             let b = substitute_value(self.tcx, &result_subst, b);
             debug!(?a, ?b, "constrain opaque type");
-            obligations
-                .extend(self.at(cause, param_env).eq(DefineOpaqueTypes::Yes, a, b)?.obligations);
+            // We use equate here instead of, for example, just registering the
+            // opaque type's hidden value directly, because we may be instantiating
+            // a query response that was canonicalized in an InferCtxt that had
+            // a different defining anchor. In that case, we may have inferred
+            // `NonLocalOpaque := LocalOpaque` but can only instantiate it in
+            // the other direction as `LocalOpaque := NonLocalOpaque`. Using eq
+            // here allows us to try both directions (in `InferCtxt::handle_opaque_type`).
+            obligations.extend(
+                self.at(cause, param_env)
+                    .eq(
+                        DefineOpaqueTypes::Yes,
+                        self.tcx.mk_opaque(a.def_id.to_def_id(), a.substs),
+                        b,
+                    )?
+                    .obligations,
+            );
         }
 
         Ok(InferOk { value: result_subst, obligations })
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 545310ad351..b88ba04b273 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -530,19 +530,18 @@ impl<'tcx> InferCtxt<'tcx> {
         // these are the same span, but not in cases like `-> (impl
         // Foo, impl Bar)`.
         let span = cause.span;
-
-        let mut obligations = vec![];
         let prev = self.inner.borrow_mut().opaque_types().register(
             OpaqueTypeKey { def_id, substs },
             OpaqueHiddenType { ty: hidden_ty, span },
             origin,
         );
-        if let Some(prev) = prev {
-            obligations = self
-                .at(&cause, param_env)
+        let mut obligations = if let Some(prev) = prev {
+            self.at(&cause, param_env)
                 .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)?
-                .obligations;
-        }
+                .obligations
+        } else {
+            Vec::new()
+        };
 
         let item_bounds = tcx.explicit_item_bounds(def_id);
 
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index c9e857141c9..681819703c2 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -80,7 +80,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> FxHashSet<(String, Option<String
                     ($reason: expr) => {
                         early_error(
                             ErrorOutputType::default(),
-                            &format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s),
+                            format!(concat!("invalid `--cfg` argument: `{}` (", $reason, ")"), s),
                         );
                     };
                 }
@@ -139,10 +139,7 @@ pub fn parse_check_cfg(specs: Vec<String>) -> CheckCfg {
                 ($reason: expr) => {
                     early_error(
                         ErrorOutputType::default(),
-                        &format!(
-                            concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"),
-                            s
-                        ),
+                        format!(concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"), s),
                     )
                 };
             }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index bbf9d9d515d..42d8d228091 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -89,6 +89,7 @@ pub fn register_plugins<'a>(
         crate_name,
         sess.crate_types().contains(&CrateType::Executable),
         sess.opts.cg.metadata.clone(),
+        sess.cfg_version,
     );
     sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
     rustc_incremental::prepare_session_directory(sess, crate_name, stable_crate_id)?;
@@ -486,6 +487,11 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
             files.push(normalize_path(profile_sample.as_path().to_path_buf()));
         }
 
+        // Debugger visualizer files
+        for debugger_visualizer in tcx.debugger_visualizers(LOCAL_CRATE) {
+            files.push(normalize_path(debugger_visualizer.path.clone().unwrap()));
+        }
+
         if sess.binary_dep_depinfo() {
             if let Some(ref backend) = sess.opts.unstable_opts.codegen_backend {
                 if backend.contains('.') {
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 6483d51a0b9..c441a8ffd6f 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -369,7 +369,7 @@ impl Linker {
 
         if sess.opts.unstable_opts.no_link {
             let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT);
-            CodegenResults::serialize_rlink(&rlink_file, &codegen_results)
+            CodegenResults::serialize_rlink(sess, &rlink_file, &codegen_results)
                 .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?;
             return Ok(());
         }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 1bae771e373..28e719a40e5 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -52,7 +52,8 @@ fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
         output_file: None,
         temps_dir,
     };
-    let sess = build_session(sessopts, io, None, registry, vec![], Default::default(), None, None);
+    let sess =
+        build_session(sessopts, io, None, registry, vec![], Default::default(), None, None, "");
     (sess, cfg)
 }
 
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 8d37b1053d8..cb19750203e 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -88,7 +88,7 @@ pub fn create_session(
     ) {
         Ok(bundle) => bundle,
         Err(e) => {
-            early_error(sopts.error_format, &format!("failed to load fluent bundle: {e}"));
+            early_error(sopts.error_format, format!("failed to load fluent bundle: {e}"));
         }
     };
 
@@ -104,6 +104,7 @@ pub fn create_session(
         lint_caps,
         file_loader,
         target_override,
+        rustc_version_str().unwrap_or("unknown"),
     );
 
     codegen_backend.init(&sess);
@@ -220,13 +221,13 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
 fn load_backend_from_dylib(path: &Path) -> MakeBackendFn {
     let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| {
         let err = format!("couldn't load codegen backend {path:?}: {err}");
-        early_error(ErrorOutputType::default(), &err);
+        early_error(ErrorOutputType::default(), err);
     });
 
     let backend_sym = unsafe { lib.get::<MakeBackendFn>(b"__rustc_codegen_backend") }
         .unwrap_or_else(|e| {
             let err = format!("couldn't load codegen backend: {e}");
-            early_error(ErrorOutputType::default(), &err);
+            early_error(ErrorOutputType::default(), err);
         });
 
     // Intentionally leak the dynamic library. We can't ever unload it
@@ -320,7 +321,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
             "failed to find a `codegen-backends` folder \
                            in the sysroot candidates:\n* {candidates}"
         );
-        early_error(ErrorOutputType::default(), &err);
+        early_error(ErrorOutputType::default(), err);
     });
     info!("probing {} for a codegen backend", sysroot.display());
 
@@ -331,7 +332,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
             sysroot.display(),
             e
         );
-        early_error(ErrorOutputType::default(), &err);
+        early_error(ErrorOutputType::default(), err);
     });
 
     let mut file: Option<PathBuf> = None;
@@ -359,7 +360,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
                 prev.display(),
                 path.display()
             );
-            early_error(ErrorOutputType::default(), &err);
+            early_error(ErrorOutputType::default(), err);
         }
         file = Some(path.clone());
     }
@@ -368,7 +369,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
         Some(ref s) => load_backend_from_dylib(s),
         None => {
             let err = format!("unsupported builtin codegen backend `{backend_name}`");
-            early_error(ErrorOutputType::default(), &err);
+            early_error(ErrorOutputType::default(), err);
         }
     }
 }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index a5639404faf..e1658d3ff82 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -521,18 +521,18 @@ lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its ass
 
 lint_opaque_hidden_inferred_bound_sugg = add this bound
 
-lint_drop_ref = calls to `std::mem::drop` with a reference instead of an owned value does nothing
+lint_dropping_references = calls to `std::mem::drop` with a reference instead of an owned value does nothing
     .label = argument has type `{$arg_ty}`
     .note = use `let _ = ...` to ignore the expression or result
 
-lint_drop_copy = calls to `std::mem::drop` with a value that implements `Copy` does nothing
+lint_dropping_copy_types = calls to `std::mem::drop` with a value that implements `Copy` does nothing
     .label = argument has type `{$arg_ty}`
     .note = use `let _ = ...` to ignore the expression or result
 
-lint_forget_ref = calls to `std::mem::forget` with a reference instead of an owned value does nothing
+lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing
     .label = argument has type `{$arg_ty}`
     .note = use `let _ = ...` to ignore the expression or result
 
-lint_forget_copy = calls to `std::mem::forget` with a value that implements `Copy` does nothing
+lint_forgetting_copy_types = calls to `std::mem::forget` with a value that implements `Copy` does nothing
     .label = argument has type `{$arg_ty}`
     .note = use `let _ = ...` to ignore the expression or result
diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs
index 259abc2af11..ed2b384805e 100644
--- a/compiler/rustc_lint/src/drop_forget_useless.rs
+++ b/compiler/rustc_lint/src/drop_forget_useless.rs
@@ -7,7 +7,7 @@ use crate::{
 };
 
 declare_lint! {
-    /// The `drop_ref` lint checks for calls to `std::mem::drop` with a reference
+    /// The `dropping_references` lint checks for calls to `std::mem::drop` with a reference
     /// instead of an owned value.
     ///
     /// ### Example
@@ -29,13 +29,13 @@ declare_lint! {
     /// reference itself, which is a no-op. It will not call the `drop` method (from
     /// the `Drop` trait implementation) on the underlying referenced value, which
     /// is likely what was intended.
-    pub DROP_REF,
+    pub DROPPING_REFERENCES,
     Warn,
     "calls to `std::mem::drop` with a reference instead of an owned value"
 }
 
 declare_lint! {
-    /// The `forget_ref` lint checks for calls to `std::mem::forget` with a reference
+    /// The `forgetting_references` lint checks for calls to `std::mem::forget` with a reference
     /// instead of an owned value.
     ///
     /// ### Example
@@ -52,13 +52,13 @@ declare_lint! {
     /// Calling `forget` on a reference will only forget the
     /// reference itself, which is a no-op. It will not forget the underlying
     /// referenced value, which is likely what was intended.
-    pub FORGET_REF,
+    pub FORGETTING_REFERENCES,
     Warn,
     "calls to `std::mem::forget` with a reference instead of an owned value"
 }
 
 declare_lint! {
-    /// The `drop_copy` lint checks for calls to `std::mem::drop` with a value
+    /// The `dropping_copy_types` lint checks for calls to `std::mem::drop` with a value
     /// that derives the Copy trait.
     ///
     /// ### Example
@@ -76,13 +76,13 @@ declare_lint! {
     /// Calling `std::mem::drop` [does nothing for types that
     /// implement Copy](https://doc.rust-lang.org/std/mem/fn.drop.html), since the
     /// value will be copied and moved into the function on invocation.
-    pub DROP_COPY,
+    pub DROPPING_COPY_TYPES,
     Warn,
     "calls to `std::mem::drop` with a value that implements Copy"
 }
 
 declare_lint! {
-    /// The `forget_copy` lint checks for calls to `std::mem::forget` with a value
+    /// The `forgetting_copy_types` lint checks for calls to `std::mem::forget` with a value
     /// that derives the Copy trait.
     ///
     /// ### Example
@@ -104,12 +104,12 @@ declare_lint! {
     /// An alternative, but also valid, explanation is that Copy types do not
     /// implement the Drop trait, which means they have no destructors. Without a
     /// destructor, there is nothing for `std::mem::forget` to ignore.
-    pub FORGET_COPY,
+    pub FORGETTING_COPY_TYPES,
     Warn,
     "calls to `std::mem::forget` with a value that implements Copy"
 }
 
-declare_lint_pass!(DropForgetUseless => [DROP_REF, FORGET_REF, DROP_COPY, FORGET_COPY]);
+declare_lint_pass!(DropForgetUseless => [DROPPING_REFERENCES, FORGETTING_REFERENCES, DROPPING_COPY_TYPES, FORGETTING_COPY_TYPES]);
 
 impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
@@ -123,16 +123,16 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
             let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
             match fn_name {
                 sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => {
-                    cx.emit_spanned_lint(DROP_REF, expr.span, DropRefDiag { arg_ty, label: arg.span });
+                    cx.emit_spanned_lint(DROPPING_REFERENCES, expr.span, DropRefDiag { arg_ty, label: arg.span });
                 },
                 sym::mem_forget if arg_ty.is_ref() => {
-                    cx.emit_spanned_lint(FORGET_REF, expr.span, ForgetRefDiag { arg_ty, label: arg.span });
+                    cx.emit_spanned_lint(FORGETTING_REFERENCES, expr.span, ForgetRefDiag { arg_ty, label: arg.span });
                 },
                 sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
-                    cx.emit_spanned_lint(DROP_COPY, expr.span, DropCopyDiag { arg_ty, label: arg.span });
+                    cx.emit_spanned_lint(DROPPING_COPY_TYPES, expr.span, DropCopyDiag { arg_ty, label: arg.span });
                 }
                 sym::mem_forget if is_copy => {
-                    cx.emit_spanned_lint(FORGET_COPY, expr.span, ForgetCopyDiag { arg_ty, label: arg.span });
+                    cx.emit_spanned_lint(FORGETTING_COPY_TYPES, expr.span, ForgetCopyDiag { arg_ty, label: arg.span });
                 }
                 _ => return,
             };
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 8e48806b504..de1c2be2875 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -662,9 +662,9 @@ pub struct ForLoopsOverFalliblesSuggestion<'a> {
     pub end_span: Span,
 }
 
-// drop_ref.rs
+// drop_forget_useless.rs
 #[derive(LintDiagnostic)]
-#[diag(lint_drop_ref)]
+#[diag(lint_dropping_references)]
 #[note]
 pub struct DropRefDiag<'a> {
     pub arg_ty: Ty<'a>,
@@ -673,7 +673,7 @@ pub struct DropRefDiag<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_drop_copy)]
+#[diag(lint_dropping_copy_types)]
 #[note]
 pub struct DropCopyDiag<'a> {
     pub arg_ty: Ty<'a>,
@@ -682,7 +682,7 @@ pub struct DropCopyDiag<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_forget_ref)]
+#[diag(lint_forgetting_references)]
 #[note]
 pub struct ForgetRefDiag<'a> {
     pub arg_ty: Ty<'a>,
@@ -691,7 +691,7 @@ pub struct ForgetRefDiag<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_forget_copy)]
+#[diag(lint_forgetting_copy_types)]
 #[note]
 pub struct ForgetCopyDiag<'a> {
     pub arg_ty: Ty<'a>,
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index eb175e96997..0fe140e08d2 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -103,8 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
             && let ty = cx.typeck_results().expr_ty(&await_expr)
             && let ty::Alias(ty::Opaque, ty::AliasTy { def_id: future_def_id, .. }) = ty.kind()
             && cx.tcx.ty_is_opaque_future(ty)
-            // FIXME: This also includes non-async fns that return `impl Future`.
             && let async_fn_def_id = cx.tcx.parent(*future_def_id)
+            && matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn)
+            // Check that this `impl Future` actually comes from an `async fn`
+            && cx.tcx.asyncness(async_fn_def_id).is_async()
             && check_must_use_def(
                 cx,
                 async_fn_def_id,
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 7b774d6865c..c43a0272477 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -1463,63 +1463,6 @@ LLVMRustGetBitcodeSliceFromObjectData(const char *data,
   return BitcodeOrError->getBufferStart();
 }
 
-// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
-// the comment in `back/lto.rs` for why this exists.
-extern "C" void
-LLVMRustThinLTOGetDICompileUnit(LLVMModuleRef Mod,
-                                DICompileUnit **A,
-                                DICompileUnit **B) {
-  Module *M = unwrap(Mod);
-  DICompileUnit **Cur = A;
-  DICompileUnit **Next = B;
-  for (DICompileUnit *CU : M->debug_compile_units()) {
-    *Cur = CU;
-    Cur = Next;
-    Next = nullptr;
-    if (Cur == nullptr)
-      break;
-  }
-}
-
-// Rewrite all `DICompileUnit` pointers to the `DICompileUnit` specified. See
-// the comment in `back/lto.rs` for why this exists.
-extern "C" void
-LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) {
-  Module *M = unwrap(Mod);
-
-  // If the original source module didn't have a `DICompileUnit` then try to
-  // merge all the existing compile units. If there aren't actually any though
-  // then there's not much for us to do so return.
-  if (Unit == nullptr) {
-    for (DICompileUnit *CU : M->debug_compile_units()) {
-      Unit = CU;
-      break;
-    }
-    if (Unit == nullptr)
-      return;
-  }
-
-  // Use LLVM's built-in `DebugInfoFinder` to find a bunch of debuginfo and
-  // process it recursively. Note that we used to specifically iterate over
-  // instructions to ensure we feed everything into it, but `processModule`
-  // started doing this the same way in LLVM 7 (commit d769eb36ab2b8).
-  DebugInfoFinder Finder;
-  Finder.processModule(*M);
-
-  // After we've found all our debuginfo, rewrite all subprograms to point to
-  // the same `DICompileUnit`.
-  for (auto &F : Finder.subprograms()) {
-    F->replaceUnit(Unit);
-  }
-
-  // Erase any other references to other `DICompileUnit` instances, the verifier
-  // will later ensure that we don't actually have any other stale references to
-  // worry about.
-  auto *MD = M->getNamedMetadata("llvm.dbg.cu");
-  MD->clearOperands();
-  MD->addOperand(Unit);
-}
-
 // Computes the LTO cache key for the provided 'ModId' in the given 'Data',
 // storing the result in 'KeyOut'.
 // Currently, this cache key is a SHA-1 hash of anything that could affect
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 001d53b1099..d0d41c614d6 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -253,7 +253,7 @@ fn add_query_desc_cached_impl(
         quote! {
             #[allow(unused_variables, unused_braces, rustc::pass_by_value)]
             #[inline]
-            pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::query_keys::#name<'tcx>) -> bool {
+            pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::query::queries::#name::Key<'tcx>) -> bool {
                 #expr
             }
         }
@@ -262,7 +262,7 @@ fn add_query_desc_cached_impl(
             // we're taking `key` by reference, but some rustc types usually prefer being passed by value
             #[allow(rustc::pass_by_value)]
             #[inline]
-            pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::query::query_keys::#name<'tcx>) -> bool {
+            pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::query::queries::#name::Key<'tcx>) -> bool {
                 false
             }
         }
@@ -273,7 +273,7 @@ fn add_query_desc_cached_impl(
 
     let desc = quote! {
         #[allow(unused_variables)]
-        pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::query_keys::#name<'tcx>) -> String {
+        pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::query::queries::#name::Key<'tcx>) -> String {
             let (#tcx, #key) = (tcx, key);
             ::rustc_middle::ty::print::with_no_trimmed_paths!(
                 format!(#desc)
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index e6e7d25773e..209bf395624 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -148,11 +148,15 @@ impl CStore {
         assert_eq!(self.metas.len(), self.stable_crate_ids.len());
         let num = CrateNum::new(self.stable_crate_ids.len());
         if let Some(&existing) = self.stable_crate_ids.get(&root.stable_crate_id()) {
-            let crate_name0 = root.name();
-            if let Some(crate_name1) = self.metas[existing].as_ref().map(|data| data.name()) {
+            // Check for (potential) conflicts with the local crate
+            if existing == LOCAL_CRATE {
+                Err(CrateError::SymbolConflictsCurrent(root.name()))
+            } else if let Some(crate_name1) = self.metas[existing].as_ref().map(|data| data.name())
+            {
+                let crate_name0 = root.name();
                 Err(CrateError::StableCrateIdCollision(crate_name0, crate_name1))
             } else {
-                Err(CrateError::SymbolConflictsCurrent(crate_name0))
+                Err(CrateError::NotFound(root.name()))
             }
         } else {
             self.metas.push(None);
@@ -943,7 +947,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                     lint::builtin::UNUSED_CRATE_DEPENDENCIES,
                     span,
                     ast::CRATE_NODE_ID,
-                    &format!(
+                    format!(
                         "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
                         name,
                         self.tcx.crate_name(LOCAL_CRATE),
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index c6af8d63289..1aab4adf0b3 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -220,7 +220,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::MetadataRef;
 use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
 use rustc_fs_util::try_canonicalize;
 use rustc_session::config::{self, CrateType};
@@ -246,6 +245,7 @@ pub(crate) struct CrateLocator<'a> {
     only_needs_metadata: bool,
     sysroot: &'a Path,
     metadata_loader: &'a dyn MetadataLoader,
+    cfg_version: &'static str,
 
     // Immutable per-search configuration.
     crate_name: Symbol,
@@ -323,6 +323,7 @@ impl<'a> CrateLocator<'a> {
             only_needs_metadata,
             sysroot: &sess.sysroot,
             metadata_loader,
+            cfg_version: sess.cfg_version,
             crate_name,
             exact_paths: if hash.is_none() {
                 sess.opts
@@ -655,7 +656,7 @@ impl<'a> CrateLocator<'a> {
     }
 
     fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> {
-        let rustc_version = rustc_version();
+        let rustc_version = rustc_version(self.cfg_version);
         let found_version = metadata.get_rustc_version();
         if found_version != rustc_version {
             info!("Rejecting via version: expected {} got {}", rustc_version, found_version);
@@ -782,7 +783,7 @@ fn get_metadata_section<'p>(
     if !filename.exists() {
         return Err(MetadataError::NotPresent(filename));
     }
-    let raw_bytes: MetadataRef = match flavor {
+    let raw_bytes = match flavor {
         CrateFlavor::Rlib => {
             loader.get_rlib_metadata(target, filename).map_err(MetadataError::LoadFailure)?
         }
@@ -843,7 +844,7 @@ fn get_metadata_section<'p>(
             slice_owned(mmap, Deref::deref)
         }
     };
-    let blob = MetadataBlob::new(raw_bytes);
+    let blob = MetadataBlob(raw_bytes);
     if blob.is_compatible() {
         Ok(blob)
     } else {
@@ -960,6 +961,7 @@ pub(crate) enum CrateError {
     DlSym(String),
     LocatorCombined(Box<CombinedLocatorError>),
     NonDylibPlugin(Symbol),
+    NotFound(Symbol),
 }
 
 enum MetadataError<'a> {
@@ -1097,7 +1099,7 @@ impl CrateError {
                         crate_name,
                         add_info,
                         found_crates,
-                        rustc_version: rustc_version(),
+                        rustc_version: rustc_version(sess.cfg_version),
                     });
                 } else if !locator.crate_rejections.via_invalid.is_empty() {
                     let mut crate_rejections = Vec::new();
@@ -1130,6 +1132,18 @@ impl CrateError {
             CrateError::NonDylibPlugin(crate_name) => {
                 sess.emit_err(errors::NoDylibPlugin { span, crate_name });
             }
+            CrateError::NotFound(crate_name) => {
+                sess.emit_err(errors::CannotFindCrate {
+                    span,
+                    crate_name,
+                    add_info: String::new(),
+                    missing_core,
+                    current_crate: sess.opts.crate_name.clone().unwrap_or("<unknown>".to_string()),
+                    is_nightly_build: sess.is_nightly_build(),
+                    profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime),
+                    locator_triple: sess.opts.target_triple.clone(),
+                });
+            }
         }
     }
 }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 1c36d5e82da..834e2453ee0 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -7,6 +7,7 @@ use crate::rmeta::*;
 use rustc_ast as ast;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::owned_slice::OwnedSlice;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell};
 use rustc_data_structures::unhash::UnhashMap;
@@ -18,6 +19,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc_hir::diagnostic_items::DiagnosticItems;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::metadata::ModChild;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::ty::codec::TyDecoder;
@@ -50,7 +52,7 @@ mod cstore_impl;
 /// A `MetadataBlob` internally is just a reference counted pointer to
 /// the actual data, so cloning it is cheap.
 #[derive(Clone)]
-pub(crate) struct MetadataBlob(Lrc<MetadataRef>);
+pub(crate) struct MetadataBlob(pub(crate) OwnedSlice);
 
 impl std::ops::Deref for MetadataBlob {
     type Target = [u8];
@@ -660,10 +662,6 @@ impl<'a, 'tcx, I: Idx, T> Decodable<DecodeContext<'a, 'tcx>> for LazyTable<I, T>
 implement_ty_decoder!(DecodeContext<'a, 'tcx>);
 
 impl MetadataBlob {
-    pub(crate) fn new(metadata_ref: MetadataRef) -> MetadataBlob {
-        MetadataBlob(Lrc::new(metadata_ref))
-    }
-
     pub(crate) fn is_compatible(&self) -> bool {
         self.blob().starts_with(METADATA_HEADER)
     }
@@ -961,7 +959,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .decode((self, sess))
     }
 
-    fn get_debugger_visualizers(self) -> Vec<rustc_span::DebuggerVisualizerFile> {
+    fn get_debugger_visualizers(self) -> Vec<DebuggerVisualizerFile> {
         self.root.debugger_visualizers.decode(self).collect::<Vec<_>>()
     }
 
@@ -1254,14 +1252,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         }
     }
 
-    fn is_foreign_item(self, id: DefIndex) -> bool {
-        if let Some(parent) = self.def_key(id).parent {
-            matches!(self.def_kind(parent), DefKind::ForeignMod)
-        } else {
-            false
-        }
-    }
-
     #[inline]
     fn def_key(self, index: DefIndex) -> DefKey {
         *self
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index fe880b939ef..7425963d30f 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -114,8 +114,8 @@ macro_rules! provide_one {
     ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => $compute:block) => {
         fn $name<'tcx>(
             $tcx: TyCtxt<'tcx>,
-            def_id_arg: rustc_middle::query::query_keys::$name<'tcx>,
-        ) -> rustc_middle::query::query_provided::$name<'tcx> {
+            def_id_arg: rustc_middle::query::queries::$name::Key<'tcx>,
+        ) -> rustc_middle::query::queries::$name::ProvidedValue<'tcx> {
             let _prof_timer =
                 $tcx.prof.generic_activity(concat!("metadata_decode_entry_", stringify!($name)));
 
@@ -280,7 +280,6 @@ provide! { tcx, def_id, other, cdata,
     }
     associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
     inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
-    is_foreign_item => { cdata.is_foreign_item(def_id.index) }
     item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
     is_mir_available => { cdata.is_item_mir_available(def_id.index) }
     is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
@@ -324,7 +323,7 @@ provide! { tcx, def_id, other, cdata,
 
     extra_filename => { cdata.root.extra_filename.clone() }
 
-    traits_in_crate => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
+    traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
     trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) }
     implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
     crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
index 05402a58701..4f280bb9d80 100644
--- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
+++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
@@ -1,6 +1,5 @@
 use crate::rmeta::DecodeContext;
 use crate::rmeta::EncodeContext;
-use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::owned_slice::OwnedSlice;
 use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
 use rustc_middle::parameterized_over_tcx;
@@ -47,7 +46,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static>
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> DefPathHashMapRef<'static> {
         let len = d.read_usize();
         let pos = d.position();
-        let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]);
+        let o = d.blob().clone().0.slice(|blob| &blob[pos..pos + len]);
 
         // Although we already have the data we need via the `OwnedSlice`, we still need
         // to advance the `DecodeContext`'s position so it's in a valid state after
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 79eb48a1a31..f067bca4b0b 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -19,6 +19,7 @@ use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::hir::nested_filter;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::{
     metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
@@ -36,9 +37,7 @@ use rustc_session::config::{CrateType, OptLevel};
 use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
 use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
 use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{
-    self, DebuggerVisualizerFile, ExternalSource, FileName, SourceFile, Span, SyntaxContext,
-};
+use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SyntaxContext};
 use std::borrow::Borrow;
 use std::collections::hash_map::Entry;
 use std::hash::Hash;
@@ -1855,7 +1854,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
     fn encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile> {
         empty_proc_macro!(self);
-        self.lazy_array(self.tcx.debugger_visualizers(LOCAL_CRATE).iter())
+        self.lazy_array(
+            self.tcx
+                .debugger_visualizers(LOCAL_CRATE)
+                .iter()
+                // Erase the path since it may contain privacy sensitive data
+                // that we don't want to end up in crate metadata.
+                // The path is only needed for the local crate because of
+                // `--emit dep-info`.
+                .map(DebuggerVisualizerFile::path_erased),
+        )
     }
 
     fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> {
@@ -1930,7 +1938,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
     fn encode_traits(&mut self) -> LazyArray<DefIndex> {
         empty_proc_macro!(self);
-        self.lazy_array(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index))
+        self.lazy_array(self.tcx.traits(LOCAL_CRATE).iter().map(|def_id| def_id.index))
     }
 
     /// Encodes an index, mapping each trait to its (local) implementations.
@@ -2276,7 +2284,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
     };
 
     // Encode the rustc version string in a predictable location.
-    rustc_version().encode(&mut ecx);
+    rustc_version(tcx.sess.cfg_version).encode(&mut ecx);
 
     // Encode all the entries and extra information in the crate,
     // culminating in the `CrateRoot` which points to all of it.
@@ -2321,7 +2329,7 @@ pub fn provide(providers: &mut Providers) {
                 .get(&def_id)
                 .expect("no traits in scope for a doc link")
         },
-        traits_in_crate: |tcx, LocalCrate| {
+        traits: |tcx, LocalCrate| {
             let mut traits = Vec::new();
             for id in tcx.hir().items() {
                 if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 9eaf330b536..97e67fcf8fd 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -2,12 +2,12 @@ use crate::creader::CrateMetadataRef;
 use decoder::Metadata;
 use def_path_hash_map::DefPathHashMapRef;
 use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use table::TableBuilder;
 
 use rustc_ast as ast;
 use rustc_attr as attr;
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::MetadataRef;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
@@ -49,8 +49,8 @@ mod def_path_hash_map;
 mod encoder;
 mod table;
 
-pub(crate) fn rustc_version() -> String {
-    format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version"))
+pub(crate) fn rustc_version(cfg_version: &'static str) -> String {
+    format!("rustc {}", cfg_version)
 }
 
 /// Metadata encoding version.
@@ -246,7 +246,7 @@ pub(crate) struct CrateRoot {
     proc_macro_data: Option<ProcMacroData>,
 
     tables: LazyTables,
-    debugger_visualizers: LazyArray<rustc_span::DebuggerVisualizerFile>,
+    debugger_visualizers: LazyArray<DebuggerVisualizerFile>,
 
     exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
 
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index c6bbf2ef0cd..64d511c261a 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -39,5 +39,7 @@ middle_strict_coherence_needs_negative_coherence =
     to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled
     .label = due to this attribute
 
+middle_requires_lang_item = requires `{$name}` lang_item
+
 middle_const_not_used_in_type_alias =
     const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index dc4aa18640f..046186d274c 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,5 +1,5 @@
 use rustc_macros::Diagnostic;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 
 use crate::ty::Ty;
 
@@ -74,6 +74,14 @@ pub(crate) struct StrictCoherenceNeedsNegativeCoherence {
 }
 
 #[derive(Diagnostic)]
+#[diag(middle_requires_lang_item)]
+pub(crate) struct RequiresLangItem {
+    #[primary_span]
+    pub span: Option<Span>,
+    pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
 #[diag(middle_const_not_used_in_type_alias)]
 pub(super) struct ConstNotUsedTraitAlias {
     pub ct: String,
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 5bf0938d518..3b59df778dc 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,4 +1,5 @@
 use crate::hir::{ModuleItems, Owner};
+use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
 use crate::query::LocalCrate;
 use crate::ty::TyCtxt;
 use rustc_ast as ast;
@@ -1165,11 +1166,26 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh {
 
     source_file_names.sort_unstable();
 
+    // We have to take care of debugger visualizers explicitly. The HIR (and
+    // thus `hir_body_hash`) contains the #[debugger_visualizer] attributes but
+    // these attributes only store the file path to the visualizer file, not
+    // their content. Yet that content is exported into crate metadata, so any
+    // changes to it need to be reflected in the crate hash.
+    let debugger_visualizers: Vec<_> = tcx
+        .debugger_visualizers(LOCAL_CRATE)
+        .iter()
+        // We ignore the path to the visualizer file since it's not going to be
+        // encoded in crate metadata and we already hash the full contents of
+        // the file.
+        .map(DebuggerVisualizerFile::path_erased)
+        .collect();
+
     let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| {
         let mut stable_hasher = StableHasher::new();
         hir_body_hash.hash_stable(&mut hcx, &mut stable_hasher);
         upstream_crates.hash_stable(&mut hcx, &mut stable_hasher);
         source_file_names.hash_stable(&mut hcx, &mut stable_hasher);
+        debugger_visualizers.hash_stable(&mut hcx, &mut stable_hasher);
         if tcx.sess.opts.incremental_relative_spans() {
             let definitions = tcx.definitions_untracked();
             let mut owner_spans: Vec<_> = krate
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 61c9e72db2c..ac0b2844177 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -10,6 +10,7 @@ use crate::query::Providers;
 use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{par_for_each_in, DynSend, DynSync};
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::*;
 use rustc_query_system::ich::StableHashingContext;
@@ -110,6 +111,12 @@ impl<'tcx> TyCtxt<'tcx> {
             None => self.type_of(def_id).map_bound(ImplSubject::Inherent),
         }
     }
+
+    /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
+    pub fn is_foreign_item(self, def_id: impl Into<DefId>) -> bool {
+        self.opt_parent(def_id.into())
+            .map_or(false, |parent| matches!(self.def_kind(parent), DefKind::ForeignMod))
+    }
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index c4e41e00520..56171314944 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -280,7 +280,7 @@ pub struct QueryResponse<'tcx, R> {
     /// should get its hidden type inferred. So we bubble the opaque type
     /// and the type it was compared against upwards and let the query caller
     /// handle it.
-    pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+    pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
     pub value: R,
 }
 
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index dc911c88574..22ee2a8c5e5 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -95,7 +95,6 @@ pub mod middle;
 pub mod mir;
 pub mod thir;
 pub mod traits;
-#[macro_use]
 pub mod ty;
 pub mod util;
 mod values;
diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
new file mode 100644
index 00000000000..a0497d805da
--- /dev/null
+++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs
@@ -0,0 +1,38 @@
+use rustc_data_structures::sync::Lrc;
+use std::path::PathBuf;
+
+#[derive(HashStable)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
+pub enum DebuggerVisualizerType {
+    Natvis,
+    GdbPrettyPrinter,
+}
+
+/// A single debugger visualizer file.
+#[derive(HashStable)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
+pub struct DebuggerVisualizerFile {
+    /// The complete debugger visualizer source.
+    pub src: Lrc<[u8]>,
+    /// Indicates which visualizer type this targets.
+    pub visualizer_type: DebuggerVisualizerType,
+    /// The file path to the visualizer file. This is used for reporting
+    /// visualizer files in dep-info. Before it is written to crate metadata,
+    /// the path is erased to `None`, so as not to emit potentially privacy
+    /// sensitive data.
+    pub path: Option<PathBuf>,
+}
+
+impl DebuggerVisualizerFile {
+    pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType, path: PathBuf) -> Self {
+        DebuggerVisualizerFile { src, visualizer_type, path: Some(path) }
+    }
+
+    pub fn path_erased(&self) -> Self {
+        DebuggerVisualizerFile {
+            src: self.src.clone(),
+            visualizer_type: self.visualizer_type,
+            path: None,
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index 343ea1f00f5..9a633e04ce7 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -18,12 +18,8 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Returns the `DefId` for a given `LangItem`.
     /// If not found, fatally aborts compilation.
     pub fn require_lang_item(self, lang_item: LangItem, span: Option<Span>) -> DefId {
-        self.lang_items().require(lang_item).unwrap_or_else(|err| {
-            if let Some(span) = span {
-                self.sess.span_fatal(span, err.to_string())
-            } else {
-                self.sess.fatal(err.to_string())
-            }
+        self.lang_items().get(lang_item).unwrap_or_else(|| {
+            self.sess.emit_fatal(crate::error::RequiresLangItem { span, name: lang_item.name() });
         })
     }
 
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index 9bb4570ef14..85c5af9ca13 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -1,4 +1,5 @@
 pub mod codegen_fn_attrs;
+pub mod debugger_visualizer;
 pub mod dependency_format;
 pub mod exported_symbols;
 pub mod lang_items;
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index d65ceef2472..055d8e9a352 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -1,7 +1,8 @@
 use super::{AllocId, AllocRange, ConstAlloc, Pointer, Scalar};
 
 use crate::mir::interpret::ConstValue;
-use crate::ty::{layout, query::TyCtxtAt, tls, Ty, ValTree};
+use crate::query::TyCtxtAt;
+use crate::ty::{layout, tls, Ty, ValTree};
 
 use rustc_data_structures::sync::Lock;
 use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index ce11dabc195..f53dc8cb0ec 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -1,9 +1,10 @@
 use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
 
 use crate::mir;
+use crate::query::{TyCtxtAt, TyCtxtEnsure};
 use crate::ty::subst::InternalSubsts;
 use crate::ty::visit::TypeVisitableExt;
-use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
+use crate::ty::{self, TyCtxt};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_session::lint;
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 1da94dd7917..5c71910a955 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -101,7 +101,7 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> {
 /// pass will be named after the type, and it will consist of a main
 /// loop that goes over each available MIR and applies `run_pass`.
 pub trait MirPass<'tcx> {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         let name = std::any::type_name::<Self>();
         if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
     }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 33b7fe0c2dc..21faf1958e9 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -749,6 +749,29 @@ pub enum TerminatorKind<'tcx> {
     },
 }
 
+impl TerminatorKind<'_> {
+    /// Returns a simple string representation of a `TerminatorKind` variant, independent of any
+    /// values it might hold (e.g. `TerminatorKind::Call` always returns `"Call"`).
+    pub const fn name(&self) -> &'static str {
+        match self {
+            TerminatorKind::Goto { .. } => "Goto",
+            TerminatorKind::SwitchInt { .. } => "SwitchInt",
+            TerminatorKind::Resume => "Resume",
+            TerminatorKind::Terminate => "Terminate",
+            TerminatorKind::Return => "Return",
+            TerminatorKind::Unreachable => "Unreachable",
+            TerminatorKind::Drop { .. } => "Drop",
+            TerminatorKind::Call { .. } => "Call",
+            TerminatorKind::Assert { .. } => "Assert",
+            TerminatorKind::Yield { .. } => "Yield",
+            TerminatorKind::GeneratorDrop => "GeneratorDrop",
+            TerminatorKind::FalseEdge { .. } => "FalseEdge",
+            TerminatorKind::FalseUnwind { .. } => "FalseUnwind",
+            TerminatorKind::InlineAsm { .. } => "InlineAsm",
+        }
+    }
+}
+
 /// Action to be taken when a stack unwind happens.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index b45f7caaabe..fd02a16130f 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -28,7 +28,7 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
     };
 
     Erased::<<T as EraseType>::Result> {
-        // SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes.
+        // SAFETY: It is safe to transmute to MaybeUninit for types with the same sizes.
         data: unsafe { transmute_copy(&src) },
     }
 }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f564f5e99e8..1528be42f6a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -12,6 +12,7 @@ use crate::infer::canonical::{self, Canonical};
 use crate::lint::LintExpectation;
 use crate::metadata::ModChild;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
+use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
 use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
 use crate::middle::lib_features::LibFeatures;
 use crate::middle::privacy::EffectiveVisibilities;
@@ -25,6 +26,7 @@ use crate::mir::interpret::{
 use crate::mir::interpret::{LitToConstError, LitToConstInput};
 use crate::mir::mono::CodegenUnit;
 use crate::query::erase::{erase, restore, Erase};
+use crate::query::plumbing::{query_ensure, query_get_at, DynamicQuery};
 use crate::thir;
 use crate::traits::query::{
     CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
@@ -36,13 +38,12 @@ use crate::traits::query::{
     OutlivesBound,
 };
 use crate::traits::specialization_graph;
-use crate::traits::{self, ImplSource};
+use crate::traits::{
+    CanonicalChalkEnvironmentAndGoal, CodegenObligationError, EvaluationResult, ImplSource,
+    ObjectSafetyViolation, ObligationCause, OverflowError, WellFormedLoc,
+};
 use crate::ty::fast_reject::SimplifiedType;
 use crate::ty::layout::ValidityRequirement;
-use crate::ty::query::{
-    query_ensure, query_get_at, DynamicQuery, IntoQueryParam, TyCtxtAt, TyCtxtEnsure,
-    TyCtxtEnsureWithValue,
-};
 use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::util::AlwaysRequiresDrop;
 use crate::ty::GeneratorDiagnosticData;
@@ -90,8 +91,11 @@ use std::sync::Arc;
 
 pub mod erase;
 mod keys;
-pub mod on_disk_cache;
 pub use keys::{AsLocalKey, Key, LocalCrate};
+pub mod on_disk_cache;
+#[macro_use]
+pub mod plumbing;
+pub use plumbing::{IntoQueryParam, TyCtxtAt, TyCtxtEnsure, TyCtxtEnsureWithValue};
 
 // Each of these queries corresponds to a function pointer field in the
 // `Providers` struct for requesting a value of that type, and a method
@@ -726,12 +730,6 @@ rustc_queries! {
         desc { |tcx| "checking if item is promotable: `{}`", tcx.def_path_str(key) }
     }
 
-    /// Returns `true` if this is a foreign item (i.e., linked via `extern { ... }`).
-    query is_foreign_item(key: DefId) -> bool {
-        desc { |tcx| "checking if `{}` is a foreign item", tcx.def_path_str(key) }
-        separate_provide_extern
-    }
-
     /// Returns `Some(generator_kind)` if the node pointed to by `def_id` is a generator.
     query generator_kind(def_id: DefId) -> Option<hir::GeneratorKind> {
         desc { |tcx| "looking up generator kind of `{}`", tcx.def_path_str(def_id) }
@@ -1278,7 +1276,7 @@ rustc_queries! {
 
     query codegen_select_candidate(
         key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)
-    ) -> Result<&'tcx ImplSource<'tcx, ()>, traits::CodegenObligationError> {
+    ) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
         cache_on_disk_if { true }
         desc { |tcx| "computing candidate for `{}`", key.1 }
     }
@@ -1299,7 +1297,7 @@ rustc_queries! {
         desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
         cache_on_disk_if { true }
     }
-    query object_safety_violations(trait_id: DefId) -> &'tcx [traits::ObjectSafetyViolation] {
+    query object_safety_violations(trait_id: DefId) -> &'tcx [ObjectSafetyViolation] {
         desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) }
     }
     query check_is_object_safe(trait_id: DefId) -> bool {
@@ -1790,12 +1788,18 @@ rustc_queries! {
         desc { "looking at the source for a crate" }
         separate_provide_extern
     }
+
     /// Returns the debugger visualizers defined for this crate.
-    query debugger_visualizers(_: CrateNum) -> &'tcx Vec<rustc_span::DebuggerVisualizerFile> {
+    /// NOTE: This query has to be marked `eval_always` because it reads data
+    ///       directly from disk that is not tracked anywhere else. I.e. it
+    ///       represents a genuine input to the query system.
+    query debugger_visualizers(_: CrateNum) -> &'tcx Vec<DebuggerVisualizerFile> {
         arena_cache
         desc { "looking up the debugger visualizers for this crate" }
         separate_provide_extern
+        eval_always
     }
+
     query postorder_cnums(_: ()) -> &'tcx [CrateNum] {
         eval_always
         desc { "generating a postorder list of CrateNums" }
@@ -1837,8 +1841,7 @@ rustc_queries! {
     }
 
     /// A list of all traits in a crate, used by rustdoc and error reporting.
-    /// NOTE: Not named just `traits` due to a naming conflict.
-    query traits_in_crate(_: CrateNum) -> &'tcx [DefId] {
+    query traits(_: CrateNum) -> &'tcx [DefId] {
         desc { "fetching all traits in a crate" }
         separate_provide_extern
     }
@@ -1952,12 +1955,12 @@ rustc_queries! {
     /// `infcx.predicate_must_hold()` instead.
     query evaluate_obligation(
         goal: CanonicalPredicateGoal<'tcx>
-    ) -> Result<traits::EvaluationResult, traits::OverflowError> {
+    ) -> Result<EvaluationResult, OverflowError> {
         desc { "evaluating trait selection obligation `{}`", goal.value.value }
     }
 
     query evaluate_goal(
-        goal: traits::CanonicalChalkEnvironmentAndGoal<'tcx>
+        goal: CanonicalChalkEnvironmentAndGoal<'tcx>
     ) -> Result<
         &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
         NoSolution
@@ -2127,8 +2130,8 @@ rustc_queries! {
     /// all of the cases that the normal `ty::Ty`-based wfcheck does. This is fine,
     /// because the `ty::Ty`-based wfcheck is always run.
     query diagnostic_hir_wf_check(
-        key: (ty::Predicate<'tcx>, traits::WellFormedLoc)
-    ) -> &'tcx Option<traits::ObligationCause<'tcx>> {
+        key: (ty::Predicate<'tcx>, WellFormedLoc)
+    ) -> &'tcx Option<ObligationCause<'tcx>> {
         arena_cache
         eval_always
         no_hash
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/query/plumbing.rs
index 647f4826876..97edfc2fca2 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/query/plumbing.rs
@@ -32,20 +32,12 @@ impl QueryKeyStringCache {
     }
 }
 
-#[derive(Clone, Copy)]
-pub struct QueryStruct<'tcx> {
-    pub try_collect_active_jobs: fn(TyCtxt<'tcx>, &mut QueryMap<DepKind>) -> Option<()>,
-    pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache),
-    pub encode_query_results:
-        Option<fn(TyCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>,
-}
-
 pub struct DynamicQuery<'tcx, C: QueryCache> {
     pub name: &'static str,
     pub eval_always: bool,
-    pub dep_kind: rustc_middle::dep_graph::DepKind,
+    pub dep_kind: DepKind,
     pub handle_cycle_error: HandleCycleError,
-    pub query_state: FieldOffset<QueryStates<'tcx>, QueryState<C::Key, crate::dep_graph::DepKind>>,
+    pub query_state: FieldOffset<QueryStates<'tcx>, QueryState<C::Key, DepKind>>,
     pub query_cache: FieldOffset<QueryCaches<'tcx>, C>,
     pub cache_on_disk: fn(tcx: TyCtxt<'tcx>, key: &C::Key) -> bool,
     pub execute_query: fn(tcx: TyCtxt<'tcx>, k: C::Key) -> C::Value,
@@ -60,8 +52,7 @@ pub struct DynamicQuery<'tcx, C: QueryCache> {
     pub loadable_from_disk:
         fn(tcx: TyCtxt<'tcx>, key: &C::Key, index: SerializedDepNodeIndex) -> bool,
     pub hash_result: HashResult<C::Value>,
-    pub value_from_cycle_error:
-        fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<crate::dep_graph::DepKind>]) -> C::Value,
+    pub value_from_cycle_error: fn(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo<DepKind>]) -> C::Value,
     pub format_value: fn(&C::Value) -> String,
 }
 
@@ -69,7 +60,6 @@ pub struct QuerySystemFns<'tcx> {
     pub engine: QueryEngine,
     pub local_providers: Providers,
     pub extern_providers: ExternProviders,
-    pub query_structs: Vec<QueryStruct<'tcx>>,
     pub encode_query_results: fn(
         tcx: TyCtxt<'tcx>,
         encoder: &mut CacheEncoder<'_, 'tcx>,
@@ -221,8 +211,8 @@ macro_rules! separate_provide_extern_decl {
     ([(separate_provide_extern) $($rest:tt)*][$name:ident]) => {
         for<'tcx> fn(
             TyCtxt<'tcx>,
-            query_keys::$name<'tcx>,
-        ) -> query_provided::$name<'tcx>
+            queries::$name::Key<'tcx>,
+        ) -> queries::$name::ProvidedValue<'tcx>
     };
     ([$other:tt $($modifiers:tt)*][$($args:tt)*]) => {
         separate_provide_extern_decl!([$($modifiers)*][$($args)*])
@@ -252,60 +242,37 @@ macro_rules! define_callbacks {
      $($(#[$attr:meta])*
         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
 
-        // HACK(eddyb) this is like the `impl QueryConfig for queries::$name`
-        // below, but using type aliases instead of associated types, to bypass
-        // the limitations around normalizing under HRTB - for example, this:
-        // `for<'tcx> fn(...) -> <queries::$name<'tcx> as QueryConfig<TyCtxt<'tcx>>>::Value`
-        // doesn't currently normalize to `for<'tcx> fn(...) -> query_values::$name<'tcx>`.
-        // This is primarily used by the `provide!` macro in `rustc_metadata`.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_keys {
-            use super::*;
-
-            $(pub type $name<'tcx> = $($K)*;)*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_keys_local {
-            use super::*;
-
-            $(pub type $name<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*);)*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_values {
-            use super::*;
-
-            $(pub type $name<'tcx> = $V;)*
-        }
+        #[allow(unused_lifetimes)]
+        pub mod queries {
+            $(pub mod $name {
+                use super::super::*;
 
-        /// This module specifies the type returned from query providers and the type used for
-        /// decoding. For regular queries this is the declared returned type `V`, but
-        /// `arena_cache` will use `<V as Deref>::Target` instead.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_provided {
-            use super::*;
+                pub type Key<'tcx> = $($K)*;
+                pub type Value<'tcx> = $V;
 
-            $(
-                pub type $name<'tcx> = query_if_arena!([$($modifiers)*] (<$V as Deref>::Target) ($V));
-            )*
-        }
+                pub type LocalKey<'tcx> = local_key_if_separate_extern!([$($modifiers)*] $($K)*);
 
-        /// This module has a function per query which takes a `query_provided` value and coverts
-        /// it to a regular `V` value by allocating it on an arena if the query has the
-        /// `arena_cache` modifier. This will happen when computing the query using a provider or
-        /// decoding a stored result.
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_provided_to_value {
-            use super::*;
+                /// This type alias specifies the type returned from query providers and the type
+                /// used for decoding. For regular queries this is the declared returned type `V`,
+                /// but `arena_cache` will use `<V as Deref>::Target` instead.
+                pub type ProvidedValue<'tcx> = query_if_arena!(
+                    [$($modifiers)*]
+                    (<$V as Deref>::Target)
+                    ($V)
+                );
 
-            $(
+                /// This function takes `ProvidedValue` and coverts it to an erased `Value` by
+                /// allocating it on an arena if the query has the `arena_cache` modifier. The
+                /// value is then erased and returned. This will happen when computing the query
+                /// using a provider or decoding a stored result.
                 #[inline(always)]
-                pub fn $name<'tcx>(
+                pub fn provided_to_erased<'tcx>(
                     _tcx: TyCtxt<'tcx>,
-                    value: query_provided::$name<'tcx>,
-                ) -> Erase<query_values::$name<'tcx>> {
+                    value: ProvidedValue<'tcx>,
+                ) -> Erase<Value<'tcx>> {
                     erase(query_if_arena!([$($modifiers)*]
                         {
-                            if mem::needs_drop::<query_provided::$name<'tcx>>() {
+                            if mem::needs_drop::<ProvidedValue<'tcx>>() {
                                 &*_tcx.query_system.arenas.$name.alloc(value)
                             } else {
                                 &*_tcx.arena.dropless.alloc(value)
@@ -314,47 +281,41 @@ macro_rules! define_callbacks {
                         (value)
                     ))
                 }
-            )*
-        }
-        #[allow(nonstandard_style, unused_lifetimes)]
-        pub mod query_storage {
-            use super::*;
 
-            $(
-                pub type $name<'tcx> = <<$($K)* as Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>>::Cache;
-            )*
+                pub type Storage<'tcx> = <
+                    <$($K)* as keys::Key>::CacheSelector as CacheSelector<'tcx, Erase<$V>>
+                >::Cache;
+
+                // Ensure that keys grow no larger than 64 bytes
+                #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+                const _: () = {
+                    if mem::size_of::<Key<'static>>() > 64 {
+                        panic!("{}", concat!(
+                            "the query `",
+                            stringify!($name),
+                            "` has a key type `",
+                            stringify!($($K)*),
+                            "` that is too large"
+                        ));
+                    }
+                };
+
+                // Ensure that values grow no larger than 64 bytes
+                #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+                const _: () = {
+                    if mem::size_of::<Value<'static>>() > 64 {
+                        panic!("{}", concat!(
+                            "the query `",
+                            stringify!($name),
+                            "` has a value type `",
+                            stringify!($V),
+                            "` that is too large"
+                        ));
+                    }
+                };
+            })*
         }
 
-        $(
-            // Ensure that keys grow no larger than 64 bytes
-            #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-            const _: () = {
-                if mem::size_of::<query_keys::$name<'static>>() > 64 {
-                    panic!("{}", concat!(
-                        "the query `",
-                        stringify!($name),
-                        "` has a key type `",
-                        stringify!($($K)*),
-                        "` that is too large"
-                    ));
-                }
-            };
-
-            // Ensure that values grow no larger than 64 bytes
-            #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-            const _: () = {
-                if mem::size_of::<query_values::$name<'static>>() > 64 {
-                    panic!("{}", concat!(
-                        "the query `",
-                        stringify!($name),
-                        "` has a value type `",
-                        stringify!($V),
-                        "` that is too large"
-                    ));
-                }
-            };
-        )*
-
         pub struct QueryArenas<'tcx> {
             $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*]
                 (WorkerLocal<TypedArena<<$V as Deref>::Target>>)
@@ -375,7 +336,7 @@ macro_rules! define_callbacks {
 
         #[derive(Default)]
         pub struct QueryCaches<'tcx> {
-            $($(#[$attr])* pub $name: query_storage::$name<'tcx>,)*
+            $($(#[$attr])* pub $name: queries::$name::Storage<'tcx>,)*
         }
 
         impl<'tcx> TyCtxtEnsure<'tcx> {
@@ -433,7 +394,7 @@ macro_rules! define_callbacks {
 
         pub struct DynamicQueries<'tcx> {
             $(
-                pub $name: DynamicQuery<'tcx, query_storage::$name<'tcx>>,
+                pub $name: DynamicQuery<'tcx, queries::$name::Storage<'tcx>>,
             )*
         }
 
@@ -447,8 +408,8 @@ macro_rules! define_callbacks {
         pub struct Providers {
             $(pub $name: for<'tcx> fn(
                 TyCtxt<'tcx>,
-                query_keys_local::$name<'tcx>,
-            ) -> query_provided::$name<'tcx>,)*
+                queries::$name::LocalKey<'tcx>,
+            ) -> queries::$name::ProvidedValue<'tcx>,)*
         }
 
         pub struct ExternProviders {
@@ -493,7 +454,7 @@ macro_rules! define_callbacks {
             $(pub $name: for<'tcx> fn(
                 TyCtxt<'tcx>,
                 Span,
-                query_keys::$name<'tcx>,
+                queries::$name::Key<'tcx>,
                 QueryMode,
             ) -> Option<Erase<$V>>,)*
         }
@@ -517,11 +478,11 @@ macro_rules! define_feedable {
         $(impl<'tcx, K: IntoQueryParam<$($K)*> + Copy> TyCtxtFeed<'tcx, K> {
             $(#[$attr])*
             #[inline(always)]
-            pub fn $name(self, value: query_provided::$name<'tcx>) {
+            pub fn $name(self, value: queries::$name::ProvidedValue<'tcx>) {
                 let key = self.key().into_query_param();
 
                 let tcx = self.tcx;
-                let erased = query_provided_to_value::$name(tcx, value);
+                let erased = queries::$name::provided_to_erased(tcx, value);
                 let value = restore::<$V>(erased);
                 let cache = &tcx.query_system.caches.$name;
 
@@ -533,12 +494,20 @@ macro_rules! define_feedable {
                             let (value_hash, old_hash): (Fingerprint, Fingerprint) = tcx.with_stable_hashing_context(|mut hcx|
                                 (hasher(&mut hcx, &value), hasher(&mut hcx, &old))
                             );
-                            assert_eq!(
-                                old_hash, value_hash,
-                                "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
-                                stringify!($name),
-                            )
+                            if old_hash != value_hash {
+                                // We have an inconsistency. This can happen if one of the two
+                                // results is tainted by errors. In this case, delay a bug to
+                                // ensure compilation is doomed, and keep the `old` value.
+                                tcx.sess.delay_span_bug(DUMMY_SP, format!(
+                                    "Trying to feed an already recorded value for query {} key={key:?}:\n\
+                                    old value: {old:?}\nnew value: {value:?}",
+                                    stringify!($name),
+                                ));
+                            }
                         } else {
+                            // The query is `no_hash`, so we have no way to perform a sanity check.
+                            // If feeding the same value multiple times needs to be supported,
+                            // the query should not be marked `no_hash`.
                             bug!(
                                 "Trying to feed an already recorded value for query {} key={key:?}:\nold value: {old:?}\nnew value: {value:?}",
                                 stringify!($name),
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 2f0b07d4c71..5b0b40cbfd9 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -701,9 +701,9 @@ impl<'tcx, N> ImplSource<'tcx, N> {
     }
 
     pub fn borrow_nested_obligations(&self) -> &[N] {
-        match &self {
-            ImplSource::UserDefined(i) => &i.nested[..],
-            ImplSource::Param(n, _) => &n,
+        match self {
+            ImplSource::UserDefined(i) => &i.nested,
+            ImplSource::Param(n, _) => n,
             ImplSource::Builtin(i) => &i.nested,
             ImplSource::AutoImpl(d) => &d.nested,
             ImplSource::Closure(c) => &c.nested,
@@ -717,6 +717,23 @@ impl<'tcx, N> ImplSource<'tcx, N> {
         }
     }
 
+    pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] {
+        match self {
+            ImplSource::UserDefined(i) => &mut i.nested,
+            ImplSource::Param(n, _) => n,
+            ImplSource::Builtin(i) => &mut i.nested,
+            ImplSource::AutoImpl(d) => &mut d.nested,
+            ImplSource::Closure(c) => &mut c.nested,
+            ImplSource::Generator(c) => &mut c.nested,
+            ImplSource::Future(c) => &mut c.nested,
+            ImplSource::Object(d) => &mut d.nested,
+            ImplSource::FnPointer(d) => &mut d.nested,
+            ImplSource::TraitAlias(d) => &mut d.nested,
+            ImplSource::TraitUpcasting(d) => &mut d.nested,
+            ImplSource::ConstDestruct(i) => &mut i.nested,
+        }
+    }
+
     pub fn map<M, F>(self, f: F) -> ImplSource<'tcx, M>
     where
         F: FnMut(N) -> M,
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 6b7b910a59b..1511c906d1e 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -124,7 +124,7 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
 pub struct ExternalConstraintsData<'tcx> {
     // FIXME: implement this.
     pub region_constraints: QueryRegionConstraints<'tcx>,
-    pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
+    pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
 }
 
 // FIXME: Having to clone `region_constraints` for folding feels bad and
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index ad9891a5dca..7c5c030c276 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -111,12 +111,30 @@ impl Ord for AdtDefData {
     }
 }
 
-/// There should be only one AdtDef for each `did`, therefore
-/// it is fine to implement `PartialEq` only based on `did`.
 impl PartialEq for AdtDefData {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
-        self.did == other.did
+        // There should be only one `AdtDefData` for each `def_id`, therefore
+        // it is fine to implement `PartialEq` only based on `def_id`.
+        //
+        // Below, we exhaustively destructure `self` and `other` so that if the
+        // definition of `AdtDefData` changes, a compile-error will be produced,
+        // reminding us to revisit this assumption.
+
+        let Self { did: self_def_id, variants: _, flags: _, repr: _ } = self;
+        let Self { did: other_def_id, variants: _, flags: _, repr: _ } = other;
+
+        let res = self_def_id == other_def_id;
+
+        // Double check that implicit assumption detailed above.
+        if cfg!(debug_assertions) && res {
+            let deep = self.flags == other.flags
+                && self.repr == other.repr
+                && self.variants == other.variants;
+            assert!(deep, "AdtDefData for the same def-id has differing data");
+        }
+
+        res
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 097bfb71a6f..5393dba8c2e 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -14,14 +14,14 @@ use crate::middle::resolve_bound_vars;
 use crate::middle::stability;
 use crate::mir::interpret::{self, Allocation, ConstAllocation};
 use crate::mir::{Body, Local, Place, PlaceElem, ProjectionKind, Promoted};
+use crate::query::plumbing::QuerySystem;
 use crate::query::LocalCrate;
 use crate::query::Providers;
+use crate::query::{IntoQueryParam, TyCtxtAt};
 use crate::thir::Thir;
 use crate::traits;
 use crate::traits::solve;
 use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
-use crate::ty::query::QuerySystem;
-use crate::ty::query::{self, TyCtxtAt};
 use crate::ty::{
     self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
     GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
@@ -80,8 +80,6 @@ use std::iter;
 use std::mem;
 use std::ops::{Bound, Deref};
 
-use super::query::IntoQueryParam;
-
 const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
 
 #[allow(rustc::usage_of_ty_tykind)]
@@ -512,7 +510,7 @@ pub struct GlobalCtxt<'tcx> {
 
     untracked: Untracked,
 
-    pub query_system: query::QuerySystem<'tcx>,
+    pub query_system: QuerySystem<'tcx>,
     pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
 
     // Internal caches for metadata decoding. No need to track deps on this.
@@ -702,7 +700,11 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
     /// ensure it gets used.
     #[track_caller]
-    pub fn ty_error_with_message<S: Into<MultiSpan>>(self, span: S, msg: &str) -> Ty<'tcx> {
+    pub fn ty_error_with_message<S: Into<MultiSpan>>(
+        self,
+        span: S,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> Ty<'tcx> {
         let reported = self.sess.delay_span_bug(span, msg);
         self.mk_ty_from_kind(Error(reported))
     }
@@ -1197,7 +1199,7 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
         iter::once(LOCAL_CRATE)
             .chain(self.crates(()).iter().copied())
-            .flat_map(move |cnum| self.traits_in_crate(cnum).iter().copied())
+            .flat_map(move |cnum| self.traits(cnum).iter().copied())
     }
 
     #[inline]
@@ -2435,7 +2437,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
     /// ensure it gets used.
     #[track_caller]
-    pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
+    pub fn ty_error_with_message(self, msg: impl Into<DiagnosticMessage>) -> Ty<'tcx> {
         self.tcx.ty_error_with_message(self.span, msg)
     }
 }
diff --git a/compiler/rustc_middle/src/ty/context/tls.rs b/compiler/rustc_middle/src/ty/context/tls.rs
index bf9806f6406..5c1c419811e 100644
--- a/compiler/rustc_middle/src/ty/context/tls.rs
+++ b/compiler/rustc_middle/src/ty/context/tls.rs
@@ -1,7 +1,7 @@
 use super::{GlobalCtxt, TyCtxt};
 
 use crate::dep_graph::TaskDepsRef;
-use crate::ty::query;
+use crate::query::plumbing::QueryJobId;
 use rustc_data_structures::sync::{self, Lock};
 use rustc_errors::Diagnostic;
 #[cfg(not(parallel_compiler))]
@@ -22,7 +22,7 @@ pub struct ImplicitCtxt<'a, 'tcx> {
 
     /// The current query job, if any. This is updated by `JobOwner::start` in
     /// `ty::query::plumbing` when executing a query.
-    pub query: Option<query::QueryJobId>,
+    pub query: Option<QueryJobId>,
 
     /// Where to store diagnostics for the current query job, if any.
     /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query.
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 47cf48f46cf..b5a743cfe34 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,5 +1,6 @@
 use crate::fluent_generated as fluent;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::query::TyCtxtAt;
 use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
 use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
@@ -268,7 +269,7 @@ pub struct LayoutCx<'tcx, C> {
 impl<'tcx> LayoutCalculator for LayoutCx<'tcx, TyCtxt<'tcx>> {
     type TargetDataLayoutRef = &'tcx TargetDataLayout;
 
-    fn delay_bug(&self, txt: &str) {
+    fn delay_bug(&self, txt: String) {
         self.tcx.sess.delay_span_bug(DUMMY_SP, txt);
     }
 
@@ -543,20 +544,20 @@ impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
     }
 }
 
-impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasDataLayout for TyCtxtAt<'tcx> {
     #[inline]
     fn data_layout(&self) -> &TargetDataLayout {
         &self.data_layout
     }
 }
 
-impl<'tcx> HasTargetSpec for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasTargetSpec for TyCtxtAt<'tcx> {
     fn target_spec(&self) -> &Target {
         &self.sess.target
     }
 }
 
-impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
+impl<'tcx> HasTyCtxt<'tcx> for TyCtxtAt<'tcx> {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
         **self
@@ -683,7 +684,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
     }
 }
 
-impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
+impl<'tcx> LayoutOfHelpers<'tcx> for LayoutCx<'tcx, TyCtxtAt<'tcx>> {
     type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
 
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index df324bcc52c..c9cd644fab0 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -37,7 +37,7 @@ use rustc_data_structures::intern::Interned;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
-use rustc_errors::ErrorGuaranteed;
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap};
@@ -122,8 +122,6 @@ pub mod inhabitedness;
 pub mod layout;
 pub mod normalize_erasing_regions;
 pub mod print;
-#[macro_use]
-pub mod query;
 pub mod relate;
 pub mod subst;
 pub mod trait_def;
@@ -1441,14 +1439,26 @@ pub struct OpaqueHiddenType<'tcx> {
 }
 
 impl<'tcx> OpaqueHiddenType<'tcx> {
-    pub fn report_mismatch(&self, other: &Self, tcx: TyCtxt<'tcx>) -> ErrorGuaranteed {
+    pub fn report_mismatch(
+        &self,
+        other: &Self,
+        opaque_def_id: LocalDefId,
+        tcx: TyCtxt<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        if let Some(diag) = tcx
+            .sess
+            .diagnostic()
+            .steal_diagnostic(tcx.def_span(opaque_def_id), StashKey::OpaqueHiddenTypeMismatch)
+        {
+            diag.cancel();
+        }
         // Found different concrete types for the opaque type.
         let sub_diag = if self.span == other.span {
             TypeMismatchReason::ConflictType { span: self.span }
         } else {
             TypeMismatchReason::PreviousUse { span: self.span }
         };
-        tcx.sess.emit_err(OpaqueHiddenTypeMismatch {
+        tcx.sess.create_err(OpaqueHiddenTypeMismatch {
             self_ty: self.ty,
             other_ty: other.ty,
             other_span: other.span,
@@ -1884,7 +1894,20 @@ impl PartialEq for VariantDef {
 
         let Self { def_id: lhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = &self;
         let Self { def_id: rhs_def_id, ctor: _, name: _, discr: _, fields: _, flags: _ } = other;
-        lhs_def_id == rhs_def_id
+
+        let res = lhs_def_id == rhs_def_id;
+
+        // Double check that implicit assumption detailed above.
+        if cfg!(debug_assertions) && res {
+            let deep = self.ctor == other.ctor
+                && self.name == other.name
+                && self.discr == other.discr
+                && self.fields == other.fields
+                && self.flags == other.flags;
+            assert!(deep, "VariantDef for the same def-id has differing data");
+        }
+
+        res
     }
 }
 
@@ -1939,7 +1962,15 @@ impl PartialEq for FieldDef {
 
         let Self { did: rhs_did, name: _, vis: _ } = other;
 
-        lhs_did == rhs_did
+        let res = lhs_did == rhs_did;
+
+        // Double check that implicit assumption detailed above.
+        if cfg!(debug_assertions) && res {
+            let deep = self.name == other.name && self.vis == other.vis;
+            assert!(deep, "FieldDef for the same def-id has differing data");
+        }
+
+        res
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 810c388ebbe..a2e77d9cdfe 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -56,6 +56,7 @@ trivially_parameterized_over_tcx! {
     std::string::String,
     crate::metadata::ModChild,
     crate::middle::codegen_fn_attrs::CodegenFnAttrs,
+    crate::middle::debugger_visualizer::DebuggerVisualizerFile,
     crate::middle::exported_symbols::SymbolExportInfo,
     crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
     crate::mir::ConstQualifs,
@@ -91,7 +92,6 @@ trivially_parameterized_over_tcx! {
     rustc_session::cstore::ForeignModule,
     rustc_session::cstore::LinkagePreference,
     rustc_session::cstore::NativeLib,
-    rustc_span::DebuggerVisualizerFile,
     rustc_span::ExpnData,
     rustc_span::ExpnHash,
     rustc_span::ExpnId,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index a8193c3e559..a064174e261 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,6 +1,6 @@
 use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
+use crate::query::IntoQueryParam;
 use crate::query::Providers;
-use crate::ty::query::IntoQueryParam;
 use crate::ty::{
     self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
     TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -1164,6 +1164,22 @@ pub trait PrettyPrinter<'tcx>:
         traits.entry(trait_ref).or_default().extend(proj_ty);
     }
 
+    fn pretty_print_inherent_projection(
+        self,
+        alias_ty: &ty::AliasTy<'tcx>,
+    ) -> Result<Self::Path, Self::Error> {
+        let def_key = self.tcx().def_key(alias_ty.def_id);
+        self.path_generic_args(
+            |cx| {
+                cx.path_append(
+                    |cx| cx.path_qualified(alias_ty.self_ty(), None),
+                    &def_key.disambiguated_data,
+                )
+            },
+            &alias_ty.substs[1..],
+        )
+    }
+
     fn ty_infer_name(&self, _: ty::TyVid) -> Option<Symbol> {
         None
     }
@@ -2821,7 +2837,11 @@ define_print_and_forward_display! {
     }
 
     ty::AliasTy<'tcx> {
-        p!(print_def_path(self.def_id, self.substs));
+        if let DefKind::Impl { of_trait: false } = cx.tcx().def_kind(cx.tcx().parent(self.def_id)) {
+            p!(pretty_print_inherent_projection(self))
+        } else {
+            p!(print_def_path(self.def_id, self.substs));
+        }
     }
 
     ty::ClosureKind {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 5a0571f4bb7..e04dbbff9a7 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -151,10 +151,14 @@ pub struct TypeckResults<'tcx> {
     /// this field will be set to `Some(ErrorGuaranteed)`.
     pub tainted_by_errors: Option<ErrorGuaranteed>,
 
-    /// All the opaque types that have hidden types set
-    /// by this function. We also store the
-    /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
-    /// even if they are only set in dead code (which doesn't show up in MIR).
+    /// All the opaque types that have hidden types set by this function.
+    /// We also store the type here, so that the compiler can use it as a hint
+    /// for figuring out hidden types, even if they are only set in dead code
+    /// (which doesn't show up in MIR).
+    ///
+    /// These types are mapped back to the opaque's identity substitutions
+    /// (with erased regions), which is why we don't associated substs with any
+    /// of these usages.
     pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
 
     /// Tracks the minimum captures required for a closure;
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index c385b00692f..bcab4c0d24b 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -15,6 +15,7 @@ use rustc_middle::mir::Place;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
+use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, Ty, UpvarSubsts};
 use rustc_span::Span;
 
@@ -225,49 +226,63 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     );
                     let (op,ty) = (Operand::Move(discr), discr_ty);
 
-                    if let Abi::Scalar(scalar) = layout.unwrap().abi{
-                        if let Primitive::Int(_, signed) = scalar.primitive() {
-                            let range = scalar.valid_range(&this.tcx);
-                            // FIXME: Handle wraparound cases too.
-                            if range.end >= range.start {
-                                let mut assumer = |range: u128, bin_op: BinOp| {
-                                    // We will be overwriting this val if our scalar is signed value
-                                    // because sign extension on unsigned types might cause unintended things
-                                    let mut range_val =
-                                        ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(discr_ty));
-                                    let bool_ty = this.tcx.types.bool;
-                                    if signed {
-                                        let scalar_size_extend = scalar.size(&this.tcx).sign_extend(range);
-                                        let discr_layout = this.tcx.layout_of(this.param_env.and(discr_ty));
-                                        let truncated_val = discr_layout.unwrap().size.truncate(scalar_size_extend);
-                                        range_val = ConstantKind::from_bits(
-                                            this.tcx,
-                                            truncated_val,
-                                            ty::ParamEnv::empty().and(discr_ty),
-                                        );
-                                    }
-                                    let lit_op = this.literal_operand(expr.span, range_val);
-                                    let is_bin_op = this.temp(bool_ty, expr_span);
-                                    this.cfg.push_assign(
-                                        block,
-                                        source_info,
-                                        is_bin_op,
-                                        Rvalue::BinaryOp(bin_op, Box::new(((lit_op), (Operand::Copy(discr))))),
-                                    );
-                                    this.cfg.push(
-                                        block,
-                                        Statement {
-                                            source_info,
-                                            kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
-                                                Operand::Copy(is_bin_op),
-                                            ))),
-                                        },
-                                    )
-                                };
-                                assumer(range.end, BinOp::Ge);
-                                assumer(range.start, BinOp::Le);
-                            }
-                        }
+                    if let Abi::Scalar(scalar) = layout.unwrap().abi
+                        && !scalar.is_always_valid(&this.tcx)
+                        && let Primitive::Int(int_width, _signed) = scalar.primitive()
+                    {
+                        let unsigned_ty = int_width.to_ty(this.tcx, false);
+                        let unsigned_place = this.temp(unsigned_ty, expr_span);
+                        this.cfg.push_assign(
+                            block,
+                            source_info,
+                            unsigned_place,
+                            Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr), unsigned_ty));
+
+                        let bool_ty = this.tcx.types.bool;
+                        let range = scalar.valid_range(&this.tcx);
+                        let merge_op =
+                            if range.start <= range.end {
+                                BinOp::BitAnd
+                            } else {
+                                BinOp::BitOr
+                            };
+
+                        let mut comparer = |range: u128, bin_op: BinOp| -> Place<'tcx> {
+                            let range_val =
+                                ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(unsigned_ty));
+                            let lit_op = this.literal_operand(expr.span, range_val);
+                            let is_bin_op = this.temp(bool_ty, expr_span);
+                            this.cfg.push_assign(
+                                block,
+                                source_info,
+                                is_bin_op,
+                                Rvalue::BinaryOp(bin_op, Box::new((Operand::Copy(unsigned_place), lit_op))),
+                            );
+                            is_bin_op
+                        };
+                        let assert_place = if range.start == 0 {
+                            comparer(range.end, BinOp::Le)
+                        } else {
+                            let start_place = comparer(range.start, BinOp::Ge);
+                            let end_place = comparer(range.end, BinOp::Le);
+                            let merge_place = this.temp(bool_ty, expr_span);
+                            this.cfg.push_assign(
+                                block,
+                                source_info,
+                                merge_place,
+                                Rvalue::BinaryOp(merge_op, Box::new((Operand::Move(start_place), Operand::Move(end_place)))),
+                            );
+                            merge_place
+                        };
+                        this.cfg.push(
+                            block,
+                            Statement {
+                                source_info,
+                                kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
+                                    Operand::Move(assert_place),
+                                ))),
+                            },
+                        );
                     }
 
                     (op,ty)
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 56c87c402fe..b01b6fbf222 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -644,24 +644,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         };
 
-        if let Some(destination) = destination {
-            if let Some(value) = value {
+        match (destination, value) {
+            (Some(destination), Some(value)) => {
                 debug!("stmt_expr Break val block_context.push(SubExpr)");
                 self.block_context.push(BlockFrame::SubExpr);
                 unpack!(block = self.expr_into_dest(destination, block, value));
                 self.block_context.pop();
-            } else {
+            }
+            (Some(destination), None) => {
                 self.cfg.push_assign_unit(block, source_info, destination, self.tcx)
             }
-        } else {
-            assert!(value.is_none(), "`return` and `break` should have a destination");
-            if self.tcx.sess.instrument_coverage() {
+            (None, Some(_)) => {
+                panic!("`return`, `become` and `break` with value and must have a destination")
+            }
+            (None, None) if self.tcx.sess.instrument_coverage() => {
                 // Unlike `break` and `return`, which push an `Assign` statement to MIR, from which
                 // a Coverage code region can be generated, `continue` needs no `Assign`; but
                 // without one, the `InstrumentCoverage` MIR pass cannot generate a code region for
                 // `continue`. Coverage will be missing unless we add a dummy `Assign` to MIR.
                 self.add_dummy_assignment(span, block, source_info);
             }
+            (None, None) => {}
         }
 
         let region_scope = self.scopes.breakable_scopes[break_index].region_scope;
@@ -671,12 +674,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         } else {
             self.scopes.breakable_scopes[break_index].continue_drops.as_mut().unwrap()
         };
-        let mut drop_idx = ROOT_NODE;
-        for scope in &self.scopes.scopes[scope_index + 1..] {
-            for drop in &scope.drops {
-                drop_idx = drops.add_drop(*drop, drop_idx);
-            }
-        }
+
+        let drop_idx = self.scopes.scopes[scope_index + 1..]
+            .iter()
+            .flat_map(|scope| &scope.drops)
+            .fold(ROOT_NODE, |drop_idx, &drop| drops.add_drop(drop, drop_idx));
+
         drops.add_entry(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index f46eb5a0ce1..c8648224ac1 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -130,6 +130,7 @@ impl<'tcx> Cx<'tcx> {
                 ExprKind::Pointer { cast: PointerCast::Unsize, source: self.thir.exprs.push(expr) }
             }
             Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.thir.exprs.push(expr) },
+            Adjust::NeverToAny if adjustment.target.is_never() => return expr,
             Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
             Adjust::Deref(None) => {
                 adjust_span(&mut expr);
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 2e68c794356..18895072c3b 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -276,6 +276,7 @@ where
                 assert_eq!(self.elaborator.param_env().reveal(), Reveal::All);
                 let field_ty =
                     tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, substs));
+
                 (tcx.mk_place_field(base_place, field, field_ty), subpath)
             })
             .collect()
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index e554c470646..35e4c24dc46 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -118,7 +118,7 @@ use rustc_middle::mir::spanview::{self, SpanViewable};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::coverage::*;
-use rustc_middle::mir::{self, BasicBlock, TerminatorKind};
+use rustc_middle::mir::{self, BasicBlock};
 use rustc_middle::ty::TyCtxt;
 use rustc_span::Span;
 
@@ -796,7 +796,7 @@ fn bcb_to_string_sections<'tcx>(
     }
     let non_term_blocks = bcb_data.basic_blocks[0..len - 1]
         .iter()
-        .map(|&bb| format!("{:?}: {}", bb, term_type(&mir_body[bb].terminator().kind)))
+        .map(|&bb| format!("{:?}: {}", bb, mir_body[bb].terminator().kind.name()))
         .collect::<Vec<_>>();
     if non_term_blocks.len() > 0 {
         sections.push(non_term_blocks.join("\n"));
@@ -804,28 +804,7 @@ fn bcb_to_string_sections<'tcx>(
     sections.push(format!(
         "{:?}: {}",
         bcb_data.basic_blocks.last().unwrap(),
-        term_type(&bcb_data.terminator(mir_body).kind)
+        bcb_data.terminator(mir_body).kind.name(),
     ));
     sections
 }
-
-/// Returns a simple string representation of a `TerminatorKind` variant, independent of any
-/// values it might hold.
-pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str {
-    match kind {
-        TerminatorKind::Goto { .. } => "Goto",
-        TerminatorKind::SwitchInt { .. } => "SwitchInt",
-        TerminatorKind::Resume => "Resume",
-        TerminatorKind::Terminate => "Terminate",
-        TerminatorKind::Return => "Return",
-        TerminatorKind::Unreachable => "Unreachable",
-        TerminatorKind::Drop { .. } => "Drop",
-        TerminatorKind::Call { .. } => "Call",
-        TerminatorKind::Assert { .. } => "Assert",
-        TerminatorKind::Yield { .. } => "Yield",
-        TerminatorKind::GeneratorDrop => "GeneratorDrop",
-        TerminatorKind::FalseEdge { .. } => "FalseEdge",
-        TerminatorKind::FalseUnwind { .. } => "FalseUnwind",
-        TerminatorKind::InlineAsm { .. } => "InlineAsm",
-    }
-}
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 97dd1dd09a2..d27200419e2 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,4 +1,3 @@
-use super::debug::term_type;
 use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB};
 
 use itertools::Itertools;
@@ -40,7 +39,7 @@ impl CoverageStatement {
                     "{}: @{}.{}: {:?}",
                     source_range_no_file(tcx, span),
                     bb.index(),
-                    term_type(&term.kind),
+                    term.kind.name(),
                     term.kind
                 )
             }
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 83a335197b3..90b58933df7 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -25,7 +25,6 @@
 //! to: `rustc_span::create_default_session_globals_then(|| { test_here(); })`.
 
 use super::counters;
-use super::debug;
 use super::graph;
 use super::spans;
 
@@ -188,12 +187,12 @@ fn debug_basic_blocks(mir_body: &Body<'_>) -> String {
                     | TerminatorKind::Goto { target }
                     | TerminatorKind::InlineAsm { destination: Some(target), .. }
                     | TerminatorKind::Yield { resume: target, .. } => {
-                        format!("{}{:?}:{} -> {:?}", sp, bb, debug::term_type(kind), target)
+                        format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), target)
                     }
                     TerminatorKind::SwitchInt { targets, .. } => {
-                        format!("{}{:?}:{} -> {:?}", sp, bb, debug::term_type(kind), targets)
+                        format!("{}{:?}:{} -> {:?}", sp, bb, kind.name(), targets)
                     }
-                    _ => format!("{}{:?}:{}", sp, bb, debug::term_type(kind)),
+                    _ => format!("{}{:?}:{}", sp, bb, kind.name()),
                 }
             })
             .collect::<Vec<_>>()
@@ -215,7 +214,7 @@ fn print_mir_graphviz(name: &str, mir_body: &Body<'_>) {
                         "    {:?} [label=\"{:?}: {}\"];\n{}",
                         bb,
                         bb,
-                        debug::term_type(&data.terminator().kind),
+                        data.terminator().kind.name(),
                         mir_body
                             .basic_blocks
                             .successors(bb)
@@ -244,7 +243,7 @@ fn print_coverage_graphviz(
                         "    {:?} [label=\"{:?}: {}\"];\n{}",
                         bcb,
                         bcb,
-                        debug::term_type(&bcb_data.terminator(mir_body).kind),
+                        bcb_data.terminator(mir_body).kind.name(),
                         basic_coverage_blocks
                             .successors(bcb)
                             .map(|successor| { format!("    {:?} -> {:?};", bcb, successor) })
diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs
index 594cbd8977e..746e3d9652d 100644
--- a/compiler/rustc_mir_transform/src/dump_mir.rs
+++ b/compiler/rustc_mir_transform/src/dump_mir.rs
@@ -12,7 +12,7 @@ use rustc_session::config::OutputType;
 pub struct Marker(pub &'static str);
 
 impl<'tcx> MirPass<'tcx> for Marker {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.0
     }
 
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index ece20d8d3e6..6c2e22a70b9 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -7,6 +7,7 @@ use rustc_index::Idx;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
+use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
 use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
@@ -167,8 +168,20 @@ impl<'tcx> Inliner<'tcx> {
     ) -> Result<std::ops::Range<BasicBlock>, &'static str> {
         let callee_attrs = self.tcx.codegen_fn_attrs(callsite.callee.def_id());
         self.check_codegen_attributes(callsite, callee_attrs)?;
+
+        let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
+        let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
+        let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
+        for arg in args {
+            if !arg.ty(&caller_body.local_decls, self.tcx).is_sized(self.tcx, self.param_env) {
+                // We do not allow inlining functions with unsized params. Inlining these functions
+                // could create unsized locals, which are unsound and being phased out.
+                return Err("Call has unsized argument");
+            }
+        }
+
         self.check_mir_is_available(caller_body, &callsite.callee)?;
-        let callee_body = self.tcx.instance_mir(callsite.callee.def);
+        let callee_body = try_instance_mir(self.tcx, callsite.callee.def)?;
         self.check_mir_body(callsite, callee_body, callee_attrs)?;
 
         if !self.tcx.consider_optimizing(|| {
@@ -188,9 +201,6 @@ impl<'tcx> Inliner<'tcx> {
         // Check call signature compatibility.
         // Normally, this shouldn't be required, but trait normalization failure can create a
         // validation ICE.
-        let terminator = caller_body[callsite.block].terminator.as_ref().unwrap();
-        let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() };
-        let destination_ty = destination.ty(&caller_body.local_decls, self.tcx).ty;
         let output_type = callee_body.return_ty();
         if !util::is_subtype(self.tcx, self.param_env, output_type, destination_ty) {
             trace!(?output_type, ?destination_ty);
@@ -1128,3 +1138,27 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
         }
     }
 }
+
+#[instrument(skip(tcx), level = "debug")]
+fn try_instance_mir<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance: InstanceDef<'tcx>,
+) -> Result<&'tcx Body<'tcx>, &'static str> {
+    match instance {
+        ty::InstanceDef::DropGlue(_, Some(ty)) => match ty.kind() {
+            ty::Adt(def, substs) => {
+                let fields = def.all_fields();
+                for field in fields {
+                    let field_ty = field.ty(tcx, substs);
+                    if field_ty.has_param() && field_ty.has_projections() {
+                        return Err("cannot build drop shim for polymorphic type");
+                    }
+                }
+
+                Ok(tcx.instance_mir(instance))
+            }
+            _ => Ok(tcx.instance_mir(instance)),
+        },
+        _ => Ok(tcx.instance_mir(instance)),
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 6bff535586a..e4dc617620e 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -5,7 +5,6 @@ use crate::MirPass;
 use rustc_hir::Mutability;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::ValidityRequirement;
-use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
 use rustc_span::symbol::Symbol;
 use rustc_target::abi::FieldIdx;
@@ -163,18 +162,6 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
                     return;
                 }
 
-                // Transmuting a fieldless enum to its repr is a discriminant read
-                if let ty::Adt(adt_def, ..) = operand_ty.kind()
-                    && adt_def.is_enum()
-                    && adt_def.is_payloadfree()
-                    && let Some(place) = operand.place()
-                    && let Some(repr_int) = adt_def.repr().int
-                    && repr_int.to_ty(self.tcx) == *cast_ty
-                {
-                    *rvalue = Rvalue::Discriminant(place);
-                    return;
-                }
-
                 // Transmuting a transparent struct/union to a field's type is a projection
                 if let ty::Adt(adt_def, substs) = operand_ty.kind()
                     && adt_def.repr().transparent()
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index e1b65823a5a..710eed3ed38 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -6,7 +6,7 @@ use crate::{validate, MirPass};
 
 /// Just like `MirPass`, except it cannot mutate `Body`.
 pub trait MirLint<'tcx> {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         let name = std::any::type_name::<Self>();
         if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
     }
@@ -26,7 +26,7 @@ impl<'tcx, T> MirPass<'tcx> for Lint<T>
 where
     T: MirLint<'tcx>,
 {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.0.name()
     }
 
@@ -49,7 +49,7 @@ impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel<T>
 where
     T: MirPass<'tcx>,
 {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         self.1.name()
     }
 
@@ -121,7 +121,7 @@ fn run_passes_inner<'tcx>(
                 validate_body(tcx, body, format!("before pass {}", name));
             }
 
-            pass.run_pass(tcx, body);
+            tcx.sess.time(name, || pass.run_pass(tcx, body));
 
             if dump_enabled {
                 dump_mir_for_pass(tcx, body, &name, true);
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 1b96df3aed5..e59219321b7 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -74,7 +74,7 @@ pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 }
 
 impl<'tcx> MirPass<'tcx> for SimplifyCfg {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
         &self.name()
     }
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 55c937b305a..35b154b7b34 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -185,9 +185,9 @@ use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
 use rustc_middle::mir::visit::Visitor as MirVisitor;
 use rustc_middle::mir::{self, Local, Location};
+use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::query::TyCtxtAt;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
 use rustc_middle::ty::{
     self, GenericParamDefKind, Instance, InstanceDef, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index 1c18e6b0b02..ecc50c3f664 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -12,10 +12,9 @@ extern crate rustc_middle;
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_hir::lang_items::LangItem;
-use rustc_middle::query::Providers;
+use rustc_middle::query::{Providers, TyCtxtAt};
 use rustc_middle::traits;
 use rustc_middle::ty::adjustment::CustomCoerceUnsized;
-use rustc_middle::ty::query::TyCtxtAt;
 use rustc_middle::ty::{self, Ty};
 
 mod collector;
diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs
index c10180ee3f4..eafe57a0c02 100644
--- a/compiler/rustc_monomorphize/src/partitioning/mod.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs
@@ -250,13 +250,13 @@ where
         cgu.create_size_estimate(tcx);
     }
 
-    debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter());
+    debug_dump(tcx, "INITIAL PARTITIONING", &initial_partitioning.codegen_units);
 
     // Merge until we have at most `max_cgu_count` codegen units.
     {
         let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
         partitioner.merge_codegen_units(cx, &mut initial_partitioning);
-        debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
+        debug_dump(tcx, "POST MERGING", &initial_partitioning.codegen_units);
     }
 
     // In the next step, we use the inlining map to determine which additional
@@ -272,7 +272,7 @@ where
         cgu.create_size_estimate(tcx);
     }
 
-    debug_dump(tcx, "POST INLINING:", post_inlining.codegen_units.iter());
+    debug_dump(tcx, "POST INLINING", &post_inlining.codegen_units);
 
     // Next we try to make as many symbols "internal" as possible, so LLVM has
     // more freedom to optimize.
@@ -322,6 +322,8 @@ where
 
     result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
 
+    debug_dump(tcx, "FINAL", &result);
+
     result
 }
 
@@ -346,33 +348,37 @@ struct PostInliningPartitioning<'tcx> {
     internalization_candidates: FxHashSet<MonoItem<'tcx>>,
 }
 
-fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I)
-where
-    I: Iterator<Item = &'a CodegenUnit<'tcx>>,
-    'tcx: 'a,
-{
+fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
     let dump = move || {
         use std::fmt::Write;
 
+        let num_cgus = cgus.len();
+        let max = cgus.iter().map(|cgu| cgu.size_estimate()).max().unwrap();
+        let min = cgus.iter().map(|cgu| cgu.size_estimate()).min().unwrap();
+        let ratio = max as f64 / min as f64;
+
         let s = &mut String::new();
-        let _ = writeln!(s, "{label}");
+        let _ = writeln!(
+            s,
+            "{label} ({num_cgus} CodegenUnits, max={max}, min={min}, max/min={ratio:.1}):"
+        );
         for cgu in cgus {
             let _ =
-                writeln!(s, "CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate());
+                writeln!(s, "CodegenUnit {} estimated size {}:", cgu.name(), cgu.size_estimate());
 
             for (mono_item, linkage) in cgu.items() {
                 let symbol_name = mono_item.symbol_name(tcx).name;
                 let symbol_hash_start = symbol_name.rfind('h');
                 let symbol_hash = symbol_hash_start.map_or("<no hash>", |i| &symbol_name[i..]);
 
-                let _ = writeln!(
+                let _ = with_no_trimmed_paths!(writeln!(
                     s,
                     " - {} [{:?}] [{}] estimated size {}",
                     mono_item,
                     linkage,
                     symbol_hash,
                     mono_item.size_estimate(tcx)
-                );
+                ));
             }
 
             let _ = writeln!(s);
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 51e90489002..c6e6b46e455 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -662,7 +662,7 @@ impl<'a> StringReader<'a> {
                 &RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
                 prefix_span,
                 ast::CRATE_NODE_ID,
-                &format!("prefix `{prefix}` is unknown"),
+                format!("prefix `{prefix}` is unknown"),
                 BuiltinLintDiagnostics::ReservedPrefix(prefix_span),
             );
         }
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 3002f23da75..bcef0f7185f 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -238,6 +238,7 @@ impl<'a> DerefMut for SnapshotParser<'a> {
 
 impl<'a> Parser<'a> {
     #[rustc_lint_diagnostics]
+    #[track_caller]
     pub fn struct_span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 03279124177..54f9fc5d2b9 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -40,7 +40,8 @@ impl<'a> Parser<'a> {
 
     /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of whether
     /// or not we have attributes
-    pub(crate) fn parse_stmt_without_recovery(
+    // Public for `cfg_eval` macro expansion.
+    pub fn parse_stmt_without_recovery(
         &mut self,
         capture_semi: bool,
         force_collect: ForceCollect,
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 982c4615aff..928fdce313d 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -186,7 +186,7 @@ fn emit_malformed_attribute(
         suggestions.push(code);
     }
     if should_warn(name) {
-        sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, &msg);
+        sess.buffer_lint(&ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg);
     } else {
         sess.span_diagnostic
             .struct_span_err(span, error_msg)
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 455d7b89f9c..41f92227e7c 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -8,7 +8,6 @@ use crate::{errors, fluent_generated as fluent};
 use rustc_ast::{ast, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, IntoDiagnosticArg, MultiSpan};
-use rustc_expand::base::resolve_path;
 use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
@@ -1916,6 +1915,10 @@ impl CheckAttrVisitor<'_> {
 
     /// Checks if the items on the `#[debugger_visualizer]` attribute are valid.
     fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool {
+        // Here we only check that the #[debugger_visualizer] attribute is attached
+        // to nothing other than a module. All other checks are done in the
+        // `debugger_visualizer` query where they need to be done for decoding
+        // anyway.
         match target {
             Target::Mod => {}
             _ => {
@@ -1924,53 +1927,7 @@ impl CheckAttrVisitor<'_> {
             }
         }
 
-        let Some(hints) = attr.meta_item_list() else {
-            self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span });
-            return false;
-        };
-
-        let hint = match hints.len() {
-            1 => &hints[0],
-            _ => {
-                self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span });
-                return false;
-            }
-        };
-
-        let Some(meta_item) = hint.meta_item() else {
-            self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span });
-            return false;
-        };
-
-        let visualizer_path = match (meta_item.name_or_empty(), meta_item.value_str()) {
-            (sym::natvis_file, Some(value)) => value,
-            (sym::gdb_script_file, Some(value)) => value,
-            (_, _) => {
-                self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: meta_item.span });
-                return false;
-            }
-        };
-
-        let file =
-            match resolve_path(&self.tcx.sess.parse_sess, visualizer_path.as_str(), attr.span) {
-                Ok(file) => file,
-                Err(mut err) => {
-                    err.emit();
-                    return false;
-                }
-            };
-
-        match std::fs::File::open(&file) {
-            Ok(_) => true,
-            Err(error) => {
-                self.tcx.sess.emit_err(errors::DebugVisualizerUnreadable {
-                    span: meta_item.span,
-                    file: &file,
-                    error,
-                });
-                false
-            }
-        }
+        true
     }
 
     /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros.
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index 8ea95b3f383..3483f7da528 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -1,60 +1,69 @@
 //! Detecting usage of the `#[debugger_visualizer]` attribute.
 
-use hir::CRATE_HIR_ID;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_ast::Attribute;
 use rustc_data_structures::sync::Lrc;
 use rustc_expand::base::resolve_path;
-use rustc_hir as hir;
-use rustc_hir::HirId;
-use rustc_middle::query::{LocalCrate, Providers};
-use rustc_middle::ty::TyCtxt;
-use rustc_span::{sym, DebuggerVisualizerFile, DebuggerVisualizerType};
+use rustc_middle::{
+    middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType},
+    query::{LocalCrate, Providers},
+    ty::TyCtxt,
+};
+use rustc_session::Session;
+use rustc_span::sym;
 
-use crate::errors::DebugVisualizerUnreadable;
+use crate::errors::{DebugVisualizerInvalid, DebugVisualizerUnreadable};
 
-fn check_for_debugger_visualizer(
-    tcx: TyCtxt<'_>,
-    hir_id: HirId,
-    debugger_visualizers: &mut FxHashSet<DebuggerVisualizerFile>,
-) {
-    let attrs = tcx.hir().attrs(hir_id);
-    for attr in attrs {
+impl DebuggerVisualizerCollector<'_> {
+    fn check_for_debugger_visualizer(&mut self, attr: &Attribute) {
         if attr.has_name(sym::debugger_visualizer) {
-            let Some(list) = attr.meta_item_list() else {
-                continue
+            let Some(hints) = attr.meta_item_list() else {
+                self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
+                return;
             };
 
-            let meta_item = match list.len() {
-                1 => match list[0].meta_item() {
-                    Some(meta_item) => meta_item,
-                    _ => continue,
-                },
-                _ => continue,
+            let hint = if hints.len() == 1 {
+                &hints[0]
+            } else {
+                self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
+                return;
             };
 
-            let visualizer_type = match meta_item.name_or_empty() {
-                sym::natvis_file => DebuggerVisualizerType::Natvis,
-                sym::gdb_script_file => DebuggerVisualizerType::GdbPrettyPrinter,
-                _ => continue,
+            let Some(meta_item) = hint.meta_item() else {
+                self.sess.emit_err(DebugVisualizerInvalid { span: attr.span });
+                return;
             };
 
-            let file = match meta_item.value_str() {
-                Some(value) => {
-                    match resolve_path(&tcx.sess.parse_sess, value.as_str(), attr.span) {
-                        Ok(file) => file,
-                        _ => continue,
+            let (visualizer_type, visualizer_path) =
+                match (meta_item.name_or_empty(), meta_item.value_str()) {
+                    (sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value),
+                    (sym::gdb_script_file, Some(value)) => {
+                        (DebuggerVisualizerType::GdbPrettyPrinter, value)
                     }
-                }
-                None => continue,
-            };
+                    (_, _) => {
+                        self.sess.emit_err(DebugVisualizerInvalid { span: meta_item.span });
+                        return;
+                    }
+                };
+
+            let file =
+                match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) {
+                    Ok(file) => file,
+                    Err(mut err) => {
+                        err.emit();
+                        return;
+                    }
+                };
 
             match std::fs::read(&file) {
                 Ok(contents) => {
-                    debugger_visualizers
-                        .insert(DebuggerVisualizerFile::new(Lrc::from(contents), visualizer_type));
+                    self.visualizers.push(DebuggerVisualizerFile::new(
+                        Lrc::from(contents),
+                        visualizer_type,
+                        file,
+                    ));
                 }
                 Err(error) => {
-                    tcx.sess.emit_err(DebugVisualizerUnreadable {
+                    self.sess.emit_err(DebugVisualizerUnreadable {
                         span: meta_item.span,
                         file: &file,
                         error,
@@ -65,29 +74,30 @@ fn check_for_debugger_visualizer(
     }
 }
 
-/// Traverses and collects the debugger visualizers for a specific crate.
-fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> {
-    // Initialize the collector.
-    let mut debugger_visualizers = FxHashSet::default();
+struct DebuggerVisualizerCollector<'a> {
+    sess: &'a Session,
+    visualizers: Vec<DebuggerVisualizerFile>,
+}
 
-    // Collect debugger visualizers in this crate.
-    tcx.hir().for_each_module(|id| {
-        check_for_debugger_visualizer(
-            tcx,
-            tcx.hir().local_def_id_to_hir_id(id),
-            &mut debugger_visualizers,
-        )
-    });
+impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> {
+    fn visit_attribute(&mut self, attr: &'ast Attribute) {
+        self.check_for_debugger_visualizer(attr);
+        rustc_ast::visit::walk_attribute(self, attr);
+    }
+}
 
-    // Collect debugger visualizers on the crate attributes.
-    check_for_debugger_visualizer(tcx, CRATE_HIR_ID, &mut debugger_visualizers);
+/// Traverses and collects the debugger visualizers for a specific crate.
+fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec<DebuggerVisualizerFile> {
+    let resolver_and_krate = tcx.resolver_for_lowering(()).borrow();
+    let krate = &*resolver_and_krate.1;
 
-    // Extract out the found debugger_visualizer items.
-    let mut visualizers = debugger_visualizers.into_iter().collect::<Vec<_>>();
+    let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() };
+    rustc_ast::visit::Visitor::visit_crate(&mut visitor, krate);
 
-    // Sort the visualizers so we always get a deterministic query result.
-    visualizers.sort();
-    visualizers
+    // We are collecting visualizers in AST-order, which is deterministic,
+    // so we don't need to do any explicit sorting in order to get a
+    // deterministic query result
+    visitor.visualizers
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index 3c542821b67..4cf0f1305a7 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -15,7 +15,7 @@
 #[macro_use]
 extern crate rustc_middle;
 
-use crate::plumbing::{encode_all_query_results, try_mark_green};
+use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
 use field_offset::offset_of;
 use rustc_data_structures::stable_hasher::HashStable;
 use rustc_data_structures::sync::AtomicU64;
@@ -23,13 +23,14 @@ use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepNodeIndex;
 use rustc_middle::dep_graph::{self, DepKind, DepKindStruct};
 use rustc_middle::query::erase::{erase, restore, Erase};
-use rustc_middle::query::on_disk_cache::OnDiskCache;
+use rustc_middle::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex, OnDiskCache};
+use rustc_middle::query::plumbing::{
+    DynamicQuery, QueryKeyStringCache, QuerySystem, QuerySystemFns,
+};
 use rustc_middle::query::AsLocalKey;
 use rustc_middle::query::{
-    query_keys, query_provided, query_provided_to_value, query_storage, query_values,
-    DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
+    queries, DynamicQueries, ExternProviders, Providers, QueryCaches, QueryEngine, QueryStates,
 };
-use rustc_middle::ty::query::{DynamicQuery, QuerySystem, QuerySystemFns};
 use rustc_middle::ty::TyCtxt;
 use rustc_query_system::dep_graph::SerializedDepNodeIndex;
 use rustc_query_system::ich::StableHashingContext;
@@ -216,7 +217,6 @@ pub fn query_system<'tcx>(
             engine: engine(incremental),
             local_providers,
             extern_providers,
-            query_structs: make_dep_kind_array!(query_structs).to_vec(),
             encode_query_results: encode_all_query_results,
             try_mark_green: try_mark_green,
         },
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 5acfeb47a12..244f0e84b43 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -81,8 +81,8 @@ impl QueryContext for QueryCtxt<'_> {
     fn try_collect_active_jobs(self) -> Option<QueryMap<DepKind>> {
         let mut jobs = QueryMap::default();
 
-        for query in &self.query_system.fns.query_structs {
-            (query.try_collect_active_jobs)(self.tcx, &mut jobs);
+        for collect in super::TRY_COLLECT_ACTIVE_JOBS.iter() {
+            collect(self.tcx, &mut jobs);
         }
 
         Some(jobs)
@@ -183,10 +183,8 @@ pub(super) fn encode_all_query_results<'tcx>(
     encoder: &mut CacheEncoder<'_, 'tcx>,
     query_result_index: &mut EncodedDepNodeIndex,
 ) {
-    for query in &tcx.query_system.fns.query_structs {
-        if let Some(encode) = query.encode_query_results {
-            encode(tcx, encoder, query_result_index);
-        }
+    for encode in super::ENCODE_QUERY_RESULTS.iter().copied().filter_map(|e| e) {
+        encode(tcx, encoder, query_result_index);
     }
 }
 
@@ -476,6 +474,16 @@ where
     }
 }
 
+macro_rules! item_if_cached {
+    ([] $tokens:tt) => {};
+    ([(cache) $($rest:tt)*] { $($tokens:tt)* }) => {
+        $($tokens)*
+    };
+    ([$other:tt $($modifiers:tt)*] $tokens:tt) => {
+        item_if_cached! { [$($modifiers)*] $tokens }
+    };
+}
+
 macro_rules! expand_if_cached {
     ([], $tokens:expr) => {{
         None
@@ -488,167 +496,227 @@ macro_rules! expand_if_cached {
     };
 }
 
+/// Don't show the backtrace for query system by default
+/// use `RUST_BACKTRACE=full` to show all the backtraces
+#[inline(never)]
+pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
+where
+    F: FnOnce() -> T,
+{
+    let result = f();
+    std::hint::black_box(());
+    result
+}
+
 // NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
 // invoked by `rustc_query_append`.
 macro_rules! define_queries {
     (
      $($(#[$attr:meta])*
         [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
-        mod get_query_incr {
-            use super::*;
 
-            $(
-                #[inline(always)]
-                #[tracing::instrument(level = "trace", skip(tcx))]
-                pub(super) fn $name<'tcx>(
+        pub(crate) mod query_impl { $(pub mod $name {
+            use super::super::*;
+            use std::marker::PhantomData;
+
+            pub mod get_query_incr {
+                use super::*;
+
+                // Adding `__rust_end_short_backtrace` marker to backtraces so that we emit the frames
+                // when `RUST_BACKTRACE=1`, add a new mod with `$name` here is to allow duplicate naming
+                #[inline(never)]
+                pub fn __rust_end_short_backtrace<'tcx>(
                     tcx: TyCtxt<'tcx>,
                     span: Span,
-                    key: query_keys::$name<'tcx>,
+                    key: queries::$name::Key<'tcx>,
                     mode: QueryMode,
-                ) -> Option<Erase<query_values::$name<'tcx>>> {
+                ) -> Option<Erase<queries::$name::Value<'tcx>>> {
                     get_query_incr(
-                        queries::$name::config(tcx),
+                        QueryType::config(tcx),
                         QueryCtxt::new(tcx),
                         span,
                         key,
                         mode
                     )
                 }
-            )*
-        }
+            }
 
-        mod get_query_non_incr {
-            use super::*;
+            pub mod get_query_non_incr {
+                use super::*;
 
-            $(
-                #[inline(always)]
-                #[tracing::instrument(level = "trace", skip(tcx))]
-                pub(super) fn $name<'tcx>(
+                #[inline(never)]
+                pub fn __rust_end_short_backtrace<'tcx>(
                     tcx: TyCtxt<'tcx>,
                     span: Span,
-                    key: query_keys::$name<'tcx>,
+                    key: queries::$name::Key<'tcx>,
                     __mode: QueryMode,
-                ) -> Option<Erase<query_values::$name<'tcx>>> {
+                ) -> Option<Erase<queries::$name::Value<'tcx>>> {
                     Some(get_query_non_incr(
-                        queries::$name::config(tcx),
+                        QueryType::config(tcx),
                         QueryCtxt::new(tcx),
                         span,
                         key,
                     ))
                 }
-            )*
-        }
+            }
 
-        pub(crate) fn engine(incremental: bool) -> QueryEngine {
-            if incremental {
-                QueryEngine {
-                    $($name: get_query_incr::$name,)*
-                }
-            } else {
-                QueryEngine {
-                    $($name: get_query_non_incr::$name,)*
+            pub fn dynamic_query<'tcx>() -> DynamicQuery<'tcx, queries::$name::Storage<'tcx>> {
+                DynamicQuery {
+                    name: stringify!($name),
+                    eval_always: is_eval_always!([$($modifiers)*]),
+                    dep_kind: dep_graph::DepKind::$name,
+                    handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
+                    query_state: offset_of!(QueryStates<'tcx> => $name),
+                    query_cache: offset_of!(QueryCaches<'tcx> => $name),
+                    cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
+                    execute_query: |tcx, key| erase(tcx.$name(key)),
+                    compute: |tcx, key| {
+                        __rust_begin_short_backtrace(||
+                            queries::$name::provided_to_erased(
+                                tcx,
+                                call_provider!([$($modifiers)*][tcx, $name, key])
+                            )
+                        )
+                    },
+                    can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
+                    try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
+                        |tcx, key, prev_index, index| {
+                            if ::rustc_middle::query::cached::$name(tcx, key) {
+                                let value = $crate::plumbing::try_load_from_disk::<
+                                    queries::$name::ProvidedValue<'tcx>
+                                >(
+                                    tcx,
+                                    prev_index,
+                                    index,
+                                );
+                                value.map(|value| queries::$name::provided_to_erased(tcx, value))
+                            } else {
+                                None
+                            }
+                        }
+                    } {
+                        |_tcx, _key, _prev_index, _index| None
+                    }),
+                    value_from_cycle_error: |tcx, cycle| {
+                        let result: queries::$name::Value<'tcx> = Value::from_cycle_error(tcx, cycle);
+                        erase(result)
+                    },
+                    loadable_from_disk: |_tcx, _key, _index| {
+                        should_ever_cache_on_disk!([$($modifiers)*] {
+                            ::rustc_middle::query::cached::$name(_tcx, _key) &&
+                                $crate::plumbing::loadable_from_disk(_tcx, _index)
+                        } {
+                            false
+                        })
+                    },
+                    hash_result: hash_result!([$($modifiers)*][queries::$name::Value<'tcx>]),
+                    format_value: |value| format!("{:?}", restore::<queries::$name::Value<'tcx>>(*value)),
                 }
             }
-        }
-
-        #[allow(nonstandard_style)]
-        mod queries {
-            use std::marker::PhantomData;
 
-            $(
-                #[derive(Copy, Clone, Default)]
-                pub struct $name<'tcx> {
-                    data: PhantomData<&'tcx ()>
-                }
-            )*
-        }
+            #[derive(Copy, Clone, Default)]
+            pub struct QueryType<'tcx> {
+                data: PhantomData<&'tcx ()>
+            }
 
-        #[allow(nonstandard_style)]
-        mod dynamic_query {
-            use super::*;
+            impl<'tcx> QueryConfigRestored<'tcx> for QueryType<'tcx> {
+                type RestoredValue = queries::$name::Value<'tcx>;
+                type Config = DynamicConfig<
+                    'tcx,
+                    queries::$name::Storage<'tcx>,
+                    { is_anon!([$($modifiers)*]) },
+                    { depth_limit!([$($modifiers)*]) },
+                    { feedable!([$($modifiers)*]) },
+                >;
 
-            $(
-                pub(super) fn $name<'tcx>() -> DynamicQuery<'tcx, query_storage::$name<'tcx>> {
-                    DynamicQuery {
-                        name: stringify!($name),
-                        eval_always: is_eval_always!([$($modifiers)*]),
-                        dep_kind: dep_graph::DepKind::$name,
-                        handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
-                        query_state: offset_of!(QueryStates<'tcx> => $name),
-                        query_cache: offset_of!(QueryCaches<'tcx> => $name),
-                        cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
-                        execute_query: |tcx, key| erase(tcx.$name(key)),
-                        compute: |tcx, key| query_provided_to_value::$name(
-                            tcx,
-                            call_provider!([$($modifiers)*][tcx, $name, key])
-                        ),
-                        can_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] true false),
-                        try_load_from_disk: should_ever_cache_on_disk!([$($modifiers)*] {
-                            |tcx, key, prev_index, index| {
-                                if ::rustc_middle::query::cached::$name(tcx, key) {
-                                    let value = $crate::plumbing::try_load_from_disk::<query_provided::$name<'tcx>>(
-                                        tcx,
-                                        prev_index,
-                                        index,
-                                    );
-                                    value.map(|value| query_provided_to_value::$name(tcx, value))
-                                } else {
-                                    None
-                                }
-                            }
-                        } {
-                            |_tcx, _key, _prev_index, _index| None
-                        }),
-                        value_from_cycle_error: |tcx, cycle| {
-                            let result: query_values::$name<'tcx> = Value::from_cycle_error(tcx, cycle);
-                            erase(result)
-                        },
-                        loadable_from_disk: |_tcx, _key, _index| {
-                            should_ever_cache_on_disk!([$($modifiers)*] {
-                                ::rustc_middle::query::cached::$name(_tcx, _key) &&
-                                    $crate::plumbing::loadable_from_disk(_tcx, _index)
-                            } {
-                                false
-                            })
-                        },
-                        hash_result: hash_result!([$($modifiers)*][query_values::$name<'tcx>]),
-                        format_value: |value| format!("{:?}", restore::<query_values::$name<'tcx>>(*value)),
+                #[inline(always)]
+                fn config(tcx: TyCtxt<'tcx>) -> Self::Config {
+                    DynamicConfig {
+                        dynamic: &tcx.query_system.dynamic_queries.$name,
                     }
                 }
-            )*
-        }
 
-        $(impl<'tcx> QueryConfigRestored<'tcx> for queries::$name<'tcx> {
-            type RestoredValue = query_values::$name<'tcx>;
-            type Config = DynamicConfig<
-                'tcx,
-                query_storage::$name<'tcx>,
-                { is_anon!([$($modifiers)*]) },
-                { depth_limit!([$($modifiers)*]) },
-                { feedable!([$($modifiers)*]) },
-            >;
-
-            #[inline(always)]
-            fn config(tcx: TyCtxt<'tcx>) -> Self::Config {
-                DynamicConfig {
-                    dynamic: &tcx.query_system.dynamic_queries.$name,
+                #[inline(always)]
+                fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
+                    restore::<queries::$name::Value<'tcx>>(value)
                 }
             }
 
-            #[inline(always)]
-            fn restore(value: <Self::Config as QueryConfig<QueryCtxt<'tcx>>>::Value) -> Self::RestoredValue {
-                restore::<query_values::$name<'tcx>>(value)
+            pub fn try_collect_active_jobs<'tcx>(tcx: TyCtxt<'tcx>, qmap: &mut QueryMap<DepKind>) {
+                let make_query = |tcx, key| {
+                    let kind = rustc_middle::dep_graph::DepKind::$name;
+                    let name = stringify!($name);
+                    $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
+                };
+                tcx.query_system.states.$name.try_collect_active_jobs(
+                    tcx,
+                    make_query,
+                    qmap,
+                ).unwrap();
+            }
+
+            pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>, string_cache: &mut QueryKeyStringCache) {
+                $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
+                    tcx,
+                    stringify!($name),
+                    &tcx.query_system.caches.$name,
+                    string_cache,
+                )
+            }
+
+            item_if_cached! { [$($modifiers)*] {
+                pub fn encode_query_results<'tcx>(
+                    tcx: TyCtxt<'tcx>,
+                    encoder: &mut CacheEncoder<'_, 'tcx>,
+                    query_result_index: &mut EncodedDepNodeIndex
+                ) {
+                    $crate::plumbing::encode_query_results::<query_impl::$name::QueryType<'tcx>>(
+                        query_impl::$name::QueryType::config(tcx),
+                        QueryCtxt::new(tcx),
+                        encoder,
+                        query_result_index,
+                    )
+                }
+            }}
+        })*}
+
+        pub(crate) fn engine(incremental: bool) -> QueryEngine {
+            if incremental {
+                QueryEngine {
+                    $($name: query_impl::$name::get_query_incr::__rust_end_short_backtrace,)*
+                }
+            } else {
+                QueryEngine {
+                    $($name: query_impl::$name::get_query_non_incr::__rust_end_short_backtrace,)*
+                }
             }
-        })*
+        }
 
         pub fn dynamic_queries<'tcx>() -> DynamicQueries<'tcx> {
             DynamicQueries {
                 $(
-                    $name: dynamic_query::$name(),
+                    $name: query_impl::$name::dynamic_query(),
                 )*
             }
         }
 
+        // These arrays are used for iteration and can't be indexed by `DepKind`.
+
+        const TRY_COLLECT_ACTIVE_JOBS: &[for<'tcx> fn(TyCtxt<'tcx>, &mut QueryMap<DepKind>)] =
+            &[$(query_impl::$name::try_collect_active_jobs),*];
+
+        const ALLOC_SELF_PROFILE_QUERY_STRINGS: &[
+            for<'tcx> fn(TyCtxt<'tcx>, &mut QueryKeyStringCache)
+        ] = &[$(query_impl::$name::alloc_self_profile_query_strings),*];
+
+        const ENCODE_QUERY_RESULTS: &[
+            Option<for<'tcx> fn(
+                TyCtxt<'tcx>,
+                &mut CacheEncoder<'_, 'tcx>,
+                &mut EncodedDepNodeIndex)
+            >
+        ] = &[$(expand_if_cached!([$($modifiers)*], query_impl::$name::encode_query_results)),*];
+
         #[allow(nonstandard_style)]
         mod query_callbacks {
             use super::*;
@@ -707,72 +775,13 @@ macro_rules! define_queries {
             }
 
             $(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
-                $crate::plumbing::query_callback::<queries::$name<'tcx>>(
+                $crate::plumbing::query_callback::<query_impl::$name::QueryType<'tcx>>(
                     is_anon!([$($modifiers)*]),
                     is_eval_always!([$($modifiers)*]),
                 )
             })*
         }
 
-        mod query_structs {
-            use super::*;
-            use rustc_middle::ty::query::QueryStruct;
-            use rustc_middle::ty::query::QueryKeyStringCache;
-            use rustc_middle::dep_graph::DepKind;
-            use crate::QueryConfigRestored;
-
-            pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
-                fn noop_try_collect_active_jobs(_: TyCtxt<'_>, _: &mut QueryMap<DepKind>) -> Option<()> {
-                    None
-                }
-                fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {}
-
-                QueryStruct {
-                    try_collect_active_jobs: noop_try_collect_active_jobs,
-                    alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings,
-                    encode_query_results: None,
-                }
-            }
-
-            pub(super) use dummy_query_struct as Null;
-            pub(super) use dummy_query_struct as Red;
-            pub(super) use dummy_query_struct as TraitSelect;
-            pub(super) use dummy_query_struct as CompileCodegenUnit;
-            pub(super) use dummy_query_struct as CompileMonoItem;
-
-            $(
-            pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct {
-                try_collect_active_jobs: |tcx, qmap| {
-                    let make_query = |tcx, key| {
-                        let kind = rustc_middle::dep_graph::DepKind::$name;
-                        let name = stringify!($name);
-                        $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
-                    };
-                    tcx.query_system.states.$name.try_collect_active_jobs(
-                        tcx,
-                        make_query,
-                        qmap,
-                    )
-                },
-                alloc_self_profile_query_strings: |tcx, string_cache| {
-                    $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
-                        tcx,
-                        stringify!($name),
-                        &tcx.query_system.caches.$name,
-                        string_cache,
-                    )
-                },
-                encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index|
-                    $crate::plumbing::encode_query_results::<super::queries::$name<'tcx>>(
-                        super::queries::$name::config(tcx),
-                        QueryCtxt::new(tcx),
-                        encoder,
-                        query_result_index,
-                    )
-                ),
-            }})*
-        }
-
         pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
             arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
         }
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 7d9306f8087..fbc6db93e01 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -2,7 +2,7 @@ use measureme::{StringComponent, StringId};
 use rustc_data_structures::profiling::SelfProfiler;
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
-use rustc_middle::ty::query::QueryKeyStringCache;
+use rustc_middle::query::plumbing::QueryKeyStringCache;
 use rustc_middle::ty::TyCtxt;
 use rustc_query_system::query::QueryCache;
 use std::fmt::Debug;
@@ -243,7 +243,7 @@ pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
 
     let mut string_cache = QueryKeyStringCache::new();
 
-    for query in &tcx.query_system.fns.query_structs {
-        (query.alloc_self_profile_query_strings)(tcx, &mut string_cache);
+    for alloc in super::ALLOC_SELF_PROFILE_QUERY_STRINGS.iter() {
+        alloc(tcx, &mut string_cache)
     }
 }
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index dbfe62ae6e9..730e4c8d30d 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -433,16 +433,22 @@ where
                 (hasher(&mut hcx, &cached_result), hasher(&mut hcx, &result))
             });
             let formatter = query.format_value();
-            debug_assert_eq!(
-                old_hash,
-                new_hash,
-                "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\
-                computed={:#?}\nfed={:#?}",
-                query.dep_kind(),
-                key,
-                formatter(&result),
-                formatter(&cached_result),
-            );
+            if old_hash != new_hash {
+                // We have an inconsistency. This can happen if one of the two
+                // results is tainted by errors. In this case, delay a bug to
+                // ensure compilation is doomed.
+                qcx.dep_context().sess().delay_span_bug(
+                    DUMMY_SP,
+                    format!(
+                        "Computed query value for {:?}({:?}) is inconsistent with fed value,\n\
+                        computed={:#?}\nfed={:#?}",
+                        query.dep_kind(),
+                        key,
+                        formatter(&result),
+                        formatter(&cached_result),
+                    ),
+                );
+            }
         }
     }
     job_owner.complete(cache, result, dep_node_index);
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 2438b3a38ed..b3d0e4ba258 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -9,12 +9,9 @@ use crate::def_collector::collect_definitions;
 use crate::imports::{Import, ImportKind};
 use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
-use crate::{
-    errors, Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot,
-};
-use crate::{
-    MacroData, NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError,
-};
+use crate::{errors, BindingKey, MacroData};
+use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot};
+use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError};
 use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError};
 
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
@@ -72,7 +69,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         T: ToNameBinding<'a>,
     {
         let binding = def.to_name_binding(self.arenas);
-        let key = self.new_key(ident, ns);
+        let key = self.new_disambiguated_key(ident, ns);
         if let Err(old_binding) = self.try_define(parent, key, binding) {
             self.report_conflict(parent, ident, ns, old_binding, &binding);
         }
@@ -379,7 +376,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             ImportKind::Single { target, type_ns_only, .. } => {
                 self.r.per_ns(|this, ns| {
                     if !type_ns_only || ns == TypeNS {
-                        let key = this.new_key(target, ns);
+                        let key = BindingKey::new(target, ns);
                         let mut resolution = this.resolution(current_module, key).borrow_mut();
                         resolution.add_single_import(import);
                     }
@@ -876,6 +873,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                     let msg = "macro-expanded `extern crate` items cannot \
                                        shadow names passed with `--extern`";
                     self.r.tcx.sess.span_err(item.span, msg);
+                    // `return` is intended to discard this binding because it's an
+                    // unregistered ambiguity error which would result in a panic
+                    // caused by inconsistency `path_res`
+                    // more details: https://github.com/rust-lang/rust/pull/111761
+                    return;
                 }
             }
             let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 6675b8ed59b..ed0a792d387 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -28,10 +28,10 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Span, SyntaxContext};
 use thin_vec::ThinVec;
 
-use crate::errors as errs;
 use crate::imports::{Import, ImportKind};
 use crate::late::{PatternSource, Rib};
 use crate::path_names_to_string;
+use crate::{errors as errs, BindingKey};
 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize};
 use crate::{HasGenericParams, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{LexicalScopeBinding, NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
@@ -550,7 +550,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
                 let sm = self.tcx.sess.source_map();
                 let def_id = match outer_res {
-                    Res::SelfTyParam { .. } | Res::SelfCtor(_) => {
+                    Res::SelfTyParam { .. } => {
                         err.span_label(span, "can't use `Self` here");
                         return err;
                     }
@@ -1832,7 +1832,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
             (msg, None)
         } else if ident.name == kw::SelfUpper {
-            ("`Self` is only available in impls, traits, and type definitions".to_string(), None)
+            // As mentioned above, `opt_ns` being `None` indicates a module path in import.
+            // We can use this to improve a confusing error for, e.g. `use Self::Variant` in an
+            // impl
+            if opt_ns.is_none() {
+                ("`Self` cannot be used in imports".to_string(), None)
+            } else {
+                (
+                    "`Self` is only available in impls, traits, and type definitions".to_string(),
+                    None,
+                )
+            }
         } else if ident.name.as_str().chars().next().map_or(false, |c| c.is_ascii_uppercase()) {
             // Check whether the name refers to an item in the value namespace.
             let binding = if let Some(ribs) = ribs {
@@ -2081,7 +2091,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         let resolutions = self.resolutions(crate_module).borrow();
-        let resolution = resolutions.get(&self.new_key(ident, MacroNS))?;
+        let binding_key = BindingKey::new(ident, MacroNS);
+        let resolution = resolutions.get(&binding_key)?;
         let binding = resolution.borrow().binding()?;
         if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
             let module_name = crate_module.kind.name().unwrap();
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 755acdd81fe..945c7ce3a9b 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -18,6 +18,7 @@ use crate::late::{
     ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind,
 };
 use crate::macros::{sub_namespace_match, MacroRulesScope};
+use crate::BindingKey;
 use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
 use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
 use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res};
@@ -865,7 +866,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             }
         };
 
-        let key = self.new_key(ident, ns);
+        let key = BindingKey::new(ident, ns);
         let resolution =
             self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports.
 
@@ -1174,10 +1175,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     return Res::Err;
                 }
             }
-            Res::Def(DefKind::TyParam, _)
-            | Res::SelfTyParam { .. }
-            | Res::SelfTyAlias { .. }
-            | Res::SelfCtor(_) => {
+            Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {
                 for rib in ribs {
                     let has_generic_params: HasGenericParams = match rib.kind {
                         RibKind::Normal
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 9e4429507b1..7c4c05d4b94 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -405,17 +405,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         t
     }
 
-    // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed resolution,
-    // also mark such failed imports as used to avoid duplicate diagnostics.
-    fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
+    // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed
+    // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.
+    fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) {
         if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
-            if target_bindings.iter().any(|binding| binding.get().is_some()) {
+            if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none()))
+            {
                 return; // Has resolution, do not create the dummy binding
             }
             let dummy_binding = self.dummy_binding;
             let dummy_binding = self.import(dummy_binding, import);
             self.per_ns(|this, ns| {
-                let key = this.new_key(target, ns);
+                let key = BindingKey::new(target, ns);
                 let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
             });
             self.record_use(target, dummy_binding, false);
@@ -474,7 +475,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             // If this import is unresolved then create a dummy import
             // resolution for it so that later resolve stages won't complain.
-            self.import_dummy_binding(import);
+            self.import_dummy_binding(import, is_indeterminate);
 
             if let Some(err) = unresolved_import_error {
                 if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
@@ -712,7 +713,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 .span_label(import.span, "cannot be imported directly")
                                 .emit();
                         }
-                        let key = this.new_key(target, ns);
+                        let key = BindingKey::new(target, ns);
                         this.update_resolution(parent, key, |_, resolution| {
                             resolution.single_imports.remove(&Interned::new_unchecked(import));
                         });
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index c053ea222a0..e0611907613 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -6,6 +6,7 @@
 //! If you wonder why there's no `early.rs`, that's because it's split into three files -
 //! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`.
 
+use crate::BindingKey;
 use crate::{path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding};
 use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult};
 use crate::{ResolutionError, Resolver, Segment, UseError};
@@ -16,7 +17,7 @@ use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::{Applicability, DiagnosticArgValue, DiagnosticId, IntoDiagnosticArg};
 use rustc_hir::def::Namespace::{self, *};
-use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
+use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
 use rustc_middle::middle::resolve_bound_vars::Set1;
@@ -2967,7 +2968,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         // If there is a TraitRef in scope for an impl, then the method must be in the trait.
         let Some((module, _)) = &self.current_trait_ref else { return; };
         ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
-        let key = self.r.new_key(ident, ns);
+        let key = BindingKey::new(ident, ns);
         let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
         debug!(?binding);
         if binding.is_none() {
@@ -2978,7 +2979,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 TypeNS => ValueNS,
                 _ => ns,
             };
-            let key = self.r.new_key(ident, ns);
+            let key = BindingKey::new(ident, ns);
             binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
             debug!(?binding);
         }
@@ -4286,12 +4287,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         }
     }
 
-    fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> bool {
+    fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
         // FIXME: This caching may be incorrect in case of multiple `macro_rules`
         // items with the same name in the same module.
         // Also hygiene is not considered.
         let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions);
-        let res = doc_link_resolutions
+        let res = *doc_link_resolutions
             .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
             .or_default()
             .entry((Symbol::intern(path_str), ns))
@@ -4306,8 +4307,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     return None;
                 }
                 res
-            })
-            .is_some();
+            });
         self.r.doc_link_resolutions = doc_link_resolutions;
         res
     }
@@ -4342,8 +4342,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             let mut any_resolved = false;
             let mut need_assoc = false;
             for ns in [TypeNS, ValueNS, MacroNS] {
-                if self.resolve_and_cache_rustdoc_path(&path_str, ns) {
-                    any_resolved = true;
+                if let Some(res) = self.resolve_and_cache_rustdoc_path(&path_str, ns) {
+                    // Rustdoc ignores tool attribute resolutions and attempts
+                    // to resolve their prefixes for diagnostics.
+                    any_resolved = !matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Tool));
                 } else if ns != MacroNS {
                     need_assoc = true;
                 }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 323b78fcd98..1e31a0ff278 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -85,6 +85,7 @@ pub mod rustdoc;
 
 fluent_messages! { "../messages.ftl" }
 
+#[derive(Debug)]
 enum Weak {
     Yes,
     No,
@@ -105,7 +106,7 @@ impl Determinacy {
 /// A specific scope in which a name can be looked up.
 /// This enum is currently used only for early resolution (imports and macros),
 /// but not for late resolution yet.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
 enum Scope<'a> {
     DeriveHelpers(LocalExpnId),
     DeriveHelpersCompat,
@@ -469,6 +470,13 @@ struct BindingKey {
     disambiguator: u32,
 }
 
+impl BindingKey {
+    fn new(ident: Ident, ns: Namespace) -> Self {
+        let ident = ident.normalize_to_macros_2_0();
+        BindingKey { ident, ns, disambiguator: 0 }
+    }
+}
+
 type Resolutions<'a> = RefCell<FxIndexMap<BindingKey, &'a RefCell<NameResolution<'a>>>>;
 
 /// One node in the tree of modules.
@@ -943,6 +951,7 @@ pub struct Resolver<'a, 'tcx> {
     empty_module: Module<'a>,
     module_map: FxHashMap<DefId, Module<'a>>,
     binding_parent_modules: FxHashMap<Interned<'a, NameBinding<'a>>, Module<'a>>,
+
     underscore_disambiguator: u32,
 
     /// Maps glob imports to the names of items actually imported.
@@ -1595,7 +1604,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         import_ids
     }
 
-    fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
+    fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
         let ident = ident.normalize_to_macros_2_0();
         let disambiguator = if ident.name == kw::Underscore {
             self.underscore_disambiguator += 1;
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index e2b8d3eea2d..a328447aca9 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -421,7 +421,7 @@ pub enum TrimmedDefPaths {
     GoodPath,
 }
 
-#[derive(Clone, Hash)]
+#[derive(Clone, Hash, Debug)]
 pub enum ResolveDocLinks {
     /// Do not resolve doc links.
     None,
@@ -1319,7 +1319,7 @@ pub(super) fn build_target_config(
     let (target, target_warnings) = target_result.unwrap_or_else(|e| {
         early_error(
             opts.error_format,
-            &format!(
+            format!(
                 "Error loading target specification: {}. \
                  Run `rustc --print target-list` for a list of built-in targets",
                 e
@@ -1327,15 +1327,14 @@ pub(super) fn build_target_config(
         )
     });
     for warning in target_warnings.warning_messages() {
-        early_warn(opts.error_format, &warning)
+        early_warn(opts.error_format, warning)
     }
 
     if !matches!(target.pointer_width, 16 | 32 | 64) {
         early_error(
             opts.error_format,
-            &format!(
-                "target specification was invalid: \
-             unrecognized target-pointer-width {}",
+            format!(
+                "target specification was invalid: unrecognized target-pointer-width {}",
                 target.pointer_width
             ),
         )
@@ -1599,7 +1598,7 @@ pub fn get_cmd_lint_options(
 
     let lint_cap = matches.opt_str("cap-lints").map(|cap| {
         lint::Level::from_str(&cap)
-            .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{cap}`")))
+            .unwrap_or_else(|| early_error(error_format, format!("unknown lint level: `{cap}`")))
     });
 
     (lint_opts, describe_lints, lint_cap)
@@ -1616,7 +1615,7 @@ pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
 
         Some(arg) => early_error(
             ErrorOutputType::default(),
-            &format!(
+            format!(
                 "argument for `--color` must be auto, \
                  always or never (instead was `{arg}`)"
             ),
@@ -1691,7 +1690,7 @@ pub fn parse_json(matches: &getopts::Matches) -> JsonConfig {
                 "future-incompat" => json_future_incompat = true,
                 s => early_error(
                     ErrorOutputType::default(),
-                    &format!("unknown `--json` option `{s}`"),
+                    format!("unknown `--json` option `{s}`"),
                 ),
             }
         }
@@ -1729,7 +1728,7 @@ pub fn parse_error_format(
 
             Some(arg) => early_error(
                 ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
-                &format!(
+                format!(
                     "argument for `--error-format` must be `human`, `json` or \
                      `short` (instead was `{arg}`)"
                 ),
@@ -1763,7 +1762,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
         Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
             early_error(
                 ErrorOutputType::default(),
-                &format!(
+                format!(
                     "argument for `--edition` must be one of: \
                      {EDITION_NAME_LIST}. (instead was `{arg}`)"
                 ),
@@ -1782,7 +1781,7 @@ pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
         } else {
             format!("edition {edition} is unstable and only available with -Z unstable-options")
         };
-        early_error(ErrorOutputType::default(), &msg)
+        early_error(ErrorOutputType::default(), msg)
     }
 
     edition
@@ -1827,7 +1826,7 @@ fn parse_output_types(
                 let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
                     early_error(
                         error_format,
-                        &format!(
+                        format!(
                             "unknown emission type: `{shorthand}` - expected one of: {display}",
                             display = OutputType::shorthands_display(),
                         ),
@@ -1866,7 +1865,7 @@ fn should_override_cgus_and_disable_thinlto(
                     for ot in &incompatible {
                         early_warn(
                             error_format,
-                            &format!(
+                            format!(
                                 "`--emit={ot}` with `-o` incompatible with \
                                  `-C codegen-units=N` for N > 1",
                             ),
@@ -1970,7 +1969,7 @@ fn collect_print_requests(
                 let prints = prints.join(", ");
                 early_error(
                     error_format,
-                    &format!("unknown print request `{req}`. Valid print requests are: {prints}"),
+                    format!("unknown print request `{req}`. Valid print requests are: {prints}"),
                 );
             }
         }
@@ -1987,7 +1986,7 @@ pub fn parse_target_triple(
         Some(target) if target.ends_with(".json") => {
             let path = Path::new(&target);
             TargetTriple::from_path(path).unwrap_or_else(|_| {
-                early_error(error_format, &format!("target file {path:?} does not exist"))
+                early_error(error_format, format!("target file {path:?} does not exist"))
             })
         }
         Some(target) => TargetTriple::TargetTriple(target),
@@ -2028,7 +2027,7 @@ fn parse_opt_level(
             arg => {
                 early_error(
                     error_format,
-                    &format!(
+                    format!(
                         "optimization level needs to be \
                             between 0-3, s or z (instead was `{arg}`)"
                     ),
@@ -2059,7 +2058,7 @@ pub(crate) fn parse_assert_incr_state(
         Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded),
         Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded),
         Some(s) => {
-            early_error(error_format, &format!("unexpected incremental state assertion value: {s}"))
+            early_error(error_format, format!("unexpected incremental state assertion value: {s}"))
         }
         None => None,
     }
@@ -2086,13 +2085,13 @@ fn parse_native_lib_kind(
                 } else {
                     ", the `-Z unstable-options` flag must also be passed to use it"
                 };
-                early_error(error_format, &format!("library kind `link-arg` is unstable{why}"))
+                early_error(error_format, format!("library kind `link-arg` is unstable{why}"))
             }
             NativeLibKind::LinkArg
         }
         _ => early_error(
             error_format,
-            &format!(
+            format!(
                 "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
             ),
         ),
@@ -2127,16 +2126,13 @@ fn parse_native_lib_modifiers(
                 } else {
                     ", the `-Z unstable-options` flag must also be passed to use it"
                 };
-                early_error(
-                    error_format,
-                    &format!("linking modifier `{modifier}` is unstable{why}"),
-                )
+                early_error(error_format, format!("linking modifier `{modifier}` is unstable{why}"))
             }
         };
         let assign_modifier = |dst: &mut Option<bool>| {
             if dst.is_some() {
                 let msg = format!("multiple `{modifier}` modifiers in a single `-l` option");
-                early_error(error_format, &msg)
+                early_error(error_format, msg)
             } else {
                 *dst = Some(value);
             }
@@ -2173,7 +2169,7 @@ fn parse_native_lib_modifiers(
             // string, like `modifiers = ""`.
             _ => early_error(
                 error_format,
-                &format!(
+                format!(
                     "unknown linking modifier `{modifier}`, expected one \
                      of: bundle, verbatim, whole-archive, as-needed"
                 ),
@@ -2303,7 +2299,7 @@ pub fn parse_externs(
                     }
                     "nounused" => nounused_dep = true,
                     "force" => force = true,
-                    _ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
+                    _ => early_error(error_format, format!("unknown --extern option `{opt}`")),
                 }
             }
         }
@@ -2369,7 +2365,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let unparsed_crate_types = matches.opt_strs("crate-type");
     let crate_types = parse_crate_types_from_list(unparsed_crate_types)
-        .unwrap_or_else(|e| early_error(error_format, &e));
+        .unwrap_or_else(|e| early_error(error_format, e));
 
     let mut unstable_opts = UnstableOptions::build(matches, error_format);
     let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
@@ -2597,7 +2593,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     };
 
     let working_dir = std::env::current_dir().unwrap_or_else(|e| {
-        early_error(error_format, &format!("Current directory is invalid: {e}"));
+        early_error(error_format, format!("Current directory is invalid: {e}"));
     });
 
     let remap = FilePathMapping::new(remap_path_prefix.clone());
@@ -2669,7 +2665,7 @@ fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Optio
         "mir-cfg" => MirCFG,
         name => early_error(
             efmt,
-            &format!(
+            format!(
                 "argument to `unpretty` must be one of `normal`, `identified`, \
                             `expanded`, `expanded,identified`, `expanded,hygiene`, \
                             `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
@@ -2747,7 +2743,7 @@ pub mod nightly_options {
             if opt.name != "Z" && !has_z_unstable_option {
                 early_error(
                     ErrorOutputType::default(),
-                    &format!(
+                    format!(
                         "the `-Z unstable-options` flag must also be passed to enable \
                          the flag `{}`",
                         opt.name
@@ -2760,11 +2756,10 @@ pub mod nightly_options {
             match opt.stability {
                 OptionStability::Unstable => {
                     let msg = format!(
-                        "the option `{}` is only accepted on the \
-                         nightly compiler",
+                        "the option `{}` is only accepted on the nightly compiler",
                         opt.name
                     );
-                    early_error(ErrorOutputType::default(), &msg);
+                    early_error(ErrorOutputType::default(), msg);
                 }
                 OptionStability::Stable => {}
             }
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index 8089d81cc22..dc475e8c6d5 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,7 +6,8 @@ use crate::search_paths::PathKind;
 use crate::utils::NativeLibKind;
 use crate::Session;
 use rustc_ast as ast;
-use rustc_data_structures::sync::{self, AppendOnlyIndexVec, MetadataRef, RwLock};
+use rustc_data_structures::owned_slice::OwnedSlice;
+use rustc_data_structures::sync::{self, AppendOnlyIndexVec, RwLock};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
 use rustc_span::hygiene::{ExpnHash, ExpnId};
@@ -203,8 +204,8 @@ pub enum ExternCrateSource {
 /// metadata in library -- this trait just serves to decouple rustc_metadata from
 /// the archive reader, which depends on LLVM.
 pub trait MetadataLoader: std::fmt::Debug {
-    fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
-    fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>;
+    fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
+    fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<OwnedSlice, String>;
 }
 
 pub type MetadataLoaderDyn = dyn MetadataLoader + Send + Sync + sync::DynSend + sync::DynSync;
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 5976b9aa3e7..2c4c4a7a6ce 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -329,21 +329,21 @@ fn build_options<O: Default>(
                     match value {
                         None => early_error(
                             error_format,
-                            &format!(
+                            format!(
                                 "{0} option `{1}` requires {2} ({3} {1}=<value>)",
                                 outputname, key, type_desc, prefix
                             ),
                         ),
                         Some(value) => early_error(
                             error_format,
-                            &format!(
+                            format!(
                                 "incorrect value `{value}` for {outputname} option `{key}` - {type_desc} was expected"
                             ),
                         ),
                     }
                 }
             }
-            None => early_error(error_format, &format!("unknown {outputname} option: `{key}`")),
+            None => early_error(error_format, format!("unknown {outputname} option: `{key}`")),
         }
     }
     return op;
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 5cc9c62617d..7b396dde91b 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -289,7 +289,7 @@ impl ParseSess {
         lint: &'static Lint,
         span: impl Into<MultiSpan>,
         node_id: NodeId,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
             buffered_lints.push(BufferedEarlyLint {
@@ -307,7 +307,7 @@ impl ParseSess {
         lint: &'static Lint,
         span: impl Into<MultiSpan>,
         node_id: NodeId,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
         diagnostic: BuiltinLintDiagnostics,
     ) {
         self.buffered_lints.with_lock(|buffered_lints| {
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index a988d7f28e6..4f593083b6f 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -211,6 +211,9 @@ pub struct Session {
 
     /// Set of enabled features for the current target, including unstable ones.
     pub unstable_target_features: FxIndexSet<Symbol>,
+
+    /// The version of the rustc process, possibly including a commit hash and description.
+    pub cfg_version: &'static str,
 }
 
 pub struct PerfStats {
@@ -490,20 +493,6 @@ impl Session {
     }
     #[rustc_lint_diagnostics]
     #[track_caller]
-    pub fn span_err_or_warn<S: Into<MultiSpan>>(
-        &self,
-        is_warning: bool,
-        sp: S,
-        msg: impl Into<DiagnosticMessage>,
-    ) {
-        if is_warning {
-            self.span_warn(sp, msg);
-        } else {
-            self.span_err(sp, msg);
-        }
-    }
-    #[rustc_lint_diagnostics]
-    #[track_caller]
     pub fn span_err<S: Into<MultiSpan>>(
         &self,
         sp: S,
@@ -1380,6 +1369,7 @@ pub fn build_session(
     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
     file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
     target_override: Option<Target>,
+    cfg_version: &'static str,
 ) -> Session {
     // FIXME: This is not general enough to make the warning lint completely override
     // normal diagnostic warnings, since the warning lint can also be denied and changed
@@ -1400,10 +1390,10 @@ pub fn build_session(
     let target_cfg = config::build_target_config(&sopts, target_override, &sysroot);
     let host_triple = TargetTriple::from_triple(config::host_triple());
     let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
-        early_error(sopts.error_format, &format!("Error loading host specification: {e}"))
+        early_error(sopts.error_format, format!("Error loading host specification: {e}"))
     });
     for warning in target_warnings.warning_messages() {
-        early_warn(sopts.error_format, &warning)
+        early_warn(sopts.error_format, warning)
     }
 
     let loader = file_loader.unwrap_or_else(|| Box::new(RealFileLoader));
@@ -1445,7 +1435,7 @@ pub fn build_session(
         match profiler {
             Ok(profiler) => Some(Arc::new(profiler)),
             Err(e) => {
-                early_warn(sopts.error_format, &format!("failed to create profiler: {e}"));
+                early_warn(sopts.error_format, format!("failed to create profiler: {e}"));
                 None
             }
         }
@@ -1524,6 +1514,7 @@ pub fn build_session(
         asm_arch,
         target_features: Default::default(),
         unstable_target_features: Default::default(),
+        cfg_version,
     };
 
     validate_commandline_args_with_session_available(&sess);
@@ -1741,18 +1732,22 @@ fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
-pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
+#[must_use = "ErrorGuaranteed must be returned from `run_compiler` in order to exit with a non-zero status code"]
+pub fn early_error_no_abort(
+    output: config::ErrorOutputType,
+    msg: impl Into<DiagnosticMessage>,
+) -> ErrorGuaranteed {
     early_error_handler(output).struct_err(msg).emit()
 }
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
-pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
+pub fn early_error(output: config::ErrorOutputType, msg: impl Into<DiagnosticMessage>) -> ! {
     early_error_handler(output).struct_fatal(msg).emit()
 }
 
 #[allow(rustc::untranslatable_diagnostic)]
 #[allow(rustc::diagnostic_outside_of_impl)]
-pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
+pub fn early_warn(output: config::ErrorOutputType, msg: impl Into<DiagnosticMessage>) {
     early_error_handler(output).struct_warn(msg).emit()
 }
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 8c58b52a5dc..f65a6aa4fb2 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -146,7 +146,12 @@ pub struct StableCrateId(pub(crate) Hash64);
 impl StableCrateId {
     /// Computes the stable ID for a crate with the given name and
     /// `-Cmetadata` arguments.
-    pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
+    pub fn new(
+        crate_name: Symbol,
+        is_exe: bool,
+        mut metadata: Vec<String>,
+        cfg_version: &'static str,
+    ) -> StableCrateId {
         let mut hasher = StableHasher::new();
         // We must hash the string text of the crate name, not the id, as the id is not stable
         // across builds.
@@ -180,7 +185,7 @@ impl StableCrateId {
         if let Some(val) = std::env::var_os("RUSTC_FORCE_RUSTC_VERSION") {
             hasher.write(val.to_string_lossy().into_owned().as_bytes())
         } else {
-            hasher.write(option_env!("CFG_VERSION").unwrap_or("unknown version").as_bytes());
+            hasher.write(cfg_version.as_bytes())
         }
 
         StableCrateId(hasher.finish())
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 97cb734619e..8d70aa47f78 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1257,29 +1257,6 @@ impl SourceFileHash {
     }
 }
 
-#[derive(HashStable_Generic)]
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
-pub enum DebuggerVisualizerType {
-    Natvis,
-    GdbPrettyPrinter,
-}
-
-/// A single debugger visualizer file.
-#[derive(HashStable_Generic)]
-#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable)]
-pub struct DebuggerVisualizerFile {
-    /// The complete debugger visualizer source.
-    pub src: Lrc<[u8]>,
-    /// Indicates which visualizer type this targets.
-    pub visualizer_type: DebuggerVisualizerType,
-}
-
-impl DebuggerVisualizerFile {
-    pub fn new(src: Lrc<[u8]>, visualizer_type: DebuggerVisualizerType) -> Self {
-        DebuggerVisualizerFile { src, visualizer_type }
-    }
-}
-
 #[derive(Clone)]
 pub enum SourceFileLines {
     /// The source file lines, in decoded (random-access) form.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9951d8f4fc1..874d578fe1d 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -164,6 +164,7 @@ symbols! {
         Capture,
         Center,
         Clone,
+        ConstParamTy,
         Context,
         Continue,
         Copy,
@@ -1583,6 +1584,7 @@ symbols! {
         unrestricted_attribute_tokens,
         unsafe_block_in_unsafe_fn,
         unsafe_cell,
+        unsafe_cell_from_mut,
         unsafe_no_drop_flag,
         unsafe_pin_internals,
         unsize,
diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs
index a3f262905c7..254ede4e6a0 100644
--- a/compiler/rustc_symbol_mangling/src/legacy.rs
+++ b/compiler/rustc_symbol_mangling/src/legacy.rs
@@ -220,7 +220,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
         match *ty.kind() {
             // Print all nominal types as paths (unlike `pretty_print_type`).
             ty::FnDef(def_id, substs)
-            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs),
 
@@ -241,6 +241,8 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> {
                 Ok(self)
             }
 
+            ty::Alias(ty::Inherent, _) => panic!("unexpected inherent projection"),
+
             _ => self.pretty_print_type(ty),
         }
     }
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index c281aa7e83a..da8a16dee8a 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -272,12 +272,11 @@ fn encode_region<'tcx>(
             s.push('E');
             compress(dict, DictKey::Region(region), &mut s);
         }
-        RegionKind::ReErased => {
+        RegionKind::ReEarlyBound(..) | RegionKind::ReErased => {
             s.push_str("u6region");
             compress(dict, DictKey::Region(region), &mut s);
         }
-        RegionKind::ReEarlyBound(..)
-        | RegionKind::ReFree(..)
+        RegionKind::ReFree(..)
         | RegionKind::ReStatic
         | RegionKind::ReError(_)
         | RegionKind::ReVar(..)
@@ -673,6 +672,14 @@ fn encode_ty<'tcx>(
             typeid.push_str(&s);
         }
 
+        // Type parameters
+        ty::Param(..) => {
+            // u5param as vendor extended type
+            let mut s = String::from("u5param");
+            compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
+            typeid.push_str(&s);
+        }
+
         // Unexpected types
         ty::Bound(..)
         | ty::Error(..)
@@ -680,7 +687,6 @@ fn encode_ty<'tcx>(
         | ty::GeneratorWitnessMIR(..)
         | ty::Infer(..)
         | ty::Alias(..)
-        | ty::Param(..)
         | ty::Placeholder(..) => {
             bug!("encode_ty: unexpected `{:?}`", ty.kind());
         }
@@ -689,6 +695,42 @@ fn encode_ty<'tcx>(
     typeid
 }
 
+/// Transforms predicates for being encoded and used in the substitution dictionary.
+fn transform_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    predicates: &List<ty::PolyExistentialPredicate<'tcx>>,
+    _options: EncodeTyOptions,
+) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
+    let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates
+        .iter()
+        .filter_map(|predicate| match predicate.skip_binder() {
+            ty::ExistentialPredicate::Trait(trait_ref) => {
+                let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id);
+                Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait(
+                    ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref),
+                )))
+            }
+            ty::ExistentialPredicate::Projection(..) => None,
+            ty::ExistentialPredicate::AutoTrait(..) => Some(predicate),
+        })
+        .collect();
+    tcx.mk_poly_existential_predicates(&predicates)
+}
+
+/// Transforms substs for being encoded and used in the substitution dictionary.
+fn transform_substs<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    substs: SubstsRef<'tcx>,
+    options: TransformTyOptions,
+) -> SubstsRef<'tcx> {
+    let substs = substs.iter().map(|subst| match subst.unpack() {
+        GenericArgKind::Type(ty) if ty.is_c_void(tcx) => tcx.mk_unit().into(),
+        GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
+        _ => subst,
+    });
+    tcx.mk_substs_from_iter(substs)
+}
+
 // Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all
 // c_void types into unit types unconditionally, generalizes pointers if
 // TransformTyOptions::GENERALIZE_POINTERS option is set, and normalizes integers if
@@ -697,7 +739,7 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
     let mut ty = ty;
 
     match ty.kind() {
-        ty::Float(..) | ty::Char | ty::Str | ty::Never | ty::Foreign(..) | ty::Dynamic(..) => {}
+        ty::Float(..) | ty::Char | ty::Str | ty::Never | ty::Foreign(..) => {}
 
         ty::Bool => {
             if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) {
@@ -870,6 +912,14 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
             }
         }
 
+        ty::Dynamic(predicates, _region, kind) => {
+            ty = tcx.mk_dynamic(
+                transform_predicates(tcx, predicates, options),
+                tcx.lifetimes.re_erased,
+                *kind,
+            );
+        }
+
         ty::Bound(..)
         | ty::Error(..)
         | ty::GeneratorWitness(..)
@@ -885,20 +935,6 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
     ty
 }
 
-/// Transforms substs for being encoded and used in the substitution dictionary.
-fn transform_substs<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    substs: SubstsRef<'tcx>,
-    options: TransformTyOptions,
-) -> SubstsRef<'tcx> {
-    let substs = substs.iter().map(|subst| match subst.unpack() {
-        GenericArgKind::Type(ty) if ty.is_c_void(tcx) => tcx.mk_unit().into(),
-        GenericArgKind::Type(ty) => transform_ty(tcx, ty, options).into(),
-        _ => subst,
-    });
-    tcx.mk_substs_from_iter(substs)
-}
-
 /// Returns a type metadata identifier for the specified FnAbi using the Itanium C++ ABI with vendor
 /// extended type qualifiers and types for Rust types that are not used at the FFI boundary.
 #[instrument(level = "trace", skip(tcx))]
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 2235524129e..4cccc639892 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -433,7 +433,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
             // Mangle all nominal types as paths.
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), substs)
             | ty::FnDef(def_id, substs)
-            | ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. })
             | ty::Closure(def_id, substs)
             | ty::Generator(def_id, substs, _) => {
                 self = self.print_def_path(def_id, substs)?;
@@ -482,6 +482,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
                 self = r.print(self)?;
             }
 
+            ty::Alias(ty::Inherent, _) => bug!("symbol_names: unexpected inherent projection"),
             ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"),
             ty::GeneratorWitnessMIR(..) => bug!("symbol_names: unexpected `GeneratorWitnessMIR`"),
         }
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 25cc82f01d5..d14e6244f7d 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -506,10 +506,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             | ty::Param(_)
             | ty::Placeholder(..)
             | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
+            | ty::Alias(ty::Inherent, _)
             | ty::Error(_) => return,
             ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
             | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"),
-            ty::Alias(_, alias_ty) => alias_ty,
+            // Excluding IATs here as they don't have meaningful item bounds.
+            ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty,
         };
 
         for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs)
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index dcfa33ae842..644bfd33970 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -177,14 +177,18 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             return Err(NoSolution);
         }
 
-        if goal.predicate.self_ty().has_non_region_infer() {
+        // The regions of a type don't affect the size of the type
+        let tcx = ecx.tcx();
+        // We should erase regions from both the param-env and type, since both
+        // may have infer regions. Specifically, after canonicalizing and instantiating,
+        // early bound regions turn into region vars in both the new and old solver.
+        let key = tcx.erase_regions(goal.param_env.and(goal.predicate.self_ty()));
+        // But if there are inference variables, we have to wait until it's resolved.
+        if key.has_non_region_infer() {
             return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
         }
 
-        let tcx = ecx.tcx();
-        let self_ty = tcx.erase_regions(goal.predicate.self_ty());
-
-        if let Ok(layout) = tcx.layout_of(goal.param_env.and(self_ty))
+        if let Ok(layout) = tcx.layout_of(key)
             && layout.layout.is_pointer_like(&tcx.data_layout)
         {
             // FIXME: We could make this faster by making a no-constraints response
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index f5f2fe54217..dc43a3d154a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -885,7 +885,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                             return;
                         }
 
-                        if self.suggest_impl_trait(&mut err, span, &obligation, trait_predicate) {
+                        if self.suggest_impl_trait(&mut err, &obligation, trait_predicate) {
                             err.emit();
                             return;
                         }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 88525e1b720..10bd027b684 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -306,6 +306,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     }
                 }
             }
+
+            // `&[{integral}]` - `FromIterator` needs that.
+            if let ty::Ref(_, ref_ty, rustc_ast::Mutability::Not) = self_ty.kind()
+                && let ty::Slice(sty) = ref_ty.kind()
+                && sty.is_integral()
+            {
+                flags.push((sym::_Self, Some("&[{integral}]".to_owned())));
+            }
         });
 
         if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index ea17f23434b..83511e898f7 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -30,9 +30,9 @@ use rustc_middle::hir::map;
 use rustc_middle::ty::error::TypeError::{self, Sorts};
 use rustc_middle::ty::{
     self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind,
-    GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
-    IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
-    TypeSuperFoldable, TypeVisitableExt, TypeckResults,
+    GeneratorDiagnosticData, GeneratorInteriorTypeCause, InferTy, InternalSubsts, IsSuggestable,
+    ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder, TypeSuperFoldable,
+    TypeVisitableExt, TypeckResults,
 };
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -261,7 +261,6 @@ pub trait TypeErrCtxtExt<'tcx> {
     fn suggest_impl_trait(
         &self,
         err: &mut Diagnostic,
-        span: Span,
         obligation: &PredicateObligation<'tcx>,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool;
@@ -1792,215 +1791,66 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
     fn suggest_impl_trait(
         &self,
         err: &mut Diagnostic,
-        span: Span,
         obligation: &PredicateObligation<'tcx>,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
-        match obligation.cause.code().peel_derives() {
-            // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
-            ObligationCauseCode::SizedReturnType => {}
-            _ => return false,
-        }
-
-        let hir = self.tcx.hir();
-        let fn_hir_id = hir.local_def_id_to_hir_id(obligation.cause.body_id);
-        let node = hir.find_by_def_id(obligation.cause.body_id);
-        let Some(hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::Fn(sig, _, body_id),
-            ..
-        })) = node
-        else {
+        let ObligationCauseCode::SizedReturnType = obligation.cause.code() else {
             return false;
         };
-        let body = hir.body(*body_id);
-        let trait_pred = self.resolve_vars_if_possible(trait_pred);
-        let ty = trait_pred.skip_binder().self_ty();
-        let is_object_safe = match ty.kind() {
-            ty::Dynamic(predicates, _, ty::Dyn) => {
-                // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
-                predicates
-                    .principal_def_id()
-                    .map_or(true, |def_id| self.tcx.check_is_object_safe(def_id))
-            }
-            // We only want to suggest `impl Trait` to `dyn Trait`s.
-            // For example, `fn foo() -> str` needs to be filtered out.
-            _ => return false,
-        };
-
-        let hir::FnRetTy::Return(ret_ty) = sig.decl.output else {
+        let ty::Dynamic(_, _, ty::Dyn) = trait_pred.self_ty().skip_binder().kind() else {
             return false;
         };
 
-        // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
-        // cases like `fn foo() -> (dyn Trait, i32) {}`.
-        // Recursively look for `TraitObject` types and if there's only one, use that span to
-        // suggest `impl Trait`.
-
-        // Visit to make sure there's a single `return` type to suggest `impl Trait`,
-        // otherwise suggest using `Box<dyn Trait>` or an enum.
-        let mut visitor = ReturnsVisitor::default();
-        visitor.visit_body(&body);
-
-        let typeck_results = self.typeck_results.as_ref().unwrap();
-        let Some(liberated_sig) = typeck_results.liberated_fn_sigs().get(fn_hir_id).copied() else { return false; };
-
-        let ret_types = visitor
-            .returns
-            .iter()
-            .filter_map(|expr| Some((expr.span, typeck_results.node_type_opt(expr.hir_id)?)))
-            .map(|(expr_span, ty)| (expr_span, self.resolve_vars_if_possible(ty)));
-        let (last_ty, all_returns_have_same_type, only_never_return) = ret_types.clone().fold(
-            (None, true, true),
-            |(last_ty, mut same, only_never_return): (std::option::Option<Ty<'_>>, bool, bool),
-             (_, ty)| {
-                let ty = self.resolve_vars_if_possible(ty);
-                same &=
-                    !matches!(ty.kind(), ty::Error(_))
-                        && last_ty.map_or(true, |last_ty| {
-                            // FIXME: ideally we would use `can_coerce` here instead, but `typeck` comes
-                            // *after* in the dependency graph.
-                            match (ty.kind(), last_ty.kind()) {
-                                (Infer(InferTy::IntVar(_)), Infer(InferTy::IntVar(_)))
-                                | (Infer(InferTy::FloatVar(_)), Infer(InferTy::FloatVar(_)))
-                                | (Infer(InferTy::FreshIntTy(_)), Infer(InferTy::FreshIntTy(_)))
-                                | (
-                                    Infer(InferTy::FreshFloatTy(_)),
-                                    Infer(InferTy::FreshFloatTy(_)),
-                                ) => true,
-                                _ => ty == last_ty,
-                            }
-                        });
-                (Some(ty), same, only_never_return && matches!(ty.kind(), ty::Never))
-            },
-        );
-        let mut spans_and_needs_box = vec![];
-
-        match liberated_sig.output().kind() {
-            ty::Dynamic(predicates, _, ty::Dyn) => {
-                let cause = ObligationCause::misc(ret_ty.span, obligation.cause.body_id);
-                let param_env = ty::ParamEnv::empty();
-
-                if !only_never_return {
-                    for (expr_span, return_ty) in ret_types {
-                        let self_ty_satisfies_dyn_predicates = |self_ty| {
-                            predicates.iter().all(|predicate| {
-                                let pred = predicate.with_self_ty(self.tcx, self_ty);
-                                let obl = Obligation::new(self.tcx, cause.clone(), param_env, pred);
-                                self.predicate_may_hold(&obl)
-                            })
-                        };
-
-                        if let ty::Adt(def, substs) = return_ty.kind()
-                            && def.is_box()
-                            && self_ty_satisfies_dyn_predicates(substs.type_at(0))
-                        {
-                            spans_and_needs_box.push((expr_span, false));
-                        } else if self_ty_satisfies_dyn_predicates(return_ty) {
-                            spans_and_needs_box.push((expr_span, true));
-                        } else {
-                            return false;
-                        }
-                    }
-                }
-            }
-            _ => return false,
-        };
-
-        let sm = self.tcx.sess.source_map();
-        if !ret_ty.span.overlaps(span) {
-            return false;
-        }
-        let snippet = if let hir::TyKind::TraitObject(..) = ret_ty.kind {
-            if let Ok(snippet) = sm.span_to_snippet(ret_ty.span) {
-                snippet
-            } else {
-                return false;
-            }
-        } else {
-            // Substitute the type, so we can print a fixup given `type Alias = dyn Trait`
-            let name = liberated_sig.output().to_string();
-            let name =
-                name.strip_prefix('(').and_then(|name| name.strip_suffix(')')).unwrap_or(&name);
-            if !name.starts_with("dyn ") {
-                return false;
-            }
-            name.to_owned()
-        };
-
         err.code(error_code!(E0746));
         err.set_primary_message("return type cannot have an unboxed trait object");
         err.children.clear();
-        let impl_trait_msg = "for information on `impl Trait`, see \
-            <https://doc.rust-lang.org/book/ch10-02-traits.html\
-            #returning-types-that-implement-traits>";
-        let trait_obj_msg = "for information on trait objects, see \
-            <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
-            #using-trait-objects-that-allow-for-values-of-different-types>";
-
-        let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
-        let trait_obj = if has_dyn { &snippet[4..] } else { &snippet };
-        if only_never_return {
-            // No return paths, probably using `panic!()` or similar.
-            // Suggest `-> impl Trait`, and if `Trait` is object safe, `-> Box<dyn Trait>`.
-            suggest_trait_object_return_type_alternatives(
-                err,
-                ret_ty.span,
-                trait_obj,
-                is_object_safe,
-            );
-        } else if let (Some(last_ty), true) = (last_ty, all_returns_have_same_type) {
-            // Suggest `-> impl Trait`.
+
+        let span = obligation.cause.span;
+        if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span)
+            && snip.starts_with("dyn ")
+        {
             err.span_suggestion(
-                ret_ty.span,
-                format!(
-                    "use `impl {1}` as the return type, as all return paths are of type `{}`, \
-                     which implements `{1}`",
-                    last_ty, trait_obj,
-                ),
-                format!("impl {}", trait_obj),
-                Applicability::MachineApplicable,
+                span.with_hi(span.lo() + BytePos(4)),
+                "return an `impl Trait` instead of a `dyn Trait`, \
+                if all returned values are the same type",
+                "impl ",
+                Applicability::MaybeIncorrect,
             );
-            err.note(impl_trait_msg);
-        } else {
-            if is_object_safe {
-                // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
-                err.multipart_suggestion(
-                    "return a boxed trait object instead",
-                    vec![
-                        (ret_ty.span.shrink_to_lo(), "Box<".to_string()),
-                        (span.shrink_to_hi(), ">".to_string()),
-                    ],
-                    Applicability::MaybeIncorrect,
-                );
-                for (span, needs_box) in spans_and_needs_box {
-                    if needs_box {
-                        err.multipart_suggestion(
-                            "... and box this value",
-                            vec![
-                                (span.shrink_to_lo(), "Box::new(".to_string()),
-                                (span.shrink_to_hi(), ")".to_string()),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
+        }
+
+        let body = self.tcx.hir().body(self.tcx.hir().body_owned_by(obligation.cause.body_id));
+
+        let mut visitor = ReturnsVisitor::default();
+        visitor.visit_body(&body);
+
+        let mut sugg =
+            vec![(span.shrink_to_lo(), "Box<".to_string()), (span.shrink_to_hi(), ">".to_string())];
+        sugg.extend(visitor.returns.into_iter().flat_map(|expr| {
+            let span = expr.span.find_ancestor_in_same_ctxt(obligation.cause.span).unwrap_or(expr.span);
+            if !span.can_be_used_for_suggestions() {
+                vec![]
+            } else if let hir::ExprKind::Call(path, ..) = expr.kind
+                && let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, method)) = path.kind
+                && method.ident.name == sym::new
+                && let hir::TyKind::Path(hir::QPath::Resolved(.., box_path)) = ty.kind
+                && box_path.res.opt_def_id().is_some_and(|def_id| Some(def_id) == self.tcx.lang_items().owned_box())
+            {
+                // Don't box `Box::new`
+                vec![]
             } else {
-                // This is currently not possible to trigger because E0038 takes precedence, but
-                // leave it in for completeness in case anything changes in an earlier stage.
-                err.note(format!(
-                    "if trait `{}` were object-safe, you could return a trait object",
-                    trait_obj,
-                ));
+                vec![
+                    (span.shrink_to_lo(), "Box::new(".to_string()),
+                    (span.shrink_to_hi(), ")".to_string()),
+                ]
             }
-            err.note(trait_obj_msg);
-            err.note(format!(
-                "if all the returned values were of the same type you could use `impl {}` as the \
-                 return type",
-                trait_obj,
-            ));
-            err.note(impl_trait_msg);
-            err.note("you can create a new `enum` with a variant for each returned type");
-        }
+        }));
+
+        err.multipart_suggestion(
+            "box the return type, and wrap all of the returned values in `Box::new`",
+            sugg,
+            Applicability::MaybeIncorrect,
+        );
+
         true
     }
 
@@ -4139,37 +3989,6 @@ impl NextTypeParamName for &[hir::GenericParam<'_>] {
     }
 }
 
-fn suggest_trait_object_return_type_alternatives(
-    err: &mut Diagnostic,
-    ret_ty: Span,
-    trait_obj: &str,
-    is_object_safe: bool,
-) {
-    err.span_suggestion(
-        ret_ty,
-        format!(
-            "use `impl {}` as the return type if all return paths have the same type but you \
-                want to expose only the trait in the signature",
-            trait_obj,
-        ),
-        format!("impl {}", trait_obj),
-        Applicability::MaybeIncorrect,
-    );
-    if is_object_safe {
-        err.multipart_suggestion(
-            format!(
-                "use a boxed trait object if all return paths implement trait `{}`",
-                trait_obj,
-            ),
-            vec![
-                (ret_ty.shrink_to_lo(), "Box<".to_string()),
-                (ret_ty.shrink_to_hi(), ">".to_string()),
-            ],
-            Applicability::MaybeIncorrect,
-        );
-    }
-}
-
 /// Collect the spans that we see the generic param `param_did`
 struct ReplaceImplTraitVisitor<'a> {
     ty_spans: &'a mut Vec<Span>,
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 223cdc48f0b..f265230ff77 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -17,6 +17,7 @@ pub mod query;
 mod select;
 mod specialize;
 mod structural_match;
+mod structural_normalize;
 mod util;
 mod vtable;
 pub mod wf;
@@ -62,6 +63,7 @@ pub use self::specialize::{
 pub use self::structural_match::{
     search_for_adt_const_param_violation, search_for_structural_match_violation,
 };
+pub use self::structural_normalize::StructurallyNormalizeExt;
 pub use self::util::elaborate;
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
 pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
@@ -143,35 +145,36 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
 fn pred_known_to_hold_modulo_regions<'tcx>(
     infcx: &InferCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    pred: impl ToPredicate<'tcx> + TypeVisitable<TyCtxt<'tcx>>,
+    pred: impl ToPredicate<'tcx>,
 ) -> bool {
-    let has_non_region_infer = pred.has_non_region_infer();
     let obligation = Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, pred);
 
     let result = infcx.evaluate_obligation_no_overflow(&obligation);
     debug!(?result);
 
-    if result.must_apply_modulo_regions() && !has_non_region_infer {
+    if result.must_apply_modulo_regions() {
         true
     } else if result.may_apply() {
-        // Because of inference "guessing", selection can sometimes claim
-        // to succeed while the success requires a guess. To ensure
-        // this function's result remains infallible, we must confirm
-        // that guess. While imperfect, I believe this is sound.
-
-        // The handling of regions in this area of the code is terrible,
-        // see issue #29149. We should be able to improve on this with
-        // NLL.
-        let ocx = ObligationCtxt::new(infcx);
-        ocx.register_obligation(obligation);
-        let errors = ocx.select_all_or_error();
-        match errors.as_slice() {
-            [] => true,
-            errors => {
-                debug!(?errors);
-                false
+        // Sometimes obligations are ambiguous because the recursive evaluator
+        // is not smart enough, so we fall back to fulfillment when we're not certain
+        // that an obligation holds or not. Even still, we must make sure that
+        // the we do no inference in the process of checking this obligation.
+        let goal = infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
+        infcx.probe(|_| {
+            let ocx = ObligationCtxt::new_in_snapshot(infcx);
+            ocx.register_obligation(obligation);
+
+            let errors = ocx.select_all_or_error();
+            match errors.as_slice() {
+                // Only known to hold if we did no inference.
+                [] => infcx.shallow_resolve(goal) == goal,
+
+                errors => {
+                    debug!(?errors);
+                    false
+                }
             }
-        }
+        })
     } else {
         false
     }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 8e684b7ac23..51069897120 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1543,7 +1543,10 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
     // Check whether the self-type is itself a projection.
     // If so, extract what we know from the trait and try to come up with a good answer.
     let bounds = match *obligation.predicate.self_ty().kind() {
-        ty::Alias(_, ref data) => tcx.item_bounds(data.def_id).subst(tcx, data.substs),
+        // Excluding IATs here as they don't have meaningful item bounds.
+        ty::Alias(ty::Projection | ty::Opaque, ref data) => {
+            tcx.item_bounds(data.def_id).subst(tcx, data.substs)
+        }
         ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -2260,7 +2263,7 @@ fn confirm_param_env_candidate<'cx, 'tcx>(
                 obligation, poly_cache_entry, e,
             );
             debug!("confirm_param_env_candidate: {}", msg);
-            let err = infcx.tcx.ty_error_with_message(obligation.cause.span, &msg);
+            let err = infcx.tcx.ty_error_with_message(obligation.cause.span, msg);
             Progress { term: err.into(), obligations: vec![] }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a8fb55df2d3..8bc82b9f549 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -143,7 +143,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
-            ty::Alias(..) => {}
+            // Excluding IATs here as they don't have meaningful item bounds.
+            ty::Alias(ty::Projection | ty::Opaque, _) => {}
             ty::Infer(ty::TyVar(_)) => {
                 span_bug!(
                     obligation.cause.span,
@@ -966,16 +967,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     ) {
         // The regions of a type don't affect the size of the type
         let tcx = self.tcx();
-        let self_ty =
-            tcx.erase_regions(tcx.erase_late_bound_regions(obligation.predicate.self_ty()));
-
+        let self_ty = tcx.erase_late_bound_regions(obligation.predicate.self_ty());
+        // We should erase regions from both the param-env and type, since both
+        // may have infer regions. Specifically, after canonicalizing and instantiating,
+        // early bound regions turn into region vars in both the new and old solver.
+        let key = tcx.erase_regions(obligation.param_env.and(self_ty));
         // But if there are inference variables, we have to wait until it's resolved.
-        if self_ty.has_non_region_infer() {
+        if key.has_non_region_infer() {
             candidates.ambiguous = true;
             return;
         }
 
-        if let Ok(layout) = tcx.layout_of(obligation.param_env.and(self_ty))
+        if let Ok(layout) = tcx.layout_of(key)
             && layout.layout.is_pointer_like(&tcx.data_layout)
         {
             candidates.vec.push(BuiltinCandidate { has_nested: false });
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 6a648294efd..0d9f55d4c2e 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -132,6 +132,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
         };
 
+        // The obligations returned by confirmation are recursively evaluated
+        // so we need to make sure they have the correct depth.
+        for subobligation in impl_src.borrow_nested_obligations_mut() {
+            subobligation.set_depth_from_parent(obligation.recursion_depth);
+        }
+
         if !obligation.predicate.is_const_if_const() {
             // normalize nested predicates according to parent predicate's constness.
             impl_src = impl_src.map(|mut o| {
@@ -156,7 +162,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let placeholder_self_ty = placeholder_trait_predicate.self_ty();
         let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
         let (def_id, substs) = match *placeholder_self_ty.kind() {
-            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
+            // Excluding IATs here as they don't have meaningful item bounds.
+            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                (def_id, substs)
+            }
             _ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
         };
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index b72ff5b78e4..b366bbd531b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -537,14 +537,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &PredicateObligation<'tcx>,
     ) -> Result<EvaluationResult, OverflowError> {
         self.evaluation_probe(|this| {
-            if this.tcx().trait_solver_next() {
-                this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])
+            let goal =
+                this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
+            let mut result = if this.tcx().trait_solver_next() {
+                this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])?
             } else {
                 this.evaluate_predicate_recursively(
                     TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
                     obligation.clone(),
-                )
+                )?
+            };
+            // If the predicate has done any inference, then downgrade the
+            // result to ambiguous.
+            if this.infcx.shallow_resolve(goal) != goal {
+                result = result.max(EvaluatedToAmbig);
             }
+            Ok(result)
         })
     }
 
@@ -1645,7 +1653,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let tcx = self.infcx.tcx;
         let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
-            ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
+            ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+                (def_id, substs)
+            }
             _ => {
                 span_bug!(
                     obligation.cause.span,
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
new file mode 100644
index 00000000000..af8dd0da579
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -0,0 +1,55 @@
+use rustc_infer::infer::at::At;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::traits::{FulfillmentError, TraitEngine};
+use rustc_middle::ty::{self, Ty};
+
+use crate::traits::{query::evaluate_obligation::InferCtxtExt, NormalizeExt, Obligation};
+
+pub trait StructurallyNormalizeExt<'tcx> {
+    fn structurally_normalize(
+        &self,
+        ty: Ty<'tcx>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx>,
+    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>;
+}
+
+impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
+    fn structurally_normalize(
+        &self,
+        mut ty: Ty<'tcx>,
+        fulfill_cx: &mut dyn TraitEngine<'tcx>,
+    ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
+        assert!(!ty.is_ty_var(), "should have resolved vars before calling");
+
+        if self.infcx.tcx.trait_solver_next() {
+            while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
+                let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
+                    kind: TypeVariableOriginKind::NormalizeProjectionType,
+                    span: self.cause.span,
+                });
+                let obligation = Obligation::new(
+                    self.infcx.tcx,
+                    self.cause.clone(),
+                    self.param_env,
+                    ty::Binder::dummy(ty::ProjectionPredicate {
+                        projection_ty,
+                        term: new_infer_ty.into(),
+                    }),
+                );
+                if self.infcx.predicate_may_hold(&obligation) {
+                    fulfill_cx.register_predicate_obligation(self.infcx, obligation);
+                    let errors = fulfill_cx.select_where_possible(self.infcx);
+                    if !errors.is_empty() {
+                        return Err(errors);
+                    }
+                    ty = self.infcx.resolve_vars_if_possible(new_infer_ty);
+                } else {
+                    break;
+                }
+            }
+            Ok(ty)
+        } else {
+            Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx))
+        }
+    }
+}
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 442d041a8a7..15c19104616 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -238,6 +238,7 @@ fn adjust_for_rust_scalar<'tcx>(
     layout: TyAndLayout<'tcx>,
     offset: Size,
     is_return: bool,
+    drop_target_pointee: Option<Ty<'tcx>>,
 ) {
     // Booleans are always a noundef i1 that needs to be zero-extended.
     if scalar.is_bool() {
@@ -251,14 +252,24 @@ fn adjust_for_rust_scalar<'tcx>(
     }
 
     // Only pointer types handled below.
-    let Scalar::Initialized { value: Pointer(_), valid_range} = scalar else { return };
+    let Scalar::Initialized { value: Pointer(_), valid_range } = scalar else { return };
 
-    if !valid_range.contains(0) {
+    // Set `nonnull` if the validity range excludes zero, or for the argument to `drop_in_place`,
+    // which must be nonnull per its documented safety requirements.
+    if !valid_range.contains(0) || drop_target_pointee.is_some() {
         attrs.set(ArgAttribute::NonNull);
     }
 
     if let Some(pointee) = layout.pointee_info_at(&cx, offset) {
-        if let Some(kind) = pointee.safe {
+        let kind = if let Some(kind) = pointee.safe {
+            Some(kind)
+        } else if let Some(pointee) = drop_target_pointee {
+            // The argument to `drop_in_place` is semantically equivalent to a mutable reference.
+            Some(PointerKind::MutableRef { unpin: pointee.is_unpin(cx.tcx, cx.param_env()) })
+        } else {
+            None
+        };
+        if let Some(kind) = kind {
             attrs.pointee_align = Some(pointee.align);
 
             // `Box` are not necessarily dereferenceable for the entire duration of the function as
@@ -362,10 +373,18 @@ fn fn_abi_new_uncached<'tcx>(
     use SpecAbi::*;
     let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall);
 
+    let is_drop_in_place =
+        fn_def_id.is_some() && fn_def_id == cx.tcx.lang_items().drop_in_place_fn();
+
     let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
         let span = tracing::debug_span!("arg_of");
         let _entered = span.enter();
         let is_return = arg_idx.is_none();
+        let is_drop_target = is_drop_in_place && arg_idx == Some(0);
+        let drop_target_pointee = is_drop_target.then(|| match ty.kind() {
+            ty::RawPtr(ty::TypeAndMut { ty, .. }) => *ty,
+            _ => bug!("argument to drop_in_place is not a raw ptr: {:?}", ty),
+        });
 
         let layout = cx.layout_of(ty)?;
         let layout = if force_thin_self_ptr && arg_idx == Some(0) {
@@ -379,7 +398,15 @@ fn fn_abi_new_uncached<'tcx>(
 
         let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
             let mut attrs = ArgAttributes::new();
-            adjust_for_rust_scalar(*cx, &mut attrs, scalar, *layout, offset, is_return);
+            adjust_for_rust_scalar(
+                *cx,
+                &mut attrs,
+                scalar,
+                *layout,
+                offset,
+                is_return,
+                drop_target_pointee,
+            );
             attrs
         });
 
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 088139a6907..498fbd93288 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2623,6 +2623,15 @@ impl ToString for String {
     }
 }
 
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "fmt_arguments_to_string_specialization", since = "CURRENT_RUSTC_VERSION")]
+impl ToString for fmt::Arguments<'_> {
+    #[inline]
+    fn to_string(&self) -> String {
+        crate::fmt::format(*self)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<str> for String {
     #[inline]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 7347980abbc..bfdb7a92bef 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -502,6 +502,7 @@ impl<T> Arc<T> {
     /// assert_eq!(*five, 5)
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_uninit() -> Arc<mem::MaybeUninit<T>> {
@@ -535,6 +536,7 @@ impl<T> Arc<T> {
     ///
     /// [zeroed]: mem::MaybeUninit::zeroed
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_zeroed() -> Arc<mem::MaybeUninit<T>> {
@@ -844,6 +846,7 @@ impl<T> Arc<[T]> {
     /// assert_eq!(*values, [1, 2, 3])
     /// ```
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_uninit_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
@@ -871,6 +874,7 @@ impl<T> Arc<[T]> {
     ///
     /// [zeroed]: mem::MaybeUninit::zeroed
     #[cfg(not(no_global_oom_handling))]
+    #[inline]
     #[unstable(feature = "new_uninit", issue = "63291")]
     #[must_use]
     pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit<T>]> {
@@ -1300,10 +1304,10 @@ impl<T: ?Sized> Arc<T> {
         mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
     ) -> *mut ArcInner<T> {
         let layout = arcinner_layout_for_value_layout(value_layout);
-        unsafe {
-            Arc::try_allocate_for_layout(value_layout, allocate, mem_to_arcinner)
-                .unwrap_or_else(|_| handle_alloc_error(layout))
-        }
+
+        let ptr = allocate(layout).unwrap_or_else(|_| handle_alloc_error(layout));
+
+        unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) }
     }
 
     /// Allocates an `ArcInner<T>` with sufficient space for
@@ -1321,7 +1325,16 @@ impl<T: ?Sized> Arc<T> {
 
         let ptr = allocate(layout)?;
 
-        // Initialize the ArcInner
+        let inner = unsafe { Self::initialize_arcinner(ptr, layout, mem_to_arcinner) };
+
+        Ok(inner)
+    }
+
+    unsafe fn initialize_arcinner(
+        ptr: NonNull<[u8]>,
+        layout: Layout,
+        mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner<T>,
+    ) -> *mut ArcInner<T> {
         let inner = mem_to_arcinner(ptr.as_non_null_ptr().as_ptr());
         debug_assert_eq!(unsafe { Layout::for_value(&*inner) }, layout);
 
@@ -1330,7 +1343,7 @@ impl<T: ?Sized> Arc<T> {
             ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
         }
 
-        Ok(inner)
+        inner
     }
 
     /// Allocates an `ArcInner<T>` with sufficient space for an unsized inner value.
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index 2f1ee8b0353..5ecd0479971 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -178,7 +178,8 @@ where
             )
         };
 
-        let len = SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end);
+        // SAFETY: `dst_buf` and `dst_end` are the start and end of the buffer.
+        let len = unsafe { SpecInPlaceCollect::collect_in_place(&mut iterator, dst_buf, dst_end) };
 
         let src = unsafe { iterator.as_inner().as_into_iter() };
         // check if SourceIter contract was upheld
@@ -239,7 +240,7 @@ trait SpecInPlaceCollect<T, I>: Iterator<Item = T> {
     /// `Iterator::__iterator_get_unchecked` calls with a `TrustedRandomAccessNoCoerce` bound
     /// on `I` which means the caller of this method must take the safety conditions
     /// of that trait into consideration.
-    fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize;
+    unsafe fn collect_in_place(&mut self, dst: *mut T, end: *const T) -> usize;
 }
 
 impl<T, I> SpecInPlaceCollect<T, I> for I
@@ -247,7 +248,7 @@ where
     I: Iterator<Item = T>,
 {
     #[inline]
-    default fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
+    default unsafe fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
         // use try-fold since
         // - it vectorizes better for some iterator adapters
         // - unlike most internal iteration methods, it only takes a &mut self
@@ -265,7 +266,7 @@ where
     I: Iterator<Item = T> + TrustedRandomAccessNoCoerce,
 {
     #[inline]
-    fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
+    unsafe fn collect_in_place(&mut self, dst_buf: *mut T, end: *const T) -> usize {
         let len = self.size();
         let mut drop_guard = InPlaceDrop { inner: dst_buf, dst: dst_buf };
         for i in 0..len {
diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs
index 9193c79bee8..60ef83223d1 100644
--- a/library/core/benches/iter.rs
+++ b/library/core/benches/iter.rs
@@ -404,7 +404,7 @@ fn bench_trusted_random_access_adapters(b: &mut Bencher) {
 
 /// Exercises the iter::Copied specialization for slice::Iter
 #[bench]
-fn bench_copied_chunks(b: &mut Bencher) {
+fn bench_next_chunk_copied(b: &mut Bencher) {
     let v = vec![1u8; 1024];
 
     b.iter(|| {
@@ -421,7 +421,7 @@ fn bench_copied_chunks(b: &mut Bencher) {
 
 /// Exercises the TrustedRandomAccess specialization in ArrayChunks
 #[bench]
-fn bench_trusted_random_access_chunks(b: &mut Bencher) {
+fn bench_next_chunk_trusted_random_access(b: &mut Bencher) {
     let v = vec![1u8; 1024];
 
     b.iter(|| {
@@ -437,3 +437,45 @@ fn bench_trusted_random_access_chunks(b: &mut Bencher) {
             .sum::<Wrapping<u64>>()
     })
 }
+
+#[bench]
+fn bench_next_chunk_filter_even(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter(|&&i| i % 2 == 0).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_predictably_true(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter(|&&i| i < 100).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_mostly_false(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter(|&&i| i > 900).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_map_even(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter_map(|&i| (i % 2 == 0).then(|| i)).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_map_predictably_true(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter_map(|&i| (i < 100).then(|| i)).next_chunk::<32>())
+}
+
+#[bench]
+fn bench_next_chunk_filter_map_mostly_false(b: &mut Bencher) {
+    let a = (0..1024).next_chunk::<1024>().unwrap();
+
+    b.iter(|| black_box(&a).iter().filter_map(|&i| (i > 900).then(|| i)).next_chunk::<32>())
+}
diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs
index 7fd14a7e1ea..ef8e4d098ed 100644
--- a/library/core/src/ascii.rs
+++ b/library/core/src/ascii.rs
@@ -91,7 +91,7 @@ pub struct EscapeDefault(escape::EscapeIterInner<4>);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn escape_default(c: u8) -> EscapeDefault {
-    let mut data = [0; 4];
+    let mut data = [Char::Null; 4];
     let range = escape::escape_ascii_into(&mut data, c);
     EscapeDefault(escape::EscapeIterInner::new(data, range))
 }
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 2c3c14853a4..744767aae44 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -2030,6 +2030,27 @@ impl<T> UnsafeCell<T> {
 }
 
 impl<T: ?Sized> UnsafeCell<T> {
+    /// Converts from `&mut T` to `&mut UnsafeCell<T>`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(unsafe_cell_from_mut)]
+    /// use std::cell::UnsafeCell;
+    ///
+    /// let mut val = 42;
+    /// let uc = UnsafeCell::from_mut(&mut val);
+    ///
+    /// *uc.get_mut() -= 1;
+    /// assert_eq!(*uc.get_mut(), 41);
+    /// ```
+    #[inline(always)]
+    #[unstable(feature = "unsafe_cell_from_mut", issue = "111645")]
+    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>) }
+    }
+
     /// Gets a mutable pointer to the wrapped value.
     ///
     /// This can be cast to a pointer of any kind.
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 1dfa9c34db1..515b8d20ead 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -392,13 +392,13 @@ impl char {
     #[inline]
     pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug {
         match self {
-            '\0' => EscapeDebug::backslash(b'0'),
-            '\t' => EscapeDebug::backslash(b't'),
-            '\r' => EscapeDebug::backslash(b'r'),
-            '\n' => EscapeDebug::backslash(b'n'),
-            '\\' => EscapeDebug::backslash(b'\\'),
-            '"' if args.escape_double_quote => EscapeDebug::backslash(b'"'),
-            '\'' if args.escape_single_quote => EscapeDebug::backslash(b'\''),
+            '\0' => EscapeDebug::backslash(ascii::Char::Digit0),
+            '\t' => EscapeDebug::backslash(ascii::Char::SmallT),
+            '\r' => EscapeDebug::backslash(ascii::Char::SmallR),
+            '\n' => EscapeDebug::backslash(ascii::Char::SmallN),
+            '\\' => EscapeDebug::backslash(ascii::Char::ReverseSolidus),
+            '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark),
+            '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe),
             _ if args.escape_grapheme_extended && self.is_grapheme_extended() => {
                 EscapeDebug::from_unicode(self.escape_unicode())
             }
@@ -503,11 +503,11 @@ impl char {
     #[inline]
     pub fn escape_default(self) -> EscapeDefault {
         match self {
-            '\t' => EscapeDefault::backslash(b't'),
-            '\r' => EscapeDefault::backslash(b'r'),
-            '\n' => EscapeDefault::backslash(b'n'),
-            '\\' | '\'' | '"' => EscapeDefault::backslash(self as u8),
-            '\x20'..='\x7e' => EscapeDefault::printable(self as u8),
+            '\t' => EscapeDefault::backslash(ascii::Char::SmallT),
+            '\r' => EscapeDefault::backslash(ascii::Char::SmallR),
+            '\n' => EscapeDefault::backslash(ascii::Char::SmallN),
+            '\\' | '\'' | '"' => EscapeDefault::backslash(self.as_ascii().unwrap()),
+            '\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()),
             _ => EscapeDefault::from_unicode(self.escape_unicode()),
         }
     }
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index e186db7052c..5c42912874c 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -38,6 +38,7 @@ pub use self::methods::encode_utf16_raw;
 #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
 pub use self::methods::encode_utf8_raw;
 
+use crate::ascii;
 use crate::error::Error;
 use crate::escape;
 use crate::fmt::{self, Write};
@@ -152,7 +153,7 @@ pub struct EscapeUnicode(escape::EscapeIterInner<10>);
 
 impl EscapeUnicode {
     fn new(chr: char) -> Self {
-        let mut data = [0; 10];
+        let mut data = [ascii::Char::Null; 10];
         let range = escape::escape_unicode_into(&mut data, chr);
         Self(escape::EscapeIterInner::new(data, range))
     }
@@ -218,14 +219,14 @@ impl fmt::Display for EscapeUnicode {
 pub struct EscapeDefault(escape::EscapeIterInner<10>);
 
 impl EscapeDefault {
-    fn printable(chr: u8) -> Self {
-        let data = [chr, 0, 0, 0, 0, 0, 0, 0, 0, 0];
-        Self(escape::EscapeIterInner::new(data, 0..1))
+    fn printable(chr: ascii::Char) -> Self {
+        let data = [chr];
+        Self(escape::EscapeIterInner::from_array(data))
     }
 
-    fn backslash(chr: u8) -> Self {
-        let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0];
-        Self(escape::EscapeIterInner::new(data, 0..2))
+    fn backslash(chr: ascii::Char) -> Self {
+        let data = [ascii::Char::ReverseSolidus, chr];
+        Self(escape::EscapeIterInner::from_array(data))
     }
 
     fn from_unicode(esc: EscapeUnicode) -> Self {
@@ -307,9 +308,9 @@ impl EscapeDebug {
         Self(EscapeDebugInner::Char(chr))
     }
 
-    fn backslash(chr: u8) -> Self {
-        let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0];
-        let iter = escape::EscapeIterInner::new(data, 0..2);
+    fn backslash(chr: ascii::Char) -> Self {
+        let data = [ascii::Char::ReverseSolidus, chr];
+        let iter = escape::EscapeIterInner::from_array(data);
         Self(EscapeDebugInner::Bytes(iter))
     }
 
@@ -318,7 +319,7 @@ impl EscapeDebug {
     }
 
     fn clear(&mut self) {
-        let bytes = escape::EscapeIterInner::new([0; 10], 0..0);
+        let bytes = escape::EscapeIterInner::from_array([]);
         self.0 = EscapeDebugInner::Bytes(bytes);
     }
 }
diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs
index 20ac3cf027f..3d471419bb8 100644
--- a/library/core/src/escape.rs
+++ b/library/core/src/escape.rs
@@ -1,34 +1,41 @@
 //! Helper code for character escaping.
 
+use crate::ascii;
 use crate::num::NonZeroUsize;
 use crate::ops::Range;
 
-const HEX_DIGITS: [u8; 16] = *b"0123456789abcdef";
+const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap();
 
 /// Escapes a byte into provided buffer; returns length of escaped
 /// representation.
-pub(crate) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range<u8> {
+pub(crate) fn escape_ascii_into(output: &mut [ascii::Char; 4], byte: u8) -> Range<u8> {
+    #[inline]
+    fn backslash(a: ascii::Char) -> ([ascii::Char; 4], u8) {
+        ([ascii::Char::ReverseSolidus, a, ascii::Char::Null, ascii::Char::Null], 2)
+    }
+
     let (data, len) = match byte {
-        b'\t' => ([b'\\', b't', 0, 0], 2),
-        b'\r' => ([b'\\', b'r', 0, 0], 2),
-        b'\n' => ([b'\\', b'n', 0, 0], 2),
-        b'\\' => ([b'\\', b'\\', 0, 0], 2),
-        b'\'' => ([b'\\', b'\'', 0, 0], 2),
-        b'"' => ([b'\\', b'"', 0, 0], 2),
-        b'\x20'..=b'\x7e' => ([byte, 0, 0, 0], 1),
-        _ => {
+        b'\t' => backslash(ascii::Char::SmallT),
+        b'\r' => backslash(ascii::Char::SmallR),
+        b'\n' => backslash(ascii::Char::SmallN),
+        b'\\' => backslash(ascii::Char::ReverseSolidus),
+        b'\'' => backslash(ascii::Char::Apostrophe),
+        b'\"' => backslash(ascii::Char::QuotationMark),
+        _ => if let Some(a) = byte.as_ascii() && !byte.is_ascii_control() {
+            ([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1)
+        } else {
             let hi = HEX_DIGITS[usize::from(byte >> 4)];
             let lo = HEX_DIGITS[usize::from(byte & 0xf)];
-            ([b'\\', b'x', hi, lo], 4)
+            ([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4)
         }
     };
     *output = data;
-    0..(len as u8)
+    0..len
 }
 
 /// Escapes a character into provided buffer using `\u{NNNN}` representation.
-pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8> {
-    output[9] = b'}';
+pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> Range<u8> {
+    output[9] = ascii::Char::RightCurlyBracket;
 
     let ch = ch as u32;
     output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize];
@@ -41,7 +48,8 @@ pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8>
     // or-ing 1 ensures that for ch==0 the code computes that one digit should
     // be printed.
     let start = (ch | 1).leading_zeros() as usize / 4 - 2;
-    output[start..start + 3].copy_from_slice(b"\\u{");
+    const UNICODE_ESCAPE_PREFIX: &[ascii::Char; 3] = b"\\u{".as_ascii().unwrap();
+    output[start..][..3].copy_from_slice(UNICODE_ESCAPE_PREFIX);
 
     (start as u8)..10
 }
@@ -52,29 +60,34 @@ pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range<u8>
 /// limited to u8 to reduce size of the structure.
 #[derive(Clone, Debug)]
 pub(crate) struct EscapeIterInner<const N: usize> {
-    // Invariant: data[alive] is all ASCII.
-    pub(crate) data: [u8; N],
+    // The element type ensures this is always ASCII, and thus also valid UTF-8.
+    pub(crate) data: [ascii::Char; N],
 
     // Invariant: alive.start <= alive.end <= N.
     pub(crate) alive: Range<u8>,
 }
 
 impl<const N: usize> EscapeIterInner<N> {
-    pub fn new(data: [u8; N], alive: Range<u8>) -> Self {
+    pub fn new(data: [ascii::Char; N], alive: Range<u8>) -> Self {
         const { assert!(N < 256) };
         debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}");
-        let this = Self { data, alive };
-        debug_assert!(this.as_bytes().is_ascii(), "Expected ASCII, got {:?}", this.as_bytes());
-        this
+        Self { data, alive }
+    }
+
+    pub fn from_array<const M: usize>(array: [ascii::Char; M]) -> Self {
+        const { assert!(M <= N) };
+
+        let mut data = [ascii::Char::Null; N];
+        data[..M].copy_from_slice(&array);
+        Self::new(data, 0..M as u8)
     }
 
-    fn as_bytes(&self) -> &[u8] {
+    pub fn as_ascii(&self) -> &[ascii::Char] {
         &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)]
     }
 
     pub fn as_str(&self) -> &str {
-        // SAFETY: self.data[self.alive] is all ASCII characters.
-        unsafe { crate::str::from_utf8_unchecked(self.as_bytes()) }
+        self.as_ascii().as_str()
     }
 
     pub fn len(&self) -> usize {
@@ -82,11 +95,11 @@ impl<const N: usize> EscapeIterInner<N> {
     }
 
     pub fn next(&mut self) -> Option<u8> {
-        self.alive.next().map(|i| self.data[usize::from(i)])
+        self.alive.next().map(|i| self.data[usize::from(i)].as_u8())
     }
 
     pub fn next_back(&mut self) -> Option<u8> {
-        self.alive.next_back().map(|i| self.data[usize::from(i)])
+        self.alive.next_back().map(|i| self.data[usize::from(i)].as_u8())
     }
 
     pub fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> {
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 07b11814f96..201bacb28c7 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -517,8 +517,6 @@ impl CStr {
     /// # Examples
     ///
     /// ```
-    /// #![feature(cstr_is_empty)]
-    ///
     /// use std::ffi::CStr;
     /// # use std::ffi::FromBytesWithNulError;
     ///
@@ -533,7 +531,8 @@ impl CStr {
     /// # }
     /// ```
     #[inline]
-    #[unstable(feature = "cstr_is_empty", issue = "102444")]
+    #[stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
     pub const fn is_empty(&self) -> bool {
         // SAFETY: We know there is at least one byte; for empty strings it
         // is the NUL terminator.
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 89d5fac30d3..3bbf5d8770b 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -45,7 +45,8 @@ where
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_exact_fixed_str` and `format_exact` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 // Don't inline this so callers that call both this and the above won't wind
@@ -71,7 +72,8 @@ where
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_shortest_str` and `format_shortest` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 fn float_to_decimal_display<T>(fmt: &mut Formatter<'_>, num: &T) -> Result
@@ -116,7 +118,8 @@ where
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_exact_exp_str` and `format_exact` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 // Don't inline this so callers that call both this and the above won't wind
@@ -143,7 +146,8 @@ where
         &mut buf,
         &mut parts,
     );
-    fmt.pad_formatted_parts(&formatted)
+    // SAFETY: `to_shortest_exp_str` and `format_shortest` produce only ASCII characters.
+    unsafe { fmt.pad_formatted_parts(&formatted) }
 }
 
 // Common code of floating point LowerExp and UpperExp.
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index bac2f31878b..1786b309c5b 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -1415,7 +1415,11 @@ impl<'a> Formatter<'a> {
     /// Takes the formatted parts and applies the padding.
     /// Assumes that the caller already has rendered the parts with required precision,
     /// so that `self.precision` can be ignored.
-    fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
+    ///
+    /// # Safety
+    ///
+    /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
+    unsafe fn pad_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
         if let Some(mut width) = self.width {
             // for the sign-aware zero padding, we render the sign first and
             // behave as if we had no sign from the beginning.
@@ -1438,10 +1442,14 @@ impl<'a> Formatter<'a> {
             let len = formatted.len();
             let ret = if width <= len {
                 // no padding
-                self.write_formatted_parts(&formatted)
+                // SAFETY: Per the precondition.
+                unsafe { self.write_formatted_parts(&formatted) }
             } else {
                 let post_padding = self.padding(width - len, Alignment::Right)?;
-                self.write_formatted_parts(&formatted)?;
+                // SAFETY: Per the precondition.
+                unsafe {
+                    self.write_formatted_parts(&formatted)?;
+                }
                 post_padding.write(self)
             };
             self.fill = old_fill;
@@ -1449,20 +1457,20 @@ impl<'a> Formatter<'a> {
             ret
         } else {
             // this is the common case and we take a shortcut
-            self.write_formatted_parts(formatted)
+            // SAFETY: Per the precondition.
+            unsafe { self.write_formatted_parts(formatted) }
         }
     }
 
-    fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
-        fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
+    /// # Safety
+    ///
+    /// Any `numfmt::Part::Copy` parts in `formatted` must contain valid UTF-8.
+    unsafe fn write_formatted_parts(&mut self, formatted: &numfmt::Formatted<'_>) -> Result {
+        unsafe fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result {
             // SAFETY: This is used for `numfmt::Part::Num` and `numfmt::Part::Copy`.
             // It's safe to use for `numfmt::Part::Num` since every char `c` is between
-            // `b'0'` and `b'9'`, which means `s` is valid UTF-8.
-            // It's also probably safe in practice to use for `numfmt::Part::Copy(buf)`
-            // since `buf` should be plain ASCII, but it's possible for someone to pass
-            // in a bad value for `buf` into `numfmt::to_shortest_str` since it is a
-            // public function.
-            // FIXME: Determine whether this could result in UB.
+            // `b'0'` and `b'9'`, which means `s` is valid UTF-8. It's safe to use for
+            // `numfmt::Part::Copy` due to this function's precondition.
             buf.write_str(unsafe { str::from_utf8_unchecked(s) })
         }
 
@@ -1489,11 +1497,15 @@ impl<'a> Formatter<'a> {
                         *c = b'0' + (v % 10) as u8;
                         v /= 10;
                     }
-                    write_bytes(self.buf, &s[..len])?;
+                    // SAFETY: Per the precondition.
+                    unsafe {
+                        write_bytes(self.buf, &s[..len])?;
+                    }
                 }
-                numfmt::Part::Copy(buf) => {
+                // SAFETY: Per the precondition.
+                numfmt::Part::Copy(buf) => unsafe {
                     write_bytes(self.buf, buf)?;
-                }
+                },
             }
         }
         Ok(())
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index d8365ae9bf9..4f42f73ebba 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -52,8 +52,12 @@ impl_int! { i8 i16 i32 i64 i128 isize }
 impl_uint! { u8 u16 u32 u64 u128 usize }
 
 /// A type that represents a specific radix
+///
+/// # Safety
+///
+/// `digit` must return an ASCII character.
 #[doc(hidden)]
-trait GenericRadix: Sized {
+unsafe trait GenericRadix: Sized {
     /// The number of digits.
     const BASE: u8;
 
@@ -129,7 +133,7 @@ struct UpperHex;
 
 macro_rules! radix {
     ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
-        impl GenericRadix for $T {
+        unsafe impl GenericRadix for $T {
             const BASE: u8 = $base;
             const PREFIX: &'static str = $prefix;
             fn digit(x: u8) -> u8 {
@@ -407,7 +411,7 @@ macro_rules! impl_Exp {
             let parts = &[
                 numfmt::Part::Copy(buf_slice),
                 numfmt::Part::Zero(added_precision),
-                numfmt::Part::Copy(exp_slice)
+                numfmt::Part::Copy(exp_slice),
             ];
             let sign = if !is_nonnegative {
                 "-"
@@ -416,8 +420,9 @@ macro_rules! impl_Exp {
             } else {
                 ""
             };
-            let formatted = numfmt::Formatted{sign, parts};
-            f.pad_formatted_parts(&formatted)
+            let formatted = numfmt::Formatted { sign, parts };
+            // SAFETY: `buf_slice` and `exp_slice` contain only ASCII characters.
+            unsafe { f.pad_formatted_parts(&formatted) }
         }
 
         $(
diff --git a/library/core/src/future/join.rs b/library/core/src/future/join.rs
index 35f0dea062e..3f35179ddc2 100644
--- a/library/core/src/future/join.rs
+++ b/library/core/src/future/join.rs
@@ -4,7 +4,7 @@ use crate::cell::UnsafeCell;
 use crate::future::{poll_fn, Future};
 use crate::mem;
 use crate::pin::Pin;
-use crate::task::{Context, Poll};
+use crate::task::{ready, Context, Poll};
 
 /// Polls multiple futures simultaneously, returning a tuple
 /// of all results once complete.
@@ -118,7 +118,7 @@ macro join_internal {
                             fut
                         })
                     };
-                    // Despite how tempting it may be to `let () = fut.poll(cx).ready()?;`
+                    // Despite how tempting it may be to `let () = ready!(fut.poll(cx));`
                     // doing so would defeat the point of `join!`: to start polling eagerly all
                     // of the futures, to allow parallelizing the waits.
                     done &= fut.poll(cx).is_ready();
@@ -180,7 +180,7 @@ impl<F: Future> Future for MaybeDone<F> {
             // Do not mix match ergonomics with unsafe.
             match *self.as_mut().get_unchecked_mut() {
                 MaybeDone::Future(ref mut f) => {
-                    let val = Pin::new_unchecked(f).poll(cx).ready()?;
+                    let val = ready!(Pin::new_unchecked(f).poll(cx));
                     self.set(Self::Done(val));
                 }
                 MaybeDone::Done(_) => {}
diff --git a/library/core/src/iter/adapters/filter.rs b/library/core/src/iter/adapters/filter.rs
index a0afaa326ad..723657b9e43 100644
--- a/library/core/src/iter/adapters/filter.rs
+++ b/library/core/src/iter/adapters/filter.rs
@@ -1,6 +1,9 @@
 use crate::fmt;
 use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
 use crate::ops::Try;
+use core::array;
+use core::mem::{ManuallyDrop, MaybeUninit};
+use core::ops::ControlFlow;
 
 /// An iterator that filters the elements of `iter` with `predicate`.
 ///
@@ -57,6 +60,58 @@ where
     }
 
     #[inline]
+    fn next_chunk<const N: usize>(
+        &mut self,
+    ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
+        let mut array: [MaybeUninit<Self::Item>; N] = MaybeUninit::uninit_array();
+
+        struct Guard<'a, T> {
+            array: &'a mut [MaybeUninit<T>],
+            initialized: usize,
+        }
+
+        impl<T> Drop for Guard<'_, T> {
+            #[inline]
+            fn drop(&mut self) {
+                if const { crate::mem::needs_drop::<T>() } {
+                    // SAFETY: self.initialized is always <= N, which also is the length of the array.
+                    unsafe {
+                        core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
+                            self.array.get_unchecked_mut(..self.initialized),
+                        ));
+                    }
+                }
+            }
+        }
+
+        let mut guard = Guard { array: &mut array, initialized: 0 };
+
+        let result = self.iter.try_for_each(|element| {
+            let idx = guard.initialized;
+            guard.initialized = idx + (self.predicate)(&element) as usize;
+
+            // SAFETY: Loop conditions ensure the index is in bounds.
+            unsafe { guard.array.get_unchecked_mut(idx) }.write(element);
+
+            if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
+        });
+
+        let guard = ManuallyDrop::new(guard);
+
+        match result {
+            ControlFlow::Break(()) => {
+                // SAFETY: The loop above is only explicitly broken when the array has been fully initialized
+                Ok(unsafe { MaybeUninit::array_assume_init(array) })
+            }
+            ControlFlow::Continue(()) => {
+                let initialized = guard.initialized;
+                // SAFETY: The range is in bounds since the loop breaks when reaching N elements.
+                Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
+            }
+        }
+    }
+
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper) // can't know a lower bound, due to the predicate
diff --git a/library/core/src/iter/adapters/filter_map.rs b/library/core/src/iter/adapters/filter_map.rs
index 6bdf53f7fc9..693479977db 100644
--- a/library/core/src/iter/adapters/filter_map.rs
+++ b/library/core/src/iter/adapters/filter_map.rs
@@ -1,6 +1,7 @@
-use crate::fmt;
 use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::mem::{ManuallyDrop, MaybeUninit};
 use crate::ops::{ControlFlow, Try};
+use crate::{array, fmt};
 
 /// An iterator that uses `f` to both filter and map elements from `iter`.
 ///
@@ -62,6 +63,65 @@ where
     }
 
     #[inline]
+    fn next_chunk<const N: usize>(
+        &mut self,
+    ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>> {
+        let mut array: [MaybeUninit<Self::Item>; N] = MaybeUninit::uninit_array();
+
+        struct Guard<'a, T> {
+            array: &'a mut [MaybeUninit<T>],
+            initialized: usize,
+        }
+
+        impl<T> Drop for Guard<'_, T> {
+            #[inline]
+            fn drop(&mut self) {
+                if const { crate::mem::needs_drop::<T>() } {
+                    // SAFETY: self.initialized is always <= N, which also is the length of the array.
+                    unsafe {
+                        core::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(
+                            self.array.get_unchecked_mut(..self.initialized),
+                        ));
+                    }
+                }
+            }
+        }
+
+        let mut guard = Guard { array: &mut array, initialized: 0 };
+
+        let result = self.iter.try_for_each(|element| {
+            let idx = guard.initialized;
+            let val = (self.f)(element);
+            guard.initialized = idx + val.is_some() as usize;
+
+            // SAFETY: Loop conditions ensure the index is in bounds.
+
+            unsafe {
+                let opt_payload_at = core::intrinsics::option_payload_ptr(&val);
+                let dst = guard.array.as_mut_ptr().add(idx);
+                crate::ptr::copy_nonoverlapping(opt_payload_at.cast(), dst, 1);
+                crate::mem::forget(val);
+            };
+
+            if guard.initialized < N { ControlFlow::Continue(()) } else { ControlFlow::Break(()) }
+        });
+
+        let guard = ManuallyDrop::new(guard);
+
+        match result {
+            ControlFlow::Break(()) => {
+                // SAFETY: The loop above is only explicitly broken when the array has been fully initialized
+                Ok(unsafe { MaybeUninit::array_assume_init(array) })
+            }
+            ControlFlow::Continue(()) => {
+                let initialized = guard.initialized;
+                // SAFETY: The range is in bounds since the loop breaks when reaching N elements.
+                Err(unsafe { array::IntoIter::new_unchecked(array, 0..initialized) })
+            }
+        }
+    }
+
+    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper) // can't know a lower bound, due to the predicate
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 76b3a32880d..0675e56358f 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -95,6 +95,16 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
     on(
+        _Self = "&[{A}]",
+        message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere",
+        label = "try explicitly collecting into a `Vec<{A}>`",
+    ),
+    on(
+        all(A = "{integer}", any(_Self = "&[{integral}]",)),
+        message = "a slice of type `{Self}` cannot be built since we need to store the elements somewhere",
+        label = "try explicitly collecting into a `Vec<{A}>`",
+    ),
+    on(
         _Self = "[{A}]",
         message = "a slice of type `{Self}` cannot be built since `{Self}` has no definite size",
         label = "try explicitly collecting into a `Vec<{A}>`",
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 0af04fac909..6c419eb16f3 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -216,6 +216,7 @@
 #![feature(intra_doc_pointers)]
 #![feature(intrinsics)]
 #![feature(lang_items)]
+#![feature(let_chains)]
 #![feature(link_llvm_intrinsics)]
 #![feature(macro_metavar_expr)]
 #![feature(min_specialization)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 47a3e78b4d5..8dab8d1a692 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -43,27 +43,17 @@ use crate::hash::Hasher;
 /// ```
 #[unstable(feature = "internal_impls_macro", issue = "none")]
 macro marker_impls {
-    ( $(#[$($meta:tt)*])* $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
-        // This inner macro is needed because... idk macros are weird.
-        // It allows repeating `meta` on all impls.
-        #[unstable(feature = "internal_impls_macro", issue = "none")]
-        macro _impl {
-            ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
-                $(#[$($meta)*])* impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
-            }
-        }
-        $( _impl! { $({$($bounds)*})? $T } )+
+    ( $(#[$($meta:tt)*])* $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => {
+        $(#[$($meta)*])* impl< $($($bounds)*)? > $Trait for $T {}
+        marker_impls! { $(#[$($meta)*])* $Trait for $($($rest)*)? }
     },
-    ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => {
-        #[unstable(feature = "internal_impls_macro", issue = "none")]
-        macro _impl {
-            ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => {
-                $(#[$($meta)*])* unsafe impl<$$($$($$bounds_)*)?> $Trait for $$T_ {}
-            }
-        }
-
-        $( _impl! { $({$($bounds)*})? $T } )+
+    ( $(#[$($meta:tt)*])* $Trait:ident for ) => {},
+
+    ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $({$($bounds:tt)*})? $T:ty $(, $($rest:tt)*)? ) => {
+        $(#[$($meta)*])* unsafe impl< $($($bounds)*)? > $Trait for $T {}
+        marker_impls! { $(#[$($meta)*])* unsafe $Trait for $($($rest)*)? }
     },
+    ( $(#[$($meta:tt)*])* unsafe $Trait:ident for ) => {},
 }
 
 /// Types that can be transferred across thread boundaries.
@@ -986,6 +976,14 @@ pub trait PointerLike {}
 #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
 pub trait ConstParamTy: StructuralEq {}
 
+/// Derive macro generating an impl of the trait `ConstParamTy`.
+#[rustc_builtin_macro]
+#[unstable(feature = "adt_const_params", issue = "95174")]
+#[cfg(not(bootstrap))]
+pub macro ConstParamTy($item:item) {
+    /* compiler built-in */
+}
+
 // FIXME(generic_const_parameter_types): handle `ty::FnDef`/`ty::Closure`
 // FIXME(generic_const_parameter_types): handle `ty::Tuple`
 marker_impls! {
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 289305253ec..afbfd6d362d 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -968,7 +968,7 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T {
 /// Integers and other types implementing [`Copy`] are unaffected by `drop`.
 ///
 /// ```
-/// # #![cfg_attr(not(bootstrap), allow(drop_copy))]
+/// # #![cfg_attr(not(bootstrap), allow(dropping_copy_types))]
 /// #[derive(Copy, Clone)]
 /// struct Foo(u8);
 ///
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index ebcce79b0f8..20be60d3535 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -28,13 +28,13 @@ pub macro panic_2015 {
         $crate::panicking::panic($msg)
     ),
     // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
-    ($msg:expr $(,)?) => (
-        $crate::panicking::panic_str($msg)
-    ),
+    ($msg:expr $(,)?) => ({
+        $crate::panicking::panic_str($msg);
+    }),
     // Special-case the single-argument case for const_panic.
-    ("{}", $arg:expr $(,)?) => (
-        $crate::panicking::panic_display(&$arg)
-    ),
+    ("{}", $arg:expr $(,)?) => ({
+        $crate::panicking::panic_display(&$arg);
+    }),
     ($fmt:expr, $($arg:tt)+) => ({
         // Semicolon to prevent temporaries inside the formatting machinery from
         // being considered alive in the caller after the panic_fmt call.
@@ -52,9 +52,9 @@ pub macro panic_2021 {
         $crate::panicking::panic("explicit panic")
     ),
     // Special-case the single-argument case for const_panic.
-    ("{}", $arg:expr $(,)?) => (
-        $crate::panicking::panic_display(&$arg)
-    ),
+    ("{}", $arg:expr $(,)?) => ({
+        $crate::panicking::panic_display(&$arg);
+    }),
     ($($t:tt)+) => ({
         // Semicolon to prevent temporaries inside the formatting machinery from
         // being considered alive in the caller after the panic_fmt call.
@@ -73,9 +73,9 @@ pub macro unreachable_2015 {
     ),
     // Use of `unreachable_display` for non_fmt_panic lint.
     // NOTE: the message ("internal error ...") is embedded directly in unreachable_display
-    ($msg:expr $(,)?) => (
-        $crate::panicking::unreachable_display(&$msg)
-    ),
+    ($msg:expr $(,)?) => ({
+        $crate::panicking::unreachable_display(&$msg);
+    }),
     ($fmt:expr, $($arg:tt)*) => (
         $crate::panic!($crate::concat!("internal error: entered unreachable code: ", $fmt), $($arg)*)
     ),
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index c4b89a63019..6b319b4355c 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -393,6 +393,8 @@ use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
 /// value in place, preventing the value referenced by that pointer from being moved
 /// unless it implements [`Unpin`].
 ///
+/// `Pin<P>` is guaranteed to have the same memory layout and ABI as `P`.
+///
 /// *See the [`pin` module] documentation for an explanation of pinning.*
 ///
 /// [`pin` module]: self
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index ecbf4e66fa4..ff9fa48f311 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -441,10 +441,18 @@ mod mut_ptr;
 ///
 /// * `to_drop` must be [valid] for both reads and writes.
 ///
-/// * `to_drop` must be properly aligned.
+/// * `to_drop` must be properly aligned, even if `T` has size 0.
 ///
-/// * The value `to_drop` points to must be valid for dropping, which may mean it must uphold
-///   additional invariants - this is type-dependent.
+/// * `to_drop` must be nonnull, even if `T` has size 0.
+///
+/// * The value `to_drop` points to must be valid for dropping, which may mean
+///   it must uphold additional invariants. These invariants depend on the type
+///   of the value being dropped. For instance, when dropping a Box, the box's
+///   pointer to the heap must be valid.
+///
+/// * While `drop_in_place` is executing, the only way to access parts of
+///   `to_drop` is through the `&mut self` references supplied to the
+///   `Drop::drop` methods that `drop_in_place` invokes.
 ///
 /// Additionally, if `T` is not [`Copy`], using the pointed-to value after
 /// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
@@ -452,8 +460,6 @@ mod mut_ptr;
 /// again. [`write()`] can be used to overwrite data without causing it to be
 /// dropped.
 ///
-/// Note that even if `T` has size `0`, the pointer must be non-null and properly aligned.
-///
 /// [valid]: self#safety
 ///
 /// # Examples
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 6fd2b87d0e3..5ece1b78c03 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -995,7 +995,7 @@ impl<T> [T] {
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
     #[must_use]
-    pub unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
+    pub const unsafe fn as_chunks_unchecked<const N: usize>(&self) -> &[[T; N]] {
         let this = self;
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe {
@@ -1043,7 +1043,7 @@ impl<T> [T] {
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
+    pub const fn as_chunks<const N: usize>(&self) -> (&[[T; N]], &[T]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at(len * N);
@@ -1075,7 +1075,7 @@ impl<T> [T] {
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
+    pub const fn as_rchunks<const N: usize>(&self) -> (&[T], &[[T; N]]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (remainder, multiple_of_n) = self.split_at(self.len() - len * N);
@@ -1152,7 +1152,7 @@ impl<T> [T] {
     #[unstable(feature = "slice_as_chunks", issue = "74985")]
     #[inline]
     #[must_use]
-    pub unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
+    pub const unsafe fn as_chunks_unchecked_mut<const N: usize>(&mut self) -> &mut [[T; N]] {
         let this = &*self;
         // SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
         let new_len = unsafe {
@@ -1195,7 +1195,7 @@ impl<T> [T] {
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
+    pub const fn as_chunks_mut<const N: usize>(&mut self) -> (&mut [[T; N]], &mut [T]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (multiple_of_n, remainder) = self.split_at_mut(len * N);
@@ -1233,7 +1233,7 @@ impl<T> [T] {
     #[inline]
     #[track_caller]
     #[must_use]
-    pub fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
+    pub const fn as_rchunks_mut<const N: usize>(&mut self) -> (&mut [T], &mut [[T; N]]) {
         assert!(N != 0, "chunk size must be non-zero");
         let len = self.len() / N;
         let (remainder, multiple_of_n) = self.split_at_mut(self.len() - len * N);
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index e6e3b55efa9..eb8595ca90d 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -1085,12 +1085,12 @@ where
 
             // SAFETY: left and right must be valid and part of v same for out.
             unsafe {
-                let to_copy = if is_less(&*right, &**left) {
-                    get_and_increment(&mut right)
-                } else {
-                    get_and_increment(left)
-                };
-                ptr::copy_nonoverlapping(to_copy, get_and_increment(out), 1);
+                let is_l = is_less(&*right, &**left);
+                let to_copy = if is_l { right } else { *left };
+                ptr::copy_nonoverlapping(to_copy, *out, 1);
+                *out = out.add(1);
+                right = right.add(is_l as usize);
+                *left = left.add(!is_l as usize);
             }
         }
     } else {
@@ -1113,32 +1113,18 @@ where
 
             // SAFETY: left and right must be valid and part of v same for out.
             unsafe {
-                let to_copy = if is_less(&*right.sub(1), &*left.sub(1)) {
-                    decrement_and_get(left)
-                } else {
-                    decrement_and_get(right)
-                };
-                ptr::copy_nonoverlapping(to_copy, decrement_and_get(&mut out), 1);
+                let is_l = is_less(&*right.sub(1), &*left.sub(1));
+                *left = left.sub(is_l as usize);
+                *right = right.sub(!is_l as usize);
+                let to_copy = if is_l { *left } else { *right };
+                out = out.sub(1);
+                ptr::copy_nonoverlapping(to_copy, out, 1);
             }
         }
     }
     // Finally, `hole` gets dropped. If the shorter run was not fully consumed, whatever remains of
     // it will now be copied into the hole in `v`.
 
-    unsafe fn get_and_increment<T>(ptr: &mut *mut T) -> *mut T {
-        let old = *ptr;
-
-        // SAFETY: ptr.add(1) must still be a valid pointer and part of `v`.
-        *ptr = unsafe { ptr.add(1) };
-        old
-    }
-
-    unsafe fn decrement_and_get<T>(ptr: &mut *mut T) -> *mut T {
-        // SAFETY: ptr.sub(1) must still be a valid pointer and part of `v`.
-        *ptr = unsafe { ptr.sub(1) };
-        *ptr
-    }
-
     // When dropped, copies the range `start..end` into `dest..`.
     struct MergeHole<T> {
         start: *mut T,
diff --git a/library/core/src/task/mod.rs b/library/core/src/task/mod.rs
index c5f89b9a2c6..3f0080e3832 100644
--- a/library/core/src/task/mod.rs
+++ b/library/core/src/task/mod.rs
@@ -13,5 +13,3 @@ pub use self::wake::{Context, RawWaker, RawWakerVTable, Waker};
 mod ready;
 #[stable(feature = "ready_macro", since = "1.64.0")]
 pub use ready::ready;
-#[unstable(feature = "poll_ready", issue = "89780")]
-pub use ready::Ready;
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 5283a576d1b..0a0f702f6fb 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -3,7 +3,6 @@
 use crate::convert;
 use crate::ops::{self, ControlFlow};
 use crate::result::Result;
-use crate::task::Ready;
 
 /// Indicates whether a value is available or if the current task has been
 /// scheduled to receive a wakeup instead.
@@ -95,38 +94,6 @@ impl<T> Poll<T> {
     pub const fn is_pending(&self) -> bool {
         !self.is_ready()
     }
-
-    /// Extracts the successful type of a [`Poll<T>`].
-    ///
-    /// When combined with the `?` operator, this function will
-    /// propagate any [`Poll::Pending`] values to the caller, and
-    /// extract the `T` from [`Poll::Ready`].
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// #![feature(poll_ready)]
-    ///
-    /// use std::task::{Context, Poll};
-    /// use std::future::{self, Future};
-    /// use std::pin::Pin;
-    ///
-    /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
-    ///     let mut fut = future::ready(42);
-    ///     let fut = Pin::new(&mut fut);
-    ///
-    ///     let num = fut.poll(cx).ready()?;
-    ///     # let _ = num; // to silence unused warning
-    ///     // ... use num
-    ///
-    ///     Poll::Ready(())
-    /// }
-    /// ```
-    #[inline]
-    #[unstable(feature = "poll_ready", issue = "89780")]
-    pub fn ready(self) -> Ready<T> {
-        Ready(self)
-    }
 }
 
 impl<T, E> Poll<Result<T, E>> {
diff --git a/library/core/src/task/ready.rs b/library/core/src/task/ready.rs
index 8d12625e88d..495d72fd14b 100644
--- a/library/core/src/task/ready.rs
+++ b/library/core/src/task/ready.rs
@@ -1,8 +1,3 @@
-use core::convert;
-use core::fmt;
-use core::ops::{ControlFlow, FromResidual, Try};
-use core::task::Poll;
-
 /// Extracts the successful type of a [`Poll<T>`].
 ///
 /// This macro bakes in propagation of [`Pending`] signals by returning early.
@@ -60,55 +55,3 @@ pub macro ready($e:expr) {
         }
     }
 }
-
-/// Extracts the successful type of a [`Poll<T>`].
-///
-/// See [`Poll::ready`] for details.
-#[unstable(feature = "poll_ready", issue = "89780")]
-pub struct Ready<T>(pub(crate) Poll<T>);
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> Try for Ready<T> {
-    type Output = T;
-    type Residual = Ready<convert::Infallible>;
-
-    #[inline]
-    fn from_output(output: Self::Output) -> Self {
-        Ready(Poll::Ready(output))
-    }
-
-    #[inline]
-    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
-        match self.0 {
-            Poll::Ready(v) => ControlFlow::Continue(v),
-            Poll::Pending => ControlFlow::Break(Ready(Poll::Pending)),
-        }
-    }
-}
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> FromResidual for Ready<T> {
-    #[inline]
-    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
-        match residual.0 {
-            Poll::Pending => Ready(Poll::Pending),
-        }
-    }
-}
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> FromResidual<Ready<convert::Infallible>> for Poll<T> {
-    #[inline]
-    fn from_residual(residual: Ready<convert::Infallible>) -> Self {
-        match residual.0 {
-            Poll::Pending => Poll::Pending,
-        }
-    }
-}
-
-#[unstable(feature = "poll_ready", issue = "89780")]
-impl<T> fmt::Debug for Ready<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_tuple("Ready").finish()
-    }
-}
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 7f033816901..aee9c89b595 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -386,6 +386,26 @@ fn offset_of() {
     // Layout of tuples is unstable
     assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1);
     assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2);
+
+    #[repr(C)]
+    struct Generic<T> {
+        x: u8,
+        y: u32,
+        z: T
+    }
+
+    trait Trait {}
+
+    // Ensure that this type of generics works
+    fn offs_of_z<T>() -> usize {
+        offset_of!(Generic<T>, z)
+    }
+
+    assert_eq!(offset_of!(Generic<u8>, z), 8);
+    assert_eq!(offs_of_z::<u8>(), 8);
+
+    // Ensure that it works with the implicit lifetime in `Box<dyn Trait + '_>`.
+    assert_eq!(offset_of!(Generic<Box<dyn Trait>>, z), 8);
 }
 
 #[test]
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 2a6b1a5ec73..89dfdfafdb1 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -15,6 +15,7 @@ use crate::ffi::OsString;
 use crate::fmt;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
 use crate::path::{Path, PathBuf};
+use crate::sealed::Sealed;
 use crate::sys::fs as fs_imp;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 use crate::time::SystemTime;
@@ -1391,6 +1392,16 @@ impl FileTimes {
     }
 }
 
+impl AsInnerMut<fs_imp::FileTimes> for FileTimes {
+    fn as_inner_mut(&mut self) -> &mut fs_imp::FileTimes {
+        &mut self.0
+    }
+}
+
+// For implementing OS extension traits in `std::os`
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl Sealed for FileTimes {}
+
 impl Permissions {
     /// Returns `true` if these permissions describe a readonly (unwritable) file.
     ///
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index a8a0b9f122d..e2480bcbbc7 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1,7 +1,7 @@
 use crate::io::prelude::*;
 
 use crate::env;
-use crate::fs::{self, File, OpenOptions};
+use crate::fs::{self, File, FileTimes, OpenOptions};
 use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
 use crate::mem::MaybeUninit;
 use crate::path::Path;
@@ -9,7 +9,7 @@ use crate::str;
 use crate::sync::Arc;
 use crate::sys_common::io::test::{tmpdir, TempDir};
 use crate::thread;
-use crate::time::{Duration, Instant};
+use crate::time::{Duration, Instant, SystemTime};
 
 use rand::RngCore;
 
@@ -1633,3 +1633,53 @@ fn rename_directory() {
     assert!(new_path.join("newdir").is_dir());
     assert!(new_path.join("newdir/temp.txt").exists());
 }
+
+#[test]
+fn test_file_times() {
+    #[cfg(target_os = "ios")]
+    use crate::os::ios::fs::FileTimesExt;
+    #[cfg(target_os = "macos")]
+    use crate::os::macos::fs::FileTimesExt;
+    #[cfg(target_os = "watchos")]
+    use crate::os::watchos::fs::FileTimesExt;
+    #[cfg(windows)]
+    use crate::os::windows::fs::FileTimesExt;
+
+    let tmp = tmpdir();
+    let file = File::create(tmp.join("foo")).unwrap();
+    let mut times = FileTimes::new();
+    let accessed = SystemTime::UNIX_EPOCH + Duration::from_secs(12345);
+    let modified = SystemTime::UNIX_EPOCH + Duration::from_secs(54321);
+    times = times.set_accessed(accessed).set_modified(modified);
+    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
+    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    {
+        times = times.set_created(created);
+    }
+    match file.set_times(times) {
+        // Allow unsupported errors on platforms which don't support setting times.
+        #[cfg(not(any(
+            windows,
+            all(
+                unix,
+                not(any(
+                    target_os = "android",
+                    target_os = "redox",
+                    target_os = "espidf",
+                    target_os = "horizon"
+                ))
+            )
+        )))]
+        Err(e) if e.kind() == ErrorKind::Unsupported => return,
+        Err(e) => panic!("error setting file times: {e:?}"),
+        Ok(_) => {}
+    }
+    let metadata = file.metadata().unwrap();
+    assert_eq!(metadata.accessed().unwrap(), accessed);
+    assert_eq!(metadata.modified().unwrap(), modified);
+    #[cfg(any(windows, target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    {
+        assert_eq!(metadata.created().unwrap(), created);
+    }
+}
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 541e95d229b..141a18a42dd 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -756,6 +756,15 @@ impl TcpListener {
     /// ];
     /// let listener = TcpListener::bind(&addrs[..]).unwrap();
     /// ```
+    ///
+    /// Creates a TCP listener bound to a port assigned by the operating system
+    /// at `127.0.0.1`.
+    ///
+    /// ```no_run
+    /// use std::net::TcpListener;
+    ///
+    /// let socket = TcpListener::bind("127.0.0.1:0").unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
         super::each_addr(addr, net_imp::TcpListener::bind).map(TcpListener)
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index 9628bcc5108..5ca4ed832f3 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -90,6 +90,15 @@ impl UdpSocket {
     /// ];
     /// let socket = UdpSocket::bind(&addrs[..]).expect("couldn't bind to address");
     /// ```
+    ///
+    /// Creates a UDP socket bound to a port assigned by the operating system
+    /// at `127.0.0.1`.
+    ///
+    /// ```no_run
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
         super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs
index 4a4637ce072..6d4d54b7c78 100644
--- a/library/std/src/os/ios/fs.rs
+++ b/library/std/src/os/ios/fs.rs
@@ -1,7 +1,9 @@
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
-use crate::fs::Metadata;
-use crate::sys_common::AsInner;
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 #[allow(deprecated)]
 use crate::os::ios::raw;
@@ -140,3 +142,19 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_lspare as u32
     }
 }
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/macos/fs.rs b/library/std/src/os/macos/fs.rs
index 91915da6a43..fe82d03d869 100644
--- a/library/std/src/os/macos/fs.rs
+++ b/library/std/src/os/macos/fs.rs
@@ -1,7 +1,9 @@
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
-use crate::fs::Metadata;
-use crate::sys_common::AsInner;
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 #[allow(deprecated)]
 use crate::os::macos::raw;
@@ -146,3 +148,19 @@ impl MetadataExt for Metadata {
         [qspare[0] as u64, qspare[1] as u64]
     }
 }
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/watchos/fs.rs b/library/std/src/os/watchos/fs.rs
index a14fe35a77c..2ecc4c68a96 100644
--- a/library/std/src/os/watchos/fs.rs
+++ b/library/std/src/os/watchos/fs.rs
@@ -1,7 +1,9 @@
 #![stable(feature = "metadata_ext", since = "1.1.0")]
 
-use crate::fs::Metadata;
-use crate::sys_common::AsInner;
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 #[allow(deprecated)]
 use crate::os::watchos::raw;
@@ -140,3 +142,19 @@ impl MetadataExt for Metadata {
         self.as_inner().as_inner().st_lspare as u32
     }
 }
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs
index a091f06dd53..94509e54796 100644
--- a/library/std/src/os/windows/fs.rs
+++ b/library/std/src/os/windows/fs.rs
@@ -9,7 +9,8 @@ use crate::io;
 use crate::path::Path;
 use crate::sealed::Sealed;
 use crate::sys;
-use crate::sys_common::{AsInner, AsInnerMut};
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
 
 /// Windows-specific extensions to [`fs::File`].
 #[stable(feature = "file_offset", since = "1.15.0")]
@@ -526,6 +527,22 @@ impl FileTypeExt for fs::FileType {
     }
 }
 
+/// Windows-specific extensions to [`fs::FileTimes`].
+#[unstable(feature = "file_set_times", issue = "98245")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[unstable(feature = "file_set_times", issue = "98245")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
+
 /// Creates a new symlink to a non-directory file on the filesystem.
 ///
 /// The `link` path will be a file symbolic link pointing to the `original`
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index a2ffd8b1e7e..69a6f3e6d5a 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -19,11 +19,11 @@ pub macro panic_2015 {
         $crate::rt::begin_panic("explicit panic")
     }),
     ($msg:expr $(,)?) => ({
-        $crate::rt::begin_panic($msg)
+        $crate::rt::begin_panic($msg);
     }),
     // Special-case the single-argument case for const_panic.
     ("{}", $arg:expr $(,)?) => ({
-        $crate::rt::panic_display(&$arg)
+        $crate::rt::panic_display(&$arg);
     }),
     ($fmt:expr, $($arg:tt)+) => ({
         // Semicolon to prevent temporaries inside the formatting machinery from
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 43203c5824d..febdeb51463 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -733,8 +733,9 @@ impl<'a> Components<'a> {
         }
     }
 
-    // parse a given byte sequence into the corresponding path component
-    fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
+    // parse a given byte sequence following the OsStr encoding into the
+    // corresponding path component
+    unsafe fn parse_single_component<'b>(&self, comp: &'b [u8]) -> Option<Component<'b>> {
         match comp {
             b"." if self.prefix_verbatim() => Some(Component::CurDir),
             b"." => None, // . components are normalized away, except at
@@ -754,7 +755,8 @@ impl<'a> Components<'a> {
             None => (0, self.path),
             Some(i) => (1, &self.path[..i]),
         };
-        (comp.len() + extra, self.parse_single_component(comp))
+        // SAFETY: `comp` is a valid substring, since it is split on a separator.
+        (comp.len() + extra, unsafe { self.parse_single_component(comp) })
     }
 
     // parse a component from the right, saying how many bytes to consume to
@@ -766,7 +768,8 @@ impl<'a> Components<'a> {
             None => (0, &self.path[start..]),
             Some(i) => (1, &self.path[start + i + 1..]),
         };
-        (comp.len() + extra, self.parse_single_component(comp))
+        // SAFETY: `comp` is a valid substring, since it is split on a separator.
+        (comp.len() + extra, unsafe { self.parse_single_component(comp) })
     }
 
     // trim away repeated separators (i.e., empty components) on the left
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 09db5b11dbf..09e9ae2720f 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -349,6 +349,8 @@ pub struct FilePermissions {
 pub struct FileTimes {
     accessed: Option<SystemTime>,
     modified: Option<SystemTime>,
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    created: Option<SystemTime>,
 }
 
 #[derive(Copy, Clone, Eq, Debug)]
@@ -591,6 +593,11 @@ impl FileTimes {
     pub fn set_modified(&mut self, t: SystemTime) {
         self.modified = Some(t);
     }
+
+    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+    pub fn set_created(&mut self, t: SystemTime) {
+        self.created = Some(t);
+    }
 }
 
 impl FileType {
@@ -1215,26 +1222,41 @@ impl File {
                     io::ErrorKind::Unsupported,
                     "setting file times not supported",
                 ))
-            } else if #[cfg(any(target_os = "android", target_os = "macos"))] {
+            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] {
+                let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3];
+                let mut num_times = 0;
+                let mut attrlist: libc::attrlist = unsafe { mem::zeroed() };
+                attrlist.bitmapcount = libc::ATTR_BIT_MAP_COUNT;
+                if times.created.is_some() {
+                    buf[num_times].write(to_timespec(times.created)?);
+                    num_times += 1;
+                    attrlist.commonattr |= libc::ATTR_CMN_CRTIME;
+                }
+                if times.modified.is_some() {
+                    buf[num_times].write(to_timespec(times.modified)?);
+                    num_times += 1;
+                    attrlist.commonattr |= libc::ATTR_CMN_MODTIME;
+                }
+                if times.accessed.is_some() {
+                    buf[num_times].write(to_timespec(times.accessed)?);
+                    num_times += 1;
+                    attrlist.commonattr |= libc::ATTR_CMN_ACCTIME;
+                }
+                cvt(unsafe { libc::fsetattrlist(
+                    self.as_raw_fd(),
+                    (&attrlist as *const libc::attrlist).cast::<libc::c_void>().cast_mut(),
+                    buf.as_ptr().cast::<libc::c_void>().cast_mut(),
+                    num_times * mem::size_of::<libc::timespec>(),
+                    0
+                ) })?;
+                Ok(())
+            } else if #[cfg(target_os = "android")] {
                 let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
-                // futimens requires macOS 10.13, and Android API level 19
+                // futimens requires Android API level 19
                 cvt(unsafe {
                     weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
                     match futimens.get() {
                         Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()),
-                        #[cfg(target_os = "macos")]
-                        None => {
-                            fn ts_to_tv(ts: &libc::timespec) -> libc::timeval {
-                                libc::timeval {
-                                    tv_sec: ts.tv_sec,
-                                    tv_usec: (ts.tv_nsec / 1000) as _
-                                }
-                            }
-                            let timevals = [ts_to_tv(&times[0]), ts_to_tv(&times[1])];
-                            libc::futimes(self.as_raw_fd(), timevals.as_ptr())
-                        }
-                        // futimes requires even newer Android.
-                        #[cfg(target_os = "android")]
                         None => return Err(io::const_io_error!(
                             io::ErrorKind::Unsupported,
                             "setting file times requires Android API level >= 19",
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index ce427766d17..21a65bc25f3 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -88,8 +88,10 @@ pub struct FilePermissions {
 pub struct FileTimes {
     accessed: Option<c::FILETIME>,
     modified: Option<c::FILETIME>,
+    created: Option<c::FILETIME>,
 }
-impl core::fmt::Debug for c::FILETIME {
+
+impl fmt::Debug for c::FILETIME {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let time = ((self.dwHighDateTime as u64) << 32) | self.dwLowDateTime as u64;
         f.debug_tuple("FILETIME").field(&time).finish()
@@ -582,7 +584,10 @@ impl File {
 
     pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
         let is_zero = |t: c::FILETIME| t.dwLowDateTime == 0 && t.dwHighDateTime == 0;
-        if times.accessed.map_or(false, is_zero) || times.modified.map_or(false, is_zero) {
+        if times.accessed.map_or(false, is_zero)
+            || times.modified.map_or(false, is_zero)
+            || times.created.map_or(false, is_zero)
+        {
             return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
                 "Cannot set file timestamp to 0",
@@ -590,18 +595,23 @@ impl File {
         }
         let is_max =
             |t: c::FILETIME| t.dwLowDateTime == c::DWORD::MAX && t.dwHighDateTime == c::DWORD::MAX;
-        if times.accessed.map_or(false, is_max) || times.modified.map_or(false, is_max) {
+        if times.accessed.map_or(false, is_max)
+            || times.modified.map_or(false, is_max)
+            || times.created.map_or(false, is_max)
+        {
             return Err(io::const_io_error!(
                 io::ErrorKind::InvalidInput,
                 "Cannot set file timestamp to 0xFFFF_FFFF_FFFF_FFFF",
             ));
         }
         cvt(unsafe {
+            let created =
+                times.created.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
             let accessed =
                 times.accessed.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
             let modified =
                 times.modified.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null());
-            c::SetFileTime(self.as_raw_handle(), ptr::null_mut(), accessed, modified)
+            c::SetFileTime(self.as_raw_handle(), created, accessed, modified)
         })?;
         Ok(())
     }
@@ -1005,6 +1015,10 @@ impl FileTimes {
     pub fn set_modified(&mut self, t: SystemTime) {
         self.modified = Some(t.into_inner());
     }
+
+    pub fn set_created(&mut self, t: SystemTime) {
+        self.created = Some(t.into_inner());
+    }
 }
 
 impl FileType {
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs
index 8752f46ff81..6f020940df1 100644
--- a/library/std/src/sys_common/backtrace.rs
+++ b/library/std/src/sys_common/backtrace.rs
@@ -68,13 +68,17 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
         }
 
         let mut hit = false;
-        let mut stop = false;
         backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
             hit = true;
+
+            // Any frames between `__rust_begin_short_backtrace` and `__rust_end_short_backtrace`
+            // are omitted from the backtrace in short mode, `__rust_end_short_backtrace` will be
+            // called before the panic hook, so we won't ignore any frames if there is no
+            // invoke of `__rust_begin_short_backtrace`.
             if print_fmt == PrintFmt::Short {
                 if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
                     if start && sym.contains("__rust_begin_short_backtrace") {
-                        stop = true;
+                        start = false;
                         return;
                     }
                     if sym.contains("__rust_end_short_backtrace") {
@@ -88,9 +92,6 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
                 res = bt_fmt.frame().symbol(frame, symbol);
             }
         });
-        if stop {
-            return false;
-        }
         #[cfg(target_os = "nto")]
         if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
             if !hit && start {
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 9420c4fec5f..8f8778efee7 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -139,7 +139,7 @@ dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -488,9 +488,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.29.0"
+version = "0.31.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
+checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
 dependencies = [
  "memchr",
 ]
@@ -654,19 +654,19 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
 
 [[package]]
 name = "serde"
-version = "1.0.137"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.137"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.102",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -704,9 +704,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.15"
+version = "2.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 746c8dcfce0..367c6190967 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -37,7 +37,7 @@ filetime = "0.2"
 cc = "1.0.69"
 libc = "0.2"
 hex = "0.4"
-object = { version = "0.29.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
+object = { version = "0.31.1", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
 serde = "1.0.137"
 # Directly use serde_derive rather than through the derive feature of serde to allow building both
 # in parallel and to allow serde_json and toml to start building as soon as serde has been built.
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index f22cdad7df4..50ace987193 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -109,7 +109,7 @@ def _download(path, url, probably_big, verbose, exception):
                 "-L", # Follow redirect.
                 "-y", "30", "-Y", "10",    # timeout if speed is < 10 bytes/sec for > 30 seconds
                 "--connect-timeout", "30",  # timeout if cannot connect within 30 seconds
-                "--retry", "3", "-Sf", url],
+                "--retry", "3", "-SRf", url],
                 stdout=outfile,    #Implements cli redirect operator '>'
                 verbose=verbose,
                 exception=True, # Will raise RuntimeError on failure
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 5c37fab5470..cf7c6596c02 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -942,7 +942,6 @@ impl<'a> Builder<'a> {
         self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
     }
 
-    /// NOTE: keep this in sync with `rustdoc::clean::utils::doc_rust_lang_org_channel`, or tests will fail on beta/stable.
     pub fn doc_rust_lang_org_channel(&self) -> String {
         let channel = match &*self.config.channel {
             "stable" => &self.version,
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index c32fe59bbf0..edca8fe9b13 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -146,6 +146,22 @@ fn alias_and_path_for_library() {
     );
 }
 
+#[test]
+fn test_beta_rev_parsing() {
+    use crate::extract_beta_rev;
+
+    // single digit revision
+    assert_eq!(extract_beta_rev("1.99.9-beta.7 (xxxxxx)"), Some("7".to_string()));
+    // multiple digits
+    assert_eq!(extract_beta_rev("1.99.9-beta.777 (xxxxxx)"), Some("777".to_string()));
+    // nightly channel (no beta revision)
+    assert_eq!(extract_beta_rev("1.99.9-nightly (xxxxxx)"), None);
+    // stable channel (no beta revision)
+    assert_eq!(extract_beta_rev("1.99.9 (xxxxxxx)"), None);
+    // invalid string
+    assert_eq!(extract_beta_rev("invalid"), None);
+}
+
 mod defaults {
     use super::{configure, first, run_build};
     use crate::builder::*;
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 710c8b52194..e192cda9a9a 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -350,7 +350,7 @@ impl SplitDebuginfo {
 }
 
 /// LTO mode used for compiling rustc itself.
-#[derive(Default, Clone, PartialEq)]
+#[derive(Default, Clone, PartialEq, Debug)]
 pub enum RustcLto {
     Off,
     #[default]
@@ -508,29 +508,42 @@ struct TomlConfig {
     profile: Option<String>,
 }
 
+/// Describes how to handle conflicts in merging two [`TomlConfig`]
+#[derive(Copy, Clone, Debug)]
+enum ReplaceOpt {
+    /// Silently ignore a duplicated value
+    IgnoreDuplicate,
+    /// Override the current value, even if it's `Some`
+    Override,
+    /// Exit with an error on duplicate values
+    ErrorOnDuplicate,
+}
+
 trait Merge {
-    fn merge(&mut self, other: Self);
+    fn merge(&mut self, other: Self, replace: ReplaceOpt);
 }
 
 impl Merge for TomlConfig {
     fn merge(
         &mut self,
-        TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen: _ }: Self,
+        TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen }: Self,
+        replace: ReplaceOpt,
     ) {
-        fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>) {
+        fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
             if let Some(new) = y {
                 if let Some(original) = x {
-                    original.merge(new);
+                    original.merge(new, replace);
                 } else {
                     *x = Some(new);
                 }
             }
         }
-        do_merge(&mut self.build, build);
-        do_merge(&mut self.install, install);
-        do_merge(&mut self.llvm, llvm);
-        do_merge(&mut self.rust, rust);
-        do_merge(&mut self.dist, dist);
+        self.changelog_seen.merge(changelog_seen, replace);
+        do_merge(&mut self.build, build, replace);
+        do_merge(&mut self.install, install, replace);
+        do_merge(&mut self.llvm, llvm, replace);
+        do_merge(&mut self.rust, rust, replace);
+        do_merge(&mut self.dist, dist, replace);
         assert!(target.is_none(), "merging target-specific config is not currently supported");
     }
 }
@@ -547,10 +560,33 @@ macro_rules! define_config {
         }
 
         impl Merge for $name {
-            fn merge(&mut self, other: Self) {
+            fn merge(&mut self, other: Self, replace: ReplaceOpt) {
                 $(
-                    if !self.$field.is_some() {
-                        self.$field = other.$field;
+                    match replace {
+                        ReplaceOpt::IgnoreDuplicate => {
+                            if self.$field.is_none() {
+                                self.$field = other.$field;
+                            }
+                        },
+                        ReplaceOpt::Override => {
+                            if other.$field.is_some() {
+                                self.$field = other.$field;
+                            }
+                        }
+                        ReplaceOpt::ErrorOnDuplicate => {
+                            if other.$field.is_some() {
+                                if self.$field.is_some() {
+                                    if cfg!(test) {
+                                        panic!("overriding existing option")
+                                    } else {
+                                        eprintln!("overriding existing option: `{}`", stringify!($field));
+                                        crate::detail_exit(2);
+                                    }
+                                } else {
+                                    self.$field = other.$field;
+                                }
+                            }
+                        }
                     }
                 )*
             }
@@ -623,6 +659,37 @@ macro_rules! define_config {
     }
 }
 
+impl<T> Merge for Option<T> {
+    fn merge(&mut self, other: Self, replace: ReplaceOpt) {
+        match replace {
+            ReplaceOpt::IgnoreDuplicate => {
+                if self.is_none() {
+                    *self = other;
+                }
+            }
+            ReplaceOpt::Override => {
+                if other.is_some() {
+                    *self = other;
+                }
+            }
+            ReplaceOpt::ErrorOnDuplicate => {
+                if other.is_some() {
+                    if self.is_some() {
+                        if cfg!(test) {
+                            panic!("overriding existing option")
+                        } else {
+                            eprintln!("overriding existing option");
+                            crate::detail_exit(2);
+                        }
+                    } else {
+                        *self = other;
+                    }
+                }
+            }
+        }
+    }
+}
+
 define_config! {
     /// TOML representation of various global build decisions.
     #[derive(Default)]
@@ -864,28 +931,27 @@ impl Config {
 
     pub fn parse(args: &[String]) -> Config {
         #[cfg(test)]
-        let get_toml = |_: &_| TomlConfig::default();
+        fn get_toml(_: &Path) -> TomlConfig {
+            TomlConfig::default()
+        }
+
         #[cfg(not(test))]
-        let get_toml = |file: &Path| {
+        fn get_toml(file: &Path) -> TomlConfig {
             let contents =
                 t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
             // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
             // TomlConfig and sub types to be monomorphized 5x by toml.
-            match toml::from_str(&contents)
+            toml::from_str(&contents)
                 .and_then(|table: toml::Value| TomlConfig::deserialize(table))
-            {
-                Ok(table) => table,
-                Err(err) => {
-                    eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
+                .unwrap_or_else(|err| {
+                    eprintln!("failed to parse TOML configuration '{}': {err}", file.display());
                     crate::detail_exit(2);
-                }
-            }
-        };
-
+                })
+        }
         Self::parse_inner(args, get_toml)
     }
 
-    fn parse_inner<'a>(args: &[String], get_toml: impl 'a + Fn(&Path) -> TomlConfig) -> Config {
+    fn parse_inner(args: &[String], get_toml: impl Fn(&Path) -> TomlConfig) -> Config {
         let mut flags = Flags::parse(&args);
         let mut config = Config::default_opts();
 
@@ -998,8 +1064,40 @@ impl Config {
             include_path.push("defaults");
             include_path.push(format!("config.{}.toml", include));
             let included_toml = get_toml(&include_path);
-            toml.merge(included_toml);
+            toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate);
+        }
+
+        let mut override_toml = TomlConfig::default();
+        for option in flags.set.iter() {
+            fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
+                toml::from_str(&option)
+                    .and_then(|table: toml::Value| TomlConfig::deserialize(table))
+            }
+
+            let mut err = match get_table(option) {
+                Ok(v) => {
+                    override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
+                    continue;
+                }
+                Err(e) => e,
+            };
+            // We want to be able to set string values without quotes,
+            // like in `configure.py`. Try adding quotes around the right hand side
+            if let Some((key, value)) = option.split_once("=") {
+                if !value.contains('"') {
+                    match get_table(&format!(r#"{key}="{value}""#)) {
+                        Ok(v) => {
+                            override_toml.merge(v, ReplaceOpt::ErrorOnDuplicate);
+                            continue;
+                        }
+                        Err(e) => err = e,
+                    }
+                }
+            }
+            eprintln!("failed to parse override `{option}`: `{err}");
+            crate::detail_exit(2)
         }
+        toml.merge(override_toml, ReplaceOpt::Override);
 
         config.changelog_seen = toml.changelog_seen;
 
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index d913ca295e2..4de84b543ed 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -1,13 +1,11 @@
-use super::{Config, Flags, TomlConfig};
+use super::{Config, Flags};
 use clap::CommandFactory;
 use std::{env, path::Path};
 
-fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig {
-    |&_| toml::from_str(config).unwrap()
-}
-
 fn parse(config: &str) -> Config {
-    Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], toml(config))
+    Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], |&_| {
+        toml::from_str(config).unwrap()
+    })
 }
 
 #[test]
@@ -94,3 +92,70 @@ fn detect_src_and_out() {
 fn clap_verify() {
     Flags::command().debug_assert();
 }
+
+#[test]
+fn override_toml() {
+    let config = Config::parse_inner(
+        &[
+            "check".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+            "--set=changelog-seen=1".to_owned(),
+            "--set=rust.lto=fat".to_owned(),
+            "--set=rust.deny-warnings=false".to_owned(),
+            "--set=build.gdb=\"bar\"".to_owned(),
+            "--set=build.tools=[\"cargo\"]".to_owned(),
+            "--set=llvm.build-config={\"foo\" = \"bar\"}".to_owned(),
+        ],
+        |&_| {
+            toml::from_str(
+                r#"
+changelog-seen = 0
+[rust]
+lto = "off"
+deny-warnings = true
+
+[build]
+gdb = "foo"
+tools = []
+
+[llvm]
+download-ci-llvm = false
+build-config = {}
+                "#,
+            )
+            .unwrap()
+        },
+    );
+    assert_eq!(config.changelog_seen, Some(1), "setting top-level value");
+    assert_eq!(
+        config.rust_lto,
+        crate::config::RustcLto::Fat,
+        "setting string value without quotes"
+    );
+    assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
+    assert_eq!(config.deny_warnings, false, "setting boolean value");
+    assert_eq!(
+        config.tools,
+        Some(["cargo".to_string()].into_iter().collect()),
+        "setting list value"
+    );
+    assert_eq!(
+        config.llvm_build_config,
+        [("foo".to_string(), "bar".to_string())].into_iter().collect(),
+        "setting dictionary value"
+    );
+}
+
+#[test]
+#[should_panic]
+fn override_toml_duplicate() {
+    Config::parse_inner(
+        &[
+            "check".to_owned(),
+            "--config=/does/not/exist".to_owned(),
+            "--set=changelog-seen=1".to_owned(),
+            "--set=changelog-seen=2".to_owned(),
+        ],
+        |&_| toml::from_str("changelog-seen = 0").unwrap(),
+    );
+}
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 3e82a381a1b..25df5b2573b 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -219,7 +219,7 @@ impl Config {
             "30", // timeout if cannot connect within 30 seconds
             "--retry",
             "3",
-            "-Sf",
+            "-SRf",
         ]);
         curl.arg(url);
         let f = File::create(tempfile).unwrap();
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 6e0c0e01af8..80e71577798 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -158,6 +158,9 @@ pub struct Flags {
     #[arg(global(true))]
     /// paths for the subcommand
     pub paths: Vec<PathBuf>,
+    /// override options in config.toml
+    #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "section.option=value")]
+    pub set: Vec<String>,
     /// arguments passed to subcommands
     #[arg(global(true), last(true), value_name = "ARGS")]
     pub free_args: Vec<String>,
@@ -365,7 +368,7 @@ pub enum Subcommand {
         #[arg(long)]
         all: bool,
     },
-    /// Duild distribution artifacts
+    /// Build distribution artifacts
     Dist,
     /// Install distribution artifacts
     Install,
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 3756976dee0..6ee50ee6573 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1324,7 +1324,7 @@ impl Build {
         match &self.config.channel[..] {
             "stable" => num.to_string(),
             "beta" => {
-                if self.rust_info().is_managed_git_subrepository() && !self.config.omit_git_hash {
+                if !self.config.omit_git_hash {
                     format!("{}-beta.{}", num, self.beta_prerelease_version())
                 } else {
                     format!("{}-beta", num)
@@ -1336,18 +1336,28 @@ impl Build {
     }
 
     fn beta_prerelease_version(&self) -> u32 {
+        fn extract_beta_rev_from_file<P: AsRef<Path>>(version_file: P) -> Option<String> {
+            let version = fs::read_to_string(version_file).ok()?;
+
+            extract_beta_rev(&version)
+        }
+
         if let Some(s) = self.prerelease_version.get() {
             return s;
         }
 
-        // Figure out how many merge commits happened since we branched off master.
-        // That's our beta number!
-        // (Note that we use a `..` range, not the `...` symmetric difference.)
-        let count =
+        // First check if there is a version file available.
+        // If available, we read the beta revision from that file.
+        // This only happens when building from a source tarball when Git should not be used.
+        let count = extract_beta_rev_from_file(self.src.join("version")).unwrap_or_else(|| {
+            // Figure out how many merge commits happened since we branched off master.
+            // That's our beta number!
+            // (Note that we use a `..` range, not the `...` symmetric difference.)
             output(self.config.git().arg("rev-list").arg("--count").arg("--merges").arg(format!(
                 "refs/remotes/origin/{}..HEAD",
                 self.config.stage0_metadata.config.nightly_branch
-            )));
+            )))
+        });
         let n = count.trim().parse().unwrap();
         self.prerelease_version.set(Some(n));
         n
@@ -1707,6 +1717,17 @@ to download LLVM rather than building it.
     }
 }
 
+/// Extract the beta revision from the full version string.
+///
+/// The full version string looks like "a.b.c-beta.y". And we need to extract
+/// the "y" part from the string.
+pub fn extract_beta_rev(version: &str) -> Option<String> {
+    let parts = version.splitn(2, "-beta.").collect::<Vec<_>>();
+    let count = parts.get(1).and_then(|s| s.find(' ').map(|p| (&s[..p]).to_string()));
+
+    count
+}
+
 #[cfg(unix)]
 fn chmod(path: &Path, perms: u32) {
     use std::os::unix::fs::*;
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs
index 67cb8837391..040a12f5d10 100644
--- a/src/bootstrap/llvm.rs
+++ b/src/bootstrap/llvm.rs
@@ -185,6 +185,7 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
         ("arm-unknown-linux-gnueabi", false),
         ("arm-unknown-linux-gnueabihf", false),
         ("armv7-unknown-linux-gnueabihf", false),
+        ("loongarch64-unknown-linux-gnu", false),
         ("mips-unknown-linux-gnu", false),
         ("mips64-unknown-linux-gnuabi64", false),
         ("mips64el-unknown-linux-gnuabi64", false),
diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs
index bedf34d89e8..fa0a4806618 100644
--- a/src/bootstrap/render_tests.rs
+++ b/src/bootstrap/render_tests.rs
@@ -168,9 +168,14 @@ impl<'a> Renderer<'a> {
         if !self.failures.is_empty() {
             println!("\nfailures:\n");
             for failure in &self.failures {
-                if let Some(stdout) = &failure.stdout {
+                if failure.stdout.is_some() || failure.message.is_some() {
                     println!("---- {} stdout ----", failure.name);
-                    println!("{stdout}");
+                    if let Some(stdout) = &failure.stdout {
+                        println!("{stdout}");
+                    }
+                    if let Some(message) = &failure.message {
+                        println!("note: {message}");
+                    }
                 }
             }
 
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 2d600704e02..2b72d6c48eb 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -620,6 +620,8 @@ impl Step for Miri {
             cargo.env("MIRIFLAGS", "-O -Zmir-opt-level=4 -Cdebug-assertions=yes");
             // Optimizations can change backtraces
             cargo.env("MIRI_SKIP_UI_CHECKS", "1");
+            // `MIRI_SKIP_UI_CHECKS` and `MIRI_BLESS` are incompatible
+            cargo.env_remove("MIRI_BLESS");
             // Optimizations can change error locations and remove UB so don't run `fail` tests.
             cargo.args(&["tests/pass", "tests/panic"]);
 
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index 5898a21d613..e799d7c9688 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -257,6 +257,22 @@ For targets: `i586-unknown-linux-gnu`
 (\*) Compressed debug is enabled by default for gas (assembly) on Linux/x86 targets,
      but that makes our `compiler_builtins` incompatible with binutils < 2.32.
 
+### `loongarch64-linux-gnu.defconfig`
+
+For targets: `loongarch64-unknown-linux-gnu`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Target options > Target Architecture = loongarch
+- Target options > Bitness = 64-bit
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 5.19.16
+- Binary utilities > Version of binutils = 2.40
+- C-library > glibc version = 2.36
+- C compiler > gcc version = 12.2.0
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
 ### `mips-linux-gnu.defconfig`
 
 For targets: `mips-unknown-linux-gnu`
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile
new file mode 100644
index 00000000000..78689c429c2
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile
@@ -0,0 +1,30 @@
+FROM ubuntu:22.04
+
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+# The latest released version does not support LoongArch.
+COPY scripts/crosstool-ng-git.sh /scripts/
+RUN sh /scripts/crosstool-ng-git.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV PATH=$PATH:/x-tools/loongarch64-unknown-linux-gnu/bin
+
+ENV CC_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-gcc \
+    AR_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-ar \
+    CXX_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-g++
+
+ENV HOSTS=loongarch64-unknown-linux-gnu
+
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
+ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig
new file mode 100644
index 00000000000..576f3631cd5
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/loongarch64-unknown-linux-gnu.defconfig
@@ -0,0 +1,14 @@
+CT_CONFIG_VERSION="4"
+CT_EXPERIMENTAL=y
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_LOONGARCH=y
+# CT_DEMULTILIB is not set
+CT_ARCH_USE_MMU=y
+CT_ARCH_ARCH="loongarch64"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_5_19=y
+CT_GLIBC_V_2_36=y
+CT_CC_GCC_ENABLE_DEFAULT_PIE=y
+CT_CC_LANG_CXX=y
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
index 6b4966ddeb4..806935b827f 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version
@@ -1 +1 @@
-0.16.3
\ No newline at end of file
+0.16.4
\ No newline at end of file
diff --git a/src/ci/docker/scripts/cross-apt-packages.sh b/src/ci/docker/scripts/cross-apt-packages.sh
index 2f8bf119424..398362ca52f 100644
--- a/src/ci/docker/scripts/cross-apt-packages.sh
+++ b/src/ci/docker/scripts/cross-apt-packages.sh
@@ -22,6 +22,7 @@ apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install
   patch \
   pkg-config \
   python3 \
+  rsync \
   sudo \
   texinfo \
   unzip \
diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh
new file mode 100644
index 00000000000..449cc476f9a
--- /dev/null
+++ b/src/ci/docker/scripts/crosstool-ng-git.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -ex
+
+URL=https://github.com/crosstool-ng/crosstool-ng
+REV=943364711a650d9b9e84c1b42c91cc0265b6ab5c
+
+mkdir crosstool-ng
+cd crosstool-ng
+git init
+git fetch --depth=1 ${URL} ${REV}
+git reset --hard FETCH_HEAD
+./bootstrap
+./configure --prefix=/usr/local
+make -j$(nproc)
+make install
+cd ..
+rm -rf crosstool-ng
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index f81e740936b..fd619467fc1 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -359,6 +359,9 @@ jobs:
           - name: dist-i686-linux
             <<: *job-linux-8c
 
+          - name: dist-loongarch64-linux
+            <<: *job-linux-8c
+
           - name: dist-mips-linux
             <<: *job-linux-8c
 
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
index 7cd5e88f6a2..8d03d3759bf 100644
--- a/src/ci/stage-build.py
+++ b/src/ci/stage-build.py
@@ -48,7 +48,6 @@ RUSTC_PGO_CRATES = [
 
 LLVM_BOLT_CRATES = LLVM_PGO_CRATES
 
-
 class Pipeline:
     # Paths
     def checkout_path(self) -> Path:
@@ -451,6 +450,44 @@ def cmd(
             )
     return subprocess.run(args, env=environment, check=True)
 
+class BenchmarkRunner:
+    def run_rustc(self, pipeline: Pipeline):
+        raise NotImplementedError
+
+    def run_llvm(self, pipeline: Pipeline):
+        raise NotImplementedError
+
+    def run_bolt(self, pipeline: Pipeline):
+        raise NotImplementedError
+
+class DefaultBenchmarkRunner(BenchmarkRunner):
+    def run_rustc(self, pipeline: Pipeline):
+        # Here we're profiling the `rustc` frontend, so we also include `Check`.
+        # The benchmark set includes various stress tests that put the frontend under pressure.
+        run_compiler_benchmarks(
+            pipeline,
+            profiles=["Check", "Debug", "Opt"],
+            scenarios=["All"],
+            crates=RUSTC_PGO_CRATES,
+            env=dict(
+                LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
+            )
+        )
+    def run_llvm(self, pipeline: Pipeline):
+        run_compiler_benchmarks(
+            pipeline,
+            profiles=["Debug", "Opt"],
+            scenarios=["Full"],
+            crates=LLVM_PGO_CRATES
+        )
+
+    def run_bolt(self, pipeline: Pipeline):
+        run_compiler_benchmarks(
+            pipeline,
+            profiles=["Check", "Debug", "Opt"],
+            scenarios=["Full"],
+            crates=LLVM_BOLT_CRATES
+        )
 
 def run_compiler_benchmarks(
         pipeline: Pipeline,
@@ -580,14 +617,10 @@ def create_pipeline() -> Pipeline:
         raise Exception(f"Optimized build is not supported for platform {sys.platform}")
 
 
-def gather_llvm_profiles(pipeline: Pipeline):
+def gather_llvm_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
     LOGGER.info("Running benchmarks with PGO instrumented LLVM")
-    run_compiler_benchmarks(
-        pipeline,
-        profiles=["Debug", "Opt"],
-        scenarios=["Full"],
-        crates=LLVM_PGO_CRATES
-    )
+
+    runner.run_llvm(pipeline)
 
     profile_path = pipeline.llvm_profile_merged_file()
     LOGGER.info(f"Merging LLVM PGO profiles to {profile_path}")
@@ -609,20 +642,12 @@ def gather_llvm_profiles(pipeline: Pipeline):
     delete_directory(pipeline.llvm_profile_dir_root())
 
 
-def gather_rustc_profiles(pipeline: Pipeline):
+def gather_rustc_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
     LOGGER.info("Running benchmarks with PGO instrumented rustc")
 
-    # Here we're profiling the `rustc` frontend, so we also include `Check`.
-    # The benchmark set includes various stress tests that put the frontend under pressure.
-    run_compiler_benchmarks(
-        pipeline,
-        profiles=["Check", "Debug", "Opt"],
-        scenarios=["All"],
-        crates=RUSTC_PGO_CRATES,
-        env=dict(
-            LLVM_PROFILE_FILE=str(pipeline.rustc_profile_template_path())
-        )
-    )
+
+    runner.run_rustc(pipeline)
+
 
     profile_path = pipeline.rustc_profile_merged_file()
     LOGGER.info(f"Merging Rustc PGO profiles to {profile_path}")
@@ -644,14 +669,10 @@ def gather_rustc_profiles(pipeline: Pipeline):
     delete_directory(pipeline.rustc_profile_dir_root())
 
 
-def gather_llvm_bolt_profiles(pipeline: Pipeline):
+def gather_llvm_bolt_profiles(pipeline: Pipeline, runner: BenchmarkRunner):
     LOGGER.info("Running benchmarks with BOLT instrumented LLVM")
-    run_compiler_benchmarks(
-        pipeline,
-        profiles=["Check", "Debug", "Opt"],
-        scenarios=["Full"],
-        crates=LLVM_BOLT_CRATES
-    )
+
+    runner.run_bolt(pipeline)
 
     merged_profile_path = pipeline.llvm_bolt_profile_merged_file()
     profile_files_path = Path("/tmp/prof.fdata")
@@ -744,7 +765,7 @@ def record_metrics(pipeline: Pipeline, timer: Timer):
     log_metrics(metrics)
 
 
-def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: List[str]):
+def execute_build_pipeline(timer: Timer, pipeline: Pipeline, runner: BenchmarkRunner, final_build_args: List[str]):
     # Clear and prepare tmp directory
     shutil.rmtree(pipeline.opt_artifacts(), ignore_errors=True)
     os.makedirs(pipeline.opt_artifacts(), exist_ok=True)
@@ -762,7 +783,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
             record_metrics(pipeline, rustc_build)
 
         with stage1.section("Gather profiles"):
-            gather_llvm_profiles(pipeline)
+            gather_llvm_profiles(pipeline, runner)
         print_free_disk_space(pipeline)
 
     clear_llvm_files(pipeline)
@@ -781,7 +802,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
             record_metrics(pipeline, rustc_build)
 
         with stage2.section("Gather profiles"):
-            gather_rustc_profiles(pipeline)
+            gather_rustc_profiles(pipeline, runner)
         print_free_disk_space(pipeline)
 
     clear_llvm_files(pipeline)
@@ -804,7 +825,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
                 record_metrics(pipeline, rustc_build)
 
             with stage3.section("Gather profiles"):
-                gather_llvm_bolt_profiles(pipeline)
+                gather_llvm_bolt_profiles(pipeline, runner)
 
         # LLVM is not being cleared here, we want to reuse the previous build
         print_free_disk_space(pipeline)
@@ -819,7 +840,7 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
         record_metrics(pipeline, stage4)
 
 
-if __name__ == "__main__":
+def run(runner: BenchmarkRunner):
     logging.basicConfig(
         level=logging.DEBUG,
         format="%(name)s %(levelname)-4s: %(message)s",
@@ -832,8 +853,9 @@ if __name__ == "__main__":
 
     timer = Timer()
     pipeline = create_pipeline()
+
     try:
-        execute_build_pipeline(timer, pipeline, build_args)
+        execute_build_pipeline(timer, pipeline, runner, build_args)
     except BaseException as e:
         LOGGER.error("The multi-stage build has failed")
         raise e
@@ -842,3 +864,7 @@ if __name__ == "__main__":
         print_free_disk_space(pipeline)
 
     print_binary_sizes(pipeline)
+
+if __name__ == "__main__":
+    runner = DefaultBenchmarkRunner()
+    run(runner)
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject d9eb4c3f75435b008881062ffa77bf0d1527b37
+Subproject f2aed2fe8e9f55508c86ba3aa4b6789b18a08a2
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject b5f7500fc40775096c2bbd204eae096612cf904
+Subproject b5f018fb5930cb733b0a8aaf2eed975d4771e74
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 28dc0f3576b55f5e57c5d6e65cd68ba3161e9fd
+Subproject 553d99b02a53b4133a40d5bd2e19958c67487c0
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 28dbeaf5c44bc7f5111ad412e99f2d7c5cec6c9
+Subproject f1e637883fafeb83bdd5906ee7f467e4d35b733
diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md
index 98b49e07171..a82a53248d4 100644
--- a/src/doc/rustc/src/exploit-mitigations.md
+++ b/src/doc/rustc/src/exploit-mitigations.md
@@ -115,9 +115,9 @@ equivalent.
   <tr>
    <td>Stack smashing protection
    </td>
-   <td>No
+   <td>Yes
    </td>
-   <td>
+   <td>Nightly
    </td>
   </tr>
   <tr>
@@ -432,18 +432,16 @@ saved return instruction pointer, and checking if this value has changed
 when returning from a function. This is also known as “Stack Protector” or
 “Stack Smashing Protector (SSP)”.
 
-The Rust compiler does not support stack smashing protection. However, more
-comprehensive alternatives to stack smashing protection exist, such as
-shadow and safe stack (see backward-edge control flow protection).
+The Rust compiler supports stack smashing protection on nightly builds[42].
 
 ![Screenshot of IDA Pro listing cross references to __stack_chk_fail in hello-rust.](images/image3.png "Cross references to __stack_chk_fail in hello-rust.")
 Fig. 14. IDA Pro listing cross references to `__stack_chk_fail` in
 hello-rust.
 
 To check if stack smashing protection is enabled for a given binary, search
-for cross references to `__stack_chk_fail`. The only cross references to
-`__stack_chk_fail` in hello-rust are from the statically-linked libbacktrace
-library (see Fig. 14).
+for cross references to `__stack_chk_fail`. The presence of these
+cross-references in Rust-compiled code (e.g., `hello_rust::main`) indicates
+that the stack smashing protection is enabled (see Fig. 14).
 
 
 ### Forward-edge control flow protection
@@ -697,3 +695,6 @@ defaults (unrelated to `READ_IMPLIES_EXEC`).
 
 41. “ControlFlowIntegrity.” The Rust Unstable Book.
     [https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity](../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity).
+
+42. bbjornse. “add codegen option for using LLVM stack smash protection #84197.”
+    GitHub. <https://github.com/rust-lang/rust/pull/84197>
diff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png
index a49e14b5ed2..ef02c605ead 100644
--- a/src/doc/rustc/src/images/image3.png
+++ b/src/doc/rustc/src/images/image3.png
Binary files differdiff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index d22e1cf7f68..3b2463aa5b2 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -88,6 +88,7 @@ target | notes
 `arm-unknown-linux-gnueabi` | ARMv6 Linux (kernel 3.2, glibc 2.17)
 `arm-unknown-linux-gnueabihf` | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17)
 `armv7-unknown-linux-gnueabihf` | ARMv7 Linux, hardfloat (kernel 3.2, glibc 2.17)
+[`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36)
 `mips-unknown-linux-gnu` | MIPS Linux (kernel 4.4, glibc 2.23)
 `mips64-unknown-linux-gnuabi64` | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23)
 `mips64el-unknown-linux-gnuabi64` | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23)
@@ -266,7 +267,6 @@ target | std | host | notes
 `i686-uwp-windows-gnu` | ? |  |
 `i686-uwp-windows-msvc` | ? |  |
 `i686-wrs-vxworks` | ? |  |
-[`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | ? |  | LoongArch64 Linux (LP64D ABI)
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
 [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? |  | MIPS64 for OpenWrt Linux MUSL
diff --git a/src/doc/rustc/src/platform-support/loongarch-linux.md b/src/doc/rustc/src/platform-support/loongarch-linux.md
index 16ccaf46b2f..999e71f8028 100644
--- a/src/doc/rustc/src/platform-support/loongarch-linux.md
+++ b/src/doc/rustc/src/platform-support/loongarch-linux.md
@@ -1,6 +1,6 @@
 # loongarch\*-unknown-linux-\*
 
-**Tier: 3**
+**Tier: 2**
 
 [LoongArch] is a new RISC ISA developed by Loongson Technology Corporation Limited.
 
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
index 089c03a0d64..9f65f1eeeb7 100644
--- a/src/etc/completions/x.py.fish
+++ b/src/etc/completions/x.py.fish
@@ -19,6 +19,7 @@ complete -c x.py -n "__fish_use_subcommand" -l rust-profile-generate -d 'generat
 complete -c x.py -n "__fish_use_subcommand" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_use_subcommand" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_use_subcommand" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_use_subcommand" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_use_subcommand" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_use_subcommand" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -36,7 +37,7 @@ complete -c x.py -n "__fish_use_subcommand" -f -a "doc" -d 'Build documentation'
 complete -c x.py -n "__fish_use_subcommand" -f -a "test" -d 'Build and run some test suites'
 complete -c x.py -n "__fish_use_subcommand" -f -a "bench" -d 'Build and run some benchmarks'
 complete -c x.py -n "__fish_use_subcommand" -f -a "clean" -d 'Clean out build directories'
-complete -c x.py -n "__fish_use_subcommand" -f -a "dist" -d 'Duild distribution artifacts'
+complete -c x.py -n "__fish_use_subcommand" -f -a "dist" -d 'Build distribution artifacts'
 complete -c x.py -n "__fish_use_subcommand" -f -a "install" -d 'Install distribution artifacts'
 complete -c x.py -n "__fish_use_subcommand" -f -a "run" -d 'Run tools contained in this repository'
 complete -c x.py -n "__fish_use_subcommand" -f -a "setup" -d 'Set up the environment for development'
@@ -62,6 +63,7 @@ complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-generate
 complete -c x.py -n "__fish_seen_subcommand_from build" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from build" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from build" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from build" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from build" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -91,6 +93,7 @@ complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-generate
 complete -c x.py -n "__fish_seen_subcommand_from check" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from check" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from check" -l all-targets -d 'Check all targets'
 complete -c x.py -n "__fish_seen_subcommand_from check" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from check" -s i -l incremental -d 'use incremental compilation'
@@ -125,6 +128,7 @@ complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-generat
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -l fix
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -s i -l incremental -d 'use incremental compilation'
@@ -155,6 +159,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-generate -
 complete -c x.py -n "__fish_seen_subcommand_from fix" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from fix" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from fix" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from fix" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -184,6 +189,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-generate -
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -l check -d 'check formatting instead of applying'
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -s i -l incremental -d 'use incremental compilation'
@@ -214,6 +220,7 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-generate -
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l open -d 'open the docs in a browser'
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l json -d 'render the documentation in JSON format in addition to the usual HTML format'
 complete -c x.py -n "__fish_seen_subcommand_from doc" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
@@ -251,6 +258,7 @@ complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-generate
 complete -c x.py -n "__fish_seen_subcommand_from test" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from test" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from test" -l no-fail-fast -d 'run all tests regardless of failure'
 complete -c x.py -n "__fish_seen_subcommand_from test" -l no-doc -d 'do not run doc tests'
 complete -c x.py -n "__fish_seen_subcommand_from test" -l doc -d 'only run doc tests'
@@ -288,6 +296,7 @@ complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-generate
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from bench" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from bench" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -317,6 +326,7 @@ complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-generate
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l all
 complete -c x.py -n "__fish_seen_subcommand_from clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from clean" -s i -l incremental -d 'use incremental compilation'
@@ -347,6 +357,7 @@ complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-generate
 complete -c x.py -n "__fish_seen_subcommand_from dist" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from dist" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from dist" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from dist" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -376,6 +387,7 @@ complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-genera
 complete -c x.py -n "__fish_seen_subcommand_from install" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from install" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from install" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from install" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from install" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -406,6 +418,7 @@ complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-generate -
 complete -c x.py -n "__fish_seen_subcommand_from run" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from run" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from run" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from run" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from run" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -435,6 +448,7 @@ complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-generate
 complete -c x.py -n "__fish_seen_subcommand_from setup" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from setup" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from setup" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from setup" -l include-default-paths -d 'include default paths in addition to the provided ones'
@@ -464,6 +478,7 @@ complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-genera
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -l rust-profile-use -d 'use PGO profile for rustc build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l set -d 'override options in config.toml' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -l run -d 'run suggested tests'
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -s i -l incremental -d 'use incremental compilation'
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
index fad2391e61f..569c186555c 100644
--- a/src/etc/completions/x.py.ps1
+++ b/src/etc/completions/x.py.ps1
@@ -43,6 +43,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -63,7 +64,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('test', 'test', [CompletionResultType]::ParameterValue, 'Build and run some test suites')
             [CompletionResult]::new('bench', 'bench', [CompletionResultType]::ParameterValue, 'Build and run some benchmarks')
             [CompletionResult]::new('clean', 'clean', [CompletionResultType]::ParameterValue, 'Clean out build directories')
-            [CompletionResult]::new('dist', 'dist', [CompletionResultType]::ParameterValue, 'Duild distribution artifacts')
+            [CompletionResult]::new('dist', 'dist', [CompletionResultType]::ParameterValue, 'Build distribution artifacts')
             [CompletionResult]::new('install', 'install', [CompletionResultType]::ParameterValue, 'Install distribution artifacts')
             [CompletionResult]::new('run', 'run', [CompletionResultType]::ParameterValue, 'Run tools contained in this repository')
             [CompletionResult]::new('setup', 'setup', [CompletionResultType]::ParameterValue, 'Set up the environment for development')
@@ -93,6 +94,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -129,6 +131,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('--all-targets', 'all-targets', [CompletionResultType]::ParameterName, 'Check all targets')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -170,6 +173,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('--fix', 'fix', [CompletionResultType]::ParameterName, 'fix')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -207,6 +211,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -243,6 +248,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'check formatting instead of applying')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -280,6 +286,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('--open', 'open', [CompletionResultType]::ParameterName, 'open the docs in a browser')
             [CompletionResult]::new('--json', 'json', [CompletionResultType]::ParameterName, 'render the documentation in JSON format in addition to the usual HTML format')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -324,6 +331,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('--no-fail-fast', 'no-fail-fast', [CompletionResultType]::ParameterName, 'run all tests regardless of failure')
             [CompletionResult]::new('--no-doc', 'no-doc', [CompletionResultType]::ParameterName, 'do not run doc tests')
             [CompletionResult]::new('--doc', 'doc', [CompletionResultType]::ParameterName, 'only run doc tests')
@@ -368,6 +376,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -404,6 +413,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'all')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
@@ -441,6 +451,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -477,6 +488,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -514,6 +526,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -550,6 +563,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
@@ -586,6 +600,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--rust-profile-use', 'rust-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for rustc build')
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
+            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
             [CompletionResult]::new('--run', 'run', [CompletionResultType]::ParameterName, 'run suggested tests')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
index 931cc4353b2..322afdb2883 100644
--- a/src/etc/completions/x.py.sh
+++ b/src/etc/completions/x.py.sh
@@ -61,7 +61,7 @@ _x.py() {
 
     case "${cmd}" in
         x.py)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -155,6 +155,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -163,7 +167,7 @@ _x.py() {
             return 0
             ;;
         x.py__bench)
-            opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -261,6 +265,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -269,7 +277,7 @@ _x.py() {
             return 0
             ;;
         x.py__build)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -363,6 +371,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -371,7 +383,7 @@ _x.py() {
             return 0
             ;;
         x.py__check)
-            opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -465,6 +477,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -473,7 +489,7 @@ _x.py() {
             return 0
             ;;
         x.py__clean)
-            opts="-v -i -j -h --all --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --all --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -567,6 +583,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -575,7 +595,7 @@ _x.py() {
             return 0
             ;;
         x.py__clippy)
-            opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -685,6 +705,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -693,7 +717,7 @@ _x.py() {
             return 0
             ;;
         x.py__dist)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -787,6 +811,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -795,7 +823,7 @@ _x.py() {
             return 0
             ;;
         x.py__doc)
-            opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -889,6 +917,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -897,7 +929,7 @@ _x.py() {
             return 0
             ;;
         x.py__fix)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -991,6 +1023,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -999,7 +1035,7 @@ _x.py() {
             return 0
             ;;
         x.py__fmt)
-            opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1093,6 +1129,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -1101,7 +1141,7 @@ _x.py() {
             return 0
             ;;
         x.py__install)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1195,6 +1235,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -1203,7 +1247,7 @@ _x.py() {
             return 0
             ;;
         x.py__run)
-            opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1301,6 +1345,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -1309,7 +1357,7 @@ _x.py() {
             return 0
             ;;
         x.py__setup)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1403,6 +1451,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -1411,7 +1463,7 @@ _x.py() {
             return 0
             ;;
         x.py__suggest)
-            opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1505,6 +1557,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
@@ -1513,7 +1569,7 @@ _x.py() {
             return 0
             ;;
         x.py__test)
-            opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1631,6 +1687,10 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
+                --set)
+                    COMPREPLY=("${cur}")
+                    return 0
+                    ;;
                 *)
                     COMPREPLY=()
                     ;;
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 4b0aee9c3ad..09e7ed293d4 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -551,7 +551,15 @@ impl<'a, I: Iterator<Item = Event<'a>>> SummaryLine<'a, I> {
 }
 
 fn check_if_allowed_tag(t: &Tag<'_>) -> bool {
-    matches!(t, Tag::Paragraph | Tag::Emphasis | Tag::Strong | Tag::Link(..) | Tag::BlockQuote)
+    matches!(
+        t,
+        Tag::Paragraph
+            | Tag::Emphasis
+            | Tag::Strong
+            | Tag::Strikethrough
+            | Tag::Link(..)
+            | Tag::BlockQuote
+    )
 }
 
 fn is_forbidden_tag(t: &Tag<'_>) -> bool {
@@ -773,7 +781,7 @@ impl<'tcx> ExtraInfo<'tcx> {
         ExtraInfo { def_id, sp, tcx }
     }
 
-    fn error_invalid_codeblock_attr(&self, msg: &str, help: &str) {
+    fn error_invalid_codeblock_attr(&self, msg: String, help: &str) {
         if let Some(def_id) = self.def_id.as_local() {
             self.tcx.struct_span_lint_hir(
                 crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
@@ -948,7 +956,7 @@ impl LangString {
                     } {
                         if let Some(extra) = extra {
                             extra.error_invalid_codeblock_attr(
-                                &format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
+                                format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
                                 help,
                             );
                         }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index d6773169639..0a2f5f6653c 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1751,7 +1751,7 @@ fn render_impl(
             if trait_.is_none() && i.inner_impl().items.is_empty() {
                 w.write_str(
                     "<div class=\"item-info\">\
-                    <div class=\"stab empty-impl\">This impl block contains no items.</div>
+                    <div class=\"stab empty-impl\">This impl block contains no items.</div>\
                 </div>",
                 );
             }
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index 99cf8e443f0..c1324c0760e 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -1,6 +1,5 @@
 .setting-line {
 	margin: 1.2em 0.6em;
-	position: relative;
 }
 
 .setting-radio input, .setting-check input {
@@ -15,11 +14,6 @@
 .setting-radio input {
 	border-radius: 50%;
 }
-.setting-check input:checked {
-	content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
-		<path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
-		<path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
-}
 
 .setting-radio span, .setting-check span {
 	padding-bottom: 1px;
@@ -52,6 +46,9 @@
 .setting-check input:checked {
 	background-color: var(--settings-input-color);
 	border-width: 1px;
+	content: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">\
+		<path d="M7,25L17,32L33,12" fill="none" stroke="black" stroke-width="5"/>\
+		<path d="M7,23L17,30L33,10" fill="none" stroke="white" stroke-width="5"/></svg>');
 }
 .setting-radio input:focus, .setting-check input:focus {
 	box-shadow: 0 0 1px 1px var(--settings-input-color);
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 5460bce21a5..0a56916edcd 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -192,11 +192,11 @@ fn init_logging() {
         Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(),
         Ok(value) => early_error(
             ErrorOutputType::default(),
-            &format!("invalid log color value '{}': expected one of always, never, or auto", value),
+            format!("invalid log color value '{}': expected one of always, never, or auto", value),
         ),
         Err(VarError::NotUnicode(value)) => early_error(
             ErrorOutputType::default(),
-            &format!(
+            format!(
                 "invalid log color value '{}': expected one of always, never, or auto",
                 value.to_string_lossy()
             ),
@@ -228,7 +228,7 @@ fn get_args() -> Option<Vec<String>> {
                 .map_err(|arg| {
                     early_warn(
                         ErrorOutputType::default(),
-                        &format!("Argument {} is not valid Unicode: {:?}", i, arg),
+                        format!("Argument {} is not valid Unicode: {:?}", i, arg),
                     );
                 })
                 .ok()
@@ -721,7 +721,7 @@ fn main_args(at_args: &[String]) -> MainResult {
     let matches = match options.parse(&args[1..]) {
         Ok(m) => m,
         Err(err) => {
-            early_error(ErrorOutputType::default(), &err.to_string());
+            early_error(ErrorOutputType::default(), err.to_string());
         }
     };
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index a885ff0ca5e..9e6894a77df 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::{
     fx::{FxHashMap, FxHashSet},
     intern::Interned,
 };
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticMessage};
 use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
@@ -24,6 +24,7 @@ use rustc_span::BytePos;
 use smallvec::{smallvec, SmallVec};
 
 use std::borrow::Cow;
+use std::fmt::Display;
 use std::mem;
 use std::ops::Range;
 
@@ -148,7 +149,7 @@ impl TryFrom<ResolveRes> for Res {
             Def(kind, id) => Ok(Res::Def(kind, id)),
             PrimTy(prim) => Ok(Res::Primitive(PrimitiveType::from_hir(prim))),
             // e.g. `#[derive]`
-            NonMacroAttr(..) | Err => Result::Err(()),
+            ToolMod | NonMacroAttr(..) | Err => Result::Err(()),
             other => bug!("unrecognized res {:?}", other),
         }
     }
@@ -841,7 +842,7 @@ impl PreprocessingError {
         match self {
             PreprocessingError::MultipleAnchors => report_multiple_anchors(cx, diag_info),
             PreprocessingError::Disambiguator(range, msg) => {
-                disambiguator_error(cx, diag_info, range.clone(), msg)
+                disambiguator_error(cx, diag_info, range.clone(), msg.as_str())
             }
             PreprocessingError::MalformedGenerics(err, path_str) => {
                 report_malformed_generics(cx, diag_info, *err, path_str)
@@ -1185,7 +1186,7 @@ impl LinkCollector<'_, '_> {
             }
             suggest_disambiguator(resolved, diag, path_str, &ori_link.link, sp);
         };
-        report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, callback);
+        report_diagnostic(self.cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, callback);
     }
 
     fn report_rawptr_assoc_feature_gate(&self, dox: &str, ori_link: &Range<usize>, item: &Item) {
@@ -1581,7 +1582,7 @@ impl Suggestion {
 fn report_diagnostic(
     tcx: TyCtxt<'_>,
     lint: &'static Lint,
-    msg: &str,
+    msg: impl Into<DiagnosticMessage> + Display,
     DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>,
     decorate: impl FnOnce(&mut Diagnostic, Option<rustc_span::Span>),
 ) {
@@ -1649,7 +1650,7 @@ fn resolution_failure(
     report_diagnostic(
         tcx,
         BROKEN_INTRA_DOC_LINKS,
-        &format!("unresolved link to `{}`", path_str),
+        format!("unresolved link to `{}`", path_str),
         &diag_info,
         |diag, sp| {
             let item = |res: Res| format!("the {} `{}`", res.descr(), res.name(tcx),);
@@ -1865,20 +1866,20 @@ fn resolution_failure(
 
 fn report_multiple_anchors(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
     let msg = format!("`{}` contains multiple anchors", diag_info.ori_link);
-    anchor_failure(cx, diag_info, &msg, 1)
+    anchor_failure(cx, diag_info, msg, 1)
 }
 
 fn report_anchor_conflict(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, def_id: DefId) {
     let (link, kind) = (diag_info.ori_link, Res::from_def_id(cx.tcx, def_id).descr());
     let msg = format!("`{link}` contains an anchor, but links to {kind}s are already anchored");
-    anchor_failure(cx, diag_info, &msg, 0)
+    anchor_failure(cx, diag_info, msg, 0)
 }
 
 /// Report an anchor failure.
 fn anchor_failure(
     cx: &DocContext<'_>,
     diag_info: DiagnosticInfo<'_>,
-    msg: &str,
+    msg: String,
     anchor_idx: usize,
 ) {
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, sp| {
@@ -1898,7 +1899,7 @@ fn disambiguator_error(
     cx: &DocContext<'_>,
     mut diag_info: DiagnosticInfo<'_>,
     disambiguator_range: Range<usize>,
-    msg: &str,
+    msg: impl Into<DiagnosticMessage> + Display,
 ) {
     diag_info.link_range = disambiguator_range;
     report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| {
@@ -1919,7 +1920,7 @@ fn report_malformed_generics(
     report_diagnostic(
         cx.tcx,
         BROKEN_INTRA_DOC_LINKS,
-        &format!("unresolved link to `{}`", path_str),
+        format!("unresolved link to `{}`", path_str),
         &diag_info,
         |diag, sp| {
             let note = match err {
@@ -1994,7 +1995,7 @@ fn ambiguity_error(
         }
     }
 
-    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, diag_info, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "ambiguous link");
         } else {
@@ -2046,7 +2047,7 @@ fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str:
     let msg =
         format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
 
-    report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, &msg, diag_info, |diag, sp| {
+    report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, msg, diag_info, |diag, sp| {
         if let Some(sp) = sp {
             diag.span_label(sp, "this item is private");
         }
diff --git a/src/llvm-project b/src/llvm-project
-Subproject ea6fa9c2d43aaf0f11559719eda9b54d356d541
+Subproject 533d3f338b804d54e5d0ac4fba6276af23002d9
diff --git a/src/rustdoc-json-types/Cargo.toml b/src/rustdoc-json-types/Cargo.toml
index d63caa7ad70..d3548036d4c 100644
--- a/src/rustdoc-json-types/Cargo.toml
+++ b/src/rustdoc-json-types/Cargo.toml
@@ -12,3 +12,4 @@ rustc-hash = "1.1.0"
 
 [dev-dependencies]
 serde_json = "1.0"
+bincode = "1"
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index 3556834071f..ba8eeaa6682 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
 use std::path::PathBuf;
 
 /// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 25;
+pub const FORMAT_VERSION: u32 = 26;
 
 /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
 /// about the language items in the local crate, as well as info about external items to allow
@@ -83,7 +83,6 @@ pub struct Item {
     /// Stringified versions of the attributes on this item (e.g. `"#[inline]"`)
     pub attrs: Vec<String>,
     pub deprecation: Option<Deprecation>,
-    #[serde(flatten)]
     pub inner: ItemEnum,
 }
 
@@ -222,7 +221,7 @@ pub enum ItemKind {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-#[serde(tag = "kind", content = "inner", rename_all = "snake_case")]
+#[serde(rename_all = "snake_case")]
 pub enum ItemEnum {
     Module(Module),
     ExternCrate {
@@ -543,7 +542,6 @@ pub enum Term {
 
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
-#[serde(tag = "kind", content = "inner")]
 pub enum Type {
     /// Structs, enums, and unions
     ResolvedPath(Path),
diff --git a/src/rustdoc-json-types/tests.rs b/src/rustdoc-json-types/tests.rs
index 399ff54b294..1126d5f786f 100644
--- a/src/rustdoc-json-types/tests.rs
+++ b/src/rustdoc-json-types/tests.rs
@@ -8,11 +8,15 @@ fn test_struct_info_roundtrip() {
         impls: vec![],
     });
 
+    // JSON
     let struct_json = serde_json::to_string(&s).unwrap();
-
     let de_s = serde_json::from_str(&struct_json).unwrap();
-
     assert_eq!(s, de_s);
+
+    // Bincode
+    let encoded: Vec<u8> = bincode::serialize(&s).unwrap();
+    let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
+    assert_eq!(s, decoded);
 }
 
 #[test]
@@ -24,9 +28,13 @@ fn test_union_info_roundtrip() {
         impls: vec![],
     });
 
+    // JSON
     let union_json = serde_json::to_string(&u).unwrap();
-
     let de_u = serde_json::from_str(&union_json).unwrap();
-
     assert_eq!(u, de_u);
+
+    // Bincode
+    let encoded: Vec<u8> = bincode::serialize(&u).unwrap();
+    let decoded: ItemEnum = bincode::deserialize(&encoded).unwrap();
+    assert_eq!(u, decoded);
 }
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 21dad9eb74a..8b28c68e04f 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -24,6 +24,7 @@ static HOSTS: &[&str] = &[
     "i686-pc-windows-gnu",
     "i686-pc-windows-msvc",
     "i686-unknown-linux-gnu",
+    "loongarch64-unknown-linux-gnu",
     "mips-unknown-linux-gnu",
     "mips64-unknown-linux-gnuabi64",
     "mips64el-unknown-linux-gnuabi64",
@@ -97,6 +98,7 @@ static TARGETS: &[&str] = &[
     "i686-unknown-linux-gnu",
     "i686-unknown-linux-musl",
     "i686-unknown-uefi",
+    "loongarch64-unknown-linux-gnu",
     "m68k-unknown-linux-gnu",
     "mips-unknown-linux-gnu",
     "mips-unknown-linux-musl",
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 09276c703a473ab33daaeb94917232e80eefd62
+Subproject 64fb38c97ac4d3a327fc9032c862dd28c8833b1
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index b9921301197..a9d42159c4b 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -39,7 +39,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 93198aabdb5..30a156c925b 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -27,7 +27,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
       with:
         ref: ${{ github.ref }}
 
@@ -83,7 +83,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -149,7 +149,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -173,7 +173,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -233,7 +233,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Install toolchain
       run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml
index 14f20212add..514706d64c8 100644
--- a/src/tools/clippy/.github/workflows/clippy_dev.yml
+++ b/src/tools/clippy/.github/workflows/clippy_dev.yml
@@ -25,7 +25,7 @@ jobs:
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     # Run
     - name: Build
diff --git a/src/tools/clippy/.github/workflows/deploy.yml b/src/tools/clippy/.github/workflows/deploy.yml
index 71d71d10359..f42928c2cd1 100644
--- a/src/tools/clippy/.github/workflows/deploy.yml
+++ b/src/tools/clippy/.github/workflows/deploy.yml
@@ -21,10 +21,10 @@ jobs:
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
       with:
         ref: ${{ env.TARGET_BRANCH }}
         path: 'out'
diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml
index 0bc2f49f5e9..7d25b6a2b79 100644
--- a/src/tools/clippy/.github/workflows/remark.yml
+++ b/src/tools/clippy/.github/workflows/remark.yml
@@ -16,10 +16,10 @@ jobs:
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3.0.2
+      uses: actions/checkout@v3
 
     - name: Setup Node.js
-      uses: actions/setup-node@v1.4.4
+      uses: actions/setup-node@v3
       with:
         node-version: '14.x'
 
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index ebf5b58a586..79f2a47110b 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -4620,6 +4620,7 @@ Released 2018-09-13
 [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
 [`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
 [`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
+[`empty_line_after_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments
 [`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr
 [`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop
 [`empty_structs_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_structs_with_brackets
@@ -4785,6 +4786,7 @@ Released 2018-09-13
 [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str
 [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map
 [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
+[`manual_next_back`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_next_back
 [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive
 [`manual_ok_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_ok_or
 [`manual_range_contains`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_range_contains
@@ -4897,6 +4899,7 @@ Released 2018-09-13
 [`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding
 [`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
 [`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
+[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
 [`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
 [`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
 [`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
@@ -4978,6 +4981,7 @@ Released 2018-09-13
 [`ref_binding_to_reference`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_binding_to_reference
 [`ref_in_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_in_deref
 [`ref_option_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_option_ref
+[`ref_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#ref_patterns
 [`regex_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#regex_macro
 [`repeat_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#repeat_once
 [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index 6745e15c006..d712d3e6750 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -278,7 +278,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT
 
 <!-- REUSE-IgnoreStart -->
 
-Copyright 2014-2022 The Rust Project Developers
+Copyright 2014-2023 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license
diff --git a/src/tools/clippy/book/src/development/type_checking.md b/src/tools/clippy/book/src/development/type_checking.md
index 225de849566..d7c2775b896 100644
--- a/src/tools/clippy/book/src/development/type_checking.md
+++ b/src/tools/clippy/book/src/development/type_checking.md
@@ -133,7 +133,7 @@ in this chapter:
 - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
 - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
 
-[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt
+[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Adt
 [AdtDef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html
 [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty
 [node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type
@@ -142,9 +142,9 @@ in this chapter:
 [kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind
 [LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html
 [LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
-[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty
+[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/typeck_results/struct.TypeckResults.html#method.pat_ty
 [Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
-[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
+[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html
 [TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html
 [middle_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.Ty.html
 [hir_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/struct.Ty.html
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 37e1e6a742f..98e69c7fd26 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -17,7 +17,7 @@ if_chain = "1.0"
 itertools = "0.10.1"
 pulldown-cmark = { version = "0.9", default-features = false }
 quine-mc_cluskey = "0.2"
-regex-syntax = "0.6"
+regex-syntax = "0.7"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = { version = "1.0", optional = true }
 tempfile = { version = "3.2", optional = true }
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index a36df55d0bd..a8dc0cb3b58 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -38,7 +38,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
             _ => return,
         };
         let Some((condition, panic_expn)) = find_assert_args(cx, e, macro_call.expn) else { return };
-        let Some((Constant::Bool(val), _)) = constant(cx, cx.typeck_results(), condition) else { return };
+        let Some(Constant::Bool(val)) = constant(cx, cx.typeck_results(), condition) else { return };
         if val {
             span_lint_and_help(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 751c262673b..897495ba108 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -178,6 +178,52 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for empty lines after documenation comments.
+    ///
+    /// ### Why is this bad?
+    /// The documentation comment was most likely meant to be an inner attribute or regular comment.
+    /// If it was intended to be a documentation comment, then the empty line should be removed to
+    /// be more idiomatic.
+    ///
+    /// ### Known problems
+    /// Only detects empty lines immediately following the documentation. If the doc comment is followed
+    /// by an attribute and then an empty line, this lint will not trigger. Use `empty_line_after_outer_attr`
+    /// in combination with this lint to detect both cases.
+    ///
+    /// Does not detect empty lines after doc attributes (e.g. `#[doc = ""]`).
+    ///
+    /// ### Example
+    /// ```rust
+    /// /// Some doc comment with a blank line after it.
+    ///
+    /// fn not_quite_good_code() { }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// /// Good (no blank line)
+    /// fn this_is_fine() { }
+    /// ```
+    ///
+    /// ```rust
+    /// // Good (convert to a regular comment)
+    ///
+    /// fn this_is_fine_too() { }
+    /// ```
+    ///
+    /// ```rust
+    /// //! Good (convert to a comment on an inner attribute)
+    ///
+    /// fn this_is_fine_as_well() { }
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub EMPTY_LINE_AFTER_DOC_COMMENTS,
+    nursery,
+    "empty line after documentation comments"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category.
     ///
     /// ### Why is this bad?
@@ -292,6 +338,30 @@ declare_clippy_lint! {
     "ensures that all `allow` and `expect` attributes have a reason"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `any` and `all` combinators in `cfg` with only one condition.
+    ///
+    /// ### Why is this bad?
+    /// If there is only one condition, no need to wrap it into `any` or `all` combinators.
+    ///
+    /// ### Example
+    /// ```rust
+    /// #[cfg(any(unix))]
+    /// pub struct Bar;
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// #[cfg(unix)]
+    /// pub struct Bar;
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub NON_MINIMAL_CFG,
+    style,
+    "ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
+}
+
 declare_lint_pass!(Attributes => [
     ALLOW_ATTRIBUTES_WITHOUT_REASON,
     INLINE_ALWAYS,
@@ -604,6 +674,8 @@ impl_lint_pass!(EarlyAttributes => [
     DEPRECATED_CFG_ATTR,
     MISMATCHED_TARGET_OS,
     EMPTY_LINE_AFTER_OUTER_ATTR,
+    EMPTY_LINE_AFTER_DOC_COMMENTS,
+    NON_MINIMAL_CFG,
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
@@ -614,15 +686,22 @@ impl EarlyLintPass for EarlyAttributes {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
         check_deprecated_cfg_attr(cx, attr, &self.msrv);
         check_mismatched_target_os(cx, attr);
+        check_minimal_cfg_condition(cx, attr);
     }
 
     extract_msrv_attr!(EarlyContext);
 }
 
+/// Check for empty lines after outer attributes.
+///
+/// Attributes and documenation comments are both considered outer attributes
+/// by the AST. However, the average user likely considers them to be different.
+/// Checking for empty lines after each of these attributes is split into two different
+/// lints but can share the same logic.
 fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
     let mut iter = item.attrs.iter().peekable();
     while let Some(attr) = iter.next() {
-        if matches!(attr.kind, AttrKind::Normal(..))
+        if (matches!(attr.kind, AttrKind::Normal(..)) || matches!(attr.kind, AttrKind::DocComment(..)))
             && attr.style == AttrStyle::Outer
             && is_present_in_source(cx, attr.span)
         {
@@ -639,13 +718,20 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
                 let lines = without_block_comments(lines);
 
                 if lines.iter().filter(|l| l.trim().is_empty()).count() > 2 {
-                    span_lint(
-                        cx,
-                        EMPTY_LINE_AFTER_OUTER_ATTR,
-                        begin_of_attr_to_item,
-                        "found an empty line after an outer attribute. \
-                        Perhaps you forgot to add a `!` to make it an inner attribute?",
-                    );
+                    let (lint_msg, lint_type) = match attr.kind {
+                        AttrKind::DocComment(..) => (
+                            "found an empty line after a doc comment. \
+                            Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?",
+                            EMPTY_LINE_AFTER_DOC_COMMENTS,
+                        ),
+                        AttrKind::Normal(..) => (
+                            "found an empty line after an outer attribute. \
+                            Perhaps you forgot to add a `!` to make it an inner attribute?",
+                            EMPTY_LINE_AFTER_OUTER_ATTR,
+                        ),
+                    };
+
+                    span_lint(cx, lint_type, begin_of_attr_to_item, lint_msg);
                 }
             }
         }
@@ -690,6 +776,48 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr
     }
 }
 
+fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
+    for item in items.iter() {
+        if let NestedMetaItem::MetaItem(meta) = item {
+            if !meta.has_name(sym::any) && !meta.has_name(sym::all) {
+                continue;
+            }
+            if let MetaItemKind::List(list) = &meta.kind {
+                check_nested_cfg(cx, list);
+                if list.len() == 1 {
+                    span_lint_and_then(
+                        cx,
+                        NON_MINIMAL_CFG,
+                        meta.span,
+                        "unneeded sub `cfg` when there is only one condition",
+                        |diag| {
+                            if let Some(snippet) = snippet_opt(cx, list[0].span()) {
+                                diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
+                            }
+                        },
+                    );
+                } else if list.is_empty() && meta.has_name(sym::all) {
+                    span_lint_and_then(
+                        cx,
+                        NON_MINIMAL_CFG,
+                        meta.span,
+                        "unneeded sub `cfg` when there is no condition",
+                        |_| {},
+                    );
+                }
+            }
+        }
+    }
+}
+
+fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
+    if attr.has_name(sym::cfg) &&
+        let Some(items) = attr.meta_item_list()
+    {
+        check_nested_cfg(cx, &items);
+    }
+}
+
 fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
     fn find_os(name: &str) -> Option<&'static str> {
         UNIX_SYSTEMS
diff --git a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
index c4520d00392..814108ed8a7 100644
--- a/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/borrow_deref_ref.rs
@@ -1,5 +1,6 @@
 use crate::reference::DEREF_ADDROF;
 use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::is_from_proc_macro;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::implements_trait;
 use clippy_utils::{get_parent_expr, is_lint_allowed};
@@ -47,8 +48,8 @@ declare_clippy_lint! {
 
 declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
 
-impl LateLintPass<'_> for BorrowDerefRef {
-    fn check_expr(&mut self, cx: &LateContext<'_>, e: &rustc_hir::Expr<'_>) {
+impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) {
         if_chain! {
             if !e.span.from_expansion();
             if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind;
@@ -58,6 +59,7 @@ impl LateLintPass<'_> for BorrowDerefRef {
             if !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..) );
             let ref_ty = cx.typeck_results().expr_ty(deref_target);
             if let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind();
+            if !is_from_proc_macro(cx, e);
             then{
 
                 if let Some(parent_expr) = get_parent_expr(cx, e){
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index dfa949d1af2..e42c3fe2432 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -8,7 +8,9 @@ use rustc_hir::{
     Block, Expr, ExprKind, Local, Node, QPath, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths};
+use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty::print::with_forced_trimmed_paths;
+use rustc_middle::ty::IsSuggestable;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::sym;
 
@@ -49,7 +51,6 @@ impl LateLintPass<'_> for BoxDefault {
             && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
             && is_default_equivalent(cx, arg)
         {
-            let arg_ty = cx.typeck_results().expr_ty(arg);
             span_lint_and_sugg(
                 cx,
                 BOX_DEFAULT,
@@ -58,8 +59,10 @@ impl LateLintPass<'_> for BoxDefault {
                 "try",
                 if is_plain_default(arg_path) || given_type(cx, expr) {
                     "Box::default()".into()
-                } else {
+                } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) {
                     with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
+                } else {
+                    return
                 },
                 Applicability::MachineApplicable
             );
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
index 322dc41b3a1..da756129db3 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
@@ -21,8 +21,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
 
 fn is_known_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
     match constant(cx, cx.typeck_results(), e) {
-        Some((Constant::F64(n), _)) => n.is_nan(),
-        Some((Constant::F32(n), _)) => n.is_nan(),
+        Some(Constant::F64(n)) => n.is_nan(),
+        Some(Constant::F32(n)) => n.is_nan(),
         _ => false,
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index 95c2ecbf791..84b99ad5c24 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -15,7 +15,7 @@ use rustc_target::abi::IntegerType;
 use super::{utils, CAST_ENUM_TRUNCATION, CAST_POSSIBLE_TRUNCATION};
 
 fn constant_int(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
-    if let Some((Constant::Int(c), _)) = constant(cx, cx.typeck_results(), expr) {
+    if let Some(Constant::Int(c)) = constant(cx, cx.typeck_results(), expr) {
         Some(c)
     } else {
         None
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index a20a97d4e56..a83dfd94dc2 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -29,7 +29,7 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
             // Don't lint for positive constants.
             let const_val = constant(cx, cx.typeck_results(), cast_op);
             if_chain! {
-                if let Some((Constant::Int(n), _)) = const_val;
+                if let Some(Constant::Int(n)) = const_val;
                 if let ty::Int(ity) = *cast_from.kind();
                 if sext(cx.tcx, n, ity) >= 0;
                 then {
diff --git a/src/tools/clippy/clippy_lints/src/dbg_macro.rs b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
index 799e71e847a..ea17e7a6071 100644
--- a/src/tools/clippy/clippy_lints/src/dbg_macro.rs
+++ b/src/tools/clippy/clippy_lints/src/dbg_macro.rs
@@ -3,10 +3,10 @@ use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_in_cfg_test, is_in_test_function};
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_hir::{Expr, ExprKind, Node};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::sym;
+use rustc_span::{sym, BytePos, Pos, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -31,6 +31,31 @@ declare_clippy_lint! {
     "`dbg!` macro is intended as a debugging tool"
 }
 
+/// Gets the span of the statement up to the next semicolon, if and only if the next
+/// non-whitespace character actually is a semicolon.
+/// E.g.
+/// ```rust,ignore
+/// 
+///    dbg!();
+///    ^^^^^^^  this span is returned
+///
+///   foo!(dbg!());
+///             no span is returned
+/// ```
+fn span_including_semi(cx: &LateContext<'_>, span: Span) -> Option<Span> {
+    let sm = cx.sess().source_map();
+    let sf = sm.lookup_source_file(span.hi());
+    let src = sf.src.as_ref()?.get(span.hi().to_usize()..)?;
+    let first_non_whitespace = src.find(|c: char| !c.is_whitespace())?;
+
+    if src.as_bytes()[first_non_whitespace] == b';' {
+        let hi = span.hi() + BytePos::from_usize(first_non_whitespace + 1);
+        Some(span.with_hi(hi))
+    } else {
+        None
+    }
+}
+
 #[derive(Copy, Clone)]
 pub struct DbgMacro {
     allow_dbg_in_tests: bool,
@@ -55,13 +80,25 @@ impl LateLintPass<'_> for DbgMacro {
                 return;
             }
             let mut applicability = Applicability::MachineApplicable;
-            let suggestion = match expr.peel_drop_temps().kind {
+
+            let (sugg_span, suggestion) = match expr.peel_drop_temps().kind {
                 // dbg!()
-                ExprKind::Block(_, _) => String::new(),
-                // dbg!(1)
-                ExprKind::Match(val, ..) => {
-                    snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string()
+                ExprKind::Block(..) => {
+                    // If the `dbg!` macro is a "free" statement and not contained within other expressions,
+                    // remove the whole statement.
+                    if let Some(Node::Stmt(stmt)) = cx.tcx.hir().find_parent(expr.hir_id)
+                        && let Some(span) = span_including_semi(cx, stmt.span.source_callsite())
+                    {
+                        (span, String::new())
+                    } else {
+                        (macro_call.span, String::from("()"))
+                    }
                 },
+                // dbg!(1)
+                ExprKind::Match(val, ..) => (
+                    macro_call.span,
+                    snippet_with_applicability(cx, val.span.source_callsite(), "..", &mut applicability).to_string(),
+                ),
                 // dbg!(2, 3)
                 ExprKind::Tup(
                     [
@@ -82,7 +119,7 @@ impl LateLintPass<'_> for DbgMacro {
                         "..",
                         &mut applicability,
                     );
-                    format!("({snippet})")
+                    (macro_call.span, format!("({snippet})"))
                 },
                 _ => return,
             };
@@ -90,7 +127,7 @@ impl LateLintPass<'_> for DbgMacro {
             span_lint_and_sugg(
                 cx,
                 DBG_MACRO,
-                macro_call.span,
+                sugg_span,
                 "the `dbg!` macro is intended as a debugging tool",
                 "remove the invocation before committing it to a version control system",
                 suggestion,
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 04993e49287..423eee47742 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -48,9 +48,11 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO,
     crate::attrs::DEPRECATED_CFG_ATTR_INFO,
     crate::attrs::DEPRECATED_SEMVER_INFO,
+    crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
     crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
     crate::attrs::INLINE_ALWAYS_INFO,
     crate::attrs::MISMATCHED_TARGET_OS_INFO,
+    crate::attrs::NON_MINIMAL_CFG_INFO,
     crate::attrs::USELESS_ATTRIBUTE_INFO,
     crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
     crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,
@@ -347,6 +349,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::ITER_WITH_DRAIN_INFO,
     crate::methods::MANUAL_FILTER_MAP_INFO,
     crate::methods::MANUAL_FIND_MAP_INFO,
+    crate::methods::MANUAL_NEXT_BACK_INFO,
     crate::methods::MANUAL_OK_OR_INFO,
     crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO,
     crate::methods::MANUAL_SPLIT_ONCE_INFO,
@@ -485,7 +488,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::operators::FLOAT_EQUALITY_WITHOUT_ABS_INFO,
     crate::operators::IDENTITY_OP_INFO,
     crate::operators::INEFFECTIVE_BIT_MASK_INFO,
-    crate::operators::INTEGER_ARITHMETIC_INFO,
     crate::operators::INTEGER_DIVISION_INFO,
     crate::operators::MISREFACTORED_ASSIGN_OP_INFO,
     crate::operators::MODULO_ARITHMETIC_INFO,
@@ -535,6 +537,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::redundant_slicing::REDUNDANT_SLICING_INFO,
     crate::redundant_static_lifetimes::REDUNDANT_STATIC_LIFETIMES_INFO,
     crate::ref_option_ref::REF_OPTION_REF_INFO,
+    crate::ref_patterns::REF_PATTERNS_INFO,
     crate::reference::DEREF_ADDROF_INFO,
     crate::regex::INVALID_REGEX_INFO,
     crate::regex::TRIVIAL_REGEX_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
index e529d81a7e9..9bd7a0dc0f3 100644
--- a/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/clippy_lints/src/default_constructed_unit_structs.rs
@@ -1,4 +1,4 @@
-use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro, match_def_path, paths};
+use clippy_utils::{diagnostics::span_lint_and_sugg, match_def_path, paths};
 use hir::{def::Res, ExprKind};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
@@ -55,7 +55,8 @@ impl LateLintPass<'_> for DefaultConstructedUnitStructs {
             if let ty::Adt(def, ..) = cx.typeck_results().expr_ty(expr).kind();
             if def.is_struct();
             if let var @ ty::VariantDef { ctor: Some((hir::def::CtorKind::Const, _)), .. } = def.non_enum_variant();
-            if !var.is_field_list_non_exhaustive() && !is_from_proc_macro(cx, expr);
+            if !var.is_field_list_non_exhaustive();
+            if !expr.span.from_expansion() && !qpath.span().from_expansion();
             then {
                 span_lint_and_sugg(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index b2f7d026cc8..9c60edb1794 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -98,7 +98,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
             let is_copy = is_copy(cx, arg_ty);
             let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
             let (lint, msg) = match fn_name {
-                // early return for uplifted lints: drop_ref, drop_copy, forget_ref, forget_copy
+                // early return for uplifted lints: dropping_references, dropping_copy_types, forgetting_references, forgetting_copy_types
                 sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => return,
                 sym::mem_forget if arg_ty.is_ref() => return,
                 sym::mem_drop if is_copy && !drop_is_single_call_in_arm => return,
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index a1a2c398a8a..3c55a563af4 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -114,7 +114,7 @@ declare_lint_pass!(FloatingPointArithmetic => [
 // Returns the specialized log method for a given base if base is constant
 // and is one of 2, 10 and e
 fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>) -> Option<&'static str> {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), base) {
+    if let Some(value) = constant(cx, cx.typeck_results(), base) {
         if F32(2.0) == value || F64(2.0) == value {
             return Some("log2");
         } else if F32(10.0) == value || F64(10.0) == value {
@@ -193,8 +193,8 @@ fn check_ln1p(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
             constant(cx, cx.typeck_results(), lhs),
             constant(cx, cx.typeck_results(), rhs),
         ) {
-            (Some((value, _)), _) if F32(1.0) == value || F64(1.0) == value => rhs,
-            (_, Some((value, _))) if F32(1.0) == value || F64(1.0) == value => lhs,
+            (Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs,
+            (_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs,
             _ => return,
         };
 
@@ -237,7 +237,7 @@ fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
 
 fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
     // Check receiver
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), receiver) {
+    if let Some(value) = constant(cx, cx.typeck_results(), receiver) {
         if let Some(method) = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
             Some("exp")
         } else if F32(2.0) == value || F64(2.0) == value {
@@ -258,7 +258,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
     }
 
     // Check argument
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+    if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
         let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
             (
                 SUBOPTIMAL_FLOPS,
@@ -298,7 +298,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
 }
 
 fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), &args[0]) {
+    if let Some(value) = constant(cx, cx.typeck_results(), &args[0]) {
         if value == Int(2) {
             if let Some(parent) = get_parent_expr(cx, expr) {
                 if let Some(grandparent) = get_parent_expr(cx, parent) {
@@ -384,8 +384,8 @@ fn detect_hypot(cx: &LateContext<'_>, receiver: &Expr<'_>) -> Option<String> {
                 _
             ) = &add_rhs.kind;
             if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
-            if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), largs_1);
-            if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), rargs_1);
+            if let Some(lvalue) = constant(cx, cx.typeck_results(), largs_1);
+            if let Some(rvalue) = constant(cx, cx.typeck_results(), rargs_1);
             if Int(2) == lvalue && Int(2) == rvalue;
             then {
                 return Some(format!("{}.hypot({})", Sugg::hir(cx, largs_0, "..").maybe_par(), Sugg::hir(cx, rargs_0, "..")));
@@ -416,7 +416,7 @@ fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if_chain! {
         if let ExprKind::Binary(Spanned { node: BinOpKind::Sub, .. }, lhs, rhs) = expr.kind;
         if cx.typeck_results().expr_ty(lhs).is_floating_point();
-        if let Some((value, _)) = constant(cx, cx.typeck_results(), rhs);
+        if let Some(value) = constant(cx, cx.typeck_results(), rhs);
         if F32(1.0) == value || F64(1.0) == value;
         if let ExprKind::MethodCall(path, self_arg, ..) = &lhs.kind;
         if cx.typeck_results().expr_ty(self_arg).is_floating_point();
@@ -669,8 +669,8 @@ fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
             mul_lhs,
             mul_rhs,
         ) = &div_lhs.kind;
-        if let Some((rvalue, _)) = constant(cx, cx.typeck_results(), div_rhs);
-        if let Some((lvalue, _)) = constant(cx, cx.typeck_results(), mul_rhs);
+        if let Some(rvalue) = constant(cx, cx.typeck_results(), div_rhs);
+        if let Some(lvalue) = constant(cx, cx.typeck_results(), mul_rhs);
         then {
             // TODO: also check for constant values near PI/180 or 180/PI
             if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) &&
diff --git a/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
index d8f4a5fe221..521045a9fed 100644
--- a/src/tools/clippy/clippy_lints/src/fn_null_check.rs
+++ b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
@@ -89,11 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
 
                     // Catching:
                     // (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
-                    _ if matches!(
-                        constant(cx, cx.typeck_results(), to_check),
-                        Some((Constant::RawPtr(0), _))
-                    ) =>
-                    {
+                    _ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => {
                         lint_expr(cx, expr);
                     },
 
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
index 012aa5a1d1d..ee7973b82ab 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -101,10 +101,10 @@ fn get_int_max(ty: Ty<'_>) -> Option<u128> {
 fn get_const<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(u128, BinOpKind, &'tcx Expr<'tcx>)> {
     if let ExprKind::Binary(op, l, r) = expr.kind {
         let tr = cx.typeck_results();
-        if let Some((Constant::Int(c), _)) = constant(cx, tr, r) {
+        if let Some(Constant::Int(c)) = constant(cx, tr, r) {
             return Some((c, op.node, l));
         };
-        if let Some((Constant::Int(c), _)) = constant(cx, tr, l) {
+        if let Some(Constant::Int(c)) = constant(cx, tr, l) {
             return Some((c, invert_op(op.node)?, r));
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index bdeddf44df7..7a269e98ff1 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -254,7 +254,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> {
                 let parent_id = map.parent_id(expr.hir_id);
                 if let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id);
                 if let hir::ExprKind::Index(_, index_expr) = parent_expr.kind;
-                if let Some((Constant::Int(index_value), _)) = constant(cx, cx.typeck_results(), index_expr);
+                if let Some(Constant::Int(index_value)) = constant(cx, cx.typeck_results(), index_expr);
                 if let Ok(index_value) = index_value.try_into();
                 if index_value < max_suggested_slice;
 
diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
index 924a361c0f6..22c14d9b04d 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -191,18 +191,14 @@ impl<'tcx> LateLintPass<'tcx> for IndexingSlicing {
 /// Returns a tuple of options with the start and end (exclusive) values of
 /// the range. If the start or end is not constant, None is returned.
 fn to_const_range(cx: &LateContext<'_>, range: higher::Range<'_>, array_size: u128) -> (Option<u128>, Option<u128>) {
-    let s = range
-        .start
-        .map(|expr| constant(cx, cx.typeck_results(), expr).map(|(c, _)| c));
+    let s = range.start.map(|expr| constant(cx, cx.typeck_results(), expr));
     let start = match s {
         Some(Some(Constant::Int(x))) => Some(x),
         Some(_) => None,
         None => Some(0),
     };
 
-    let e = range
-        .end
-        .map(|expr| constant(cx, cx.typeck_results(), expr).map(|(c, _)| c));
+    let e = range.end.map(|expr| constant(cx, cx.typeck_results(), expr));
     let end = match e {
         Some(Some(Constant::Int(x))) => {
             if range.limits == RangeLimits::Closed {
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index 16772a9d598..e6614180920 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -1,10 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
 use clippy_utils::{is_must_use_func_call, paths};
-use rustc_hir::{ExprKind, Local, PatKind};
+use rustc_hir::{Local, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::IsSuggestable;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::{BytePos, Span};
 
@@ -138,7 +140,7 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [
 ];
 
 impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
-    fn check_local(&mut self, cx: &LateContext<'_>, local: &Local<'_>) {
+    fn check_local(&mut self, cx: &LateContext<'tcx>, local: &Local<'tcx>) {
         if !in_external_macro(cx.tcx.sess, local.span)
             && let PatKind::Wild = local.pat.kind
             && let Some(init) = local.init
@@ -191,15 +193,17 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
             if local.pat.default_binding_modes && local.ty.is_none() {
                 // When `default_binding_modes` is true, the `let` keyword is present.
 
-				// Ignore function calls that return impl traits...
-				if let Some(init) = local.init &&
-				matches!(init.kind, ExprKind::Call(_, _) | ExprKind::MethodCall(_, _, _, _)) {
-					let expr_ty = cx.typeck_results().expr_ty(init);
-					if expr_ty.is_impl_trait() {
-						return;
-					}
-				}
+                // Ignore unnameable types
+                if let Some(init) = local.init
+                    && !cx.typeck_results().expr_ty(init).is_suggestable(cx.tcx, true)
+                {
+                    return;
+                }
 
+                // Ignore if it is from a procedural macro...
+                if is_from_proc_macro(cx, init) {
+                    return;
+                }
 
 				span_lint_and_help(
                     cx,
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 3517842a01e..b442a4ac5f6 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -266,6 +266,7 @@ mod redundant_pub_crate;
 mod redundant_slicing;
 mod redundant_static_lifetimes;
 mod ref_option_ref;
+mod ref_patterns;
 mod reference;
 mod regex;
 mod return_self_not_must_use;
@@ -331,8 +332,11 @@ mod zero_div_zero;
 mod zero_sized_map_values;
 // end lints modules, do not remove this comment, it’s used in `update_lints`
 
-use crate::utils::conf::{format_error, TryConf};
 pub use crate::utils::conf::{lookup_conf_file, Conf};
+use crate::utils::{
+    conf::{format_error, metadata::get_configuration_metadata, TryConf},
+    FindAll,
+};
 
 /// Register all pre expansion lints
 ///
@@ -471,7 +475,22 @@ pub(crate) struct LintInfo {
 pub fn explain(name: &str) {
     let target = format!("clippy::{}", name.to_ascii_uppercase());
     match declared_lints::LINTS.iter().find(|info| info.lint.name == target) {
-        Some(info) => print!("{}", info.explanation),
+        Some(info) => {
+            println!("{}", info.explanation);
+            // Check if the lint has configuration
+            let mdconf = get_configuration_metadata();
+            if let Some(config_vec_positions) = mdconf
+                .iter()
+                .find_all(|cconf| cconf.lints.contains(&info.lint.name_lower()[8..].to_owned()))
+            {
+                // If it has, print it
+                println!("### Configuration for {}:\n", info.lint.name_lower());
+                for position in config_vec_positions {
+                    let conf = &mdconf[position];
+                    println!("  - {}: {} (default: {})", conf.name, conf.doc, conf.default);
+                }
+            }
+        },
         None => println!("unknown lint: {name}"),
     }
 }
@@ -971,6 +990,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
     store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments));
     store.register_late_pass(|_| Box::new(items_after_test_module::ItemsAfterTestModule));
+    store.register_early_pass(|| Box::new(ref_patterns::RefPatterns));
     store.register_late_pass(|_| Box::new(default_constructed_unit_structs::DefaultConstructedUnitStructs));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
index bba9bb445a7..09b2032e20f 100644
--- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
@@ -25,7 +25,7 @@ declare_clippy_lint! {
     ///
     /// ### Known problems
     /// This lint suggests replacing `filter_map()` or `flat_map()` applied to a `Lines`
-    /// instance in all cases. There two cases where the suggestion might not be
+    /// instance in all cases. There are two cases where the suggestion might not be
     /// appropriate or necessary:
     ///
     /// - If the `Lines` instance can never produce any error, or if an error is produced
diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
index 1247370b74a..3f8b42ffe80 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -38,7 +38,6 @@ declare_clippy_lint! {
     /// Could be written:
     ///
     /// ```rust
-    /// # #![feature(let_else)]
     /// # fn main () {
     /// # let w = Some(0);
     /// let Some(v) = w else { return };
@@ -69,29 +68,23 @@ impl_lint_pass!(ManualLetElse => [MANUAL_LET_ELSE]);
 
 impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
     fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) {
-        let if_let_or_match = if_chain! {
-            if self.msrv.meets(msrvs::LET_ELSE);
-            if !in_external_macro(cx.sess(), stmt.span);
-            if let StmtKind::Local(local) = stmt.kind;
-            if let Some(init) = local.init;
-            if local.els.is_none();
-            if local.ty.is_none();
-            if init.span.ctxt() == stmt.span.ctxt();
-            if let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init);
-            then {
-                if_let_or_match
-            } else {
-                return;
-            }
-        };
+        if !self.msrv.meets(msrvs::LET_ELSE) || in_external_macro(cx.sess(), stmt.span) {
+            return;
+        }
 
+        if let StmtKind::Local(local) = stmt.kind &&
+            let Some(init) = local.init &&
+            local.els.is_none() &&
+            local.ty.is_none() &&
+            init.span.ctxt() == stmt.span.ctxt() &&
+            let Some(if_let_or_match) = IfLetOrMatch::parse(cx, init) {
         match if_let_or_match {
             IfLetOrMatch::IfLet(if_let_expr, let_pat, if_then, if_else) => if_chain! {
                 if expr_is_simple_identity(let_pat, if_then);
                 if let Some(if_else) = if_else;
                 if expr_diverges(cx, if_else);
                 then {
-                    emit_manual_let_else(cx, stmt.span, if_let_expr, let_pat, if_else);
+                    emit_manual_let_else(cx, stmt.span, if_let_expr, local.pat, let_pat, if_else);
                 }
             },
             IfLetOrMatch::Match(match_expr, arms, source) => {
@@ -128,15 +121,23 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
                     return;
                 }
 
-                emit_manual_let_else(cx, stmt.span, match_expr, pat_arm.pat, diverging_arm.body);
+                emit_manual_let_else(cx, stmt.span, match_expr, local.pat, pat_arm.pat, diverging_arm.body);
             },
         }
+        };
     }
 
     extract_msrv_attr!(LateContext);
 }
 
-fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat: &Pat<'_>, else_body: &Expr<'_>) {
+fn emit_manual_let_else(
+    cx: &LateContext<'_>,
+    span: Span,
+    expr: &Expr<'_>,
+    local: &Pat<'_>,
+    pat: &Pat<'_>,
+    else_body: &Expr<'_>,
+) {
     span_lint_and_then(
         cx,
         MANUAL_LET_ELSE,
@@ -145,12 +146,11 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
         |diag| {
             // This is far from perfect, for example there needs to be:
             // * mut additions for the bindings
-            // * renamings of the bindings
+            // * renamings of the bindings for `PatKind::Or`
             // * unused binding collision detection with existing ones
             // * putting patterns with at the top level | inside ()
             // for this to be machine applicable.
             let mut app = Applicability::HasPlaceholders;
-            let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
             let (sn_expr, _) = snippet_with_context(cx, expr.span, span.ctxt(), "", &mut app);
             let (sn_else, _) = snippet_with_context(cx, else_body.span, span.ctxt(), "", &mut app);
 
@@ -159,10 +159,21 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
             } else {
                 format!("{{ {sn_else} }}")
             };
-            let sn_bl = if matches!(pat.kind, PatKind::Or(..)) {
-                format!("({sn_pat})")
-            } else {
-                sn_pat.into_owned()
+            let sn_bl = match pat.kind {
+                PatKind::Or(..) => {
+                    let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
+                    format!("({sn_pat})")
+                },
+                // Replace the variable name iff `TupleStruct` has one argument like `Variant(v)`.
+                PatKind::TupleStruct(ref w, args, ..) if args.len() == 1 => {
+                    let sn_wrapper = cx.sess().source_map().span_to_snippet(w.span()).unwrap_or_default();
+                    let (sn_inner, _) = snippet_with_context(cx, local.span, span.ctxt(), "", &mut app);
+                    format!("{sn_wrapper}({sn_inner})")
+                },
+                _ => {
+                    let (sn_pat, _) = snippet_with_context(cx, pat.span, span.ctxt(), "", &mut app);
+                    sn_pat.into_owned()
+                },
             };
             let sugg = format!("let {sn_bl} = {sn_expr} else {else_bl};");
             diag.span_suggestion(span, "consider writing", sugg, app);
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 7d28c111624..93d977a5c96 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -144,7 +144,7 @@ fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx E
 
 // Returns the length of the `expr` if it's a constant string or char.
 fn constant_length(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<u128> {
-    let (value, _) = constant(cx, cx.typeck_results(), expr)?;
+    let value = constant(cx, cx.typeck_results(), expr)?;
     match value {
         Constant::Str(value) => Some(value.len() as u128),
         Constant::Char(value) => Some(value.len_utf8() as u128),
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index 33bc20dad6b..0064619ef89 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -1,10 +1,12 @@
+use super::REDUNDANT_PATTERN_MATCHING;
 use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_lint_allowed;
 use clippy_utils::is_wild;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::span_contains_comment;
 use rustc_ast::{Attribute, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat};
+use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat, PatKind, QPath};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
 use rustc_span::source_map::Spanned;
@@ -99,6 +101,14 @@ where
                 }
             }
 
+            for arm in iter_without_last.clone() {
+                if let Some(pat) = arm.1 {
+                    if !is_lint_allowed(cx, REDUNDANT_PATTERN_MATCHING, pat.hir_id) && is_some(pat.kind) {
+                        return false;
+                    }
+                }
+            }
+
             // The suggestion may be incorrect, because some arms can have `cfg` attributes
             // evaluated into `false` and so such arms will be stripped before.
             let mut applicability = Applicability::MaybeIncorrect;
@@ -170,3 +180,13 @@ fn find_bool_lit(ex: &ExprKind<'_>) -> Option<bool> {
         _ => None,
     }
 }
+
+fn is_some(path_kind: PatKind<'_>) -> bool {
+    match path_kind {
+        PatKind::TupleStruct(QPath::Resolved(_, path), [first, ..], _) if is_wild(first) => {
+            let name = path.segments[0].ident;
+            name.name == rustc_span::sym::Some
+        },
+        _ => false,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index a48f4c77f85..ae8262ace96 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -282,9 +282,8 @@ impl<'a> NormalizedPat<'a> {
                 // TODO: Handle negative integers. They're currently treated as a wild match.
                 ExprKind::Lit(lit) => match lit.node {
                     LitKind::Str(sym, _) => Self::LitStr(sym),
-                    LitKind::ByteStr(ref bytes, _) => Self::LitBytes(bytes),
+                    LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Byte(val) => Self::LitInt(val.into()),
-                    LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Char(val) => Self::LitInt(val.into()),
                     LitKind::Int(val, _) => Self::LitInt(val),
                     LitKind::Bool(val) => Self::LitBool(val),
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index 87b63eead25..55ec9d4474f 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -25,9 +25,9 @@ mod wild_in_or_pats;
 
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{snippet_opt, walk_span_to_context};
-use clippy_utils::{higher, in_constant, is_span_match};
+use clippy_utils::{higher, in_constant, is_span_match, tokenize_with_text};
 use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat};
-use rustc_lexer::{tokenize, TokenKind};
+use rustc_lexer::TokenKind;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -1147,12 +1147,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
         // Assume true. This would require either an invalid span, or one which crosses file boundaries.
         return true;
     };
-    let mut pos = 0usize;
-    let mut iter = tokenize(&snip).map(|t| {
-        let start = pos;
-        pos += t.len as usize;
-        (t.kind, start..pos)
-    });
+    let mut iter = tokenize_with_text(&snip);
 
     // Search for the token sequence [`#`, `[`, `cfg`]
     while iter.any(|(t, _)| matches!(t, TokenKind::Pound)) {
@@ -1163,7 +1158,7 @@ fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
             )
         });
         if matches!(iter.next(), Some((TokenKind::OpenBracket, _)))
-            && matches!(iter.next(), Some((TokenKind::Ident, range)) if &snip[range.clone()] == "cfg")
+            && matches!(iter.next(), Some((TokenKind::Ident, "cfg")))
         {
             return true;
         }
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index ae69ca8a339..abf2525a61c 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -34,7 +34,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
             if let Arm { pat, guard: None, .. } = *arm {
                 if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
                     let lhs_const = match lhs {
-                        Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
+                        Some(lhs) => constant(cx, cx.typeck_results(), lhs)?,
                         None => {
                             let min_val_const = ty.numeric_min_val(cx.tcx)?;
                             let min_constant = mir::ConstantKind::from_value(
@@ -45,7 +45,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                         },
                     };
                     let rhs_const = match rhs {
-                        Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
+                        Some(rhs) => constant(cx, cx.typeck_results(), rhs)?,
                         None => {
                             let max_val_const = ty.numeric_max_val(cx.tcx)?;
                             let max_constant = mir::ConstantKind::from_value(
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index af121f317cd..e81e09da425 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -189,73 +189,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
     if arms.len() == 2 {
         let node_pair = (&arms[0].pat.kind, &arms[1].pat.kind);
 
-        let found_good_method = match node_pair {
-            (
-                PatKind::TupleStruct(ref path_left, patterns_left, _),
-                PatKind::TupleStruct(ref path_right, patterns_right, _),
-            ) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
-                if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) {
-                    find_good_method_for_match(
-                        cx,
-                        arms,
-                        path_left,
-                        path_right,
-                        Item::Lang(ResultOk),
-                        Item::Lang(ResultErr),
-                        "is_ok()",
-                        "is_err()",
-                    )
-                    .or_else(|| {
-                        find_good_method_for_match(
-                            cx,
-                            arms,
-                            path_left,
-                            path_right,
-                            Item::Diag(sym::IpAddr, sym!(V4)),
-                            Item::Diag(sym::IpAddr, sym!(V6)),
-                            "is_ipv4()",
-                            "is_ipv6()",
-                        )
-                    })
-                } else {
-                    None
-                }
-            },
-            (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right))
-            | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _))
-                if patterns.len() == 1 =>
-            {
-                if let PatKind::Wild = patterns[0].kind {
-                    find_good_method_for_match(
-                        cx,
-                        arms,
-                        path_left,
-                        path_right,
-                        Item::Lang(OptionSome),
-                        Item::Lang(OptionNone),
-                        "is_some()",
-                        "is_none()",
-                    )
-                    .or_else(|| {
-                        find_good_method_for_match(
-                            cx,
-                            arms,
-                            path_left,
-                            path_right,
-                            Item::Lang(PollReady),
-                            Item::Lang(PollPending),
-                            "is_ready()",
-                            "is_pending()",
-                        )
-                    })
-                } else {
-                    None
-                }
-            },
-            _ => None,
-        };
-
-        if let Some(good_method) = found_good_method {
+        if let Some(good_method) = found_good_method(cx, arms, node_pair) {
             let span = expr.span.to(op.span);
             let result_expr = match &op.kind {
                 ExprKind::AddrOf(_, _, borrowed) => borrowed,
@@ -279,6 +213,127 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
     }
 }
 
+fn found_good_method<'a>(
+    cx: &LateContext<'_>,
+    arms: &[Arm<'_>],
+    node: (&PatKind<'_>, &PatKind<'_>),
+) -> Option<&'a str> {
+    match node {
+        (
+            PatKind::TupleStruct(ref path_left, patterns_left, _),
+            PatKind::TupleStruct(ref path_right, patterns_right, _),
+        ) if patterns_left.len() == 1 && patterns_right.len() == 1 => {
+            if let (PatKind::Wild, PatKind::Wild) = (&patterns_left[0].kind, &patterns_right[0].kind) {
+                find_good_method_for_match(
+                    cx,
+                    arms,
+                    path_left,
+                    path_right,
+                    Item::Lang(ResultOk),
+                    Item::Lang(ResultErr),
+                    "is_ok()",
+                    "is_err()",
+                )
+                .or_else(|| {
+                    find_good_method_for_match(
+                        cx,
+                        arms,
+                        path_left,
+                        path_right,
+                        Item::Diag(sym::IpAddr, sym!(V4)),
+                        Item::Diag(sym::IpAddr, sym!(V6)),
+                        "is_ipv4()",
+                        "is_ipv6()",
+                    )
+                })
+            } else {
+                None
+            }
+        },
+        (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Path(ref path_right))
+        | (PatKind::Path(ref path_left), PatKind::TupleStruct(ref path_right, patterns, _))
+            if patterns.len() == 1 =>
+        {
+            if let PatKind::Wild = patterns[0].kind {
+                find_good_method_for_match(
+                    cx,
+                    arms,
+                    path_left,
+                    path_right,
+                    Item::Lang(OptionSome),
+                    Item::Lang(OptionNone),
+                    "is_some()",
+                    "is_none()",
+                )
+                .or_else(|| {
+                    find_good_method_for_match(
+                        cx,
+                        arms,
+                        path_left,
+                        path_right,
+                        Item::Lang(PollReady),
+                        Item::Lang(PollPending),
+                        "is_ready()",
+                        "is_pending()",
+                    )
+                })
+            } else {
+                None
+            }
+        },
+        (PatKind::TupleStruct(ref path_left, patterns, _), PatKind::Wild) if patterns.len() == 1 => {
+            if let PatKind::Wild = patterns[0].kind {
+                get_good_method(cx, arms, path_left)
+            } else {
+                None
+            }
+        },
+        (PatKind::Path(ref path_left), PatKind::Wild) => get_good_method(cx, arms, path_left),
+        _ => None,
+    }
+}
+
+fn get_ident(path: &QPath<'_>) -> Option<rustc_span::symbol::Ident> {
+    match path {
+        QPath::Resolved(_, path) => {
+            let name = path.segments[0].ident;
+            Some(name)
+        },
+        _ => None,
+    }
+}
+
+fn get_good_method<'a>(cx: &LateContext<'_>, arms: &[Arm<'_>], path_left: &QPath<'_>) -> Option<&'a str> {
+    if let Some(name) = get_ident(path_left) {
+        return match name.as_str() {
+            "Ok" => {
+                find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultOk), "is_ok()", "is_err()")
+            },
+            "Err" => {
+                find_good_method_for_matches_macro(cx, arms, path_left, Item::Lang(ResultErr), "is_err()", "is_ok()")
+            },
+            "Some" => find_good_method_for_matches_macro(
+                cx,
+                arms,
+                path_left,
+                Item::Lang(OptionSome),
+                "is_some()",
+                "is_none()",
+            ),
+            "None" => find_good_method_for_matches_macro(
+                cx,
+                arms,
+                path_left,
+                Item::Lang(OptionNone),
+                "is_none()",
+                "is_some()",
+            ),
+            _ => None,
+        };
+    }
+    None
+}
+
 #[derive(Clone, Copy)]
 enum Item {
     Lang(LangItem),
@@ -289,10 +344,11 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
     let Some(id) = cx.typeck_results().qpath_res(path, pat.hir_id).opt_def_id() else { return false };
 
     match expected_item {
-        Item::Lang(expected_lang_item) => {
-            let expected_id = cx.tcx.lang_items().require(expected_lang_item).unwrap();
-            cx.tcx.parent(id) == expected_id
-        },
+        Item::Lang(expected_lang_item) => cx
+            .tcx
+            .lang_items()
+            .get(expected_lang_item)
+            .map_or(false, |expected_id| cx.tcx.parent(id) == expected_id),
         Item::Diag(expected_ty, expected_variant) => {
             let ty = cx.typeck_results().pat_ty(pat);
 
@@ -345,3 +401,29 @@ fn find_good_method_for_match<'a>(
         _ => None,
     }
 }
+
+fn find_good_method_for_matches_macro<'a>(
+    cx: &LateContext<'_>,
+    arms: &[Arm<'_>],
+    path_left: &QPath<'_>,
+    expected_item_left: Item,
+    should_be_left: &'a str,
+    should_be_right: &'a str,
+) -> Option<&'a str> {
+    let first_pat = arms[0].pat;
+
+    let body_node_pair = if is_pat_variant(cx, first_pat, path_left, expected_item_left) {
+        (&arms[0].body.kind, &arms[1].body.kind)
+    } else {
+        return None;
+    };
+
+    match body_node_pair {
+        (ExprKind::Lit(lit_left), ExprKind::Lit(lit_right)) => match (&lit_left.node, &lit_right.node) {
+            (LitKind::Bool(true), LitKind::Bool(false)) => Some(should_be_left),
+            (LitKind::Bool(false), LitKind::Bool(true)) => Some(should_be_right),
+            _ => None,
+        },
+        _ => None,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
index c830958d5c8..d1609eebfdc 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth_zero.rs
@@ -13,7 +13,7 @@ use super::ITER_NTH_ZERO;
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) {
     if_chain! {
         if is_trait_method(cx, expr, sym::Iterator);
-        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg);
+        if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg);
         then {
             let mut applicability = Applicability::MachineApplicable;
             span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
index 64c09214a76..b631cd00cda 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iterator_step_by_zero.rs
@@ -9,7 +9,7 @@ use super::ITERATOR_STEP_BY_ZERO;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
     if is_trait_method(cx, expr, sym::Iterator) {
-        if let Some((Constant::Int(0), _)) = constant(cx, cx.typeck_results(), arg) {
+        if let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) {
             span_lint(
                 cx,
                 ITERATOR_STEP_BY_ZERO,
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
new file mode 100644
index 00000000000..5f3fec53827
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_next_back.rs
@@ -0,0 +1,38 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_trait_method;
+use clippy_utils::ty::implements_trait;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_span::symbol::sym;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx Expr<'_>,
+    rev_call: &'tcx Expr<'_>,
+    rev_recv: &'tcx Expr<'_>,
+) {
+    let rev_recv_ty = cx.typeck_results().expr_ty(rev_recv);
+
+    // check that the receiver of `rev` implements `DoubleEndedIterator` and
+    // that `rev` and `next` come from `Iterator`
+    if cx
+        .tcx
+        .get_diagnostic_item(sym::DoubleEndedIterator)
+        .map_or(false, |double_ended_iterator| {
+            implements_trait(cx, rev_recv_ty, double_ended_iterator, &[])
+        })
+        && is_trait_method(cx, rev_call, sym::Iterator)
+        && is_trait_method(cx, expr, sym::Iterator)
+    {
+        span_lint_and_sugg(
+            cx,
+            super::MANUAL_NEXT_BACK,
+            expr.span.with_lo(rev_recv.span.hi()),
+            "manual backwards iteration",
+            "use",
+            String::from(".next_back()"),
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 06b88e34d24..9a594d964ab 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -45,6 +45,7 @@ mod iter_overeager_cloned;
 mod iter_skip_next;
 mod iter_with_drain;
 mod iterator_step_by_zero;
+mod manual_next_back;
 mod manual_ok_or;
 mod manual_saturating_arithmetic;
 mod manual_str_repeat;
@@ -3132,8 +3133,11 @@ declare_clippy_lint! {
     /// ### Example
     /// ```rust
     /// # let iterator = vec![1].into_iter();
-    /// let len = iterator.clone().collect::<Vec<_>>().len();
-    /// // should be
+    /// let len = iterator.collect::<Vec<_>>().len();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # let iterator = vec![1].into_iter();
     /// let len = iterator.count();
     /// ```
     #[clippy::version = "1.30.0"]
@@ -3193,6 +3197,29 @@ declare_clippy_lint! {
     "calling `drain` in order to `clear` a container"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `.rev().next()` on a `DoubleEndedIterator`
+    ///
+    /// ### Why is this bad?
+    /// `.next_back()` is cleaner.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # let foo = [0; 10];
+    /// foo.iter().rev().next();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # let foo = [0; 10];
+    /// foo.iter().next_back();
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub MANUAL_NEXT_BACK,
+    style,
+    "manual reverse iteration of `DoubleEndedIterator`"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -3321,6 +3348,7 @@ impl_lint_pass!(Methods => [
     NEEDLESS_COLLECT,
     SUSPICIOUS_COMMAND_ARG_SPACE,
     CLEAR_WITH_DRAIN,
+    MANUAL_NEXT_BACK,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -3677,6 +3705,7 @@ impl Methods {
                             ("iter", []) => iter_next_slice::check(cx, expr, recv2),
                             ("skip", [arg]) => iter_skip_next::check(cx, expr, recv2, arg),
                             ("skip_while", [_]) => skip_while_next::check(cx, expr),
+                            ("rev", [])=> manual_next_back::check(cx, expr, recv, recv2),
                             _ => {},
                         }
                     }
@@ -3741,13 +3770,13 @@ impl Methods {
                     unnecessary_sort_by::check(cx, expr, recv, arg, true);
                 },
                 ("splitn" | "rsplitn", [count_arg, pat_arg]) => {
-                    if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+                    if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
                         suspicious_splitn::check(cx, name, expr, recv, count);
                         str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv);
                     }
                 },
                 ("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
-                    if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
+                    if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
                         suspicious_splitn::check(cx, name, expr, recv, count);
                     }
                 },
diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
index 0b0c6adc504..6841aaf626c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs
@@ -1,6 +1,5 @@
 use super::NEEDLESS_COLLECT;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
-use clippy_utils::higher;
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_type_diagnostic_item, make_normalized_projection, make_projection};
@@ -8,6 +7,7 @@ use clippy_utils::{
     can_move_expr_to_closure, get_enclosing_block, get_parent_node, is_trait_method, path_to_local, path_to_local_id,
     CaptureKind,
 };
+use clippy_utils::{fn_def_id, higher};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
@@ -16,7 +16,7 @@ use rustc_hir::{
 };
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{self, AssocKind, EarlyBinder, GenericArg, GenericArgKind, Ty};
+use rustc_middle::ty::{self, AssocKind, Clause, EarlyBinder, GenericArg, GenericArgKind, PredicateKind, Ty};
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, Symbol};
 
@@ -32,6 +32,8 @@ pub(super) fn check<'tcx>(
     if let Some(parent) = get_parent_node(cx.tcx, collect_expr.hir_id) {
         match parent {
             Node::Expr(parent) => {
+                check_collect_into_intoiterator(cx, parent, collect_expr, call_span, iter_expr);
+
                 if let ExprKind::MethodCall(name, _, args @ ([] | [_]), _) = parent.kind {
                     let mut app = Applicability::MachineApplicable;
                     let name = name.ident.as_str();
@@ -134,6 +136,68 @@ pub(super) fn check<'tcx>(
     }
 }
 
+/// checks for for collecting into a (generic) method or function argument
+/// taking an `IntoIterator`
+fn check_collect_into_intoiterator<'tcx>(
+    cx: &LateContext<'tcx>,
+    parent: &'tcx Expr<'tcx>,
+    collect_expr: &'tcx Expr<'tcx>,
+    call_span: Span,
+    iter_expr: &'tcx Expr<'tcx>,
+) {
+    if let Some(id) = fn_def_id(cx, parent) {
+        let args = match parent.kind {
+            ExprKind::Call(_, args) | ExprKind::MethodCall(_, _, args, _) => args,
+            _ => &[],
+        };
+        // find the argument index of the `collect_expr` in the
+        // function / method call
+        if let Some(arg_idx) = args.iter().position(|e| e.hir_id == collect_expr.hir_id).map(|i| {
+            if matches!(parent.kind, ExprKind::MethodCall(_, _, _, _)) {
+                i + 1
+            } else {
+                i
+            }
+        }) {
+            // extract the input types of the function/method call
+            // that contains `collect_expr`
+            let inputs = cx
+                .tcx
+                .liberate_late_bound_regions(id, cx.tcx.fn_sig(id).subst_identity())
+                .inputs();
+
+            // map IntoIterator generic bounds to their signature
+            // types and check whether the argument type is an
+            // `IntoIterator`
+            if cx
+                .tcx
+                .param_env(id)
+                .caller_bounds()
+                .into_iter()
+                .filter_map(|p| {
+                    if let PredicateKind::Clause(Clause::Trait(t)) = p.kind().skip_binder()
+                            && cx.tcx.is_diagnostic_item(sym::IntoIterator,t.trait_ref.def_id) {
+                                Some(t.self_ty())
+                            } else {
+                                None
+                            }
+                })
+                .any(|ty| ty == inputs[arg_idx])
+            {
+                span_lint_and_sugg(
+                    cx,
+                    NEEDLESS_COLLECT,
+                    call_span.with_lo(iter_expr.span.hi()),
+                    NEEDLESS_COLLECT_MSG,
+                    "remove this call",
+                    String::new(),
+                    Applicability::MachineApplicable,
+                );
+            }
+        }
+    }
+}
+
 /// Checks if the given method call matches the expected signature of `([&[mut]] self) -> bool`
 fn is_is_empty_sig(cx: &LateContext<'_>, call_id: HirId) -> bool {
     cx.typeck_results().type_dependent_def_id(call_id).map_or(false, |id| {
diff --git a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
index a345ec813ff..bb4cdd2a6fa 100644
--- a/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/repeat_once.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_lang_item;
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(
     recv: &'tcx Expr<'_>,
     repeat_arg: &'tcx Expr<'_>,
 ) {
-    if constant_context(cx, cx.typeck_results()).expr(repeat_arg) == Some(Constant::Int(1)) {
+    if constant(cx, cx.typeck_results(), repeat_arg) == Some(Constant::Int(1)) {
         let ty = cx.typeck_results().expr_ty(recv).peel_refs();
         if ty.is_str() {
             span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 91f7ce1dbe5..5ea12c44184 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -316,7 +316,7 @@ fn parse_iter_usage<'tcx>(
                     };
                 },
                 ("nth" | "skip", [idx_expr]) if cx.tcx.trait_of_item(did) == Some(iter_id) => {
-                    if let Some((Constant::Int(idx), _)) = constant(cx, cx.typeck_results(), idx_expr) {
+                    if let Some(Constant::Int(idx)) = constant(cx, cx.typeck_results(), idx_expr) {
                         let span = if name.ident.as_str() == "nth" {
                             e.span
                         } else {
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index 3752b9a946f..303f0125690 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -16,9 +16,12 @@ use rustc_span::source_map::{ExpnKind, Span};
 
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    get_parent_expr, in_constant, is_integer_literal, is_no_std_crate, iter_input_pats, last_path_segment, SpanlessEq,
+    get_parent_expr, in_constant, is_integer_literal, is_lint_allowed, is_no_std_crate, iter_input_pats,
+    last_path_segment, SpanlessEq,
 };
 
+use crate::ref_patterns::REF_PATTERNS;
+
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for function arguments and let bindings denoted as
@@ -162,6 +165,10 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
             return;
         }
         for arg in iter_input_pats(decl, body) {
+            // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
+            if !is_lint_allowed(cx, REF_PATTERNS, arg.pat.hir_id) {
+                return;
+            }
             if let PatKind::Binding(BindingAnnotation(ByRef::Yes, _), ..) = arg.pat.kind {
                 span_lint(
                     cx,
@@ -180,6 +187,8 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
             if let StmtKind::Local(local) = stmt.kind;
             if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind;
             if let Some(init) = local.init;
+            // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue.
+            if is_lint_allowed(cx, REF_PATTERNS, local.pat.hir_id);
             then {
                 let ctxt = local.span.ctxt();
                 let mut app = Applicability::MachineApplicable;
diff --git a/src/tools/clippy/clippy_lints/src/needless_bool.rs b/src/tools/clippy/clippy_lints/src/needless_bool.rs
index 71281a0b40b..62af42a3961 100644
--- a/src/tools/clippy/clippy_lints/src/needless_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_bool.rs
@@ -146,7 +146,7 @@ fn is_parent_stmt(cx: &LateContext<'_>, id: HirId) -> bool {
 impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         use self::Expression::{Bool, RetBool};
-        if e.span.from_expansion() {
+        if e.span.from_expansion() || !span_extract_comment(cx.tcx.sess.source_map(), e.span).is_empty() {
             return;
         }
         if let Some(higher::If {
@@ -209,8 +209,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBool {
             }
             if let Some((lhs_a, a)) = fetch_assign(then) &&
                 let Some((lhs_b, b)) = fetch_assign(r#else) &&
-                SpanlessEq::new(cx).eq_expr(lhs_a, lhs_b) &&
-                span_extract_comment(cx.tcx.sess.source_map(), e.span).is_empty()
+                SpanlessEq::new(cx).eq_expr(lhs_a, lhs_b)
             {
                 let mut applicability = Applicability::MachineApplicable;
                 let cond = Sugg::hir_with_applicability(cx, cond, "..", &mut applicability);
diff --git a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index d29ca37eaeb..f4863600ccc 100644
--- a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -121,7 +121,7 @@ fn detect_absurd_comparison<'tcx>(
 fn detect_extreme_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<ExtremeExpr<'tcx>> {
     let ty = cx.typeck_results().expr_ty(expr);
 
-    let cv = constant(cx, cx.typeck_results(), expr)?.0;
+    let cv = constant(cx, cx.typeck_results(), expr)?;
 
     let which = match (ty.kind(), cv) {
         (&ty::Bool, Constant::Bool(false)) | (&ty::Uint(_), Constant::Int(0)) => ExtremeType::Minimum,
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index f72595987ee..5c240276b76 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -21,7 +21,7 @@ const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[
     ["f64", "f64"],
     ["std::num::Saturating", "std::num::Saturating"],
     ["std::num::Wrapping", "std::num::Wrapping"],
-    ["std::string::String", "&str"],
+    ["std::string::String", "str"],
 ];
 const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
 const INTEGER_METHODS: &[&str] = &["saturating_div", "wrapping_div", "wrapping_rem", "wrapping_rem_euclid"];
@@ -113,7 +113,7 @@ impl ArithmeticSideEffects {
         if let hir::ExprKind::Lit(lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
             return Some(n)
         }
-        if let Some((Constant::Int(n), _)) = constant(cx, cx.typeck_results(), expr) {
+        if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) {
             return Some(n);
         }
         None
@@ -144,8 +144,10 @@ impl ArithmeticSideEffects {
         ) {
             return;
         };
-        let lhs_ty = cx.typeck_results().expr_ty(lhs);
-        let rhs_ty = cx.typeck_results().expr_ty(rhs);
+        let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
+        let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
+        let lhs_ty = cx.typeck_results().expr_ty(actual_lhs).peel_refs();
+        let rhs_ty = cx.typeck_results().expr_ty(actual_rhs).peel_refs();
         if self.has_allowed_binary(lhs_ty, rhs_ty) {
             return;
         }
@@ -154,8 +156,6 @@ impl ArithmeticSideEffects {
                 // At least for integers, shifts are already handled by the CTFE
                 return;
             }
-            let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
-            let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
             match (
                 Self::literal_integer(cx, actual_lhs),
                 Self::literal_integer(cx, actual_rhs),
diff --git a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
index 1369b3e7462..1fddf0f50e3 100644
--- a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
@@ -166,7 +166,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
 }
 
 fn fetch_int_literal(cx: &LateContext<'_>, lit: &Expr<'_>) -> Option<u128> {
-    match constant(cx, cx.typeck_results(), lit)?.0 {
+    match constant(cx, cx.typeck_results(), lit)? {
         Constant::Int(n) => Some(n),
         _ => None,
     }
diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
index 786ae1552ad..e18064b7061 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_nan.rs
@@ -18,7 +18,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Exp
 }
 
 fn is_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
-    if let Some((value, _)) = constant(cx, cx.typeck_results(), e) {
+    if let Some(value) = constant(cx, cx.typeck_results(), e) {
         match value {
             Constant::F32(num) => num.is_nan(),
             Constant::F64(num) => num.is_nan(),
diff --git a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
index 49e662cacb0..f120be13836 100644
--- a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
@@ -19,7 +19,7 @@ pub(crate) fn check<'tcx>(
     if op == BinOpKind::Div
         && let ExprKind::MethodCall(method_path, self_arg, [], _) = left.kind
         && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(self_arg).peel_refs(), sym::Duration)
-        && let Some((Constant::Int(divisor), _)) = constant(cx, cx.typeck_results(), right)
+        && let Some(Constant::Int(divisor)) = constant(cx, cx.typeck_results(), right)
     {
         let suggested_fn = match (method_path.ident.as_str(), divisor) {
             ("subsec_micros", 1_000) | ("subsec_nanos", 1_000_000) => "subsec_millis",
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
index 97ddcdb2479..15dff126be7 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_cmp.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant, Constant};
+use clippy_utils::consts::{constant_with_source, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::get_item_name;
 use clippy_utils::sugg::Sugg;
@@ -18,9 +18,16 @@ pub(crate) fn check<'tcx>(
     right: &'tcx Expr<'_>,
 ) {
     if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
-        if is_allowed(cx, left) || is_allowed(cx, right) {
-            return;
-        }
+        let left_is_local = match constant_with_source(cx, cx.typeck_results(), left) {
+            Some((c, s)) if !is_allowed(&c) => s.is_local(),
+            Some(_) => return,
+            None => true,
+        };
+        let right_is_local = match constant_with_source(cx, cx.typeck_results(), right) {
+            Some((c, s)) if !is_allowed(&c) => s.is_local(),
+            Some(_) => return,
+            None => true,
+        };
 
         // Allow comparing the results of signum()
         if is_signum(cx, left) && is_signum(cx, right) {
@@ -34,10 +41,7 @@ pub(crate) fn check<'tcx>(
             }
         }
         let is_comparing_arrays = is_array(cx, left) || is_array(cx, right);
-        let (lint, msg) = get_lint_and_message(
-            is_named_constant(cx, left) || is_named_constant(cx, right),
-            is_comparing_arrays,
-        );
+        let (lint, msg) = get_lint_and_message(left_is_local && right_is_local, is_comparing_arrays);
         span_lint_and_then(cx, lint, expr.span, msg, |diag| {
             let lhs = Sugg::hir(cx, left, "..");
             let rhs = Sugg::hir(cx, right, "..");
@@ -59,44 +63,33 @@ pub(crate) fn check<'tcx>(
     }
 }
 
-fn get_lint_and_message(
-    is_comparing_constants: bool,
-    is_comparing_arrays: bool,
-) -> (&'static rustc_lint::Lint, &'static str) {
-    if is_comparing_constants {
+fn get_lint_and_message(is_local: bool, is_comparing_arrays: bool) -> (&'static rustc_lint::Lint, &'static str) {
+    if is_local {
         (
-            FLOAT_CMP_CONST,
+            FLOAT_CMP,
             if is_comparing_arrays {
-                "strict comparison of `f32` or `f64` constant arrays"
+                "strict comparison of `f32` or `f64` arrays"
             } else {
-                "strict comparison of `f32` or `f64` constant"
+                "strict comparison of `f32` or `f64`"
             },
         )
     } else {
         (
-            FLOAT_CMP,
+            FLOAT_CMP_CONST,
             if is_comparing_arrays {
-                "strict comparison of `f32` or `f64` arrays"
+                "strict comparison of `f32` or `f64` constant arrays"
             } else {
-                "strict comparison of `f32` or `f64`"
+                "strict comparison of `f32` or `f64` constant"
             },
         )
     }
 }
 
-fn is_named_constant<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
-    if let Some((_, res)) = constant(cx, cx.typeck_results(), expr) {
-        res
-    } else {
-        false
-    }
-}
-
-fn is_allowed<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
-    match constant(cx, cx.typeck_results(), expr) {
-        Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(),
-        Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(),
-        Some((Constant::Vec(vec), _)) => vec.iter().all(|f| match f {
+fn is_allowed(val: &Constant) -> bool {
+    match val {
+        &Constant::F32(f) => f == 0.0 || f.is_infinite(),
+        &Constant::F64(f) => f == 0.0 || f.is_infinite(),
+        Constant::Vec(vec) => vec.iter().all(|f| match f {
             Constant::F32(f) => *f == 0.0 || (*f).is_infinite(),
             Constant::F64(f) => *f == 0.0 || (*f).is_infinite(),
             _ => false,
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index 19599731bd6..d63a836e73d 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -98,32 +98,6 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for integer arithmetic operations which could overflow or panic.
-    ///
-    /// Specifically, checks for any operators (`+`, `-`, `*`, `<<`, etc) which are capable
-    /// of overflowing according to the [Rust
-    /// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
-    /// or which can panic (`/`, `%`). No bounds analysis or sophisticated reasoning is
-    /// attempted.
-    ///
-    /// ### Why is this bad?
-    /// Integer overflow will trigger a panic in debug builds or will wrap in
-    /// release mode. Division by zero will cause a panic in either mode. In some applications one
-    /// wants explicitly checked, wrapping or saturating arithmetic.
-    ///
-    /// ### Example
-    /// ```rust
-    /// # let a = 0;
-    /// a + 1;
-    /// ```
-    #[clippy::version = "pre 1.29.0"]
-    pub INTEGER_ARITHMETIC,
-    restriction,
-    "any integer arithmetic expression which could overflow or panic"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Checks for float arithmetic.
     ///
     /// ### Why is this bad?
@@ -787,7 +761,6 @@ pub struct Operators {
 impl_lint_pass!(Operators => [
     ABSURD_EXTREME_COMPARISONS,
     ARITHMETIC_SIDE_EFFECTS,
-    INTEGER_ARITHMETIC,
     FLOAT_ARITHMETIC,
     ASSIGN_OP_PATTERN,
     MISREFACTORED_ASSIGN_OP,
diff --git a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
index af4e74947f4..a2c3a4d8ba7 100644
--- a/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/modulo_arithmetic.rs
@@ -40,7 +40,7 @@ struct OperandInfo {
 
 fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<OperandInfo> {
     match constant(cx, cx.typeck_results(), operand) {
-        Some((Constant::Int(v), _)) => match *cx.typeck_results().expr_ty(expr).kind() {
+        Some(Constant::Int(v)) => match *cx.typeck_results().expr_ty(expr).kind() {
             ty::Int(ity) => {
                 let value = sext(cx.tcx, v, ity);
                 return Some(OperandInfo {
@@ -58,10 +58,10 @@ fn analyze_operand(operand: &Expr<'_>, cx: &LateContext<'_>, expr: &Expr<'_>) ->
             },
             _ => {},
         },
-        Some((Constant::F32(f), _)) => {
+        Some(Constant::F32(f)) => {
             return Some(floating_point_operand_info(&f));
         },
-        Some((Constant::F64(f), _)) => {
+        Some(Constant::F64(f)) => {
             return Some(floating_point_operand_info(&f));
         },
         _ => {},
diff --git a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
index 77fd45b199a..102845ceed0 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -1,8 +1,6 @@
-use super::{FLOAT_ARITHMETIC, INTEGER_ARITHMETIC};
+use super::FLOAT_ARITHMETIC;
 use clippy_utils::consts::constant_simple;
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::is_from_proc_macro;
-use clippy_utils::is_integer_literal;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::source_map::Span;
@@ -45,31 +43,8 @@ impl Context {
             _ => (),
         }
 
-        let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
-        if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() {
-            if is_from_proc_macro(cx, expr) {
-                return;
-            }
-            match op {
-                hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
-                    hir::ExprKind::Lit(_lit) => (),
-                    hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
-                        if is_integer_literal(expr, 1) {
-                            span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                            self.expr_id = Some(expr.hir_id);
-                        }
-                    },
-                    _ => {
-                        span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                        self.expr_id = Some(expr.hir_id);
-                    },
-                },
-                _ => {
-                    span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                    self.expr_id = Some(expr.hir_id);
-                },
-            }
-        } else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
+        let (_, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
+        if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
             span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
             self.expr_id = Some(expr.hir_id);
         }
@@ -80,17 +55,9 @@ impl Context {
             return;
         }
         let ty = cx.typeck_results().expr_ty(arg);
-        if constant_simple(cx, cx.typeck_results(), expr).is_none() {
-            if ty.is_integral() {
-                if is_from_proc_macro(cx, expr) {
-                    return;
-                }
-                span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
-                self.expr_id = Some(expr.hir_id);
-            } else if ty.is_floating_point() {
-                span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
-                self.expr_id = Some(expr.hir_id);
-            }
+        if constant_simple(cx, cx.typeck_results(), expr).is_none() && ty.is_floating_point() {
+            span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
+            self.expr_id = Some(expr.hir_id);
         }
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
index bbbcda069c5..aa6d4004268 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -122,7 +122,7 @@ fn try_get_option_occurrence<'tcx>(
         ExprKind::Unary(UnOp::Deref, inner_expr) | ExprKind::AddrOf(_, _, inner_expr) => inner_expr,
         _ => expr,
     };
-    let inner_pat = try_get_inner_pat(cx, pat)?;
+    let (inner_pat, is_result) = try_get_inner_pat_and_is_result(cx, pat)?;
     if_chain! {
         if let PatKind::Binding(bind_annotation, _, id, None) = inner_pat.kind;
         if let Some(some_captures) = can_move_expr_to_closure(cx, if_then);
@@ -176,7 +176,7 @@ fn try_get_option_occurrence<'tcx>(
                 ),
                 none_expr: format!(
                     "{}{}",
-                    if method_sugg == "map_or" { "" } else { "|| " },
+                    if method_sugg == "map_or" { "" } else if is_result { "|_| " } else { "|| "},
                     Sugg::hir_with_context(cx, none_body, ctxt, "..", &mut app),
                 ),
             });
@@ -186,11 +186,13 @@ fn try_get_option_occurrence<'tcx>(
     None
 }
 
-fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'tcx Pat<'tcx>> {
+fn try_get_inner_pat_and_is_result<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<(&'tcx Pat<'tcx>, bool)> {
     if let PatKind::TupleStruct(ref qpath, [inner_pat], ..) = pat.kind {
         let res = cx.qpath_res(qpath, pat.hir_id);
-        if is_res_lang_ctor(cx, res, OptionSome) || is_res_lang_ctor(cx, res, ResultOk) {
-            return Some(inner_pat);
+        if is_res_lang_ctor(cx, res, OptionSome) {
+            return Some((inner_pat, false));
+        } else if is_res_lang_ctor(cx, res, ResultOk) {
+            return Some((inner_pat, true));
         }
     }
     None
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index fc655fe2d0b..dd7ded491e7 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -319,7 +319,7 @@ fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option<R
             _ => return None,
         };
         if let Some(id) = path_to_local(l) {
-            if let Some((c, _)) = constant(cx, cx.typeck_results(), r) {
+            if let Some(c) = constant(cx, cx.typeck_results(), r) {
                 return Some(RangeBounds {
                     val: c,
                     expr: r,
@@ -331,7 +331,7 @@ fn check_range_bounds<'a>(cx: &'a LateContext<'_>, ex: &'a Expr<'_>) -> Option<R
                 });
             }
         } else if let Some(id) = path_to_local(r) {
-            if let Some((c, _)) = constant(cx, cx.typeck_results(), l) {
+            if let Some(c) = constant(cx, cx.typeck_results(), l) {
                 return Some(RangeBounds {
                     val: c,
                     expr: l,
@@ -451,8 +451,8 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
         if let Some(higher::Range { start: Some(start), end: Some(end), limits }) = higher::Range::hir(expr);
         let ty = cx.typeck_results().expr_ty(start);
         if let ty::Int(_) | ty::Uint(_) = ty.kind();
-        if let Some((start_idx, _)) = constant(cx, cx.typeck_results(), start);
-        if let Some((end_idx, _)) = constant(cx, cx.typeck_results(), end);
+        if let Some(start_idx) = constant(cx, cx.typeck_results(), start);
+        if let Some(end_idx) = constant(cx, cx.typeck_results(), end);
         if let Some(ordering) = Constant::partial_cmp(cx.tcx, ty, &start_idx, &end_idx);
         if is_empty_range(limits, ordering);
         then {
diff --git a/src/tools/clippy/clippy_lints/src/ref_patterns.rs b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
new file mode 100644
index 00000000000..b1530eed1c1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/ref_patterns.rs
@@ -0,0 +1,44 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_ast::ast::{BindingAnnotation, Pat, PatKind};
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usages of the `ref` keyword.
+    /// ### Why is this bad?
+    /// The `ref` keyword can be confusing for people unfamiliar with it, and often
+    /// it is more concise to use `&` instead.
+    /// ### Example
+    /// ```rust
+    /// let opt = Some(5);
+    /// if let Some(ref foo) = opt {}
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let opt = Some(5);
+    /// if let Some(foo) = &opt {}
+    /// ```
+    #[clippy::version = "1.71.0"]
+    pub REF_PATTERNS,
+    restriction,
+    "use of a ref pattern, e.g. Some(ref value)"
+}
+declare_lint_pass!(RefPatterns => [REF_PATTERNS]);
+
+impl EarlyLintPass for RefPatterns {
+    fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &Pat) {
+        if let PatKind::Ident(BindingAnnotation::REF, _, _) = pat.kind
+                && !pat.span.from_expansion()
+        {
+            span_lint_and_help(
+                cx,
+                REF_PATTERNS,
+                pat.span,
+                "usage of ref pattern",
+                None,
+                "consider using `&` for clarity instead",
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index b8b32df6cc6..ef19c6f4617 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -122,37 +122,39 @@ fn lint_syntax_error(cx: &LateContext<'_>, error: &regex_syntax::Error, unescape
 }
 
 fn const_str<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> Option<String> {
-    constant(cx, cx.typeck_results(), e).and_then(|(c, _)| match c {
+    constant(cx, cx.typeck_results(), e).and_then(|c| match c {
         Constant::Str(s) => Some(s),
         _ => None,
     })
 }
 
 fn is_trivial_regex(s: &regex_syntax::hir::Hir) -> Option<&'static str> {
-    use regex_syntax::hir::Anchor::{EndText, StartText};
-    use regex_syntax::hir::HirKind::{Alternation, Anchor, Concat, Empty, Literal};
+    use regex_syntax::hir::HirKind::{Alternation, Concat, Empty, Literal, Look};
+    use regex_syntax::hir::Look as HirLook;
 
     let is_literal = |e: &[regex_syntax::hir::Hir]| e.iter().all(|e| matches!(*e.kind(), Literal(_)));
 
     match *s.kind() {
-        Empty | Anchor(_) => Some("the regex is unlikely to be useful as it is"),
+        Empty | Look(_) => Some("the regex is unlikely to be useful as it is"),
         Literal(_) => Some("consider using `str::contains`"),
         Alternation(ref exprs) => {
-            if exprs.iter().all(|e| e.kind().is_empty()) {
+            if exprs.iter().all(|e| matches!(e.kind(), Empty)) {
                 Some("the regex is unlikely to be useful as it is")
             } else {
                 None
             }
         },
         Concat(ref exprs) => match (exprs[0].kind(), exprs[exprs.len() - 1].kind()) {
-            (&Anchor(StartText), &Anchor(EndText)) if exprs[1..(exprs.len() - 1)].is_empty() => {
+            (&Look(HirLook::Start), &Look(HirLook::End)) if exprs[1..(exprs.len() - 1)].is_empty() => {
                 Some("consider using `str::is_empty`")
             },
-            (&Anchor(StartText), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+            (&Look(HirLook::Start), &Look(HirLook::End)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
                 Some("consider using `==` on `str`s")
             },
-            (&Anchor(StartText), &Literal(_)) if is_literal(&exprs[1..]) => Some("consider using `str::starts_with`"),
-            (&Literal(_), &Anchor(EndText)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
+            (&Look(HirLook::Start), &Literal(_)) if is_literal(&exprs[1..]) => {
+                Some("consider using `str::starts_with`")
+            },
+            (&Literal(_), &Look(HirLook::End)) if is_literal(&exprs[1..(exprs.len() - 1)]) => {
                 Some("consider using `str::ends_with`")
             },
             _ if is_literal(exprs) => Some("consider using `str::contains`"),
@@ -175,10 +177,7 @@ fn check_set<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
 }
 
 fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
-    let mut parser = regex_syntax::ParserBuilder::new()
-        .unicode(true)
-        .allow_invalid_utf8(!utf8)
-        .build();
+    let mut parser = regex_syntax::ParserBuilder::new().unicode(true).utf8(!utf8).build();
 
     if let ExprKind::Lit(lit) = expr.kind {
         if let LitKind::Str(ref r, style) = lit.node {
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 52e22c0c630..b0db56bb417 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -15,6 +15,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
     ("clippy::identity_conversion", "clippy::useless_conversion"),
     ("clippy::if_let_some_result", "clippy::match_result_ok"),
+    ("clippy::integer_arithmetic", "clippy::arithmetic_side_effects"),
     ("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
     ("clippy::new_without_default_derive", "clippy::new_without_default"),
     ("clippy::option_and_then_some", "clippy::bind_instead_of_map"),
@@ -32,13 +33,13 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::zero_width_space", "clippy::invisible_characters"),
     ("clippy::clone_double_ref", "suspicious_double_ref_op"),
     ("clippy::drop_bounds", "drop_bounds"),
-    ("clippy::drop_copy", "drop_copy"),
-    ("clippy::drop_ref", "drop_ref"),
+    ("clippy::drop_copy", "dropping_copy_types"),
+    ("clippy::drop_ref", "dropping_references"),
     ("clippy::for_loop_over_option", "for_loops_over_fallibles"),
     ("clippy::for_loop_over_result", "for_loops_over_fallibles"),
     ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
-    ("clippy::forget_copy", "forget_copy"),
-    ("clippy::forget_ref", "forget_ref"),
+    ("clippy::forget_copy", "forgetting_copy_types"),
+    ("clippy::forget_ref", "forgetting_references"),
     ("clippy::into_iter_on_array", "array_into_iter"),
     ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
     ("clippy::invalid_ref", "invalid_value"),
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 5b588e914fd..483f860a8b5 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -132,7 +132,7 @@ declare_clippy_lint! {
     /// Probably lots of false positives. If an index comes from a known valid position (e.g.
     /// obtained via `char_indices` over the same string), it is totally OK.
     ///
-    /// # Example
+    /// ### Example
     /// ```rust,should_panic
     /// &"Ölkanne"[1..];
     /// ```
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index b5f11b4acae..4ccda15068b 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -37,12 +37,12 @@ declare_clippy_lint! {
     #[clippy::version = "1.38.0"]
     pub TYPE_REPETITION_IN_BOUNDS,
     nursery,
-    "types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`"
+    "types are repeated unnecessarily in trait bounds, use `+` instead of using `T: _, T: _`"
 }
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for cases where generics are being used and multiple
+    /// Checks for cases where generics or trait objects are being used and multiple
     /// syntax specifications for trait bounds are used simultaneously.
     ///
     /// ### Why is this bad?
@@ -167,6 +167,61 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
             }
         }
     }
+
+    fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
+        if_chain! {
+            if let TyKind::Ref(.., mut_ty) = &ty.kind;
+            if let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind;
+            if bounds.len() > 2;
+            then {
+
+                // Build up a hash of every trait we've seen
+                // When we see a trait for the first time, add it to unique_traits
+                // so we can later use it to build a string of all traits exactly once, without duplicates
+
+                let mut seen_def_ids = FxHashSet::default();
+                let mut unique_traits = Vec::new();
+
+                // Iterate the bounds and add them to our seen hash
+                // If we haven't yet seen it, add it to the fixed traits
+                for bound in bounds.iter() {
+                    let Some(def_id) = bound.trait_ref.trait_def_id() else { continue; };
+
+                    let new_trait = seen_def_ids.insert(def_id);
+
+                    if new_trait {
+                        unique_traits.push(bound);
+                    }
+                }
+
+                // If the number of unique traits isn't the same as the number of traits in the bounds,
+                // there must be 1 or more duplicates
+                if bounds.len() != unique_traits.len() {
+                    let mut bounds_span = bounds[0].span;
+
+                    for bound in bounds.iter().skip(1) {
+                        bounds_span = bounds_span.to(bound.span);
+                    }
+
+                    let fixed_trait_snippet = unique_traits
+                        .iter()
+                        .filter_map(|b| snippet_opt(cx, b.span))
+                        .collect::<Vec<_>>()
+                        .join(" + ");
+
+                    span_lint_and_sugg(
+                        cx,
+                        TRAIT_DUPLICATION_IN_BOUNDS,
+                        bounds_span,
+                        "this trait bound is already specified in trait declaration",
+                        "try",
+                        fixed_trait_snippet,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+            }
+        }
+    }
 }
 
 impl TraitBounds {
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
index e75d7f6bf1d..4944381da24 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_null_to_fn.rs
@@ -31,9 +31,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
     match arg.kind {
         // Catching:
         // transmute over constants that resolve to `null`.
-        ExprKind::Path(ref _qpath)
-            if matches!(constant(cx, cx.typeck_results(), arg), Some((Constant::RawPtr(0), _))) =>
-        {
+        ExprKind::Path(ref _qpath) if matches!(constant(cx, cx.typeck_results(), arg), Some(Constant::RawPtr(0))) => {
             lint_expr(cx, expr);
             true
         },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
index 1e407fc4138..770914e99e1 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
@@ -1,4 +1,4 @@
-use clippy_utils::consts::{constant_context, Constant};
+use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
 use rustc_hir::{Expr, ExprKind};
@@ -16,9 +16,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
     }
 
     // Catching transmute over constants that resolve to `null`.
-    let mut const_eval_context = constant_context(cx, cx.typeck_results());
     if let ExprKind::Path(ref _qpath) = arg.kind &&
-        let Some(Constant::RawPtr(0)) = const_eval_context.expr(arg)
+        let Some(Constant::RawPtr(0)) = constant(cx, cx.typeck_results(), arg)
     {
         span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
         return true;
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index ddbe6b2c790..28c3fc859e3 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -1,4 +1,5 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::is_ty_alias;
 use clippy_utils::source::{snippet, snippet_with_context};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
@@ -138,6 +139,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                 if_chain! {
                     if let ExprKind::Path(ref qpath) = path.kind;
                     if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
+                    if !is_ty_alias(qpath);
                     then {
                         let a = cx.typeck_results().expr_ty(e);
                         let b = cx.typeck_results().expr_ty(arg);
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 935ea90d245..3c2bf5abab2 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -308,7 +308,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 bind!(self, vec);
                 kind!("CStr(ref {vec})");
                 chain!(self, "let [{:?}] = **{vec}", vec.value);
-            }
+            },
             LitKind::Str(s, _) => {
                 bind!(self, s);
                 kind!("Str({s}, _)");
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 5f05d971fce..f6de66bb514 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -174,16 +174,15 @@ macro_rules! define_Conf {
             }
         }
 
-        #[cfg(feature = "internal")]
         pub mod metadata {
-            use crate::utils::internal_lints::metadata_collector::ClippyConfiguration;
+            use crate::utils::ClippyConfiguration;
 
             macro_rules! wrap_option {
                 () => (None);
                 ($x:literal) => (Some($x));
             }
 
-            pub(crate) fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
+            pub fn get_configuration_metadata() -> Vec<ClippyConfiguration> {
                 vec![
                     $(
                         {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
index 3d0d4a52511..7a1cd3effae 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs
@@ -8,7 +8,11 @@
 //! a simple mistake)
 
 use crate::renamed_lints::RENAMED_LINTS;
-use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
+use crate::utils::{
+    collect_configs,
+    internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type},
+    ClippyConfiguration,
+};
 
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
@@ -520,111 +524,6 @@ impl Serialize for ApplicabilityInfo {
     }
 }
 
-// ==================================================================
-// Configuration
-// ==================================================================
-#[derive(Debug, Clone, Default)]
-pub struct ClippyConfiguration {
-    name: String,
-    config_type: &'static str,
-    default: String,
-    lints: Vec<String>,
-    doc: String,
-    #[allow(dead_code)]
-    deprecation_reason: Option<&'static str>,
-}
-
-impl ClippyConfiguration {
-    pub fn new(
-        name: &'static str,
-        config_type: &'static str,
-        default: String,
-        doc_comment: &'static str,
-        deprecation_reason: Option<&'static str>,
-    ) -> Self {
-        let (lints, doc) = parse_config_field_doc(doc_comment)
-            .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
-
-        Self {
-            name: to_kebab(name),
-            lints,
-            doc,
-            config_type,
-            default,
-            deprecation_reason,
-        }
-    }
-
-    fn to_markdown_paragraph(&self) -> String {
-        format!(
-            "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
-            self.name,
-            self.doc
-                .lines()
-                .map(|line| line.strip_prefix("    ").unwrap_or(line))
-                .join("\n"),
-            self.default,
-            self.config_type,
-            self.lints
-                .iter()
-                .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
-                .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
-                .join("\n"),
-        )
-    }
-
-    fn to_markdown_table_entry(&self) -> String {
-        format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
-    }
-}
-
-fn collect_configs() -> Vec<ClippyConfiguration> {
-    crate::utils::conf::metadata::get_configuration_metadata()
-}
-
-/// This parses the field documentation of the config struct.
-///
-/// ```rust, ignore
-/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
-/// ```
-///
-/// Would yield:
-/// ```rust, ignore
-/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
-/// ```
-fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
-    const DOC_START: &str = " Lint: ";
-    if_chain! {
-        if doc_comment.starts_with(DOC_START);
-        if let Some(split_pos) = doc_comment.find('.');
-        then {
-            let mut doc_comment = doc_comment.to_string();
-            let mut documentation = doc_comment.split_off(split_pos);
-
-            // Extract lints
-            doc_comment.make_ascii_lowercase();
-            let lints: Vec<String> = doc_comment
-                .split_off(DOC_START.len())
-                .split(", ")
-                .map(str::to_string)
-                .collect();
-
-            // Format documentation correctly
-            // split off leading `.` from lint name list and indent for correct formatting
-            documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n    ");
-
-            Some((lints, documentation))
-        } else {
-            None
-        }
-    }
-}
-
-/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
-fn to_kebab(config_name: &str) -> String {
-    config_name.replace('_', "-")
-}
-
 impl fmt::Display for ClippyConfiguration {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
         writeln!(
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index dc647af264c..d3ea7cafa80 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -4,3 +4,143 @@ pub mod dump_hir;
 pub mod format_args_collector;
 #[cfg(feature = "internal")]
 pub mod internal_lints;
+#[cfg(feature = "internal")]
+use itertools::Itertools;
+
+/// Transforms a given `snake_case_string` to a tasty `kebab-case-string`
+fn to_kebab(config_name: &str) -> String {
+    config_name.replace('_', "-")
+}
+
+// ==================================================================
+// Configuration
+// ==================================================================
+#[derive(Debug, Clone, Default)] //~ ERROR no such field
+pub struct ClippyConfiguration {
+    pub name: String,
+    #[allow(dead_code)]
+    config_type: &'static str,
+    pub default: String,
+    pub lints: Vec<String>,
+    pub doc: String,
+    #[allow(dead_code)]
+    deprecation_reason: Option<&'static str>,
+}
+
+impl ClippyConfiguration {
+    pub fn new(
+        name: &'static str,
+        config_type: &'static str,
+        default: String,
+        doc_comment: &'static str,
+        deprecation_reason: Option<&'static str>,
+    ) -> Self {
+        let (lints, doc) = parse_config_field_doc(doc_comment)
+            .unwrap_or_else(|| (vec![], "[ERROR] MALFORMED DOC COMMENT".to_string()));
+
+        Self {
+            name: to_kebab(name),
+            lints,
+            doc,
+            config_type,
+            default,
+            deprecation_reason,
+        }
+    }
+
+    #[cfg(feature = "internal")]
+    fn to_markdown_paragraph(&self) -> String {
+        format!(
+            "### {}\n{}\n\n**Default Value:** `{}` (`{}`)\n\n{}\n\n",
+            self.name,
+            self.doc
+                .lines()
+                .map(|line| line.strip_prefix("    ").unwrap_or(line))
+                .join("\n"),
+            self.default,
+            self.config_type,
+            self.lints
+                .iter()
+                .map(|name| name.to_string().split_whitespace().next().unwrap().to_string())
+                .map(|name| format!("* [{name}](https://rust-lang.github.io/rust-clippy/master/index.html#{name})"))
+                .join("\n"),
+        )
+    }
+
+    #[cfg(feature = "internal")]
+    fn to_markdown_table_entry(&self) -> String {
+        format!("| [{}](#{}) | `{}` |", self.name, self.name, self.default)
+    }
+}
+
+#[cfg(feature = "internal")]
+fn collect_configs() -> Vec<ClippyConfiguration> {
+    crate::utils::conf::metadata::get_configuration_metadata()
+}
+
+/// This parses the field documentation of the config struct.
+///
+/// ```rust, ignore
+/// parse_config_field_doc(cx, "Lint: LINT_NAME_1, LINT_NAME_2. Papa penguin, papa penguin")
+/// ```
+///
+/// Would yield:
+/// ```rust, ignore
+/// Some(["lint_name_1", "lint_name_2"], "Papa penguin, papa penguin")
+/// ```
+fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
+    const DOC_START: &str = " Lint: ";
+    if_chain! {
+        if doc_comment.starts_with(DOC_START);
+        if let Some(split_pos) = doc_comment.find('.');
+        then {
+            let mut doc_comment = doc_comment.to_string();
+            let mut documentation = doc_comment.split_off(split_pos);
+
+            // Extract lints
+            doc_comment.make_ascii_lowercase();
+            let lints: Vec<String> = doc_comment
+                .split_off(DOC_START.len())
+                .split(", ")
+                .map(str::to_string)
+                .collect();
+
+            // Format documentation correctly
+            // split off leading `.` from lint name list and indent for correct formatting
+            documentation = documentation.trim_start_matches('.').trim().replace("\n ", "\n    ");
+
+            Some((lints, documentation))
+        } else {
+            None
+        }
+    }
+}
+
+// Shamelessly stolen from find_all (https://github.com/nectariner/find_all)
+pub trait FindAll: Iterator + Sized {
+    fn find_all<P>(&mut self, predicate: P) -> Option<Vec<usize>>
+    where
+        P: FnMut(&Self::Item) -> bool;
+}
+
+impl<I> FindAll for I
+where
+    I: Iterator,
+{
+    fn find_all<P>(&mut self, mut predicate: P) -> Option<Vec<usize>>
+    where
+        P: FnMut(&Self::Item) -> bool,
+    {
+        let mut occurences = Vec::<usize>::default();
+        for (index, element) in self.enumerate() {
+            if predicate(&element) {
+                occurences.push(index);
+            }
+        }
+
+        match occurences.len() {
+            0 => None,
+            _ => Some(occurences),
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index 297a80e5767..7329e508106 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -84,7 +84,7 @@ impl UselessVec {
         let mut applicability = Applicability::MachineApplicable;
         let snippet = match *vec_args {
             higher::VecArgs::Repeat(elem, len) => {
-                if let Some((Constant::Int(len_constant), _)) = constant(cx, cx.typeck_results(), len) {
+                if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
                     #[expect(clippy::cast_possible_truncation)]
                     if len_constant as u64 * size_of(cx, elem) > self.too_large_for_stack {
                         return;
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 36f910c983f..a9089fba3c5 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -7,7 +7,7 @@ use rustc_hir::{
     def::{DefKind, Res},
     Item, ItemKind, PathSegment, UseKind,
 };
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::kw;
@@ -117,6 +117,10 @@ impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]);
 
 impl LateLintPass<'_> for WildcardImports {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        if cx.sess().is_test_crate() {
+            return;
+        }
+
         if is_test_module_or_function(cx.tcx, item) {
             self.test_modules_deep = self.test_modules_deep.saturating_add(1);
         }
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 8075881e3bb..fb772644c0d 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -1,18 +1,21 @@
 #![allow(clippy::float_cmp)]
 
+use crate::source::{get_source_text, walk_span_to_context};
 use crate::{clip, is_direct_expn_of, sext, unsext};
 use if_chain::if_chain;
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
+use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::ty::SubstsRef;
 use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
+use rustc_middle::ty::{List, SubstsRef};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Symbol;
+use rustc_span::SyntaxContext;
 use std::cmp::Ordering::{self, Equal};
 use std::hash::{Hash, Hasher};
 use std::iter;
@@ -210,8 +213,7 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
     match *lit {
         LitKind::Str(ref is, _) => Constant::Str(is.to_string()),
         LitKind::Byte(b) => Constant::Int(u128::from(b)),
-        LitKind::ByteStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
-        LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
+        LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)),
         LitKind::Char(c) => Constant::Char(c),
         LitKind::Int(n, _) => Constant::Int(n),
         LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty {
@@ -228,27 +230,46 @@ pub fn lit_to_mir_constant(lit: &LitKind, ty: Option<Ty<'_>>) -> Constant {
     }
 }
 
+/// The source of a constant value.
+pub enum ConstantSource {
+    /// The value is determined solely from the expression.
+    Local,
+    /// The value is dependent on a defined constant.
+    Constant,
+}
+impl ConstantSource {
+    pub fn is_local(&self) -> bool {
+        matches!(self, Self::Local)
+    }
+}
+
+/// Attempts to evaluate the expression as a constant.
 pub fn constant<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
-) -> Option<(Constant, bool)> {
-    let mut cx = ConstEvalLateContext {
-        lcx,
-        typeck_results,
-        param_env: lcx.param_env,
-        needed_resolution: false,
-        substs: ty::List::empty(),
-    };
-    cx.expr(e).map(|cst| (cst, cx.needed_resolution))
+) -> Option<Constant> {
+    ConstEvalLateContext::new(lcx, typeck_results).expr(e)
+}
+
+/// Attempts to evaluate the expression as a constant.
+pub fn constant_with_source<'tcx>(
+    lcx: &LateContext<'tcx>,
+    typeck_results: &ty::TypeckResults<'tcx>,
+    e: &Expr<'_>,
+) -> Option<(Constant, ConstantSource)> {
+    let mut ctxt = ConstEvalLateContext::new(lcx, typeck_results);
+    let res = ctxt.expr(e);
+    res.map(|x| (x, ctxt.source))
 }
 
+/// Attempts to evaluate an expression only if it's value is not dependent on other items.
 pub fn constant_simple<'tcx>(
     lcx: &LateContext<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     e: &Expr<'_>,
 ) -> Option<Constant> {
-    constant(lcx, typeck_results, e).and_then(|(cst, res)| if res { None } else { Some(cst) })
+    constant_with_source(lcx, typeck_results, e).and_then(|(c, s)| s.is_local().then_some(c))
 }
 
 pub fn constant_full_int<'tcx>(
@@ -297,29 +318,25 @@ impl Ord for FullInt {
     }
 }
 
-/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckResults`.
-pub fn constant_context<'a, 'tcx>(
-    lcx: &'a LateContext<'tcx>,
-    typeck_results: &'a ty::TypeckResults<'tcx>,
-) -> ConstEvalLateContext<'a, 'tcx> {
-    ConstEvalLateContext {
-        lcx,
-        typeck_results,
-        param_env: lcx.param_env,
-        needed_resolution: false,
-        substs: ty::List::empty(),
-    }
-}
-
 pub struct ConstEvalLateContext<'a, 'tcx> {
     lcx: &'a LateContext<'tcx>,
     typeck_results: &'a ty::TypeckResults<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    needed_resolution: bool,
+    source: ConstantSource,
     substs: SubstsRef<'tcx>,
 }
 
 impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
+    fn new(lcx: &'a LateContext<'tcx>, typeck_results: &'a ty::TypeckResults<'tcx>) -> Self {
+        Self {
+            lcx,
+            typeck_results,
+            param_env: lcx.param_env,
+            source: ConstantSource::Local,
+            substs: List::empty(),
+        }
+    }
+
     /// Simple constant folding: Insert an expression, get a constant or none.
     pub fn expr(&mut self, e: &Expr<'_>) -> Option<Constant> {
         match e.kind {
@@ -454,11 +471,9 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
                     .const_eval_resolve(self.param_env, mir::UnevaluatedConst::new(def_id, substs), None)
                     .ok()
                     .map(|val| rustc_middle::mir::ConstantKind::from_value(val, ty))?;
-                let result = miri_to_const(self.lcx.tcx, result);
-                if result.is_some() {
-                    self.needed_resolution = true;
-                }
-                result
+                let result = miri_to_const(self.lcx.tcx, result)?;
+                self.source = ConstantSource::Constant;
+                Some(result)
             },
             // FIXME: cover all usable cases.
             _ => None,
@@ -492,8 +507,33 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
 
     /// A block can only yield a constant if it only has one constant expression.
     fn block(&mut self, block: &Block<'_>) -> Option<Constant> {
-        if block.stmts.is_empty() {
-            block.expr.as_ref().and_then(|b| self.expr(b))
+        if block.stmts.is_empty()
+            && let Some(expr) = block.expr
+        {
+            // Try to detect any `cfg`ed statements or empty macro expansions.
+            let span = block.span.data();
+            if span.ctxt == SyntaxContext::root() {
+                if let Some(expr_span) = walk_span_to_context(expr.span, span.ctxt)
+                    && let expr_lo = expr_span.lo()
+                    && expr_lo >= span.lo
+                    && let Some(src) = get_source_text(self.lcx, span.lo..expr_lo)
+                    && let Some(src) = src.as_str()
+                {
+                    use rustc_lexer::TokenKind::{Whitespace, LineComment, BlockComment, Semi, OpenBrace};
+                    if !tokenize(src)
+                        .map(|t| t.kind)
+                        .filter(|t| !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi))
+                        .eq([OpenBrace])
+                    {
+                        self.source = ConstantSource::Constant;
+                    }
+                } else {
+                    // Unable to access the source. Assume a non-local dependency.
+                    self.source = ConstantSource::Constant;
+                }
+            }
+
+            self.expr(expr)
         } else {
             None
         }
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 9b7408d5133..a49246a7832 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -1,6 +1,7 @@
 use crate::consts::constant_simple;
 use crate::macros::macro_backtrace;
-use crate::source::snippet_opt;
+use crate::source::{get_source_text, snippet_opt, walk_span_to_context, SpanRange};
+use crate::tokenize_with_text;
 use rustc_ast::ast::InlineAsmTemplatePiece;
 use rustc_data_structures::fx::FxHasher;
 use rustc_hir::def::Res;
@@ -13,8 +14,9 @@ use rustc_hir::{
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::TypeckResults;
-use rustc_span::{sym, Symbol};
+use rustc_span::{sym, BytePos, ExpnKind, MacroKind, Symbol, SyntaxContext};
 use std::hash::{Hash, Hasher};
+use std::ops::Range;
 
 /// Callback that is called when two expressions are not equal in the sense of `SpanlessEq`, but
 /// other conditions would make them equal.
@@ -65,6 +67,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
     pub fn inter_expr(&mut self) -> HirEqInterExpr<'_, 'a, 'tcx> {
         HirEqInterExpr {
             inner: self,
+            left_ctxt: SyntaxContext::root(),
+            right_ctxt: SyntaxContext::root(),
             locals: HirIdMap::default(),
         }
     }
@@ -92,6 +96,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
 
 pub struct HirEqInterExpr<'a, 'b, 'tcx> {
     inner: &'a mut SpanlessEq<'b, 'tcx>,
+    left_ctxt: SyntaxContext,
+    right_ctxt: SyntaxContext,
 
     // When binding are declared, the binding ID in the left expression is mapped to the one on the
     // right. For example, when comparing `{ let x = 1; x + 2 }` and `{ let y = 1; y + 2 }`,
@@ -126,52 +132,88 @@ impl HirEqInterExpr<'_, '_, '_> {
     }
 
     /// Checks whether two blocks are the same.
+    #[expect(clippy::similar_names)]
     fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool {
-        match (left.stmts, left.expr, right.stmts, right.expr) {
-            ([], None, [], None) => {
-                // For empty blocks, check to see if the tokens are equal. This will catch the case where a macro
-                // expanded to nothing, or the cfg attribute was used.
-                let (Some(left), Some(right)) = (
-                    snippet_opt(self.inner.cx, left.span),
-                    snippet_opt(self.inner.cx, right.span),
-                ) else { return true };
-                let mut left_pos = 0;
-                let left = tokenize(&left)
-                    .map(|t| {
-                        let end = left_pos + t.len as usize;
-                        let s = &left[left_pos..end];
-                        left_pos = end;
-                        (t, s)
-                    })
-                    .filter(|(t, _)| {
-                        !matches!(
-                            t.kind,
-                            TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
-                        )
-                    })
-                    .map(|(_, s)| s);
-                let mut right_pos = 0;
-                let right = tokenize(&right)
-                    .map(|t| {
-                        let end = right_pos + t.len as usize;
-                        let s = &right[right_pos..end];
-                        right_pos = end;
-                        (t, s)
-                    })
-                    .filter(|(t, _)| {
-                        !matches!(
-                            t.kind,
-                            TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace
-                        )
-                    })
-                    .map(|(_, s)| s);
-                left.eq(right)
-            },
-            _ => {
-                over(left.stmts, right.stmts, |l, r| self.eq_stmt(l, r))
-                    && both(&left.expr, &right.expr, |l, r| self.eq_expr(l, r))
-            },
+        use TokenKind::{BlockComment, LineComment, Semi, Whitespace};
+        if left.stmts.len() != right.stmts.len() {
+            return false;
+        }
+        let lspan = left.span.data();
+        let rspan = right.span.data();
+        if lspan.ctxt != SyntaxContext::root() && rspan.ctxt != SyntaxContext::root() {
+            // Don't try to check in between statements inside macros.
+            return over(left.stmts, right.stmts, |left, right| self.eq_stmt(left, right))
+                && both(&left.expr, &right.expr, |left, right| self.eq_expr(left, right));
+        }
+        if lspan.ctxt != rspan.ctxt {
+            return false;
         }
+
+        let mut lstart = lspan.lo;
+        let mut rstart = rspan.lo;
+
+        for (left, right) in left.stmts.iter().zip(right.stmts) {
+            if !self.eq_stmt(left, right) {
+                return false;
+            }
+
+            // Try to detect any `cfg`ed statements or empty macro expansions.
+            let Some(lstmt_span) = walk_span_to_context(left.span, lspan.ctxt) else {
+                return false;
+            };
+            let Some(rstmt_span) = walk_span_to_context(right.span, rspan.ctxt) else {
+                return false;
+            };
+            let lstmt_span = lstmt_span.data();
+            let rstmt_span = rstmt_span.data();
+
+            if lstmt_span.lo < lstart && rstmt_span.lo < rstart {
+                // Can happen when macros expand to multiple statements, or rearrange statements.
+                // Nothing in between the statements to check in this case.
+                continue;
+            }
+            if lstmt_span.lo < lstart || rstmt_span.lo < rstart {
+                // Only one of the blocks had a weird macro.
+                return false;
+            }
+            if !eq_span_tokens(self.inner.cx, lstart..lstmt_span.lo, rstart..rstmt_span.lo, |t| {
+                !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+            }) {
+                return false;
+            }
+
+            lstart = lstmt_span.hi;
+            rstart = rstmt_span.hi;
+        }
+
+        let (lend, rend) = match (left.expr, right.expr) {
+            (Some(left), Some(right)) => {
+                if !self.eq_expr(left, right) {
+                    return false;
+                }
+                let Some(lexpr_span) = walk_span_to_context(left.span, lspan.ctxt) else {
+                    return false;
+                };
+                let Some(rexpr_span) = walk_span_to_context(right.span, rspan.ctxt) else {
+                    return false;
+                };
+                (lexpr_span.lo(), rexpr_span.lo())
+            },
+            (None, None) => (lspan.hi, rspan.hi),
+            (Some(_), None) | (None, Some(_)) => return false,
+        };
+
+        if lend < lstart && rend < rstart {
+            // Can happen when macros rearrange the input.
+            // Nothing in between the statements to check in this case.
+            return true;
+        } else if lend < lstart || rend < rstart {
+            // Only one of the blocks had a weird macro
+            return false;
+        }
+        eq_span_tokens(self.inner.cx, lstart..lend, rstart..rend, |t| {
+            !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+        })
     }
 
     fn should_ignore(&mut self, expr: &Expr<'_>) -> bool {
@@ -207,7 +249,7 @@ impl HirEqInterExpr<'_, '_, '_> {
 
     #[expect(clippy::similar_names)]
     pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
-        if !self.inner.allow_side_effects && left.span.ctxt() != right.span.ctxt() {
+        if !self.check_ctxt(left.span.ctxt(), right.span.ctxt()) {
             return false;
         }
 
@@ -440,6 +482,45 @@ impl HirEqInterExpr<'_, '_, '_> {
     fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) -> bool {
         left.ident.name == right.ident.name && self.eq_ty(left.ty(), right.ty())
     }
+
+    fn check_ctxt(&mut self, left: SyntaxContext, right: SyntaxContext) -> bool {
+        if self.left_ctxt == left && self.right_ctxt == right {
+            return true;
+        } else if self.left_ctxt == left || self.right_ctxt == right {
+            // Only one context has changed. This can only happen if the two nodes are written differently.
+            return false;
+        } else if left != SyntaxContext::root() {
+            let mut left_data = left.outer_expn_data();
+            let mut right_data = right.outer_expn_data();
+            loop {
+                use TokenKind::{BlockComment, LineComment, Whitespace};
+                if left_data.macro_def_id != right_data.macro_def_id
+                    || (matches!(left_data.kind, ExpnKind::Macro(MacroKind::Bang, name) if name == sym::cfg)
+                        && !eq_span_tokens(self.inner.cx, left_data.call_site, right_data.call_site, |t| {
+                            !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. })
+                        }))
+                {
+                    // Either a different chain of macro calls, or different arguments to the `cfg` macro.
+                    return false;
+                }
+                let left_ctxt = left_data.call_site.ctxt();
+                let right_ctxt = right_data.call_site.ctxt();
+                if left_ctxt == SyntaxContext::root() && right_ctxt == SyntaxContext::root() {
+                    break;
+                }
+                if left_ctxt == SyntaxContext::root() || right_ctxt == SyntaxContext::root() {
+                    // Different lengths for the expansion stack. This can only happen if nodes are written differently,
+                    // or shouldn't be compared to start with.
+                    return false;
+                }
+                left_data = left_ctxt.outer_expn_data();
+                right_data = right_ctxt.outer_expn_data();
+            }
+        }
+        self.left_ctxt = left;
+        self.right_ctxt = right;
+        true
+    }
 }
 
 /// Some simple reductions like `{ return }` => `return`
@@ -1038,3 +1119,34 @@ pub fn hash_expr(cx: &LateContext<'_>, e: &Expr<'_>) -> u64 {
     h.hash_expr(e);
     h.finish()
 }
+
+#[expect(clippy::similar_names)]
+fn eq_span_tokens(
+    cx: &LateContext<'_>,
+    left: impl SpanRange,
+    right: impl SpanRange,
+    pred: impl Fn(TokenKind) -> bool,
+) -> bool {
+    fn f(cx: &LateContext<'_>, left: Range<BytePos>, right: Range<BytePos>, pred: impl Fn(TokenKind) -> bool) -> bool {
+        if let Some(lsrc) = get_source_text(cx, left)
+            && let Some(lsrc) = lsrc.as_str()
+            && let Some(rsrc) = get_source_text(cx, right)
+            && let Some(rsrc) = rsrc.as_str()
+        {
+            let pred = |t: &(_, _)| pred(t.0);
+            let map = |(_, x)| x;
+
+            let ltok = tokenize_with_text(lsrc)
+                .filter(pred)
+                .map(map);
+            let rtok = tokenize_with_text(rsrc)
+                .filter(pred)
+                .map(map);
+            ltok.eq(rtok)
+        } else {
+            // Unable to access the source. Conservatively assume the blocks aren't equal.
+            false
+        }
+    }
+    f(cx, left.into_range(), right.into_range(), pred)
+}
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 964104fc31d..575c29a6b6f 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -1,5 +1,6 @@
 #![feature(array_chunks)]
 #![feature(box_patterns)]
+#![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(lint_reasons)]
 #![feature(never_type)]
@@ -76,6 +77,7 @@ use std::sync::OnceLock;
 use std::sync::{Mutex, MutexGuard};
 
 use if_chain::if_chain;
+use itertools::Itertools;
 use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashMap;
@@ -282,6 +284,15 @@ pub fn is_wild(pat: &Pat<'_>) -> bool {
     matches!(pat.kind, PatKind::Wild)
 }
 
+/// Checks if the given `QPath` belongs to a type alias.
+pub fn is_ty_alias(qpath: &QPath<'_>) -> bool {
+    match *qpath {
+        QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias, ..)),
+        QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => { is_ty_alias(&qpath) },
+        _ => false,
+    }
+}
+
 /// Checks if the method call given in `expr` belongs to the given trait.
 /// This is a deprecated function, consider using [`is_trait_method`].
 pub fn match_trait_method(cx: &LateContext<'_>, expr: &Expr<'_>, path: &[&str]) -> bool {
@@ -1488,7 +1499,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                 && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, min_val.to_valtree()))
                 && let min_const_kind = ConstantKind::from_value(const_val, bnd_ty)
                 && let Some(min_const) = miri_to_const(cx.tcx, min_const_kind)
-                && let Some((start_const, _)) = constant(cx, cx.typeck_results(), start)
+                && let Some(start_const) = constant(cx, cx.typeck_results(), start)
             {
                 start_const == min_const
             } else {
@@ -1504,7 +1515,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti
                         && let const_val = cx.tcx.valtree_to_const_val((bnd_ty, max_val.to_valtree()))
                         && let max_const_kind = ConstantKind::from_value(const_val, bnd_ty)
                         && let Some(max_const) = miri_to_const(cx.tcx, max_const_kind)
-                        && let Some((end_const, _)) = constant(cx, cx.typeck_results(), end)
+                        && let Some(end_const) = constant(cx, cx.typeck_results(), end)
                     {
                         end_const == max_const
                     } else {
@@ -1536,7 +1547,7 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
         return true;
     }
     let enclosing_body = cx.tcx.hir().enclosing_body_owner(e.hir_id);
-    if let Some((Constant::Int(v), _)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
+    if let Some(Constant::Int(v)) = constant(cx, cx.tcx.typeck(enclosing_body), e) {
         return value == v;
     }
     false
@@ -2480,6 +2491,17 @@ pub fn walk_to_expr_usage<'tcx, T>(
     None
 }
 
+/// Tokenizes the input while keeping the text associated with each token.
+pub fn tokenize_with_text(s: &str) -> impl Iterator<Item = (TokenKind, &str)> {
+    let mut pos = 0;
+    tokenize(s).map(move |t| {
+        let end = pos + t.len;
+        let range = pos as usize..end as usize;
+        pos = end;
+        (t.kind, s.get(range).unwrap_or_default())
+    })
+}
+
 /// Checks whether a given span has any comment token
 /// This checks for all types of comment: line "//", block "/**", doc "///" "//!"
 pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
@@ -2496,23 +2518,11 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
 /// Comments are returned wrapped with their relevant delimiters
 pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
     let snippet = sm.span_to_snippet(span).unwrap_or_default();
-    let mut comments_buf: Vec<String> = Vec::new();
-    let mut index: usize = 0;
-
-    for token in tokenize(&snippet) {
-        let token_range = index..(index + token.len as usize);
-        index += token.len as usize;
-        match token.kind {
-            TokenKind::BlockComment { .. } | TokenKind::LineComment { .. } => {
-                if let Some(comment) = snippet.get(token_range) {
-                    comments_buf.push(comment.to_string());
-                }
-            },
-            _ => (),
-        }
-    }
-
-    comments_buf.join("\n")
+    let res = tokenize_with_text(&snippet)
+        .filter(|(t, _)| matches!(t, TokenKind::BlockComment { .. } | TokenKind::LineComment { .. }))
+        .map(|(_, s)| s)
+        .join("\n");
+    res
 }
 
 pub fn span_find_starting_semi(sm: &SourceMap, span: Span) -> Span {
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index 62fa37660fa..0f60290644a 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -2,14 +2,64 @@
 
 #![allow(clippy::module_name_repetitions)]
 
+use rustc_data_structures::sync::Lrc;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_session::Session;
-use rustc_span::hygiene;
 use rustc_span::source_map::{original_sp, SourceMap};
+use rustc_span::{hygiene, SourceFile};
 use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
 use std::borrow::Cow;
+use std::ops::Range;
+
+/// A type which can be converted to the range portion of a `Span`.
+pub trait SpanRange {
+    fn into_range(self) -> Range<BytePos>;
+}
+impl SpanRange for Span {
+    fn into_range(self) -> Range<BytePos> {
+        let data = self.data();
+        data.lo..data.hi
+    }
+}
+impl SpanRange for SpanData {
+    fn into_range(self) -> Range<BytePos> {
+        self.lo..self.hi
+    }
+}
+impl SpanRange for Range<BytePos> {
+    fn into_range(self) -> Range<BytePos> {
+        self
+    }
+}
+
+pub struct SourceFileRange {
+    pub sf: Lrc<SourceFile>,
+    pub range: Range<usize>,
+}
+impl SourceFileRange {
+    /// Attempts to get the text from the source file. This can fail if the source text isn't
+    /// loaded.
+    pub fn as_str(&self) -> Option<&str> {
+        self.sf.src.as_ref().and_then(|x| x.get(self.range.clone()))
+    }
+}
+
+/// Gets the source file, and range in the file, of the given span. Returns `None` if the span
+/// extends through multiple files, or is malformed.
+pub fn get_source_text(cx: &impl LintContext, sp: impl SpanRange) -> Option<SourceFileRange> {
+    fn f(sm: &SourceMap, sp: Range<BytePos>) -> Option<SourceFileRange> {
+        let start = sm.lookup_byte_offset(sp.start);
+        let end = sm.lookup_byte_offset(sp.end);
+        if !Lrc::ptr_eq(&start.sf, &end.sf) || start.pos > end.pos {
+            return None;
+        }
+        let range = start.pos.to_usize()..end.pos.to_usize();
+        Some(SourceFileRange { sf: start.sf, range })
+    }
+    f(cx.sess().source_map(), sp.into_range())
+}
 
 /// Like `snippet_block`, but add braces if the expr is not an `ExprKind::Block`.
 pub fn expr_block<T: LintContext>(
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 60b8a5ac071..bc7fb711ed8 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-05-05"
+channel = "nightly-2023-05-20"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
index acb98d7ba98..99ce7028390 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
@@ -3,6 +3,7 @@
 //@normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs"
 //@normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
 //@normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
+//@normalize-stderr-test: "running on .*" -> "running on <target>"
 //@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
 
 #![deny(clippy::internal)]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
index b4619e980f3..0fc385cd693 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -1,12 +1,14 @@
 thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
-error: internal compiler error: unexpected panic
-
-note: the compiler unexpectedly panicked. this is a bug.
+error: the compiler unexpectedly panicked. this is a bug.
 
 note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new
 
+note: rustc 1.71.0-nightly (521f4dae1 2023-05-19) running on <target>
+
+note: compiler flags: -C prefer-dynamic -Z ui-testing
+
 note: Clippy version: foo
 
 thread panicked while panicking. aborting.
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index ab408bdf261..f95af1017bc 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -458,4 +458,12 @@ pub fn issue_10583(a: u16) -> u16 {
     10 / a
 }
 
+pub fn issue_10767() {
+    let n = &1.0;
+    n + n;
+    3.1_f32 + &1.2_f32;
+    &3.4_f32 + 1.5_f32;
+    &3.5_f32 + &1.3_f32;
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
index 165e4bc8272..75526461792 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.fixed
@@ -1,7 +1,11 @@
 //@run-rustfix
+//@aux-build: proc_macros.rs
 
 #![allow(dead_code, unused_variables)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 fn main() {}
 
 mod should_lint {
@@ -47,6 +51,17 @@ mod should_not_lint2 {
     }
 }
 
+with_span!(
+    span
+
+    fn just_returning(x: &u32) -> &u32 {
+        x
+    }
+
+    fn dont_lint_proc_macro() {
+        let a = &mut &*just_returning(&12);
+    }
+);
 // this mod explains why we should not lint `& &* (&T)`
 mod false_negative {
     fn foo() {
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.rs b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
index 66c8d69bef9..e319d365f7e 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.rs
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.rs
@@ -1,7 +1,11 @@
 //@run-rustfix
+//@aux-build: proc_macros.rs
 
 #![allow(dead_code, unused_variables)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
 fn main() {}
 
 mod should_lint {
@@ -47,6 +51,17 @@ mod should_not_lint2 {
     }
 }
 
+with_span!(
+    span
+
+    fn just_returning(x: &u32) -> &u32 {
+        x
+    }
+
+    fn dont_lint_proc_macro() {
+        let a = &mut &*just_returning(&12);
+    }
+);
 // this mod explains why we should not lint `& &* (&T)`
 mod false_negative {
     fn foo() {
diff --git a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
index d72de37c69f..1e47cda6796 100644
--- a/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
+++ b/src/tools/clippy/tests/ui/borrow_deref_ref.stderr
@@ -1,5 +1,5 @@
 error: deref on an immutable reference
-  --> $DIR/borrow_deref_ref.rs:10:17
+  --> $DIR/borrow_deref_ref.rs:14:17
    |
 LL |         let b = &*a;
    |                 ^^^ help: if you would like to reborrow, try removing `&*`: `a`
@@ -7,13 +7,13 @@ LL |         let b = &*a;
    = note: `-D clippy::borrow-deref-ref` implied by `-D warnings`
 
 error: deref on an immutable reference
-  --> $DIR/borrow_deref_ref.rs:12:22
+  --> $DIR/borrow_deref_ref.rs:16:22
    |
 LL |         let b = &mut &*bar(&12);
    |                      ^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `bar(&12)`
 
 error: deref on an immutable reference
-  --> $DIR/borrow_deref_ref.rs:55:23
+  --> $DIR/borrow_deref_ref.rs:70:23
    |
 LL |         let addr_y = &&*x as *const _ as usize; // assert ok
    |                       ^^^ help: if you would like to reborrow, try removing `&*`: `x`
diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed
index e6331290420..840902b5323 100644
--- a/src/tools/clippy/tests/ui/box_default.fixed
+++ b/src/tools/clippy/tests/ui/box_default.fixed
@@ -35,6 +35,13 @@ fn main() {
     let _more = ret_ty_fn();
     call_ty_fn(Box::default());
     issue_10381();
+
+    // `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
+    // `Box::<Option<[closure@...]>::default()`
+    //
+    // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
+    let mut unnameable = Box::new(Option::default());
+    let _ = unnameable.insert(|| {});
 }
 
 fn ret_ty_fn() -> Box<bool> {
diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs
index 34a05a29c5a..3618486a473 100644
--- a/src/tools/clippy/tests/ui/box_default.rs
+++ b/src/tools/clippy/tests/ui/box_default.rs
@@ -35,6 +35,13 @@ fn main() {
     let _more = ret_ty_fn();
     call_ty_fn(Box::new(u8::default()));
     issue_10381();
+
+    // `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
+    // `Box::<Option<[closure@...]>::default()`
+    //
+    // Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
+    let mut unnameable = Box::new(Option::default());
+    let _ = unnameable.insert(|| {});
 }
 
 fn ret_ty_fn() -> Box<bool> {
diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr
index c9834863601..13dfc5ae48a 100644
--- a/src/tools/clippy/tests/ui/box_default.stderr
+++ b/src/tools/clippy/tests/ui/box_default.stderr
@@ -73,25 +73,25 @@ LL |     call_ty_fn(Box::new(u8::default()));
    |                ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:41:5
+  --> $DIR/box_default.rs:48:5
    |
 LL |     Box::new(bool::default())
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:58:28
+  --> $DIR/box_default.rs:65:28
    |
 LL |     let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:67:17
+  --> $DIR/box_default.rs:74:17
    |
 LL |         let _ = Box::new(WeirdPathed::default());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:79:18
+  --> $DIR/box_default.rs:86:18
    |
 LL |             Some(Box::new(Foo::default()))
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Foo>::default()`
diff --git a/src/tools/clippy/tests/ui/collapsible_if.fixed b/src/tools/clippy/tests/ui/collapsible_if.fixed
index d2aba2ac59b..c6514a55934 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_if.fixed
@@ -1,5 +1,10 @@
 //@run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+#![allow(
+    clippy::assertions_on_constants,
+    clippy::equatable_if_let,
+    clippy::nonminimal_bool,
+    clippy::eq_op
+)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.rs b/src/tools/clippy/tests/ui/collapsible_if.rs
index e0bef7f9c97..2c85b68df63 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_if.rs
@@ -1,5 +1,10 @@
 //@run-rustfix
-#![allow(clippy::assertions_on_constants, clippy::equatable_if_let)]
+#![allow(
+    clippy::assertions_on_constants,
+    clippy::equatable_if_let,
+    clippy::nonminimal_bool,
+    clippy::eq_op
+)]
 
 #[rustfmt::skip]
 #[warn(clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/collapsible_if.stderr b/src/tools/clippy/tests/ui/collapsible_if.stderr
index 6327444df21..c687bae1acc 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_if.stderr
@@ -1,5 +1,5 @@
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:9:5
+  --> $DIR/collapsible_if.rs:14:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" {
@@ -17,7 +17,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:15:5
+  --> $DIR/collapsible_if.rs:20:5
    |
 LL | /     if x == "hello" || x == "world" {
 LL | |         if y == "world" || y == "hello" {
@@ -34,7 +34,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:21:5
+  --> $DIR/collapsible_if.rs:26:5
    |
 LL | /     if x == "hello" && x == "world" {
 LL | |         if y == "world" || y == "hello" {
@@ -51,7 +51,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:27:5
+  --> $DIR/collapsible_if.rs:32:5
    |
 LL | /     if x == "hello" || x == "world" {
 LL | |         if y == "world" && y == "hello" {
@@ -68,7 +68,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:33:5
+  --> $DIR/collapsible_if.rs:38:5
    |
 LL | /     if x == "hello" && x == "world" {
 LL | |         if y == "world" && y == "hello" {
@@ -85,7 +85,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:39:5
+  --> $DIR/collapsible_if.rs:44:5
    |
 LL | /     if 42 == 1337 {
 LL | |         if 'a' != 'A' {
@@ -102,7 +102,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:95:5
+  --> $DIR/collapsible_if.rs:100:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" { // Collapsible
@@ -119,7 +119,7 @@ LL +     }
    |
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:154:5
+  --> $DIR/collapsible_if.rs:159:5
    |
 LL | /     if matches!(true, true) {
 LL | |         if matches!(true, true) {}
@@ -127,7 +127,7 @@ LL | |     }
    | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
 
 error: this `if` statement can be collapsed
-  --> $DIR/collapsible_if.rs:159:5
+  --> $DIR/collapsible_if.rs:164:5
    |
 LL | /     if matches!(true, true) && truth() {
 LL | |         if matches!(true, true) {}
diff --git a/src/tools/clippy/tests/ui/dbg_macro.rs b/src/tools/clippy/tests/ui/dbg_macro.rs
index 8701e3cd29f..10788d40481 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.rs
+++ b/src/tools/clippy/tests/ui/dbg_macro.rs
@@ -4,6 +4,7 @@
 fn foo(n: u32) -> u32 {
     if let Some(n) = dbg!(n.checked_sub(4)) { n } else { n }
 }
+fn bar(_: ()) {}
 
 fn factorial(n: u32) -> u32 {
     if dbg!(n <= 1) {
@@ -21,6 +22,32 @@ fn main() {
     dbg!(1, 2, 3, 4, 5);
 }
 
+fn issue9914() {
+    macro_rules! foo {
+        ($x:expr) => {
+            $x;
+        };
+    }
+    macro_rules! foo2 {
+        ($x:expr) => {
+            $x;
+        };
+    }
+    macro_rules! expand_to_dbg {
+        () => {
+            dbg!();
+        };
+    }
+
+    dbg!();
+    #[allow(clippy::let_unit_value)]
+    let _ = dbg!();
+    bar(dbg!());
+    foo!(dbg!());
+    foo2!(foo!(dbg!()));
+    expand_to_dbg!();
+}
+
 mod issue7274 {
     trait Thing<'b> {
         fn foo(&self);
diff --git a/src/tools/clippy/tests/ui/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro.stderr
index ddb5f1342e9..530e7663317 100644
--- a/src/tools/clippy/tests/ui/dbg_macro.stderr
+++ b/src/tools/clippy/tests/ui/dbg_macro.stderr
@@ -11,7 +11,7 @@ LL |     if let Some(n) = n.checked_sub(4) { n } else { n }
    |                      ~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:9:8
+  --> $DIR/dbg_macro.rs:10:8
    |
 LL |     if dbg!(n <= 1) {
    |        ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL |     if n <= 1 {
    |        ~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:10:9
+  --> $DIR/dbg_macro.rs:11:9
    |
 LL |         dbg!(1)
    |         ^^^^^^^
@@ -33,7 +33,7 @@ LL |         1
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:12:9
+  --> $DIR/dbg_macro.rs:13:9
    |
 LL |         dbg!(n * factorial(n - 1))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -44,7 +44,7 @@ LL |         n * factorial(n - 1)
    |
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:17:5
+  --> $DIR/dbg_macro.rs:18:5
    |
 LL |     dbg!(42);
    |     ^^^^^^^^
@@ -55,7 +55,7 @@ LL |     42;
    |     ~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:18:5
+  --> $DIR/dbg_macro.rs:19:5
    |
 LL |     dbg!(dbg!(dbg!(42)));
    |     ^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL |     dbg!(dbg!(42));
    |     ~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:19:14
+  --> $DIR/dbg_macro.rs:20:14
    |
 LL |     foo(3) + dbg!(factorial(4));
    |              ^^^^^^^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL |     foo(3) + factorial(4);
    |              ~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:20:5
+  --> $DIR/dbg_macro.rs:21:5
    |
 LL |     dbg!(1, 2, dbg!(3, 4));
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -88,7 +88,7 @@ LL |     (1, 2, dbg!(3, 4));
    |     ~~~~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:21:5
+  --> $DIR/dbg_macro.rs:22:5
    |
 LL |     dbg!(1, 2, 3, 4, 5);
    |     ^^^^^^^^^^^^^^^^^^^
@@ -99,7 +99,63 @@ LL |     (1, 2, 3, 4, 5);
    |     ~~~~~~~~~~~~~~~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:41:9
+  --> $DIR/dbg_macro.rs:42:5
+   |
+LL |     dbg!();
+   |     ^^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL -     dbg!();
+LL +     
+   |
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:44:13
+   |
+LL |     let _ = dbg!();
+   |             ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     let _ = ();
+   |             ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:45:9
+   |
+LL |     bar(dbg!());
+   |         ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     bar(());
+   |         ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:46:10
+   |
+LL |     foo!(dbg!());
+   |          ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     foo!(());
+   |          ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:47:16
+   |
+LL |     foo2!(foo!(dbg!()));
+   |                ^^^^^^
+   |
+help: remove the invocation before committing it to a version control system
+   |
+LL |     foo2!(foo!(()));
+   |                ~~
+
+error: the `dbg!` macro is intended as a debugging tool
+  --> $DIR/dbg_macro.rs:68:9
    |
 LL |         dbg!(2);
    |         ^^^^^^^
@@ -110,7 +166,7 @@ LL |         2;
    |         ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:47:5
+  --> $DIR/dbg_macro.rs:74:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -121,7 +177,7 @@ LL |     1;
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:52:5
+  --> $DIR/dbg_macro.rs:79:5
    |
 LL |     dbg!(1);
    |     ^^^^^^^
@@ -132,7 +188,7 @@ LL |     1;
    |     ~
 
 error: the `dbg!` macro is intended as a debugging tool
-  --> $DIR/dbg_macro.rs:58:9
+  --> $DIR/dbg_macro.rs:85:9
    |
 LL |         dbg!(1);
    |         ^^^^^^^
@@ -142,5 +198,5 @@ help: remove the invocation before committing it to a version control system
 LL |         1;
    |         ~
 
-error: aborting due to 13 previous errors
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
index 4c2d1ea48e1..e1012f38bba 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.fixed
@@ -105,6 +105,7 @@ fn main() {
     // should lint
     let _ = PhantomData::<usize>;
     let _: PhantomData<i32> = PhantomData;
+    let _: PhantomData<i32> = std::marker::PhantomData;
     let _ = UnitStruct;
 
     // should not lint
@@ -116,4 +117,21 @@ fn main() {
     let _ = EmptyStruct::default();
     let _ = FakeDefault::default();
     let _ = <FakeDefault as Default>::default();
+
+    macro_rules! in_macro {
+        ($i:ident) => {{
+            let _ = UnitStruct::default();
+            let _ = $i::default();
+        }};
+    }
+
+    in_macro!(UnitStruct);
+
+    macro_rules! struct_from_macro {
+        () => {
+            UnitStruct
+        };
+    }
+
+    let _ = <struct_from_macro!()>::default();
 }
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
index 850793dd5de..c7b4313dbf0 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.rs
@@ -105,6 +105,7 @@ fn main() {
     // should lint
     let _ = PhantomData::<usize>::default();
     let _: PhantomData<i32> = PhantomData::default();
+    let _: PhantomData<i32> = std::marker::PhantomData::default();
     let _ = UnitStruct::default();
 
     // should not lint
@@ -116,4 +117,21 @@ fn main() {
     let _ = EmptyStruct::default();
     let _ = FakeDefault::default();
     let _ = <FakeDefault as Default>::default();
+
+    macro_rules! in_macro {
+        ($i:ident) => {{
+            let _ = UnitStruct::default();
+            let _ = $i::default();
+        }};
+    }
+
+    in_macro!(UnitStruct);
+
+    macro_rules! struct_from_macro {
+        () => {
+            UnitStruct
+        };
+    }
+
+    let _ = <struct_from_macro!()>::default();
 }
diff --git a/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
index 4058943d087..61a32fb10e5 100644
--- a/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
+++ b/src/tools/clippy/tests/ui/default_constructed_unit_structs.stderr
@@ -25,10 +25,16 @@ LL |     let _: PhantomData<i32> = PhantomData::default();
    |                                          ^^^^^^^^^^^ help: remove this call to `default`
 
 error: use of `default` to create a unit struct
-  --> $DIR/default_constructed_unit_structs.rs:108:23
+  --> $DIR/default_constructed_unit_structs.rs:108:55
+   |
+LL |     let _: PhantomData<i32> = std::marker::PhantomData::default();
+   |                                                       ^^^^^^^^^^^ help: remove this call to `default`
+
+error: use of `default` to create a unit struct
+  --> $DIR/default_constructed_unit_structs.rs:109:23
    |
 LL |     let _ = UnitStruct::default();
    |                       ^^^^^^^^^^^ help: remove this call to `default`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
new file mode 100644
index 00000000000..e843770f578
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
@@ -0,0 +1,132 @@
+//@aux-build:proc_macro_attr.rs
+#![warn(clippy::empty_line_after_doc_comments)]
+#![allow(clippy::assertions_on_constants)]
+#![feature(custom_inner_attributes)]
+#![rustfmt::skip]
+
+#[macro_use]
+extern crate proc_macro_attr;
+
+mod some_mod {
+    //! This doc comment should *NOT* produce a warning
+
+    mod some_inner_mod {
+        fn some_noop() {}
+    }
+}
+
+/// This should produce a warning
+
+fn with_doc_and_newline() { assert!(true)}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+/// some comment
+fn with_one_newline_and_comment() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/// some comment
+fn with_no_newline_and_comment() { assert!(true) }
+
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+fn with_one_newline() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+
+fn with_two_newlines() { assert!(true) }
+
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+enum Baz {
+    One,
+    Two
+}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+struct Foo {
+    one: isize,
+    two: isize
+}
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+
+mod foo {
+}
+
+/// This doc comment should produce a warning
+
+/** This is also a doc comment and should produce a warning
+ */
+
+// This should *NOT* produce a warning
+#[allow(non_camel_case_types)]
+#[allow(missing_docs)]
+#[allow(missing_docs)]
+fn three_attributes() { assert!(true) }
+
+// This should *NOT* produce a warning
+#[doc = "
+Returns the escaped value of the textual representation of
+
+"]
+pub fn function() -> bool {
+    true
+}
+
+// This should *NOT* produce a warning
+#[derive(Clone, Copy)]
+pub enum FooFighter {
+    Bar1,
+
+    Bar2,
+
+    Bar3,
+
+    Bar4
+}
+
+// This should *NOT* produce a warning because the empty line is inside a block comment
+#[crate_type = "lib"]
+/*
+
+*/
+pub struct S;
+
+// This should *NOT* produce a warning
+#[crate_type = "lib"]
+/* test */
+pub struct T;
+
+// This should *NOT* produce a warning
+// See https://github.com/rust-lang/rust-clippy/issues/5567
+#[fake_async_trait]
+pub trait Bazz {
+    fn foo() -> Vec<u8> {
+        let _i = "";
+
+
+
+        vec![]
+    }
+}
+
+#[derive(Clone, Copy)]
+#[dummy(string = "first line
+
+second line
+")]
+pub struct Args;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
new file mode 100644
index 00000000000..2ca1b51679e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.stderr
@@ -0,0 +1,36 @@
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+  --> $DIR/empty_line_after_doc_comments.rs:18:1
+   |
+LL | / /// This should produce a warning
+LL | |
+LL | | fn with_doc_and_newline() { assert!(true)}
+   | |_
+   |
+   = note: `-D clippy::empty-line-after-doc-comments` implied by `-D warnings`
+
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+  --> $DIR/empty_line_after_doc_comments.rs:68:1
+   |
+LL | / /// This doc comment should produce a warning
+LL | |
+LL | | /** This is also a doc comment and should produce a warning
+LL | |  */
+...  |
+LL | | #[allow(missing_docs)]
+LL | | fn three_attributes() { assert!(true) }
+   | |_
+
+error: found an empty line after a doc comment. Perhaps you need to use `//!` to make a comment on a module, remove the empty line, or make a regular comment with `//`?
+  --> $DIR/empty_line_after_doc_comments.rs:70:1
+   |
+LL | / /** This is also a doc comment and should produce a warning
+LL | |  */
+LL | |
+LL | | // This should *NOT* produce a warning
+...  |
+LL | | #[allow(missing_docs)]
+LL | | fn three_attributes() { assert!(true) }
+   | |_
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/float_arithmetic.rs b/src/tools/clippy/tests/ui/float_arithmetic.rs
index 60fa7569eb9..a928c35e8bc 100644
--- a/src/tools/clippy/tests/ui/float_arithmetic.rs
+++ b/src/tools/clippy/tests/ui/float_arithmetic.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)]
+#![warn(clippy::arithmetic_side_effects, clippy::float_arithmetic)]
 #![allow(
     unused,
     clippy::shadow_reuse,
diff --git a/src/tools/clippy/tests/ui/integer_arithmetic.rs b/src/tools/clippy/tests/ui/integer_arithmetic.rs
deleted file mode 100644
index ab9b6094c2c..00000000000
--- a/src/tools/clippy/tests/ui/integer_arithmetic.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-//@aux-build:proc_macro_derive.rs
-
-#![warn(clippy::integer_arithmetic, clippy::float_arithmetic)]
-#![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::op_ref)]
-
-extern crate proc_macro_derive;
-
-#[derive(proc_macro_derive::ShadowDerive)]
-pub struct Nothing;
-
-#[rustfmt::skip]
-fn main() {
-    let mut i = 1i32;
-    let mut var1 = 13i32;
-    let mut var2 = -1i32;
-    1 + i;
-    i * 2;
-    1 %
-    i / 2; // no error, this is part of the expression in the preceding line
-    i - 2 + 2 - i;
-    -i;
-    i >> 1;
-    i << 1;
-
-    // no error, overflows are checked by `overflowing_literals`
-    -1;
-    -(-1);
-
-    i & 1; // no wrapping
-    i | 1;
-    i ^ 1;
-
-    i += 1;
-    i -= 1;
-    i *= 2;
-    i /= 2;
-    i /= 0;
-    i /= -1;
-    i /= var1;
-    i /= var2;
-    i %= 2;
-    i %= 0;
-    i %= -1;
-    i %= var1;
-    i %= var2;
-    i <<= 3;
-    i >>= 2;
-
-    // no errors
-    i |= 1;
-    i &= 1;
-    i ^= i;
-
-    // No errors for the following items because they are constant expressions
-    enum Foo {
-        Bar = -2,
-    }
-    struct Baz([i32; 1 + 1]);
-    union Qux {
-        field: [i32; 1 + 1],
-    }
-    type Alias = [i32; 1 + 1];
-
-    const FOO: i32 = -2;
-    static BAR: i32 = -2;
-
-    let _: [i32; 1 + 1] = [0, 0];
-
-    let _: [i32; 1 + 1] = {
-        let a: [i32; 1 + 1] = [0, 0];
-        a
-    };
-
-    trait Trait {
-        const ASSOC: i32 = 1 + 1;
-    }
-
-    impl Trait for Foo {
-        const ASSOC: i32 = {
-            let _: [i32; 1 + 1];
-            fn foo() {}
-            1 + 1
-        };
-    }
-}
-
-// warn on references as well! (#5328)
-pub fn int_arith_ref() {
-    3 + &1;
-    &3 + 1;
-    &3 + &1;
-}
-
-pub fn foo(x: &i32) -> i32 {
-    let a = 5;
-    a + x
-}
-
-pub fn bar(x: &i32, y: &i32) -> i32 {
-    x + y
-}
-
-pub fn baz(x: i32, y: &i32) -> i32 {
-    x + y
-}
-
-pub fn qux(x: i32, y: i32) -> i32 {
-    (&x + &y)
-}
diff --git a/src/tools/clippy/tests/ui/integer_arithmetic.stderr b/src/tools/clippy/tests/ui/integer_arithmetic.stderr
deleted file mode 100644
index add3b6b90fa..00000000000
--- a/src/tools/clippy/tests/ui/integer_arithmetic.stderr
+++ /dev/null
@@ -1,169 +0,0 @@
-error: this operation will panic at runtime
-  --> $DIR/integer_arithmetic.rs:37:5
-   |
-LL |     i /= 0;
-   |     ^^^^^^ attempt to divide `_` by zero
-   |
-   = note: `#[deny(unconditional_panic)]` on by default
-
-error: this operation will panic at runtime
-  --> $DIR/integer_arithmetic.rs:42:5
-   |
-LL |     i %= 0;
-   |     ^^^^^^ attempt to calculate the remainder of `_` with a divisor of zero
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:16:5
-   |
-LL |     1 + i;
-   |     ^^^^^
-   |
-   = note: `-D clippy::integer-arithmetic` implied by `-D warnings`
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:17:5
-   |
-LL |     i * 2;
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:18:5
-   |
-LL | /     1 %
-LL | |     i / 2; // no error, this is part of the expression in the preceding line
-   | |_____^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:20:5
-   |
-LL |     i - 2 + 2 - i;
-   |     ^^^^^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:21:5
-   |
-LL |     -i;
-   |     ^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:22:5
-   |
-LL |     i >> 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:23:5
-   |
-LL |     i << 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:33:5
-   |
-LL |     i += 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:34:5
-   |
-LL |     i -= 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:35:5
-   |
-LL |     i *= 2;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:38:11
-   |
-LL |     i /= -1;
-   |           ^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:39:5
-   |
-LL |     i /= var1;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:40:5
-   |
-LL |     i /= var2;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:43:11
-   |
-LL |     i %= -1;
-   |           ^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:44:5
-   |
-LL |     i %= var1;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:45:5
-   |
-LL |     i %= var2;
-   |     ^^^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:46:5
-   |
-LL |     i <<= 3;
-   |     ^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:47:5
-   |
-LL |     i >>= 2;
-   |     ^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:89:5
-   |
-LL |     3 + &1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:90:5
-   |
-LL |     &3 + 1;
-   |     ^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:91:5
-   |
-LL |     &3 + &1;
-   |     ^^^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:96:5
-   |
-LL |     a + x
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:100:5
-   |
-LL |     x + y
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:104:5
-   |
-LL |     x + y
-   |     ^^^^^
-
-error: integer arithmetic detected
-  --> $DIR/integer_arithmetic.rs:108:5
-   |
-LL |     (&x + &y)
-   |     ^^^^^^^^^
-
-error: aborting due to 27 previous errors
-
diff --git a/src/tools/clippy/tests/ui/issue-111399.rs b/src/tools/clippy/tests/ui/issue-111399.rs
new file mode 100644
index 00000000000..b65e6c7261a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/issue-111399.rs
@@ -0,0 +1,13 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that rustc doesn't crash on the trait bound `Self::Ty: std::marker::Freeze`.
+
+pub struct Struct;
+
+impl Struct {
+    pub type Ty = usize;
+    pub const CT: Self::Ty = 42;
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.rs b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
index 8486137d3a6..2c313ff35d5 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.rs
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
@@ -1,6 +1,12 @@
+//@aux-build: proc_macros.rs
+
 #![allow(unused)]
 #![warn(clippy::let_underscore_untyped)]
 
+extern crate proc_macros;
+use proc_macros::with_span;
+
+use clippy_utils::is_from_proc_macro;
 use std::future::Future;
 use std::{boxed::Box, fmt::Display};
 
@@ -32,6 +38,14 @@ fn g() -> impl Fn() {
     || {}
 }
 
+with_span!(
+    span
+
+    fn dont_lint_proc_macro() {
+        let _ = a();
+    }
+);
+
 fn main() {
     let _ = a();
     let _ = b(1);
@@ -40,6 +54,7 @@ fn main() {
     let _ = e();
     let _ = f();
     let _ = g();
+    let closure = || {};
 
     _ = a();
     _ = b(1);
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
index 6844cb998f7..bbf2508af10 100644
--- a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
@@ -1,60 +1,60 @@
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:36:5
+  --> $DIR/let_underscore_untyped.rs:50:5
    |
 LL |     let _ = a();
    |     ^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:36:10
+  --> $DIR/let_underscore_untyped.rs:50:10
    |
 LL |     let _ = a();
    |          ^
    = note: `-D clippy::let-underscore-untyped` implied by `-D warnings`
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:37:5
+  --> $DIR/let_underscore_untyped.rs:51:5
    |
 LL |     let _ = b(1);
    |     ^^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:37:10
+  --> $DIR/let_underscore_untyped.rs:51:10
    |
 LL |     let _ = b(1);
    |          ^
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:39:5
+  --> $DIR/let_underscore_untyped.rs:53:5
    |
 LL |     let _ = d(&1);
    |     ^^^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:39:10
+  --> $DIR/let_underscore_untyped.rs:53:10
    |
 LL |     let _ = d(&1);
    |          ^
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:40:5
+  --> $DIR/let_underscore_untyped.rs:54:5
    |
 LL |     let _ = e();
    |     ^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:40:10
+  --> $DIR/let_underscore_untyped.rs:54:10
    |
 LL |     let _ = e();
    |          ^
 
 error: non-binding `let` without a type annotation
-  --> $DIR/let_underscore_untyped.rs:41:5
+  --> $DIR/let_underscore_untyped.rs:55:5
    |
 LL |     let _ = f();
    |     ^^^^^^^^^^^^
    |
 help: consider adding a type annotation
-  --> $DIR/let_underscore_untyped.rs:41:10
+  --> $DIR/let_underscore_untyped.rs:55:10
    |
 LL |     let _ = f();
    |          ^
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
index d175597a44a..3996d775f55 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -8,6 +8,12 @@
 )]
 #![warn(clippy::manual_let_else)]
 
+enum Variant {
+    A(usize, usize),
+    B(usize),
+    C,
+}
+
 fn g() -> Option<()> {
     None
 }
@@ -135,6 +141,15 @@ fn fire() {
         };
     }
     create_binding_if_some!(w, g());
+
+    fn e() -> Variant {
+        Variant::A(0, 0)
+    }
+
+    // Should not be renamed
+    let v = if let Variant::A(a, 0) = e() { a } else { return };
+    // Should be renamed
+    let v = if let Variant::B(b) = e() { b } else { return };
 }
 
 fn not_fire() {
diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr
index 52aac6bc673..f6f56f7b00e 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else.stderr
@@ -1,13 +1,13 @@
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:18:5
+  --> $DIR/manual_let_else.rs:24:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { return };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { return };`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
    |
    = note: `-D clippy::manual-let-else` implied by `-D warnings`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:19:5
+  --> $DIR/manual_let_else.rs:25:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -18,13 +18,13 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         return;
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:25:5
+  --> $DIR/manual_let_else.rs:31:5
    |
 LL | /     let v = if let Some(v) = g() {
 LL | |         // Blocks around the identity should have no impact
@@ -45,25 +45,25 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:38:9
+  --> $DIR/manual_let_else.rs:44:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { continue };
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { continue };`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:39:9
+  --> $DIR/manual_let_else.rs:45:9
    |
 LL |         let v = if let Some(v_some) = g() { v_some } else { break };
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { break };`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:43:5
+  --> $DIR/manual_let_else.rs:49:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { panic!() };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { panic!() };`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:46:5
+  --> $DIR/manual_let_else.rs:52:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -74,13 +74,13 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         std::process::abort()
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:53:5
+  --> $DIR/manual_let_else.rs:59:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -91,13 +91,13 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         if true { return } else { panic!() }
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:60:5
+  --> $DIR/manual_let_else.rs:66:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -109,14 +109,14 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         if true {}
 LL +         panic!();
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:70:5
+  --> $DIR/manual_let_else.rs:76:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -129,7 +129,7 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         match () {
 LL +             _ if panic!() => {},
 LL +             _ => panic!(),
@@ -138,13 +138,13 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:80:5
+  --> $DIR/manual_let_else.rs:86:5
    |
 LL |     let v = if let Some(v_some) = g() { v_some } else { if panic!() {} };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v_some) = g() else { if panic!() {} };`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { if panic!() {} };`
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:83:5
+  --> $DIR/manual_let_else.rs:89:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -157,7 +157,7 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         match panic!() {
 LL +             _ => {},
 LL +         }
@@ -165,7 +165,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:92:5
+  --> $DIR/manual_let_else.rs:98:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -178,7 +178,7 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else { if true {
+LL ~     let Some(v) = g() else { if true {
 LL +         return;
 LL +     } else {
 LL +         panic!("diverge");
@@ -186,7 +186,7 @@ LL +     } };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:101:5
+  --> $DIR/manual_let_else.rs:107:5
    |
 LL | /     let v = if let Some(v_some) = g() {
 LL | |         v_some
@@ -199,7 +199,7 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g() else {
+LL ~     let Some(v) = g() else {
 LL +         match (g(), g()) {
 LL +             (Some(_), None) => return,
 LL +             (None, Some(_)) => {
@@ -215,7 +215,7 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:118:5
+  --> $DIR/manual_let_else.rs:124:5
    |
 LL | /     let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) {
 LL | |         v_some
@@ -226,13 +226,13 @@ LL | |     };
    |
 help: consider writing
    |
-LL ~     let Some(v_some) = g().map(|v| (v, 42)) else {
+LL ~     let Some((v, w)) = g().map(|v| (v, 42)) else {
 LL +         return;
 LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:125:5
+  --> $DIR/manual_let_else.rs:131:5
    |
 LL | /     let v = if let (Some(v_some), w_some) = (g(), 0) {
 LL | |         (w_some, v_some)
@@ -249,10 +249,10 @@ LL +     };
    |
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:134:13
+  --> $DIR/manual_let_else.rs:140:13
    |
 LL |             let $n = if let Some(v) = $e { v } else { return };
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };`
 ...
 LL |     create_binding_if_some!(w, g());
    |     ------------------------------- in this macro invocation
@@ -260,13 +260,25 @@ LL |     create_binding_if_some!(w, g());
    = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: this could be rewritten as `let...else`
-  --> $DIR/manual_let_else.rs:247:5
+  --> $DIR/manual_let_else.rs:150:5
+   |
+LL |     let v = if let Variant::A(a, 0) = e() { a } else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(a, 0) = e() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:152:5
+   |
+LL |     let v = if let Variant::B(b) = e() { b } else { return };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(v) = e() else { return };`
+
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else.rs:262:5
    |
 LL | /     let _ = match ff {
 LL | |         Some(value) => value,
 LL | |         _ => macro_call!(),
 LL | |     };
-   | |______^ help: consider writing: `let Some(value) = ff else { macro_call!() };`
+   | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };`
 
-error: aborting due to 18 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
index 7abaa0b85d2..bacc14dc967 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -5,7 +5,7 @@ LL | /     let v = match g() {
 LL | |         Some(v_some) => v_some,
 LL | |         None => return,
 LL | |     };
-   | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+   | |______^ help: consider writing: `let Some(v) = g() else { return };`
    |
    = note: `-D clippy::manual-let-else` implied by `-D warnings`
 
@@ -16,7 +16,7 @@ LL | /     let v = match g() {
 LL | |         Some(v_some) => v_some,
 LL | |         _ => return,
 LL | |     };
-   | |______^ help: consider writing: `let Some(v_some) = g() else { return };`
+   | |______^ help: consider writing: `let Some(v) = g() else { return };`
 
 error: this could be rewritten as `let...else`
   --> $DIR/manual_let_else_match.rs:44:9
diff --git a/src/tools/clippy/tests/ui/manual_next_back.fixed b/src/tools/clippy/tests/ui/manual_next_back.fixed
new file mode 100644
index 00000000000..e8a47063ad6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.fixed
@@ -0,0 +1,36 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_next_back)]
+
+struct FakeIter(std::ops::Range<i32>);
+
+impl FakeIter {
+    fn rev(self) -> Self {
+        self
+    }
+
+    fn next(&self) {}
+}
+
+impl DoubleEndedIterator for FakeIter {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.0.next_back()
+    }
+}
+
+impl Iterator for FakeIter {
+    type Item = i32;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+fn main() {
+    // should not lint
+    FakeIter(0..10).rev().next();
+
+    // should lint
+    let _ = (0..10).next_back().unwrap();
+    let _ = "something".bytes().next_back();
+}
diff --git a/src/tools/clippy/tests/ui/manual_next_back.rs b/src/tools/clippy/tests/ui/manual_next_back.rs
new file mode 100644
index 00000000000..9ec89242241
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.rs
@@ -0,0 +1,36 @@
+//@run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::manual_next_back)]
+
+struct FakeIter(std::ops::Range<i32>);
+
+impl FakeIter {
+    fn rev(self) -> Self {
+        self
+    }
+
+    fn next(&self) {}
+}
+
+impl DoubleEndedIterator for FakeIter {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.0.next_back()
+    }
+}
+
+impl Iterator for FakeIter {
+    type Item = i32;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+fn main() {
+    // should not lint
+    FakeIter(0..10).rev().next();
+
+    // should lint
+    let _ = (0..10).rev().next().unwrap();
+    let _ = "something".bytes().rev().next();
+}
diff --git a/src/tools/clippy/tests/ui/manual_next_back.stderr b/src/tools/clippy/tests/ui/manual_next_back.stderr
new file mode 100644
index 00000000000..94ccaa9e4cc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_next_back.stderr
@@ -0,0 +1,16 @@
+error: manual backwards iteration
+  --> $DIR/manual_next_back.rs:34:20
+   |
+LL |     let _ = (0..10).rev().next().unwrap();
+   |                    ^^^^^^^^^^^^^ help: use: `.next_back()`
+   |
+   = note: `-D clippy::manual-next-back` implied by `-D warnings`
+
+error: manual backwards iteration
+  --> $DIR/manual_next_back.rs:35:32
+   |
+LL |     let _ = "something".bytes().rev().next();
+   |                                ^^^^^^^^^^^^^ help: use: `.next_back()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
index 7215660da67..60f59066173 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
@@ -15,7 +15,7 @@ fn main() {
     let _y = matches!(x, Some(0));
 
     // Lint
-    let _w = matches!(x, Some(_));
+    let _w = x.is_some();
 
     // Turn into is_none
     let _z = x.is_none();
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
index 46f67ef4900..b72fe10b748 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
@@ -10,7 +10,7 @@ LL | |     };
    |
    = note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
 
-error: match expression looks like `matches!` macro
+error: redundant pattern matching, consider using `is_some()`
   --> $DIR/match_expr_like_matches_macro.rs:21:14
    |
 LL |       let _w = match x {
@@ -18,7 +18,9 @@ LL |       let _w = match x {
 LL | |         Some(_) => true,
 LL | |         _ => false,
 LL | |     };
-   | |_____^ help: try this: `matches!(x, Some(_))`
+   | |_____^ help: try this: `x.is_some()`
+   |
+   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_none()`
   --> $DIR/match_expr_like_matches_macro.rs:27:14
@@ -29,8 +31,6 @@ LL | |         Some(_) => false,
 LL | |         None => true,
 LL | |     };
    | |_____^ help: try this: `x.is_none()`
-   |
-   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: match expression looks like `matches!` macro
   --> $DIR/match_expr_like_matches_macro.rs:33:15
diff --git a/src/tools/clippy/tests/ui/match_same_arms.rs b/src/tools/clippy/tests/ui/match_same_arms.rs
index 0b9342c9c42..3914b45464c 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms.rs
@@ -53,4 +53,84 @@ mod issue4244 {
     }
 }
 
-fn main() {}
+macro_rules! m {
+    (foo) => {};
+    (bar) => {};
+}
+macro_rules! foo {
+    () => {
+        1
+    };
+}
+macro_rules! bar {
+    () => {
+        1
+    };
+}
+
+fn main() {
+    let x = 0;
+    let _ = match 0 {
+        0 => {
+            m!(foo);
+            x
+        },
+        1 => {
+            m!(bar);
+            x
+        },
+        _ => 1,
+    };
+
+    let _ = match 0 {
+        0 => {
+            m!(foo);
+            0
+        },
+        1 => {
+            m!(bar);
+            0
+        },
+        _ => 1,
+    };
+
+    let _ = match 0 {
+        0 => {
+            let mut x = 0;
+            #[cfg(not_enabled)]
+            {
+                x = 5;
+            }
+            #[cfg(not(not_enabled))]
+            {
+                x = 6;
+            }
+            x
+        },
+        1 => {
+            let mut x = 0;
+            #[cfg(also_not_enabled)]
+            {
+                x = 5;
+            }
+            #[cfg(not(also_not_enabled))]
+            {
+                x = 6;
+            }
+            x
+        },
+        _ => 0,
+    };
+
+    let _ = match 0 {
+        0 => foo!(),
+        1 => bar!(),
+        _ => 1,
+    };
+
+    let _ = match 0 {
+        0 => cfg!(not_enabled),
+        1 => cfg!(also_not_enabled),
+        _ => false,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index 82b2c433d99..60b2975be04 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -239,4 +239,10 @@ fn main() {
         3 => core::convert::identity::<u32>(todo!()),
         _ => 5,
     };
+
+    let _ = match 0 {
+        0 => cfg!(not_enable),
+        1 => cfg!(not_enable),
+        _ => false,
+    };
 }
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr
index 06cd4300054..8fb461bd286 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -192,5 +192,20 @@ note: other arm here
 LL |         Some(Bar { x: 0, y: 5, .. }) => 1,
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors
+error: this match arm has an identical body to another arm
+  --> $DIR/match_same_arms2.rs:245:9
+   |
+LL |         1 => cfg!(not_enable),
+   |         -^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         help: try merging the arm patterns: `1 | 0`
+   |
+   = help: or try changing either arm body
+note: other arm here
+  --> $DIR/match_same_arms2.rs:244:9
+   |
+LL |         0 => cfg!(not_enable),
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
 
diff --git a/src/tools/clippy/tests/ui/mem_forget.rs b/src/tools/clippy/tests/ui/mem_forget.rs
index 5137448a6d4..edb9d87d032 100644
--- a/src/tools/clippy/tests/ui/mem_forget.rs
+++ b/src/tools/clippy/tests/ui/mem_forget.rs
@@ -5,7 +5,7 @@ use std::mem as memstuff;
 use std::mem::forget as forgetSomething;
 
 #[warn(clippy::mem_forget)]
-#[allow(forget_copy)]
+#[allow(forgetting_copy_types)]
 fn main() {
     let five: i32 = 5;
     forgetSomething(five);
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
index f28153e56b0..4ef6f0ca92f 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -2,7 +2,7 @@
 #![allow(unused)]
 #![allow(deref_nullptr)]
 #![allow(clippy::unnecessary_operation)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 #![warn(clippy::multiple_unsafe_ops_per_block)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
index f860852e7b7..bf1911881c8 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.fixed
@@ -63,6 +63,13 @@ fn main() {
     needless_bool2(x);
     needless_bool3(x);
     needless_bool_condition();
+
+    if a == b {
+        true
+    } else {
+        // Do not lint as this comment might be important
+        false
+    };
 }
 
 fn bool_ret3(x: bool) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.rs b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
index 6680dab5b6d..a6c465d4fbd 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.rs
@@ -99,6 +99,13 @@ fn main() {
     needless_bool2(x);
     needless_bool3(x);
     needless_bool_condition();
+
+    if a == b {
+        true
+    } else {
+        // Do not lint as this comment might be important
+        false
+    };
 }
 
 fn bool_ret3(x: bool) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
index d2c48376f76..fa906374fb3 100644
--- a/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_bool/fixable.stderr
@@ -91,7 +91,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `a < b`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:105:5
+  --> $DIR/fixable.rs:112:5
    |
 LL | /     if x {
 LL | |         return true;
@@ -101,7 +101,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:113:5
+  --> $DIR/fixable.rs:120:5
    |
 LL | /     if x {
 LL | |         return false;
@@ -111,7 +111,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:121:5
+  --> $DIR/fixable.rs:128:5
    |
 LL | /     if x && y {
 LL | |         return true;
@@ -121,7 +121,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return x && y`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:129:5
+  --> $DIR/fixable.rs:136:5
    |
 LL | /     if x && y {
 LL | |         return false;
@@ -131,7 +131,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `return !(x && y)`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:137:8
+  --> $DIR/fixable.rs:144:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
@@ -139,25 +139,25 @@ LL |     if x == true {};
    = note: `-D clippy::bool-comparison` implied by `-D warnings`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:141:8
+  --> $DIR/fixable.rs:148:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: equality checks against true are unnecessary
-  --> $DIR/fixable.rs:151:8
+  --> $DIR/fixable.rs:158:8
    |
 LL |     if x == true {};
    |        ^^^^^^^^^ help: try simplifying it as shown: `x`
 
 error: equality checks against false can be replaced by a negation
-  --> $DIR/fixable.rs:152:8
+  --> $DIR/fixable.rs:159:8
    |
 LL |     if x == false {};
    |        ^^^^^^^^^^ help: try simplifying it as shown: `!x`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:161:12
+  --> $DIR/fixable.rs:168:12
    |
 LL |       } else if returns_bool() {
    |  ____________^
@@ -168,7 +168,7 @@ LL | |     };
    | |_____^ help: you can reduce it to: `{ !returns_bool() }`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:174:5
+  --> $DIR/fixable.rs:181:5
    |
 LL | /     if unsafe { no(4) } & 1 != 0 {
 LL | |         true
@@ -178,13 +178,13 @@ LL | |     };
    | |_____^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:179:30
+  --> $DIR/fixable.rs:186:30
    |
 LL |     let _brackets_unneeded = if unsafe { no(4) } & 1 != 0 { true } else { false };
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `unsafe { no(4) } & 1 != 0`
 
 error: this if-then-else expression returns a bool literal
-  --> $DIR/fixable.rs:182:9
+  --> $DIR/fixable.rs:189:9
    |
 LL |         if unsafe { no(4) } & 1 != 0 { true } else { false }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `(unsafe { no(4) } & 1 != 0)`
diff --git a/src/tools/clippy/tests/ui/needless_collect.fixed b/src/tools/clippy/tests/ui/needless_collect.fixed
index 024c22de225..b7e80af5015 100644
--- a/src/tools/clippy/tests/ui/needless_collect.fixed
+++ b/src/tools/clippy/tests/ui/needless_collect.fixed
@@ -62,4 +62,16 @@ fn main() {
 
     let _ = sample.iter().next().is_none();
     let _ = sample.iter().any(|x| x == &0);
+
+    #[allow(clippy::double_parens)]
+    {
+        Vec::<u8>::new().extend((0..10));
+        foo((0..10));
+        bar((0..10).collect::<Vec<_>>(), (0..10));
+        baz((0..10), (), ('a'..='z'))
+    }
 }
+
+fn foo(_: impl IntoIterator<Item = usize>) {}
+fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
+fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect.rs b/src/tools/clippy/tests/ui/needless_collect.rs
index 7ed7babec30..680b6fa5b55 100644
--- a/src/tools/clippy/tests/ui/needless_collect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect.rs
@@ -62,4 +62,16 @@ fn main() {
 
     let _ = sample.iter().collect::<VecWrapper<_>>().is_empty();
     let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
+
+    #[allow(clippy::double_parens)]
+    {
+        Vec::<u8>::new().extend((0..10).collect::<Vec<_>>());
+        foo((0..10).collect::<Vec<_>>());
+        bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
+        baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
+    }
 }
+
+fn foo(_: impl IntoIterator<Item = usize>) {}
+fn bar<I: IntoIterator<Item = usize>>(_: Vec<usize>, _: I) {}
+fn baz<I: IntoIterator<Item = usize>>(_: I, _: (), _: impl IntoIterator<Item = char>) {}
diff --git a/src/tools/clippy/tests/ui/needless_collect.stderr b/src/tools/clippy/tests/ui/needless_collect.stderr
index 584d2a1d835..ad22a7b057e 100644
--- a/src/tools/clippy/tests/ui/needless_collect.stderr
+++ b/src/tools/clippy/tests/ui/needless_collect.stderr
@@ -90,5 +90,29 @@ error: avoid using `collect()` when not needed
 LL |     let _ = sample.iter().collect::<VecWrapper<_>>().contains(&&0);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `any(|x| x == &0)`
 
-error: aborting due to 15 previous errors
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:68:40
+   |
+LL |         Vec::<u8>::new().extend((0..10).collect::<Vec<_>>());
+   |                                        ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:69:20
+   |
+LL |         foo((0..10).collect::<Vec<_>>());
+   |                    ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:70:49
+   |
+LL |         bar((0..10).collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
+   |                                                 ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: avoid using `collect()` when not needed
+  --> $DIR/needless_collect.rs:71:37
+   |
+LL |         baz((0..10), (), ('a'..='z').collect::<Vec<_>>())
+   |                                     ^^^^^^^^^^^^^^^^^^^^ help: remove this call
+
+error: aborting due to 19 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index ee4e5007dc5..d49ae5d8636 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -231,8 +231,9 @@ fn needless_return_macro() -> String {
 }
 
 fn issue_9361() -> i32 {
-    #[allow(clippy::integer_arithmetic)]
-    return 1 + 2;
+    let n = 1;
+    #[allow(clippy::arithmetic_side_effects)]
+    return n + n;
 }
 
 fn issue8336(x: i32) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index cd999db4f40..36763826174 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -239,8 +239,9 @@ fn needless_return_macro() -> String {
 }
 
 fn issue_9361() -> i32 {
-    #[allow(clippy::integer_arithmetic)]
-    return 1 + 2;
+    let n = 1;
+    #[allow(clippy::arithmetic_side_effects)]
+    return n + n;
 }
 
 fn issue8336(x: i32) -> bool {
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 87d0cd3e14c..05f6038cd25 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -328,7 +328,7 @@ LL |     return format!("Hello {}", "world!");
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:249:9
+  --> $DIR/needless_return.rs:250:9
    |
 LL |         return true;
    |         ^^^^^^^^^^^
@@ -336,7 +336,7 @@ LL |         return true;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:251:9
+  --> $DIR/needless_return.rs:252:9
    |
 LL |         return false;
    |         ^^^^^^^^^^^^
@@ -344,7 +344,7 @@ LL |         return false;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:258:13
+  --> $DIR/needless_return.rs:259:13
    |
 LL |             return 10;
    |             ^^^^^^^^^
@@ -352,7 +352,7 @@ LL |             return 10;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:261:13
+  --> $DIR/needless_return.rs:262:13
    |
 LL |             return 100;
    |             ^^^^^^^^^^
@@ -360,7 +360,7 @@ LL |             return 100;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:269:9
+  --> $DIR/needless_return.rs:270:9
    |
 LL |         return 0;
    |         ^^^^^^^^
@@ -368,7 +368,7 @@ LL |         return 0;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:276:13
+  --> $DIR/needless_return.rs:277:13
    |
 LL |             return *(x as *const isize);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -376,7 +376,7 @@ LL |             return *(x as *const isize);
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:278:13
+  --> $DIR/needless_return.rs:279:13
    |
 LL |             return !*(x as *const isize);
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -384,7 +384,7 @@ LL |             return !*(x as *const isize);
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:285:20
+  --> $DIR/needless_return.rs:286:20
    |
 LL |           let _ = 42;
    |  ____________________^
@@ -395,7 +395,7 @@ LL | |         return;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:292:20
+  --> $DIR/needless_return.rs:293:20
    |
 LL |         let _ = 42; return;
    |                    ^^^^^^^
@@ -403,7 +403,7 @@ LL |         let _ = 42; return;
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:304:9
+  --> $DIR/needless_return.rs:305:9
    |
 LL |         return Ok(format!("ok!"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -411,7 +411,7 @@ LL |         return Ok(format!("ok!"));
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:306:9
+  --> $DIR/needless_return.rs:307:9
    |
 LL |         return Err(format!("err!"));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -419,7 +419,7 @@ LL |         return Err(format!("err!"));
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:312:9
+  --> $DIR/needless_return.rs:313:9
    |
 LL |         return if true { 1 } else { 2 };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -427,7 +427,7 @@ LL |         return if true { 1 } else { 2 };
    = help: remove `return`
 
 error: unneeded `return` statement
-  --> $DIR/needless_return.rs:316:9
+  --> $DIR/needless_return.rs:317:9
    |
 LL |         return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.fixed b/src/tools/clippy/tests/ui/non_minimal_cfg.fixed
new file mode 100644
index 00000000000..430caafb33e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.fixed
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![allow(unused)]
+
+#[cfg(windows)]
+fn hermit() {}
+
+#[cfg(windows)]
+fn wasi() {}
+
+#[cfg(all(unix, not(windows)))]
+fn the_end() {}
+
+#[cfg(any())]
+fn any() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.rs b/src/tools/clippy/tests/ui/non_minimal_cfg.rs
new file mode 100644
index 00000000000..a38ce1c21d6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.rs
@@ -0,0 +1,17 @@
+//@run-rustfix
+
+#![allow(unused)]
+
+#[cfg(all(windows))]
+fn hermit() {}
+
+#[cfg(any(windows))]
+fn wasi() {}
+
+#[cfg(all(any(unix), all(not(windows))))]
+fn the_end() {}
+
+#[cfg(any())]
+fn any() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg.stderr b/src/tools/clippy/tests/ui/non_minimal_cfg.stderr
new file mode 100644
index 00000000000..cdfd728aa61
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg.stderr
@@ -0,0 +1,28 @@
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:5:7
+   |
+LL | #[cfg(all(windows))]
+   |       ^^^^^^^^^^^^ help: try: `windows`
+   |
+   = note: `-D clippy::non-minimal-cfg` implied by `-D warnings`
+
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:8:7
+   |
+LL | #[cfg(any(windows))]
+   |       ^^^^^^^^^^^^ help: try: `windows`
+
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:11:11
+   |
+LL | #[cfg(all(any(unix), all(not(windows))))]
+   |           ^^^^^^^^^ help: try: `unix`
+
+error: unneeded sub `cfg` when there is only one condition
+  --> $DIR/non_minimal_cfg.rs:11:22
+   |
+LL | #[cfg(all(any(unix), all(not(windows))))]
+   |                      ^^^^^^^^^^^^^^^^^ help: try: `not(windows)`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg2.rs b/src/tools/clippy/tests/ui/non_minimal_cfg2.rs
new file mode 100644
index 00000000000..a4c6abce387
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg2.rs
@@ -0,0 +1,6 @@
+#![allow(unused)]
+
+#[cfg(all())]
+fn all() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr
new file mode 100644
index 00000000000..2a9a36fbcef
--- /dev/null
+++ b/src/tools/clippy/tests/ui/non_minimal_cfg2.stderr
@@ -0,0 +1,10 @@
+error: unneeded sub `cfg` when there is no condition
+  --> $DIR/non_minimal_cfg2.rs:3:7
+   |
+LL | #[cfg(all())]
+   |       ^^^^^
+   |
+   = note: `-D clippy::non-minimal-cfg` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index 57f341e0276..2b8ce5477cc 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -92,6 +92,15 @@ fn pattern_to_vec(pattern: &str) -> Vec<String> {
         .collect::<Vec<_>>()
 }
 
+// #10335
+fn test_result_impure_else(variable: Result<u32, &str>) {
+    variable.map_or_else(|_| {
+        println!("Err");
+    }, |binding| {
+        println!("Ok {binding}");
+    })
+}
+
 enum DummyEnum {
     One(u8),
     Two,
@@ -113,6 +122,7 @@ fn main() {
     unop_bad(&None, None);
     let _ = longer_body(None);
     test_map_or_else(None);
+    test_result_impure_else(Ok(42));
     let _ = negative_tests(None);
     let _ = impure_else(None);
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index 19f9f704517..cfbec8cb27d 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -115,6 +115,15 @@ fn pattern_to_vec(pattern: &str) -> Vec<String> {
         .collect::<Vec<_>>()
 }
 
+// #10335
+fn test_result_impure_else(variable: Result<u32, &str>) {
+    if let Ok(binding) = variable {
+        println!("Ok {binding}");
+    } else {
+        println!("Err");
+    }
+}
+
 enum DummyEnum {
     One(u8),
     Two,
@@ -136,6 +145,7 @@ fn main() {
     unop_bad(&None, None);
     let _ = longer_body(None);
     test_map_or_else(None);
+    test_result_impure_else(Ok(42));
     let _ = negative_tests(None);
     let _ = impure_else(None);
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index f5e4affb672..91d52fc79b8 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -152,14 +152,33 @@ LL | |                 vec![s.to_string()]
 LL | |             }
    | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])`
 
+error: use Option::map_or_else instead of an if let/else
+  --> $DIR/option_if_let_else.rs:120:5
+   |
+LL | /     if let Ok(binding) = variable {
+LL | |         println!("Ok {binding}");
+LL | |     } else {
+LL | |         println!("Err");
+LL | |     }
+   | |_____^
+   |
+help: try
+   |
+LL ~     variable.map_or_else(|_| {
+LL +         println!("Err");
+LL +     }, |binding| {
+LL +         println!("Ok {binding}");
+LL +     })
+   |
+
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:133:13
+  --> $DIR/option_if_let_else.rs:142:13
    |
 LL |     let _ = if let Some(x) = optional { x + 2 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:142:13
+  --> $DIR/option_if_let_else.rs:152:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -181,13 +200,13 @@ LL ~         });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:170:13
+  --> $DIR/option_if_let_else.rs:180:13
    |
 LL |     let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:174:13
+  --> $DIR/option_if_let_else.rs:184:13
    |
 LL |       let _ = if let Some(x) = Some(0) {
    |  _____________^
@@ -207,7 +226,7 @@ LL ~     });
    |
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:213:13
+  --> $DIR/option_if_let_else.rs:223:13
    |
 LL |       let _ = match s {
    |  _____________^
@@ -217,7 +236,7 @@ LL | |     };
    | |_____^ help: try: `s.map_or(1, |string| string.len())`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:217:13
+  --> $DIR/option_if_let_else.rs:227:13
    |
 LL |       let _ = match Some(10) {
    |  _____________^
@@ -227,7 +246,7 @@ LL | |     };
    | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:223:13
+  --> $DIR/option_if_let_else.rs:233:13
    |
 LL |       let _ = match res {
    |  _____________^
@@ -237,7 +256,7 @@ LL | |     };
    | |_____^ help: try: `res.map_or(1, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:227:13
+  --> $DIR/option_if_let_else.rs:237:13
    |
 LL |       let _ = match res {
    |  _____________^
@@ -247,10 +266,10 @@ LL | |     };
    | |_____^ help: try: `res.map_or(1, |a| a + 1)`
 
 error: use Option::map_or instead of an if let/else
-  --> $DIR/option_if_let_else.rs:231:13
+  --> $DIR/option_if_let_else.rs:241:13
    |
 LL |     let _ = if let Ok(a) = res { a + 1 } else { 5 };
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
 
-error: aborting due to 20 previous errors
+error: aborting due to 21 previous errors
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.fixed b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
index 81a716bd276..2df87a26d6d 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.fixed
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.fixed
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::partialeq_to_none)]
+#![allow(clippy::eq_op)]
 
 struct Foobar;
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.rs b/src/tools/clippy/tests/ui/partialeq_to_none.rs
index f454715fa30..df6233b9afd 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.rs
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.rs
@@ -1,5 +1,6 @@
 //@run-rustfix
 #![warn(clippy::partialeq_to_none)]
+#![allow(clippy::eq_op)]
 
 struct Foobar;
 
diff --git a/src/tools/clippy/tests/ui/partialeq_to_none.stderr b/src/tools/clippy/tests/ui/partialeq_to_none.stderr
index d06ab7aee55..4f84862a22b 100644
--- a/src/tools/clippy/tests/ui/partialeq_to_none.stderr
+++ b/src/tools/clippy/tests/ui/partialeq_to_none.stderr
@@ -1,5 +1,5 @@
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:14:8
+  --> $DIR/partialeq_to_none.rs:15:8
    |
 LL |     if f != None { "yay" } else { "nay" }
    |        ^^^^^^^^^ help: use `Option::is_some()` instead: `f.is_some()`
@@ -7,55 +7,55 @@ LL |     if f != None { "yay" } else { "nay" }
    = note: `-D clippy::partialeq-to-none` implied by `-D warnings`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:44:13
+  --> $DIR/partialeq_to_none.rs:45:13
    |
 LL |     let _ = x == None;
    |             ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:45:13
+  --> $DIR/partialeq_to_none.rs:46:13
    |
 LL |     let _ = x != None;
    |             ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:46:13
+  --> $DIR/partialeq_to_none.rs:47:13
    |
 LL |     let _ = None == x;
    |             ^^^^^^^^^ help: use `Option::is_none()` instead: `x.is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:47:13
+  --> $DIR/partialeq_to_none.rs:48:13
    |
 LL |     let _ = None != x;
    |             ^^^^^^^^^ help: use `Option::is_some()` instead: `x.is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:49:8
+  --> $DIR/partialeq_to_none.rs:50:8
    |
 LL |     if foobar() == None {}
    |        ^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `foobar().is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:51:8
+  --> $DIR/partialeq_to_none.rs:52:8
    |
 LL |     if bar().ok() != None {}
    |        ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `bar().ok().is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:53:13
+  --> $DIR/partialeq_to_none.rs:54:13
    |
 LL |     let _ = Some(1 + 2) != None;
    |             ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `Some(1 + 2).is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:55:13
+  --> $DIR/partialeq_to_none.rs:56:13
    |
 LL |     let _ = { Some(0) } == None;
    |             ^^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `{ Some(0) }.is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:57:13
+  --> $DIR/partialeq_to_none.rs:58:13
    |
 LL |       let _ = {
    |  _____________^
@@ -77,31 +77,31 @@ LL ~     }.is_some();
    |
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:67:13
+  --> $DIR/partialeq_to_none.rs:68:13
    |
 LL |     let _ = optref() == &&None;
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:68:13
+  --> $DIR/partialeq_to_none.rs:69:13
    |
 LL |     let _ = &&None != optref();
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:69:13
+  --> $DIR/partialeq_to_none.rs:70:13
    |
 LL |     let _ = **optref() == None;
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_none()` instead: `optref().is_none()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:70:13
+  --> $DIR/partialeq_to_none.rs:71:13
    |
 LL |     let _ = &None != *optref();
    |             ^^^^^^^^^^^^^^^^^^ help: use `Option::is_some()` instead: `optref().is_some()`
 
 error: binary comparison to literal `Option::None`
-  --> $DIR/partialeq_to_none.rs:73:13
+  --> $DIR/partialeq_to_none.rs:74:13
    |
 LL |     let _ = None != *x;
    |             ^^^^^^^^^^ help: use `Option::is_some()` instead: `(*x).is_some()`
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
index d62f7d26a35..accdf1da9dd 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
@@ -46,6 +46,7 @@ fn main() {
     let _ = if opt.is_some() { true } else { false };
 
     issue6067();
+    issue10726();
 
     let _ = if gen_opt().is_some() {
         1
@@ -88,3 +89,21 @@ fn issue7921() {
     if (&None::<()>).is_none() {}
     if (&None::<()>).is_none() {}
 }
+
+fn issue10726() {
+    let x = Some(42);
+
+    x.is_some();
+
+    x.is_none();
+
+    x.is_none();
+
+    x.is_some();
+
+    // Don't lint
+    match x {
+        Some(21) => true,
+        _ => false,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
index d6429426573..ec684bdf71c 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
@@ -55,6 +55,7 @@ fn main() {
     let _ = if let Some(_) = opt { true } else { false };
 
     issue6067();
+    issue10726();
 
     let _ = if let Some(_) = gen_opt() {
         1
@@ -103,3 +104,33 @@ fn issue7921() {
     if let None = *(&None::<()>) {}
     if let None = *&None::<()> {}
 }
+
+fn issue10726() {
+    let x = Some(42);
+
+    match x {
+        Some(_) => true,
+        _ => false,
+    };
+
+    match x {
+        None => true,
+        _ => false,
+    };
+
+    match x {
+        Some(_) => false,
+        _ => true,
+    };
+
+    match x {
+        None => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Some(21) => true,
+        _ => false,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
index 7c5a047e455..a69eb390520 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
@@ -77,49 +77,49 @@ LL |     let _ = if let Some(_) = opt { true } else { false };
    |             -------^^^^^^^------ help: try this: `if opt.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:59:20
+  --> $DIR/redundant_pattern_matching_option.rs:60:20
    |
 LL |     let _ = if let Some(_) = gen_opt() {
    |             -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:61:19
+  --> $DIR/redundant_pattern_matching_option.rs:62:19
    |
 LL |     } else if let None = gen_opt() {
    |            -------^^^^------------ help: try this: `if gen_opt().is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:67:12
+  --> $DIR/redundant_pattern_matching_option.rs:68:12
    |
 LL |     if let Some(..) = gen_opt() {}
    |     -------^^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:82:12
+  --> $DIR/redundant_pattern_matching_option.rs:83:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:84:12
+  --> $DIR/redundant_pattern_matching_option.rs:85:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:86:15
+  --> $DIR/redundant_pattern_matching_option.rs:87:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:88:15
+  --> $DIR/redundant_pattern_matching_option.rs:89:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:90:5
+  --> $DIR/redundant_pattern_matching_option.rs:91:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -128,7 +128,7 @@ LL | |     };
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:95:5
+  --> $DIR/redundant_pattern_matching_option.rs:96:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
@@ -137,16 +137,52 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:103:12
+  --> $DIR/redundant_pattern_matching_option.rs:104:12
    |
 LL |     if let None = *(&None::<()>) {}
    |     -------^^^^----------------- help: try this: `if (&None::<()>).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:104:12
+  --> $DIR/redundant_pattern_matching_option.rs:105:12
    |
 LL |     if let None = *&None::<()> {}
    |     -------^^^^--------------- help: try this: `if (&None::<()>).is_none()`
 
-error: aborting due to 22 previous errors
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_option.rs:111:5
+   |
+LL | /     match x {
+LL | |         Some(_) => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_some()`
+
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/redundant_pattern_matching_option.rs:116:5
+   |
+LL | /     match x {
+LL | |         None => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_none()`
+
+error: redundant pattern matching, consider using `is_none()`
+  --> $DIR/redundant_pattern_matching_option.rs:121:5
+   |
+LL | /     match x {
+LL | |         Some(_) => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_none()`
+
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_option.rs:126:5
+   |
+LL | /     match x {
+LL | |         None => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_some()`
+
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
index c48d1522935..e4032ae44b7 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
@@ -43,6 +43,7 @@ fn main() {
     issue5504();
     issue6067();
     issue6065();
+    issue10726();
 
     let _ = if gen_res().is_ok() {
         1
@@ -107,3 +108,28 @@ const fn issue6067() {
 
     Err::<i32, i32>(42).is_err();
 }
+
+fn issue10726() {
+    // This is optional, but it makes the examples easier
+    let x: Result<i32, i32> = Ok(42);
+
+    x.is_ok();
+
+    x.is_err();
+
+    x.is_err();
+
+    x.is_ok();
+
+    // Don't lint
+    match x {
+        Err(16) => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Ok(16) => false,
+        _ => true,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
index 26f37d169fa..39eb10df878 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
@@ -55,6 +55,7 @@ fn main() {
     issue5504();
     issue6067();
     issue6065();
+    issue10726();
 
     let _ = if let Ok(_) = gen_res() {
         1
@@ -125,3 +126,40 @@ const fn issue6067() {
         Err(_) => true,
     };
 }
+
+fn issue10726() {
+    // This is optional, but it makes the examples easier
+    let x: Result<i32, i32> = Ok(42);
+
+    match x {
+        Ok(_) => true,
+        _ => false,
+    };
+
+    match x {
+        Ok(_) => false,
+        _ => true,
+    };
+
+    match x {
+        Err(_) => true,
+        _ => false,
+    };
+
+    match x {
+        Err(_) => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Err(16) => false,
+        _ => true,
+    };
+
+    // Don't lint
+    match x {
+        Ok(16) => false,
+        _ => true,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
index d6a46babb77..5893ae4dcc4 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
@@ -73,67 +73,67 @@ LL |     let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
    |             -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:59:20
+  --> $DIR/redundant_pattern_matching_result.rs:60:20
    |
 LL |     let _ = if let Ok(_) = gen_res() {
    |             -------^^^^^------------ help: try this: `if gen_res().is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:61:19
+  --> $DIR/redundant_pattern_matching_result.rs:62:19
    |
 LL |     } else if let Err(_) = gen_res() {
    |            -------^^^^^^------------ help: try this: `if gen_res().is_err()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:84:19
+  --> $DIR/redundant_pattern_matching_result.rs:85:19
    |
 LL |         while let Some(_) = r#try!(result_opt()) {}
    |         ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:85:16
+  --> $DIR/redundant_pattern_matching_result.rs:86:16
    |
 LL |         if let Some(_) = r#try!(result_opt()) {}
    |         -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:91:12
+  --> $DIR/redundant_pattern_matching_result.rs:92:12
    |
 LL |     if let Some(_) = m!() {}
    |     -------^^^^^^^------- help: try this: `if m!().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_result.rs:92:15
+  --> $DIR/redundant_pattern_matching_result.rs:93:15
    |
 LL |     while let Some(_) = m!() {}
    |     ----------^^^^^^^------- help: try this: `while m!().is_some()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:110:12
+  --> $DIR/redundant_pattern_matching_result.rs:111:12
    |
 LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
    |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:112:12
+  --> $DIR/redundant_pattern_matching_result.rs:113:12
    |
 LL |     if let Err(_) = Err::<i32, i32>(42) {}
    |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:114:15
+  --> $DIR/redundant_pattern_matching_result.rs:115:15
    |
 LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:116:15
+  --> $DIR/redundant_pattern_matching_result.rs:117:15
    |
 LL |     while let Err(_) = Ok::<i32, i32>(10) {}
    |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
 
 error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching_result.rs:118:5
+  --> $DIR/redundant_pattern_matching_result.rs:119:5
    |
 LL | /     match Ok::<i32, i32>(42) {
 LL | |         Ok(_) => true,
@@ -142,7 +142,7 @@ LL | |     };
    | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
 
 error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching_result.rs:123:5
+  --> $DIR/redundant_pattern_matching_result.rs:124:5
    |
 LL | /     match Err::<i32, i32>(42) {
 LL | |         Ok(_) => false,
@@ -150,5 +150,41 @@ LL | |         Err(_) => true,
 LL | |     };
    | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
 
-error: aborting due to 22 previous errors
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:134:5
+   |
+LL | /     match x {
+LL | |         Ok(_) => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:139:5
+   |
+LL | /     match x {
+LL | |         Ok(_) => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_err()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:144:5
+   |
+LL | /     match x {
+LL | |         Err(_) => true,
+LL | |         _ => false,
+LL | |     };
+   | |_____^ help: try this: `x.is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:149:5
+   |
+LL | /     match x {
+LL | |         Err(_) => false,
+LL | |         _ => true,
+LL | |     };
+   | |_____^ help: try this: `x.is_ok()`
+
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/ref_patterns.rs b/src/tools/clippy/tests/ui/ref_patterns.rs
new file mode 100644
index 00000000000..c51e0bc76ef
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_patterns.rs
@@ -0,0 +1,19 @@
+#![allow(unused)]
+#![warn(clippy::ref_patterns)]
+
+fn use_in_pattern() {
+    let opt = Some(5);
+    match opt {
+        None => {},
+        Some(ref opt) => {},
+    }
+}
+
+fn use_in_binding() {
+    let x = 5;
+    let ref y = x;
+}
+
+fn use_in_parameter(ref x: i32) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/ref_patterns.stderr b/src/tools/clippy/tests/ui/ref_patterns.stderr
new file mode 100644
index 00000000000..aa007782683
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ref_patterns.stderr
@@ -0,0 +1,27 @@
+error: usage of ref pattern
+  --> $DIR/ref_patterns.rs:8:14
+   |
+LL |         Some(ref opt) => {},
+   |              ^^^^^^^
+   |
+   = help: consider using `&` for clarity instead
+   = note: `-D clippy::ref-patterns` implied by `-D warnings`
+
+error: usage of ref pattern
+  --> $DIR/ref_patterns.rs:14:9
+   |
+LL |     let ref y = x;
+   |         ^^^^^
+   |
+   = help: consider using `&` for clarity instead
+
+error: usage of ref pattern
+  --> $DIR/ref_patterns.rs:17:21
+   |
+LL | fn use_in_parameter(ref x: i32) {}
+   |                     ^^^^^
+   |
+   = help: consider using `&` for clarity instead
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/regex.rs b/src/tools/clippy/tests/ui/regex.rs
index ab8ac97a0e7..a5f79b139bc 100644
--- a/src/tools/clippy/tests/ui/regex.rs
+++ b/src/tools/clippy/tests/ui/regex.rs
@@ -34,8 +34,10 @@ fn syntax_error() {
     let set_error = RegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]);
     let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+\.(com|org|net)"]);
 
+    // These following three cases are considering valid since regex-1.8.0
     let raw_string_error = Regex::new(r"[...\/...]");
     let raw_string_error = Regex::new(r#"[...\/...]"#);
+    let _ = Regex::new(r"(?<hi>hi)").unwrap();
 
     let escaped_string_span = Regex::new("\\b\\c");
 
diff --git a/src/tools/clippy/tests/ui/regex.stderr b/src/tools/clippy/tests/ui/regex.stderr
index c2440f39e0a..6b8a772e7f0 100644
--- a/src/tools/clippy/tests/ui/regex.stderr
+++ b/src/tools/clippy/tests/ui/regex.stderr
@@ -82,23 +82,11 @@ error: regex parse error:
 LL |     let bset_error = BRegexSet::new(&[OPENING_PAREN, r"[a-z]+/.(com|org|net)"]);
    |                                       ^^^^^^^^^^^^^
 
-error: regex syntax error: unrecognized escape sequence
-  --> $DIR/regex.rs:37:45
-   |
-LL |     let raw_string_error = Regex::new(r"[...//...]");
-   |                                             ^^
-
-error: regex syntax error: unrecognized escape sequence
-  --> $DIR/regex.rs:38:46
-   |
-LL |     let raw_string_error = Regex::new(r#"[...//...]"#);
-   |                                              ^^
-
 error: regex parse error:
            /b/c
              ^^
        error: unrecognized escape sequence
-  --> $DIR/regex.rs:40:42
+  --> $DIR/regex.rs:42:42
    |
 LL |     let escaped_string_span = Regex::new("/b/c");
    |                                          ^^^^^^^^
@@ -106,13 +94,13 @@ LL |     let escaped_string_span = Regex::new("/b/c");
    = help: consider using a raw string literal: `r".."`
 
 error: regex syntax error: duplicate flag
-  --> $DIR/regex.rs:42:34
+  --> $DIR/regex.rs:44:34
    |
 LL |     let aux_span = Regex::new("(?ixi)");
    |                                  ^ ^
 
 error: trivial regex
-  --> $DIR/regex.rs:46:33
+  --> $DIR/regex.rs:48:33
    |
 LL |     let trivial_eq = Regex::new("^foobar$");
    |                                 ^^^^^^^^^^
@@ -120,7 +108,7 @@ LL |     let trivial_eq = Regex::new("^foobar$");
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:48:48
+  --> $DIR/regex.rs:50:48
    |
 LL |     let trivial_eq_builder = RegexBuilder::new("^foobar$");
    |                                                ^^^^^^^^^^
@@ -128,7 +116,7 @@ LL |     let trivial_eq_builder = RegexBuilder::new("^foobar$");
    = help: consider using `==` on `str`s
 
 error: trivial regex
-  --> $DIR/regex.rs:50:42
+  --> $DIR/regex.rs:52:42
    |
 LL |     let trivial_starts_with = Regex::new("^foobar");
    |                                          ^^^^^^^^^
@@ -136,7 +124,7 @@ LL |     let trivial_starts_with = Regex::new("^foobar");
    = help: consider using `str::starts_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:52:40
+  --> $DIR/regex.rs:54:40
    |
 LL |     let trivial_ends_with = Regex::new("foobar$");
    |                                        ^^^^^^^^^
@@ -144,7 +132,7 @@ LL |     let trivial_ends_with = Regex::new("foobar$");
    = help: consider using `str::ends_with`
 
 error: trivial regex
-  --> $DIR/regex.rs:54:39
+  --> $DIR/regex.rs:56:39
    |
 LL |     let trivial_contains = Regex::new("foobar");
    |                                       ^^^^^^^^
@@ -152,7 +140,7 @@ LL |     let trivial_contains = Regex::new("foobar");
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:56:39
+  --> $DIR/regex.rs:58:39
    |
 LL |     let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
    |                                       ^^^^^^^^^^^^^^^^
@@ -160,7 +148,7 @@ LL |     let trivial_contains = Regex::new(NOT_A_REAL_REGEX);
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:58:40
+  --> $DIR/regex.rs:60:40
    |
 LL |     let trivial_backslash = Regex::new("a/.b");
    |                                        ^^^^^^^
@@ -168,7 +156,7 @@ LL |     let trivial_backslash = Regex::new("a/.b");
    = help: consider using `str::contains`
 
 error: trivial regex
-  --> $DIR/regex.rs:61:36
+  --> $DIR/regex.rs:63:36
    |
 LL |     let trivial_empty = Regex::new("");
    |                                    ^^
@@ -176,7 +164,7 @@ LL |     let trivial_empty = Regex::new("");
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:63:36
+  --> $DIR/regex.rs:65:36
    |
 LL |     let trivial_empty = Regex::new("^");
    |                                    ^^^
@@ -184,7 +172,7 @@ LL |     let trivial_empty = Regex::new("^");
    = help: the regex is unlikely to be useful as it is
 
 error: trivial regex
-  --> $DIR/regex.rs:65:36
+  --> $DIR/regex.rs:67:36
    |
 LL |     let trivial_empty = Regex::new("^$");
    |                                    ^^^^
@@ -192,12 +180,12 @@ LL |     let trivial_empty = Regex::new("^$");
    = help: consider using `str::is_empty`
 
 error: trivial regex
-  --> $DIR/regex.rs:67:44
+  --> $DIR/regex.rs:69:44
    |
 LL |     let binary_trivial_empty = BRegex::new("^$");
    |                                            ^^^^
    |
    = help: consider using `str::is_empty`
 
-error: aborting due to 25 previous errors
+error: aborting due to 23 previous errors
 
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 9036f892612..dfe45dec8a7 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -16,6 +16,7 @@
 #![allow(clippy::mixed_read_write_in_expression)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
+#![allow(clippy::arithmetic_side_effects)]
 #![allow(clippy::overly_complex_bool_expr)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::bind_instead_of_map)]
@@ -29,11 +30,11 @@
 #![allow(clippy::invisible_characters)]
 #![allow(suspicious_double_ref_op)]
 #![allow(drop_bounds)]
-#![allow(drop_copy)]
-#![allow(drop_ref)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
 #![allow(for_loops_over_fallibles)]
-#![allow(forget_copy)]
-#![allow(forget_ref)]
+#![allow(forgetting_copy_types)]
+#![allow(forgetting_references)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -58,6 +59,7 @@
 #![warn(clippy::mixed_read_write_in_expression)]
 #![warn(clippy::useless_conversion)]
 #![warn(clippy::match_result_ok)]
+#![warn(clippy::arithmetic_side_effects)]
 #![warn(clippy::overly_complex_bool_expr)]
 #![warn(clippy::new_without_default)]
 #![warn(clippy::bind_instead_of_map)]
@@ -75,13 +77,13 @@
 #![warn(clippy::invisible_characters)]
 #![warn(suspicious_double_ref_op)]
 #![warn(drop_bounds)]
-#![warn(drop_copy)]
-#![warn(drop_ref)]
+#![warn(dropping_copy_types)]
+#![warn(dropping_references)]
 #![warn(for_loops_over_fallibles)]
 #![warn(for_loops_over_fallibles)]
 #![warn(for_loops_over_fallibles)]
-#![warn(forget_copy)]
-#![warn(forget_ref)]
+#![warn(forgetting_copy_types)]
+#![warn(forgetting_references)]
 #![warn(array_into_iter)]
 #![warn(invalid_atomic_ordering)]
 #![warn(invalid_value)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 43cabe810f3..ce8eca5a308 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -16,6 +16,7 @@
 #![allow(clippy::mixed_read_write_in_expression)]
 #![allow(clippy::useless_conversion)]
 #![allow(clippy::match_result_ok)]
+#![allow(clippy::arithmetic_side_effects)]
 #![allow(clippy::overly_complex_bool_expr)]
 #![allow(clippy::new_without_default)]
 #![allow(clippy::bind_instead_of_map)]
@@ -29,11 +30,11 @@
 #![allow(clippy::invisible_characters)]
 #![allow(suspicious_double_ref_op)]
 #![allow(drop_bounds)]
-#![allow(drop_copy)]
-#![allow(drop_ref)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
 #![allow(for_loops_over_fallibles)]
-#![allow(forget_copy)]
-#![allow(forget_ref)]
+#![allow(forgetting_copy_types)]
+#![allow(forgetting_references)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -58,6 +59,7 @@
 #![warn(clippy::eval_order_dependence)]
 #![warn(clippy::identity_conversion)]
 #![warn(clippy::if_let_some_result)]
+#![warn(clippy::integer_arithmetic)]
 #![warn(clippy::logic_bug)]
 #![warn(clippy::new_without_default_derive)]
 #![warn(clippy::option_and_then_some)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 1ad7cf412c8..3fca60aa2eb 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:48:9
+  --> $DIR/rename.rs:49:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -7,280 +7,286 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:49:9
+  --> $DIR/rename.rs:50:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:50:9
+  --> $DIR/rename.rs:51:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:51:9
+  --> $DIR/rename.rs:52:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:53:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
+error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
+  --> $DIR/rename.rs:62:9
+   |
+LL | #![warn(clippy::integer_arithmetic)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
+
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
-error: lint `clippy::drop_copy` has been renamed to `drop_copy`
-  --> $DIR/rename.rs:78:9
+error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
+  --> $DIR/rename.rs:80:9
    |
 LL | #![warn(clippy::drop_copy)]
-   |         ^^^^^^^^^^^^^^^^^ help: use the new name: `drop_copy`
+   |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
-error: lint `clippy::drop_ref` has been renamed to `drop_ref`
-  --> $DIR/rename.rs:79:9
+error: lint `clippy::drop_ref` has been renamed to `dropping_references`
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::drop_ref)]
-   |         ^^^^^^^^^^^^^^^^ help: use the new name: `drop_ref`
+   |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
-error: lint `clippy::forget_copy` has been renamed to `forget_copy`
-  --> $DIR/rename.rs:83:9
+error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
+  --> $DIR/rename.rs:85:9
    |
 LL | #![warn(clippy::forget_copy)]
-   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forget_copy`
+   |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
-error: lint `clippy::forget_ref` has been renamed to `forget_ref`
-  --> $DIR/rename.rs:84:9
+error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
+  --> $DIR/rename.rs:86:9
    |
 LL | #![warn(clippy::forget_ref)]
-   |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forget_ref`
+   |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:87:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:88:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:89:9
+  --> $DIR/rename.rs:91:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:90:9
+  --> $DIR/rename.rs:92:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:91:9
+  --> $DIR/rename.rs:93:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:92:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:93:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:94:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 47 previous errors
+error: aborting due to 48 previous errors
 
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
index eef8024b131..fdac0e4cb1e 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
@@ -2,6 +2,8 @@
 #![deny(clippy::trait_duplication_in_bounds)]
 #![allow(unused)]
 
+use std::any::Any;
+
 fn bad_foo<T: Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
     unimplemented!();
 }
@@ -109,4 +111,12 @@ fn qualified_path<T: std::clone::Clone + foo::Clone>(arg0: T) {
     unimplemented!();
 }
 
+fn good_trait_object(arg0: &(dyn Any + Send)) {
+    unimplemented!();
+}
+
+fn bad_trait_object(arg0: &(dyn Any + Send)) {
+    unimplemented!();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
index a7a1caf2880..a0300da5555 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
@@ -2,6 +2,8 @@
 #![deny(clippy::trait_duplication_in_bounds)]
 #![allow(unused)]
 
+use std::any::Any;
+
 fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
     unimplemented!();
 }
@@ -109,4 +111,12 @@ fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
     unimplemented!();
 }
 
+fn good_trait_object(arg0: &(dyn Any + Send)) {
+    unimplemented!();
+}
+
+fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
+    unimplemented!();
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
index af800ba7888..539b6114ca3 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.stderr
@@ -1,5 +1,5 @@
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:5:15
+  --> $DIR/trait_duplication_in_bounds.rs:7:15
    |
 LL | fn bad_foo<T: Clone + Clone + Clone + Copy, U: Clone + Copy>(arg0: T, argo1: U) {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
@@ -11,46 +11,52 @@ LL | #![deny(clippy::trait_duplication_in_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:11:8
+  --> $DIR/trait_duplication_in_bounds.rs:13:8
    |
 LL |     T: Clone + Clone + Clone + Copy,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:39:26
+  --> $DIR/trait_duplication_in_bounds.rs:41:26
    |
 LL | trait BadSelfTraitBound: Clone + Clone + Clone {
    |                          ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:46:15
+  --> $DIR/trait_duplication_in_bounds.rs:48:15
    |
 LL |         Self: Clone + Clone + Clone;
    |               ^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:60:24
+  --> $DIR/trait_duplication_in_bounds.rs:62:24
    |
 LL | trait BadTraitBound<T: Clone + Clone + Clone + Copy, U: Clone + Copy> {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these where clauses contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:67:12
+  --> $DIR/trait_duplication_in_bounds.rs:69:12
    |
 LL |         T: Clone + Clone + Clone + Copy,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Clone + Copy`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:100:19
+  --> $DIR/trait_duplication_in_bounds.rs:102:19
    |
 LL | fn bad_generic<T: GenericTrait<u64> + GenericTrait<u32> + GenericTrait<u64>>(arg0: T) {
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `GenericTrait<u64> + GenericTrait<u32>`
 
 error: these bounds contain repeated elements
-  --> $DIR/trait_duplication_in_bounds.rs:108:22
+  --> $DIR/trait_duplication_in_bounds.rs:110:22
    |
 LL | fn qualified_path<T: std::clone::Clone + Clone + foo::Clone>(arg0: T) {
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::clone::Clone + foo::Clone`
 
-error: aborting due to 8 previous errors
+error: this trait bound is already specified in trait declaration
+  --> $DIR/trait_duplication_in_bounds.rs:118:33
+   |
+LL | fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
+   |                                 ^^^^^^^^^^^^^^^^^ help: try: `Any + Send`
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index 01eb6c5b080..c16caa38fe9 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -33,6 +33,11 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
     Ok(())
 }
 
+fn dont_lint_on_type_alias() {
+    type A = i32;
+    _ = A::from(0i32);
+}
+
 fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
     let text = "foo\r\nbar\n\nbaz\n";
     let lines = text.lines();
@@ -106,6 +111,7 @@ fn main() {
     test_questionmark().unwrap();
     test_issue_3913().unwrap();
 
+    dont_lint_on_type_alias();
     dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_expr_implementing_iterator();
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index 34b43a6299b..c75a2bce4ca 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -33,6 +33,11 @@ fn test_issue_3913() -> Result<(), std::io::Error> {
     Ok(())
 }
 
+fn dont_lint_on_type_alias() {
+    type A = i32;
+    _ = A::from(0i32);
+}
+
 fn dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr() {
     let text = "foo\r\nbar\n\nbaz\n";
     let lines = text.lines();
@@ -106,6 +111,7 @@ fn main() {
     test_questionmark().unwrap();
     test_issue_3913().unwrap();
 
+    dont_lint_on_type_alias();
     dont_lint_into_iter_on_immutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_mutable_local_implementing_iterator_in_expr();
     lint_into_iter_on_expr_implementing_iterator();
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index be067c6843a..4dca3aac533 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -23,97 +23,97 @@ LL |         let _: i32 = 0i32.into();
    |                      ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:45:22
+  --> $DIR/useless_conversion.rs:50:22
    |
 LL |     if Some("ok") == lines.into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:50:21
+  --> $DIR/useless_conversion.rs:55:21
    |
 LL |     let mut lines = text.lines().into_iter();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:56:22
+  --> $DIR/useless_conversion.rs:61:22
    |
 LL |     if Some("ok") == text.lines().into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> $DIR/useless_conversion.rs:62:13
+  --> $DIR/useless_conversion.rs:67:13
    |
 LL |     let _ = NUMBERS.into_iter().next();
    |             ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> $DIR/useless_conversion.rs:67:17
+  --> $DIR/useless_conversion.rs:72:17
    |
 LL |     let mut n = NUMBERS.into_iter();
    |                 ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:128:21
+  --> $DIR/useless_conversion.rs:134:21
    |
 LL |     let _: String = "foo".to_string().into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:129:21
+  --> $DIR/useless_conversion.rs:135:21
    |
 LL |     let _: String = From::from("foo".to_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:130:13
+  --> $DIR/useless_conversion.rs:136:13
    |
 LL |     let _ = String::from("foo".to_string());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:131:13
+  --> $DIR/useless_conversion.rs:137:13
    |
 LL |     let _ = String::from(format!("A: {:04}", 123));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> $DIR/useless_conversion.rs:132:13
+  --> $DIR/useless_conversion.rs:138:13
    |
 LL |     let _ = "".lines().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
 
 error: useless conversion to the same type: `std::vec::IntoIter<i32>`
-  --> $DIR/useless_conversion.rs:133:13
+  --> $DIR/useless_conversion.rs:139:13
    |
 LL |     let _ = vec![1, 2, 3].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> $DIR/useless_conversion.rs:134:21
+  --> $DIR/useless_conversion.rs:140:21
    |
 LL |     let _: String = format!("Hello {}", "world").into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
 
 error: useless conversion to the same type: `i32`
-  --> $DIR/useless_conversion.rs:139:13
+  --> $DIR/useless_conversion.rs:145:13
    |
 LL |     let _ = i32::from(a + b) * 3;
    |             ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> $DIR/useless_conversion.rs:145:23
+  --> $DIR/useless_conversion.rs:151:23
    |
 LL |     let _: Foo<'a'> = s2.into();
    |                       ^^^^^^^^^ help: consider removing `.into()`: `s2`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> $DIR/useless_conversion.rs:147:13
+  --> $DIR/useless_conversion.rs:153:13
    |
 LL |     let _ = Foo::<'a'>::from(s3);
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3`
 
 error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>`
-  --> $DIR/useless_conversion.rs:149:13
+  --> $DIR/useless_conversion.rs:155:13
    |
 LL |     let _ = vec![s4, s4, s4].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
diff --git a/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs b/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs
new file mode 100644
index 00000000000..203c4e15b50
--- /dev/null
+++ b/src/tools/clippy/tests/ui/wildcard_imports_cfgtest.rs
@@ -0,0 +1,19 @@
+//@compile-flags: --test
+
+#![warn(clippy::wildcard_imports)]
+#![allow(unused, clippy::unnecessary_wraps, clippy::let_unit_value)]
+
+// Test for #10580, the lint should ignore it because of the crate's cfg test flag.
+
+fn foofoo() {}
+
+mod outer {
+    mod inner {
+        use super::super::*;
+        fn barbar() {
+            let _ = foofoo();
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 3f8f6a7b98c..c40b71f6ca7 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -17,9 +17,9 @@ contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIB
 
 [assign.owners]
 "/.github" = ["@flip1995"]
+"/book" = ["@flip1995"]
 "/util/gh-pages" = ["@xFrednet"]
 "*" = [
-    "@flip1995",
     "@Manishearth",
     "@llogiq",
     "@giraffate",
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 0d42504c7f4..e5297d41a61 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -20,6 +20,7 @@ once_cell = "1.16.0"
 walkdir = "2"
 glob = "0.3.0"
 lazycell = "1.3.0"
+anyhow = "1"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 4ede4603789..5bc4d164265 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -32,6 +32,7 @@ use std::process::{Child, Command, ExitStatus, Output, Stdio};
 use std::str;
 use std::sync::Arc;
 
+use anyhow::Context;
 use glob::glob;
 use once_cell::sync::Lazy;
 use tracing::*;
@@ -131,7 +132,11 @@ pub fn run(config: Arc<Config>, testpaths: &TestPaths, revision: Option<&str>) {
     }
 
     let cx = TestCx { config: &config, props: &props, testpaths, revision };
-    create_dir_all(&cx.output_base_dir()).unwrap();
+    create_dir_all(&cx.output_base_dir())
+        .with_context(|| {
+            format!("failed to create output base directory {}", cx.output_base_dir().display())
+        })
+        .unwrap();
     if props.incremental {
         cx.init_incremental_test();
     }
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 737423a2cd1..7bedb5d48f6 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -184,6 +184,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "ctrlc"
+version = "3.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639"
+dependencies = [
+ "nix",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
 name = "diff"
 version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -421,6 +431,7 @@ name = "miri"
 version = "0.1.0"
 dependencies = [
  "colored",
+ "ctrlc",
  "env_logger",
  "getrandom",
  "lazy_static",
@@ -438,6 +449,18 @@ dependencies = [
 ]
 
 [[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "static_assertions",
+]
+
+[[package]]
 name = "object"
 version = "0.30.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -714,6 +737,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
 
 [[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
 name = "syn"
 version = "2.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index 5987b0df8d6..683f99ca4de 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -29,6 +29,7 @@ smallvec = "1.7"
 # for more information.
 rustc-workspace-hack = "1.0.0"
 measureme = "10.0.0"
+ctrlc = "3.2.5"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/src/tools/miri/cargo-miri/src/arg.rs b/src/tools/miri/cargo-miri/src/arg.rs
index e8bac4625f7..d7216060358 100644
--- a/src/tools/miri/cargo-miri/src/arg.rs
+++ b/src/tools/miri/cargo-miri/src/arg.rs
@@ -40,7 +40,8 @@ impl<'s, I: Iterator<Item = Cow<'s, str>>> Iterator for ArgSplitFlagValue<'_, I>
         if arg == "--" {
             // Stop searching at `--`.
             self.args = None;
-            return None;
+            // But yield the `--` so that it does not get lost!
+            return Some(Err(Cow::Borrowed("--")));
         }
         // These branches cannot be merged if we want to avoid the allocation in the `Borrowed` branch.
         match &arg {
@@ -79,9 +80,8 @@ impl<'a, I: Iterator<Item = String> + 'a> ArgSplitFlagValue<'a, I> {
     ) -> impl Iterator<Item = Result<String, String>> + 'a {
         ArgSplitFlagValue::new(args.map(Cow::Owned), name).map(|x| {
             match x {
-                Ok(Cow::Owned(s)) => Ok(s),
-                Err(Cow::Owned(s)) => Err(s),
-                _ => panic!("iterator converted owned to borrowed"),
+                Ok(s) => Ok(s.into_owned()),
+                Err(s) => Err(s.into_owned()),
             }
         })
     }
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index 37f66d0033f..465e4a1b2d2 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -113,30 +113,17 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
     };
     let metadata = get_cargo_metadata();
     let mut cmd = cargo();
-    cmd.arg(cargo_cmd);
-
-    // Forward all arguments before `--` other than `--target-dir` and its value to Cargo.
-    // (We want to *change* the target-dir value, so we must not forward it.)
-    let mut target_dir = None;
-    for arg in ArgSplitFlagValue::from_string_iter(&mut args, "--target-dir") {
-        match arg {
-            Ok(value) => {
-                if target_dir.is_some() {
-                    show_error!("`--target-dir` is provided more than once");
-                }
-                target_dir = Some(value.into());
-            }
-            Err(arg) => {
-                cmd.arg(arg);
-            }
-        }
+    cmd.arg(&cargo_cmd);
+    // In nextest we have to also forward the main `verb`.
+    if cargo_cmd == "nextest" {
+        cmd.arg(
+            args.next()
+                .unwrap_or_else(|| show_error!("`cargo miri nextest` expects a verb (e.g. `run`)")),
+        );
     }
-    // Detect the target directory if it's not specified via `--target-dir`.
-    // (`cargo metadata` does not support `--target-dir`, that's why we have to handle this ourselves.)
-    let target_dir = target_dir.get_or_insert_with(|| metadata.target_directory.clone());
-    // Set `--target-dir` to `miri` inside the original target directory.
-    target_dir.push("miri");
-    cmd.arg("--target-dir").arg(target_dir);
+    // We set the following flags *before* forwarding more arguments.
+    // This is needed to fix <https://github.com/rust-lang/miri/issues/2829>: cargo will stop
+    // interpreting things as flags when it sees the first positional argument.
 
     // Make sure the build target is explicitly set.
     // This is needed to make the `target.runner` settings do something,
@@ -154,8 +141,23 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
     cmd.arg("--config")
         .arg(format!("target.'cfg(all())'.runner=[{cargo_miri_path_for_toml}, 'runner']"));
 
-    // Forward all further arguments after `--` to cargo.
-    cmd.arg("--").args(args);
+    // Set `--target-dir` to `miri` inside the original target directory.
+    let mut target_dir = match get_arg_flag_value("--target-dir") {
+        Some(dir) => PathBuf::from(dir),
+        None => metadata.target_directory.clone().into_std_path_buf(),
+    };
+    target_dir.push("miri");
+    cmd.arg("--target-dir").arg(target_dir);
+
+    // *After* we set all the flags that need setting, forward everything else. Make sure to skip
+    // `--target-dir` (which would otherwise be set twice).
+    for arg in
+        ArgSplitFlagValue::from_string_iter(&mut args, "--target-dir").filter_map(Result::err)
+    {
+        cmd.arg(arg);
+    }
+    // Forward all further arguments (not consumed by `ArgSplitFlagValue`) to cargo.
+    cmd.args(args);
 
     // Set `RUSTC_WRAPPER` to ourselves.  Cargo will prepend that binary to its usual invocation,
     // i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index b450f986149..0bff100dc14 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-69fef92ab2f287f072b66fb7b4f62c8bb4acba43
+8b4b20836b832e91aa605a2faf5e2a55190202c8
diff --git a/src/tools/miri/src/concurrency/thread.rs b/src/tools/miri/src/concurrency/thread.rs
index e9bbae4d504..d85cac7bcbb 100644
--- a/src/tools/miri/src/concurrency/thread.rs
+++ b/src/tools/miri/src/concurrency/thread.rs
@@ -3,6 +3,7 @@
 use std::cell::RefCell;
 use std::collections::hash_map::Entry;
 use std::num::TryFromIntError;
+use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
 use std::task::Poll;
 use std::time::{Duration, SystemTime};
 
@@ -1012,8 +1013,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
     /// termination).
     fn run_threads(&mut self) -> InterpResult<'tcx, !> {
+        static SIGNALED: AtomicBool = AtomicBool::new(false);
+        ctrlc::set_handler(move || {
+            // Indicate that we have ben signaled to stop. If we were already signaled, exit
+            // immediately. In our interpreter loop we try to consult this value often, but if for
+            // whatever reason we don't get to that check or the cleanup we do upon finding that
+            // this bool has become true takes a long time, the exit here will promptly exit the
+            // process on the second Ctrl-C.
+            if SIGNALED.swap(true, Relaxed) {
+                std::process::exit(1);
+            }
+        })
+        .unwrap();
         let this = self.eval_context_mut();
         loop {
+            if SIGNALED.load(Relaxed) {
+                this.machine.handle_abnormal_termination();
+                std::process::exit(1);
+            }
             match this.machine.threads.schedule(&this.machine.clock)? {
                 SchedulingAction::ExecuteStep => {
                     if !this.step()? {
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 32717a0d28b..29f518fe58b 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -713,6 +713,15 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
         let def_id = frame.instance.def_id();
         def_id.is_local() || self.local_crates.contains(&def_id.krate)
     }
+
+    /// Called when the interpreter is going to shut down abnormally, such as due to a Ctrl-C.
+    pub(crate) fn handle_abnormal_termination(&mut self) {
+        // All strings in the profile data are stored in a single string table which is not
+        // written to disk until the profiler is dropped. If the interpreter exits without dropping
+        // the profiler, it is not possible to interpret the profile data and all measureme tools
+        // will panic when given the file.
+        drop(self.profiler.take());
+    }
 }
 
 impl VisitTags for MiriMachine<'_, '_> {
diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs
index 1e4ab2f0f62..323991249d3 100644
--- a/src/tools/miri/src/shims/backtrace.rs
+++ b/src/tools/miri/src/shims/backtrace.rs
@@ -102,7 +102,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let ptr_layout = this.layout_of(ptr_ty)?;
 
                 for (i, ptr) in ptrs.into_iter().enumerate() {
-                    let offset = ptr_layout.size * i.try_into().unwrap();
+                    let offset = ptr_layout.size.checked_mul(i.try_into().unwrap(), this).unwrap();
 
                     let op_place = buf_place.offset(offset, ptr_layout, this)?;
 
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 44bca3796f9..aa0794c00be 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -166,7 +166,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     dependency_format.1.iter().enumerate().filter_map(|(num, &linkage)| {
                         // We add 1 to the number because that's what rustc also does everywhere it
                         // calls `CrateNum::new`...
-                        #[allow(clippy::integer_arithmetic)]
+                        #[allow(clippy::arithmetic_side_effects)]
                         (linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1))
                     }),
                 ) {
@@ -707,7 +707,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     .position(|&c| c == val)
                 {
                     let idx = u64::try_from(idx).unwrap();
-                    #[allow(clippy::integer_arithmetic)] // idx < num, so this never wraps
+                    #[allow(clippy::arithmetic_side_effects)] // idx < num, so this never wraps
                     let new_ptr = ptr.offset(Size::from_bytes(num - idx - 1), this)?;
                     this.write_pointer(new_ptr, dest)?;
                 } else {
@@ -916,10 +916,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let a = this.read_scalar(a)?.to_u64()?;
                 let b = this.read_scalar(b)?.to_u64()?;
 
-                #[allow(clippy::integer_arithmetic)]
+                #[allow(clippy::arithmetic_side_effects)]
                 // adding two u64 and a u8 cannot wrap in a u128
                 let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b);
-                #[allow(clippy::integer_arithmetic)] // it's a u128, we can shift by 64
+                #[allow(clippy::arithmetic_side_effects)] // it's a u128, we can shift by 64
                 let (c_out, sum) = ((wide_sum >> 64).truncate::<u8>(), wide_sum.truncate::<u64>());
 
                 let c_out_field = this.place_field(dest, 0)?;
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index 114c66253f7..1995db715e8 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -563,7 +563,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let (op, op_len) = this.operand_to_simd(op)?;
                 let bitmask_len = op_len.max(8);
 
-                assert!(dest.layout.ty.is_integral());
+                // Returns either an unsigned integer or array of `u8`.
+                assert!(
+                    dest.layout.ty.is_integral()
+                        || matches!(dest.layout.ty.kind(), ty::Array(elemty, _) if elemty == &this.tcx.types.u8)
+                );
                 assert!(bitmask_len <= 64);
                 assert_eq!(bitmask_len, dest.layout.size.bits());
                 let op_len = u32::try_from(op_len).unwrap();
@@ -577,7 +581,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                             .unwrap();
                     }
                 }
-                this.write_int(res, dest)?;
+                // We have to force the place type to be an int so that we can write `res` into it.
+                let mut dest = this.force_allocation(dest)?;
+                dest.layout = this.machine.layouts.uint(dest.layout.size).unwrap();
+                this.write_int(res, &dest.into())?;
             }
 
             name => throw_unsup_format!("unimplemented intrinsic: `simd_{name}`"),
@@ -605,7 +612,7 @@ fn simd_bitmask_index(idx: u32, vec_len: u32, endianness: Endian) -> u32 {
     assert!(idx < vec_len);
     match endianness {
         Endian::Little => idx,
-        #[allow(clippy::integer_arithmetic)] // idx < vec_len
+        #[allow(clippy::arithmetic_side_effects)] // idx < vec_len
         Endian::Big => vec_len - 1 - idx, // reverse order of bits
     }
 }
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index 918efda3777..a423a0786b7 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -1,4 +1,4 @@
-#![warn(clippy::integer_arithmetic)]
+#![warn(clippy::arithmetic_side_effects)]
 
 mod backtrace;
 #[cfg(target_os = "linux")]
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index 2f24c00ce14..756dec1beca 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -108,7 +108,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         Ok(0)
     }
 
-    #[allow(non_snake_case, clippy::integer_arithmetic)]
+    #[allow(non_snake_case, clippy::arithmetic_side_effects)]
     fn GetSystemTimeAsFileTime(
         &mut self,
         LPFILETIME_op: &OpTy<'tcx, Provenance>,
diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs
index 685feeaf892..62bd087e7e8 100644
--- a/src/tools/miri/src/shims/tls.rs
+++ b/src/tools/miri/src/shims/tls.rs
@@ -56,7 +56,7 @@ impl<'tcx> Default for TlsData<'tcx> {
 impl<'tcx> TlsData<'tcx> {
     /// Generate a new TLS key with the given destructor.
     /// `max_size` determines the integer size the key has to fit in.
-    #[allow(clippy::integer_arithmetic)]
+    #[allow(clippy::arithmetic_side_effects)]
     pub fn create_tls_key(
         &mut self,
         dtor: Option<ty::Instance<'tcx>>,
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index abec782b4f0..d1b09cd7b55 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -458,7 +458,7 @@ pub struct DirHandler {
 }
 
 impl DirHandler {
-    #[allow(clippy::integer_arithmetic)]
+    #[allow(clippy::arithmetic_side_effects)]
     fn insert_new(&mut self, read_dir: ReadDir) -> u64 {
         let id = self.next_id;
         self.next_id += 1;
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index ffe3ca69c58..6889c430042 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -247,7 +247,7 @@ pub fn futex<'tcx>(
             // before doing the syscall.
             this.atomic_fence(AtomicFenceOrd::SeqCst)?;
             let mut n = 0;
-            #[allow(clippy::integer_arithmetic)]
+            #[allow(clippy::arithmetic_side_effects)]
             for _ in 0..val {
                 if let Some(thread) = this.futex_wake(addr_usize, bitset) {
                     this.unblock_thread(thread);
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index f72ba5cca7a..b8bb7f62452 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -219,7 +219,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     .copied()
                     .scan(Size::ZERO, |a, x| {
                         let res = Some(*a);
-                        *a += x;
+                        *a = a.checked_add(x, this).unwrap();
                         res
                     })
                     .collect();
diff --git a/src/tools/miri/src/shims/windows/handle.rs b/src/tools/miri/src/shims/windows/handle.rs
index 8bffa9991c7..d9ae1b22409 100644
--- a/src/tools/miri/src/shims/windows/handle.rs
+++ b/src/tools/miri/src/shims/windows/handle.rs
@@ -62,7 +62,7 @@ impl Handle {
         let floor_log2 = variant_count.ilog2();
 
         // we need to add one for non powers of two to compensate for the difference
-        #[allow(clippy::integer_arithmetic)] // cannot overflow
+        #[allow(clippy::arithmetic_side_effects)] // cannot overflow
         if variant_count.is_power_of_two() { floor_log2 } else { floor_log2 + 1 }
     }
 
@@ -87,7 +87,7 @@ impl Handle {
 
         // packs the data into the lower `data_size` bits
         // and packs the discriminant right above the data
-        #[allow(clippy::integer_arithmetic)] // cannot overflow
+        #[allow(clippy::arithmetic_side_effects)] // cannot overflow
         return discriminant << data_size | data;
     }
 
@@ -106,11 +106,11 @@ impl Handle {
         let data_size = u32::BITS.checked_sub(disc_size).unwrap();
 
         // the lower `data_size` bits of this mask are 1
-        #[allow(clippy::integer_arithmetic)] // cannot overflow
+        #[allow(clippy::arithmetic_side_effects)] // cannot overflow
         let data_mask = 2u32.pow(data_size) - 1;
 
         // the discriminant is stored right above the lower `data_size` bits
-        #[allow(clippy::integer_arithmetic)] // cannot overflow
+        #[allow(clippy::arithmetic_side_effects)] // cannot overflow
         let discriminant = handle >> data_size;
 
         // the data is stored in the lower `data_size` bits
diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py
index 46b3afa70e5..9df90c725e4 100755
--- a/src/tools/miri/test-cargo-miri/run-test.py
+++ b/src/tools/miri/test-cargo-miri/run-test.py
@@ -108,8 +108,9 @@ def test_cargo_miri_run():
         env={'MIRITESTVAR': "wrongval"}, # changing the env var causes a rebuild (re-runs build.rs),
                                          # so keep it set
     )
+    # This also covers passing arguments without `--`: Cargo will forward unused positional arguments to the program.
     test("`cargo miri run` (with arguments and target)",
-        cargo_miri("run") + ["--bin", "cargo-miri-test", "--", "hello world", '"hello world"', r'he\\llo\"world'],
+        cargo_miri("run") + ["--bin", "cargo-miri-test", "hello world", '"hello world"', r'he\\llo\"world'],
         "run.args.stdout.ref", "run.args.stderr.ref",
     )
     test("`cargo miri r` (subcrate, no isolation)",
diff --git a/src/tools/miri/tests/fail/never_say_never.rs b/src/tools/miri/tests/fail/never_say_never.rs
index f6d3dc790bf..fd082e367a8 100644
--- a/src/tools/miri/tests/fail/never_say_never.rs
+++ b/src/tools/miri/tests/fail/never_say_never.rs
@@ -6,10 +6,8 @@
 
 fn main() {
     let y = &5;
-    let x: ! = unsafe {
-        *(y as *const _ as *const !) //~ ERROR: entering unreachable code
-    };
-    f(x)
+    let x: ! = unsafe { *(y as *const _ as *const !) };
+    f(x) //~ ERROR: entering unreachable code
 }
 
 fn f(x: !) -> ! {
diff --git a/src/tools/miri/tests/fail/never_say_never.stderr b/src/tools/miri/tests/fail/never_say_never.stderr
index a2a63b8baf5..9d3a8df525a 100644
--- a/src/tools/miri/tests/fail/never_say_never.stderr
+++ b/src/tools/miri/tests/fail/never_say_never.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: entering unreachable code
   --> $DIR/never_say_never.rs:LL:CC
    |
-LL |         *(y as *const _ as *const !)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ entering unreachable code
+LL |     f(x)
+   |     ^^^^ entering unreachable code
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs
index bf4204c61fd..a5a1930ed65 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write2.rs
@@ -1,4 +1,4 @@
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 fn main() {
     let target = &mut 42;
diff --git a/src/tools/miri/tests/fail/uninit_buffer.rs b/src/tools/miri/tests/fail/uninit_buffer.rs
index 8a330058375..d622b2fa7d8 100644
--- a/src/tools/miri/tests/fail/uninit_buffer.rs
+++ b/src/tools/miri/tests/fail/uninit_buffer.rs
@@ -1,6 +1,6 @@
 //@error-in-other-file: memory is uninitialized at [0x4..0x10]
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::alloc::{alloc, dealloc, Layout};
 use std::slice::from_raw_parts;
diff --git a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
index 443f481c087..ca825901372 100644
--- a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
+++ b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.rs
@@ -1,7 +1,7 @@
 //@error-in-other-file: memory is uninitialized at [0x4..0x8]
 //@normalize-stderr-test: "a[0-9]+" -> "ALLOC"
 #![feature(strict_provenance)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 // Test printing allocations that contain single-byte provenance.
 
diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs
index 173ac654b03..ee67a65a4f9 100644
--- a/src/tools/miri/tests/pass/portable-simd.rs
+++ b/src/tools/miri/tests/pass/portable-simd.rs
@@ -2,6 +2,10 @@
 #![feature(portable_simd, platform_intrinsics)]
 use std::simd::*;
 
+extern "platform-intrinsic" {
+    pub(crate) fn simd_bitmask<T, U>(x: T) -> U;
+}
+
 fn simd_ops_f32() {
     let a = f32x4::splat(10.0);
     let b = f32x4::from_array([1.0, 2.0, 3.0, -4.0]);
@@ -208,11 +212,40 @@ fn simd_mask() {
     assert_eq!(bitmask, 0b1010001101001001);
     assert_eq!(Mask::<i64, 16>::from_bitmask(bitmask), mask);
 
+    // Also directly call intrinsic, to test both kinds of return types.
+    unsafe {
+        let bitmask1: u16 = simd_bitmask(mask.to_int());
+        let bitmask2: [u8; 2] = simd_bitmask(mask.to_int());
+        if cfg!(target_endian = "little") {
+            assert_eq!(bitmask1, 0b1010001101001001);
+            assert_eq!(bitmask2, [0b01001001, 0b10100011]);
+        } else {
+            // All the bitstrings are reversed compared to above, but the array elements are in the
+            // same order.
+            assert_eq!(bitmask1, 0b1001001011000101);
+            assert_eq!(bitmask2, [0b10010010, 0b11000101]);
+        }
+    }
+
+    // Mask less than 8 bits long, which is a special case (padding with 0s).
     let values = [false, false, false, true];
     let mask = Mask::<i64, 4>::from_array(values);
     let bitmask = mask.to_bitmask();
     assert_eq!(bitmask, 0b1000);
     assert_eq!(Mask::<i64, 4>::from_bitmask(bitmask), mask);
+
+    // Also directly call intrinsic, to test both kinds of return types.
+    unsafe {
+        let bitmask1: u8 = simd_bitmask(mask.to_int());
+        let bitmask2: [u8; 1] = simd_bitmask(mask.to_int());
+        if cfg!(target_endian = "little") {
+            assert_eq!(bitmask1, 0b1000);
+            assert_eq!(bitmask2, [0b1000]);
+        } else {
+            assert_eq!(bitmask1, 0b0001);
+            assert_eq!(bitmask2, [0b0001]);
+        }
+    }
 }
 
 fn simd_cast() {
diff --git a/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs b/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
index 9f743f0b566..6e13a9ea836 100644
--- a/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
+++ b/src/tools/miri/tests/pass/stacked-borrows/zst-field-retagging-terminates.rs
@@ -1,7 +1,7 @@
 //@compile-flags: -Zmiri-retag-fields
 // Checks that the test does not run forever (which relies on a fast path).
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 fn main() {
     let array = [(); usize::MAX];
diff --git a/src/tools/replace-version-placeholder/src/main.rs b/src/tools/replace-version-placeholder/src/main.rs
index 0aebfc4aad2..5c9c18b9b36 100644
--- a/src/tools/replace-version-placeholder/src/main.rs
+++ b/src/tools/replace-version-placeholder/src/main.rs
@@ -8,15 +8,13 @@ fn main() {
     let version_path = root_path.join("src").join("version");
     let version_str = t!(std::fs::read_to_string(&version_path), version_path);
     let version_str = version_str.trim();
-    walk::walk(
-        &root_path,
+    walk::walk_many(
+        &[&root_path.join("compiler"), &root_path.join("library")],
         |path, _is_dir| {
             walk::filter_dirs(path)
                 // We exempt these as they require the placeholder
                 // for their operation
                 || path.ends_with("compiler/rustc_attr/src/builtin.rs")
-                || path.ends_with("src/tools/tidy/src/features/version.rs")
-                || path.ends_with("src/tools/replace-version-placeholder")
         },
         &mut |entry, contents| {
             if !contents.contains(VERSION_PLACEHOLDER) {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index e1004c796c5..2e778110931 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -117,6 +117,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "autocfg",
     "bitflags",
     "block-buffer",
+    "byteorder", // via ruzstd in object in thorin-dwp
     "cc",
     "cfg-if",
     "chalk-derive",
@@ -217,6 +218,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "rustc-rayon",
     "rustc-rayon-core",
     "rustc_version",
+    "ruzstd", // via object in thorin-dwp
     "ryu",
     "scoped-tls",
     "scopeguard",
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index ee12f4acb10..be3a5d3aa0f 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -35,6 +35,7 @@ const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
     "tests/ui/macros/syntax-extension-source-utils-files/includeme.fragment", // more include
     "tests/ui/unused-crate-deps/test.mk", // why would you use make
     "tests/ui/proc-macro/auxiliary/included-file.txt", // more include
+    "tests/ui/invalid/foo.natvis.xml", // sample debugger visualizer
 ];
 
 fn check_entries(tests_path: &Path, bad: &mut bool) {
diff --git a/tests/assembly/option-nonzero-eq.rs b/tests/assembly/option-nonzero-eq.rs
new file mode 100644
index 00000000000..f5d88de76dd
--- /dev/null
+++ b/tests/assembly/option-nonzero-eq.rs
@@ -0,0 +1,28 @@
+// revisions: WIN LIN
+// [WIN] only-windows
+// [LIN] only-linux
+// assembly-output: emit-asm
+// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel
+// only-x86_64
+// ignore-sgx
+// ignore-debug
+
+use std::cmp::Ordering;
+
+// CHECK-lABEL: ordering_eq:
+#[no_mangle]
+pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
+    // Linux (System V): first two arguments are rdi then rsi
+    // Windows: first two arguments are rcx then rdx
+    // Both use rax for the return value.
+
+    // CHECK-NOT: mov
+    // CHECK-NOT: test
+    // CHECK-NOT: cmp
+
+    // LIN: cmp dil, sil
+    // WIN: cmp cl, dl
+    // CHECK-NEXT: sete al
+    // CHECK-NEXT: ret
+    l == r
+}
diff --git a/tests/codegen/drop-in-place-noalias.rs b/tests/codegen/drop-in-place-noalias.rs
new file mode 100644
index 00000000000..725e6fc048d
--- /dev/null
+++ b/tests/codegen/drop-in-place-noalias.rs
@@ -0,0 +1,38 @@
+// compile-flags: -O -C no-prepopulate-passes
+
+// Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`.
+// Note that non-Unpin types should not get `noalias`, matching &mut behavior.
+
+#![crate_type="lib"]
+
+use std::marker::PhantomPinned;
+
+// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructUnpin{{.*}}({{.*\*|ptr}} noalias noundef align 4 dereferenceable(12) %{{.+}})
+
+// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}({{.*\*|ptr}} noundef nonnull align 4 %{{.+}})
+
+pub struct StructUnpin {
+    a: i32,
+    b: i32,
+    c: i32,
+}
+
+impl Drop for StructUnpin {
+    fn drop(&mut self) {}
+}
+
+pub struct StructNotUnpin {
+    a: i32,
+    b: i32,
+    c: i32,
+    p: PhantomPinned,
+}
+
+impl Drop for StructNotUnpin {
+    fn drop(&mut self) {}
+}
+
+pub unsafe fn main(x: StructUnpin, y: StructNotUnpin) {
+    drop(x);
+    drop(y);
+}
diff --git a/tests/codegen/issues/issue-111603.rs b/tests/codegen/issues/issue-111603.rs
new file mode 100644
index 00000000000..90b3c314d2f
--- /dev/null
+++ b/tests/codegen/issues/issue-111603.rs
@@ -0,0 +1,28 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![feature(get_mut_unchecked, new_uninit)]
+
+use std::sync::Arc;
+
+// CHECK-LABEL: @new_uninit
+#[no_mangle]
+pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> {
+    // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+    // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+    let mut arc = Arc::new_uninit();
+    unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]);
+    unsafe { arc.assume_init() }
+}
+
+// CHECK-LABEL: @new_uninit_slice
+#[no_mangle]
+pub fn new_uninit_slice(x: u64) -> Arc<[u64]> {
+    // CHECK: call alloc::sync::arcinner_layout_for_value_layout
+    // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
+    let mut arc = Arc::new_uninit_slice(1000);
+    for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } {
+        elem.write(x);
+    }
+    unsafe { arc.assume_init() }
+}
diff --git a/tests/codegen/noalias-box-off.rs b/tests/codegen/noalias-box-off.rs
index afd17c7c160..c82c53b2a48 100644
--- a/tests/codegen/noalias-box-off.rs
+++ b/tests/codegen/noalias-box-off.rs
@@ -4,5 +4,8 @@
 
 // CHECK-LABEL: @box_should_not_have_noalias_if_disabled(
 // CHECK-NOT: noalias
+// CHECK-SAME: %foo)
 #[no_mangle]
-pub fn box_should_not_have_noalias_if_disabled(_b: Box<u8>) {}
+pub fn box_should_not_have_noalias_if_disabled(foo: Box<u8>) {
+    drop(foo);
+}
diff --git a/tests/codegen/option-nonzero-eq.rs b/tests/codegen/option-nonzero-eq.rs
index 835decd3e5f..a394695f3bd 100644
--- a/tests/codegen/option-nonzero-eq.rs
+++ b/tests/codegen/option-nonzero-eq.rs
@@ -7,6 +7,9 @@ use core::cmp::Ordering;
 use core::num::{NonZeroU32, NonZeroI64};
 use core::ptr::NonNull;
 
+// See also tests/assembly/option-nonzero-eq.rs, for cases with `assume`s in the
+// LLVM and thus don't optimize down clearly here, but do in assembly.
+
 // CHECK-lABEL: @non_zero_eq
 #[no_mangle]
 pub fn non_zero_eq(l: Option<NonZeroU32>, r: Option<NonZeroU32>) -> bool {
@@ -33,12 +36,3 @@ pub fn non_null_eq(l: Option<NonNull<u8>>, r: Option<NonNull<u8>>) -> bool {
     // CHECK-NEXT: ret i1
     l == r
 }
-
-// CHECK-lABEL: @ordering_eq
-#[no_mangle]
-pub fn ordering_eq(l: Option<Ordering>, r: Option<Ordering>) -> bool {
-    // CHECK: start:
-    // CHECK-NEXT: icmp eq i8
-    // CHECK-NEXT: ret i1
-    l == r
-}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
index 71e26e3fe8a..ebb26cd35c0 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-id-itanium-cxx-abi.rs
@@ -44,7 +44,7 @@ impl<T> Trait1<T> for i32 {
 }
 
 // Trait implementation
-impl<T> Trait1<T> for Struct1<T> {
+impl<T, U> Trait1<T> for Struct1<U> {
     fn foo(&self) { }
 }
 
@@ -536,15 +536,15 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
 // CHECK: ![[TYPE93]] = !{i64 0, !"_ZTSFvPFu3i32S_EE"}
 // CHECK: ![[TYPE94]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_E"}
 // CHECK: ![[TYPE95]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_S0_E"}
-// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
-// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEEE"}
-// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_E"}
-// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5tupleIu3i32EEu{{[0-9]+}}NtNtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnce6OutputIS0_ES_u6regionEES5_S5_E"}
+// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_S3_E"}
+// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_S3_E"}
+// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEEE"}
+// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_E"}
+// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_S3_E"}
 // CHECK: ![[TYPE105]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEEE"}
 // CHECK: ![[TYPE106]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_E"}
 // CHECK: ![[TYPE107]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_S2_E"}
@@ -566,9 +566,9 @@ pub fn foo149(_: Type14<Bar>, _: Type14<Bar>, _: Type14<Bar>) { }
 // CHECK: ![[TYPE123]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32EE"}
 // CHECK: ![[TYPE124]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_E"}
 // CHECK: ![[TYPE125]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_S0_E"}
-// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_EE"}
-// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_E"}
-// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu3i32Eu6regionES_ES3_S3_E"}
+// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32EE"}
+// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_E"}
+// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait1Iu5paramEu6regionEu3i32ES4_S4_E"}
 // CHECK: ![[TYPE129]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_EE"}
 // CHECK: ![[TYPE130]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_E"}
 // CHECK: ![[TYPE131]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_51sanitizer_cfi_emit_type_metadata_id_itanium_cxx_abi6Trait13fooIu3i32S_ES0_S0_E"}
diff --git a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
index ab5dcec7936..0f79adab7bd 100644
--- a/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer-cfi-emit-type-metadata-trait-objects.rs
@@ -1,44 +1,120 @@
 // Verifies that type metadata identifiers for trait objects are emitted correctly.
 //
 // needs-sanitizer-cfi
-// compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi
+// compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Ctarget-feature=-crt-static -Zsanitizer=cfi
 
 #![crate_type="lib"]
 
-trait Trait1 {
+pub trait Trait1 {
     fn foo(&self);
 }
 
-struct Type1;
+#[derive(Clone, Copy)]
+pub struct Type1;
 
 impl Trait1 for Type1 {
     fn foo(&self) {
     }
 }
 
-pub fn foo() {
-    let a = Type1;
+pub trait Trait2<T> {
+    fn bar(&self);
+}
+
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+    fn bar(&self) {
+    }
+}
+
+pub trait Trait3<T> {
+    fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+    fn baz(&self, _: &U) {
+    }
+}
+
+pub trait Trait4<'a, T> {
+    type Output: 'a;
+    fn qux(&self, _: &T) -> Self::Output;
+}
+
+pub struct Type4;
+
+impl<'a, T, U> Trait4<'a, U> for T {
+    type Output = &'a i32;
+    fn qux(&self, _: &U) -> Self::Output {
+        &0
+    }
+}
+
+pub fn foo1(a: &dyn Trait1) {
     a.foo();
-    // CHECK-LABEL: define{{.*}}foo{{.*}}!type !{{[0-9]+}}
-    // CHECK:       call <sanitizer_cfi_emit_type_metadata_trait_objects::Type1 as sanitizer_cfi_emit_type_metadata_trait_objects::Trait1>::foo
+    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE1:[[:print:]]+]]")
 }
 
-pub fn bar() {
+pub fn bar1() {
     let a = Type1;
     let b = &a as &dyn Trait1;
     b.foo();
-    // CHECK-LABEL: define{{.*}}bar{{.*}}!type !{{[0-9]+}}
-    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0|%1}}, metadata !"[[TYPE1:[[:print:]]+]]")
+    // CHECK-LABEL: define{{.*}}4bar1{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
 }
 
-pub fn baz() {
-    let a = Type1;
-    let b = &a as &dyn Trait1;
-    a.foo();
-    b.foo();
-    // CHECK-LABEL: define{{.*}}baz{{.*}}!type !{{[0-9]+}}
-    // CHECK:       call <sanitizer_cfi_emit_type_metadata_trait_objects::Type1 as sanitizer_cfi_emit_type_metadata_trait_objects::Trait1>::foo
-    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%0|%1}}, metadata !"[[TYPE1:[[:print:]]+]]")
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+    a.bar();
+    // CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn bar2() {
+    let a = Type2;
+    foo2(&a);
+    let b = &a as &dyn Trait2<i32>;
+    b.bar();
+    // CHECK-LABEL: define{{.*}}4bar2{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]")
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+    let b = Type3;
+    a.baz(&b);
+    // CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
+}
+
+pub fn bar3() {
+    let a = Type3;
+    foo3(&a);
+    let b = &a as &dyn Trait3<Type3>;
+    b.baz(&a);
+    // CHECK-LABEL: define{{.*}}4bar3{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]")
+}
+
+pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
+    let b = Type4;
+    a.qux(&b);
+    // CHECK-LABEL: define{{.*}}4foo4{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
+}
+
+pub fn bar4<'a>() {
+    let a = Type4;
+    foo4(&a);
+    let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
+    b.qux(&a);
+    // CHECK-LABEL: define{{.*}}4bar4{{.*}}!type !{{[0-9]+}}
+    // CHECK:       call i1 @llvm.type.test({{i8\*|ptr}} {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]")
 }
 
 // CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE2]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE3]]"}
+// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE4]]"}
diff --git a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
index 81e0d9344f7..004a67e7df2 100644
--- a/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
+++ b/tests/codegen/sanitizer-kcfi-emit-type-metadata-trait-objects.rs
@@ -30,40 +30,115 @@ trait Freeze { }
 #[lang="drop_in_place"]
 fn drop_in_place_fn<T>() { }
 
-trait Trait1 {
+pub trait Trait1 {
     fn foo(&self);
 }
 
-struct Type1;
+pub struct Type1;
 
 impl Trait1 for Type1 {
     fn foo(&self) {
     }
 }
 
-pub fn foo() {
-    let a = Type1;
+pub trait Trait2<T> {
+    fn bar(&self);
+}
+
+pub struct Type2;
+
+impl Trait2<i32> for Type2 {
+    fn bar(&self) {
+    }
+}
+
+pub trait Trait3<T> {
+    fn baz(&self, _: &T);
+}
+
+pub struct Type3;
+
+impl<T, U> Trait3<U> for T {
+    fn baz(&self, _: &U) {
+    }
+}
+
+pub trait Trait4<'a, T> {
+    type Output: 'a;
+    fn qux(&self, _: &T) -> Self::Output;
+}
+
+pub struct Type4;
+
+impl<'a, T, U> Trait4<'a, U> for T {
+    type Output = &'a i32;
+    fn qux(&self, _: &U) -> Self::Output {
+        &0
+    }
+}
+
+pub fn foo1(a: &dyn Trait1) {
     a.foo();
-    // CHECK-LABEL: define{{.*}}foo{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
-    // CHECK:       call <sanitizer_kcfi_emit_type_metadata_trait_objects::Type1 as sanitizer_kcfi_emit_type_metadata_trait_objects::Trait1>::foo
+    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
 }
 
-pub fn bar() {
+pub fn bar1() {
     let a = Type1;
     let b = &a as &dyn Trait1;
     b.foo();
-    // CHECK-LABEL: define{{.*}}bar{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
-    // CHECK:       call void %0({{\{\}\*|ptr}} align 1 {{%b\.0|%_1}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+    // CHECK-LABEL: define{{.*}}4bar1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
 }
 
-pub fn baz() {
-    let a = Type1;
-    let b = &a as &dyn Trait1;
-    a.foo();
-    b.foo();
-    // CHECK-LABEL: define{{.*}}baz{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
-    // CHECK:       call <sanitizer_kcfi_emit_type_metadata_trait_objects::Type1 as sanitizer_kcfi_emit_type_metadata_trait_objects::Trait1>::foo
-    // CHECK:       call void %0({{\{\}\*|ptr}} align 1 {{%b\.0|%_1}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
+pub fn foo2<T>(a: &dyn Trait2<T>) {
+    a.bar();
+    // CHECK-LABEL: define{{.*}}4foo2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn bar2() {
+    let a = Type2;
+    foo2(&a);
+    let b = &a as &dyn Trait2<i32>;
+    b.bar();
+    // CHECK-LABEL: define{{.*}}4bar2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
+}
+
+pub fn foo3(a: &dyn Trait3<Type3>) {
+    let b = Type3;
+    a.baz(&b);
+    // CHECK-LABEL: define{{.*}}4foo3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
+}
+
+pub fn bar3() {
+    let a = Type3;
+    foo3(&a);
+    let b = &a as &dyn Trait3<Type3>;
+    b.baz(&a);
+    // CHECK-LABEL: define{{.*}}4bar3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
+}
+
+pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
+    let b = Type4;
+    a.qux(&b);
+    // CHECK-LABEL: define{{.*}}4foo4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
+}
+
+pub fn bar4<'a>() {
+    let a = Type4;
+    foo4(&a);
+    let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
+    b.qux(&a);
+    // CHECK-LABEL: define{{.*}}4bar4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
+    // CHECK:       call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
 }
 
 // CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE2]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE3]]}
+// CHECK: !{{[0-9]+}} = !{i32 [[TYPE4]]}
diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs
new file mode 100644
index 00000000000..51334c12158
--- /dev/null
+++ b/tests/codegen/tied-features-strength.rs
@@ -0,0 +1,29 @@
+// ignore-tidy-linelength
+// revisions: ENABLE_SVE DISABLE_SVE DISABLE_NEON ENABLE_NEON
+// compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu
+// needs-llvm-components: aarch64
+
+// The "+v8a" feature is matched as optional as it isn't added when we
+// are targeting older LLVM versions. Once the min supported version
+// is LLVM-14 we can remove the optional regex matching for this feature.
+
+// [ENABLE_SVE] compile-flags: -C target-feature=+sve
+// ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+sve,?)|(\+neon,?))*}}" }
+
+// [DISABLE_SVE] compile-flags: -C target-feature=-sve
+// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-sve,?)|(\+neon,?))*}}" }
+
+// [DISABLE_NEON] compile-flags: -C target-feature=-neon
+// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(-fp-armv8,?)|(-neon,?))*}}" }
+
+// [ENABLE_NEON] compile-flags: -C target-feature=+neon
+// ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" }
+
+
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+pub fn test() {}
diff --git a/tests/incremental/const-generic-type-cycle.rs b/tests/incremental/const-generic-type-cycle.rs
new file mode 100644
index 00000000000..ca7b12e9e62
--- /dev/null
+++ b/tests/incremental/const-generic-type-cycle.rs
@@ -0,0 +1,17 @@
+// Verify that we do not ICE when we try to overwrite an anon-const's type because of a trait
+// cycle.
+//
+// compile-flags: -Zincremental-ignore-spans
+// revisions: cpass cfail
+// error-pattern: cycle detected when computing type of `Bar::N`
+
+#![feature(trait_alias)]
+#![crate_type="lib"]
+
+#[cfg(cpass)]
+trait Bar<const N: usize> {}
+
+#[cfg(cfail)]
+trait Bar<const N: dyn BB> {}
+
+trait BB = Bar<{ 2 + 1 }>;
diff --git a/tests/mir-opt/building/enum_cast.bar.built.after.mir b/tests/mir-opt/building/enum_cast.bar.built.after.mir
index 0746e0b498e..9f14c028465 100644
--- a/tests/mir-opt/building/enum_cast.bar.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.bar.built.after.mir
@@ -5,17 +5,16 @@ fn bar(_1: Bar) -> usize {
     let mut _0: usize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
     let _2: Bar;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
     let mut _3: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
-    let mut _4: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+    let mut _4: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
     let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
 
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _4 = Ge(const 1_isize, _3);      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_4);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _5 = Le(const 0_isize, _3);      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_5);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _4 = _3 as u8 (IntToInt);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _5 = Le(_4, const 1_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        assume(move _5);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
         return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
diff --git a/tests/mir-opt/building/enum_cast.boo.built.after.mir b/tests/mir-opt/building/enum_cast.boo.built.after.mir
index 699c876b01a..715dedcf24d 100644
--- a/tests/mir-opt/building/enum_cast.boo.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.boo.built.after.mir
@@ -5,17 +5,16 @@ fn boo(_1: Boo) -> usize {
     let mut _0: usize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
     let _2: Boo;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
     let mut _3: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
-    let mut _4: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+    let mut _4: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
     let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
 
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
         _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _4 = Ge(const 1_u8, _3);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_4);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        _5 = Le(const 0_u8, _3);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
-        assume(_5);                      // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _4 = _3 as u8 (IntToInt);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _5 = Le(_4, const 1_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        assume(move _5);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
         StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
         return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
index 1112177fbbf..6c177c61eca 100644
--- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
@@ -6,7 +6,7 @@ fn droppy() -> () {
     let _2: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+2:13: +2:14
     let _4: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
     let mut _5: isize;                   // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
-    let mut _6: bool;                    // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
+    let mut _6: u8;                      // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
     let mut _7: bool;                    // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
     let _8: Droppy;                      // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
     scope 1 {
@@ -31,10 +31,9 @@ fn droppy() -> () {
         StorageLive(_4);                 // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
         _4 = move _2;                    // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
         _5 = discriminant(_4);           // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        _6 = Ge(const 2_isize, _5);      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        assume(_6);                      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        _7 = Le(const 0_isize, _5);      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
-        assume(_7);                      // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+        _6 = _5 as u8 (IntToInt);        // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+        _7 = Le(_6, const 2_u8);         // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+        assume(move _7);                 // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
         _3 = move _5 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
         drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27
     }
diff --git a/tests/mir-opt/building/enum_cast.far.built.after.mir b/tests/mir-opt/building/enum_cast.far.built.after.mir
new file mode 100644
index 00000000000..ab8129ca01c
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.far.built.after.mir
@@ -0,0 +1,22 @@
+// MIR for `far` after built
+
+fn far(_1: Far) -> isize {
+    debug far => _1;                     // in scope 0 at $DIR/enum_cast.rs:+0:8: +0:11
+    let mut _0: isize;                   // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
+    let _2: Far;                         // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+    let mut _3: i16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+    let mut _4: u16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+    let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _4 = _3 as u16 (IntToInt);       // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _5 = Le(_4, const 1_u16);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        assume(move _5);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        _0 = move _3 as isize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
+        return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/building/enum_cast.offsetty.built.after.mir b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir
new file mode 100644
index 00000000000..7b2b583f20f
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.offsetty.built.after.mir
@@ -0,0 +1,26 @@
+// MIR for `offsetty` after built
+
+fn offsetty(_1: NotStartingAtZero) -> u32 {
+    debug x => _1;                       // in scope 0 at $DIR/enum_cast.rs:+0:13: +0:14
+    let mut _0: u32;                     // return place in scope 0 at $DIR/enum_cast.rs:+0:38: +0:41
+    let _2: NotStartingAtZero;           // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _3: isize;                   // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _4: u8;                      // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _6: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _7: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _4 = _3 as u8 (IntToInt);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _5 = Ge(_4, const 4_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _6 = Le(_4, const 8_u8);         // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _7 = BitAnd(move _5, move _6);   // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        assume(move _7);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _0 = move _3 as u32 (IntToInt);  // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:12: +1:13
+        return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs
index 98fd5acfb14..431b5c708b9 100644
--- a/tests/mir-opt/building/enum_cast.rs
+++ b/tests/mir-opt/building/enum_cast.rs
@@ -1,6 +1,7 @@
 // EMIT_MIR enum_cast.foo.built.after.mir
 // EMIT_MIR enum_cast.bar.built.after.mir
 // EMIT_MIR enum_cast.boo.built.after.mir
+// EMIT_MIR enum_cast.far.built.after.mir
 
 enum Foo {
     A
@@ -15,6 +16,11 @@ enum Boo {
     A, B
 }
 
+#[repr(i16)]
+enum Far {
+    A, B
+}
+
 fn foo(foo: Foo) -> usize {
     foo as usize
 }
@@ -27,6 +33,10 @@ fn boo(boo: Boo) -> usize {
     boo as usize
 }
 
+fn far(far: Far) -> isize {
+    far as isize
+}
+
 // EMIT_MIR enum_cast.droppy.built.after.mir
 enum Droppy {
     A, B, C
@@ -46,5 +56,37 @@ fn droppy() {
     let z = Droppy::B;
 }
 
+#[repr(i16)]
+enum SignedAroundZero {
+    A = -2,
+    B = 0,
+    C = 2,
+}
+
+#[repr(u16)]
+enum UnsignedAroundZero {
+    A = 65535,
+    B = 0,
+    C = 1,
+}
+
+// EMIT_MIR enum_cast.signy.built.after.mir
+fn signy(x: SignedAroundZero) -> i16 {
+    x as i16
+}
+
+// EMIT_MIR enum_cast.unsigny.built.after.mir
+fn unsigny(x: UnsignedAroundZero) -> u16 {
+    // FIXME: This doesn't get an around-the-end range today, sadly.
+    x as u16
+}
+
+enum NotStartingAtZero { A = 4, B = 6, C = 8 }
+
+// EMIT_MIR enum_cast.offsetty.built.after.mir
+fn offsetty(x: NotStartingAtZero) -> u32 {
+    x as u32
+}
+
 fn main() {
 }
diff --git a/tests/mir-opt/building/enum_cast.signy.built.after.mir b/tests/mir-opt/building/enum_cast.signy.built.after.mir
new file mode 100644
index 00000000000..ef4fea604ec
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.signy.built.after.mir
@@ -0,0 +1,26 @@
+// MIR for `signy` after built
+
+fn signy(_1: SignedAroundZero) -> i16 {
+    debug x => _1;                       // in scope 0 at $DIR/enum_cast.rs:+0:10: +0:11
+    let mut _0: i16;                     // return place in scope 0 at $DIR/enum_cast.rs:+0:34: +0:37
+    let _2: SignedAroundZero;            // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _3: i16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+    let mut _4: u16;                     // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _5: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _6: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+    let mut _7: bool;                    // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:6
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _4 = _3 as u16 (IntToInt);       // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _5 = Ge(_4, const 65534_u16);    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _6 = Le(_4, const 2_u16);        // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _7 = BitOr(move _5, move _6);    // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        assume(move _7);                 // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        _0 = move _3 as i16 (IntToInt);  // scope 0 at $DIR/enum_cast.rs:+1:5: +1:13
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+1:12: +1:13
+        return;                          // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/building/enum_cast.unsigny.built.after.mir b/tests/mir-opt/building/enum_cast.unsigny.built.after.mir
new file mode 100644
index 00000000000..7ca147b1596
--- /dev/null
+++ b/tests/mir-opt/building/enum_cast.unsigny.built.after.mir
@@ -0,0 +1,17 @@
+// MIR for `unsigny` after built
+
+fn unsigny(_1: UnsignedAroundZero) -> u16 {
+    debug x => _1;                       // in scope 0 at $DIR/enum_cast.rs:+0:12: +0:13
+    let mut _0: u16;                     // return place in scope 0 at $DIR/enum_cast.rs:+0:38: +0:41
+    let _2: UnsignedAroundZero;          // in scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+    let mut _3: u16;                     // in scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+        _2 = move _1;                    // scope 0 at $DIR/enum_cast.rs:+2:5: +2:6
+        _3 = discriminant(_2);           // scope 0 at $DIR/enum_cast.rs:+2:5: +2:13
+        _0 = move _3 as u16 (IntToInt);  // scope 0 at $DIR/enum_cast.rs:+2:5: +2:13
+        StorageDead(_2);                 // scope 0 at $DIR/enum_cast.rs:+2:12: +2:13
+        return;                          // scope 0 at $DIR/enum_cast.rs:+3:2: +3:2
+    }
+}
diff --git a/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff b/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff
index c5907e7cf18..15117ea890e 100644
--- a/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/combine_transmutes.adt_transmutes.InstSimplify.diff
@@ -4,59 +4,29 @@
   fn adt_transmutes() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/combine_transmutes.rs:+0:32: +0:32
       let _1: u8;                          // in scope 0 at $DIR/combine_transmutes.rs:+1:9: +1:11
-      let mut _2: EnumNoRepr;              // in scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:41
-      let mut _4: EnumNoRepr;              // in scope 0 at $DIR/combine_transmutes.rs:+2:28: +2:41
-      let mut _6: EnumReprIsize;           // in scope 0 at $DIR/combine_transmutes.rs:+3:31: +3:47
-      let mut _8: EnumReprIsize;           // in scope 0 at $DIR/combine_transmutes.rs:+4:31: +4:47
-      let mut _10: std::cmp::Ordering;     // in scope 0 at $DIR/combine_transmutes.rs:+5:28: +5:52
-      let mut _12: std::cmp::Ordering;     // in scope 0 at $DIR/combine_transmutes.rs:+6:28: +6:52
-      let mut _14: std::option::Option<std::num::NonZeroU8>; // in scope 0 at $DIR/combine_transmutes.rs:+7:28: +7:58
-      let mut _16: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+8:29: +8:54
-      let mut _18: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+9:29: +9:54
-      let mut _20: Union32;                // in scope 0 at $DIR/combine_transmutes.rs:+10:29: +10:47
-      let mut _22: Union32;                // in scope 0 at $DIR/combine_transmutes.rs:+11:29: +11:47
-      let mut _24: std::mem::MaybeUninit<std::string::String>; // in scope 0 at $DIR/combine_transmutes.rs:+12:46: +12:77
+      let mut _2: std::option::Option<std::num::NonZeroU8>; // in scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58
+      let mut _4: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+2:29: +2:54
+      let mut _6: std::num::Wrapping<i16>; // in scope 0 at $DIR/combine_transmutes.rs:+3:29: +3:54
+      let mut _8: Union32;                 // in scope 0 at $DIR/combine_transmutes.rs:+4:29: +4:47
+      let mut _10: Union32;                // in scope 0 at $DIR/combine_transmutes.rs:+5:29: +5:47
+      let mut _12: std::mem::MaybeUninit<std::string::String>; // in scope 0 at $DIR/combine_transmutes.rs:+6:46: +6:77
       scope 1 {
           debug _a => _1;                  // in scope 1 at $DIR/combine_transmutes.rs:+1:9: +1:11
-          let _3: i8;                      // in scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11
+          let _3: i16;                     // in scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11
           scope 2 {
               debug _a => _3;              // in scope 2 at $DIR/combine_transmutes.rs:+2:9: +2:11
-              let _5: usize;               // in scope 2 at $DIR/combine_transmutes.rs:+3:9: +3:11
+              let _5: u16;                 // in scope 2 at $DIR/combine_transmutes.rs:+3:9: +3:11
               scope 3 {
                   debug _a => _5;          // in scope 3 at $DIR/combine_transmutes.rs:+3:9: +3:11
-                  let _7: isize;           // in scope 3 at $DIR/combine_transmutes.rs:+4:9: +4:11
+                  let _7: u32;             // in scope 3 at $DIR/combine_transmutes.rs:+4:9: +4:11
                   scope 4 {
                       debug _a => _7;      // in scope 4 at $DIR/combine_transmutes.rs:+4:9: +4:11
-                      let _9: u8;          // in scope 4 at $DIR/combine_transmutes.rs:+5:9: +5:11
+                      let _9: i32;         // in scope 4 at $DIR/combine_transmutes.rs:+5:9: +5:11
                       scope 5 {
                           debug _a => _9;  // in scope 5 at $DIR/combine_transmutes.rs:+5:9: +5:11
-                          let _11: i8;     // in scope 5 at $DIR/combine_transmutes.rs:+6:9: +6:11
+                          let _11: std::mem::ManuallyDrop<std::string::String>; // in scope 5 at $DIR/combine_transmutes.rs:+6:9: +6:11
                           scope 6 {
                               debug _a => _11; // in scope 6 at $DIR/combine_transmutes.rs:+6:9: +6:11
-                              let _13: u8; // in scope 6 at $DIR/combine_transmutes.rs:+7:9: +7:11
-                              scope 7 {
-                                  debug _a => _13; // in scope 7 at $DIR/combine_transmutes.rs:+7:9: +7:11
-                                  let _15: i16; // in scope 7 at $DIR/combine_transmutes.rs:+8:9: +8:11
-                                  scope 8 {
-                                      debug _a => _15; // in scope 8 at $DIR/combine_transmutes.rs:+8:9: +8:11
-                                      let _17: u16; // in scope 8 at $DIR/combine_transmutes.rs:+9:9: +9:11
-                                      scope 9 {
-                                          debug _a => _17; // in scope 9 at $DIR/combine_transmutes.rs:+9:9: +9:11
-                                          let _19: u32; // in scope 9 at $DIR/combine_transmutes.rs:+10:9: +10:11
-                                          scope 10 {
-                                              debug _a => _19; // in scope 10 at $DIR/combine_transmutes.rs:+10:9: +10:11
-                                              let _21: i32; // in scope 10 at $DIR/combine_transmutes.rs:+11:9: +11:11
-                                              scope 11 {
-                                                  debug _a => _21; // in scope 11 at $DIR/combine_transmutes.rs:+11:9: +11:11
-                                                  let _23: std::mem::ManuallyDrop<std::string::String>; // in scope 11 at $DIR/combine_transmutes.rs:+12:9: +12:11
-                                                  scope 12 {
-                                                      debug _a => _23; // in scope 12 at $DIR/combine_transmutes.rs:+12:9: +12:11
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
-                              }
                           }
                       }
                   }
@@ -66,93 +36,55 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/combine_transmutes.rs:+1:9: +1:11
-          StorageLive(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:41
-          _2 = EnumNoRepr::A;              // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:41
-          _1 = move _2 as u8 (Transmute);  // scope 0 at $DIR/combine_transmutes.rs:+1:18: +1:42
-          StorageDead(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:41: +1:42
+          StorageLive(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58
+          _2 = Option::<NonZeroU8>::Some(const _); // scope 0 at $DIR/combine_transmutes.rs:+1:28: +1:58
+                                           // mir::Constant
+                                           // + span: $DIR/combine_transmutes.rs:35:33: 35:57
+                                           // + literal: Const { ty: NonZeroU8, val: Unevaluated(NonZeroU8::MAX, [], None) }
+          _1 = move _2 as u8 (Transmute);  // scope 0 at $DIR/combine_transmutes.rs:+1:18: +1:59
+          StorageDead(_2);                 // scope 0 at $DIR/combine_transmutes.rs:+1:58: +1:59
           StorageLive(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+2:9: +2:11
-          StorageLive(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:28: +2:41
-          _4 = EnumNoRepr::B;              // scope 1 at $DIR/combine_transmutes.rs:+2:28: +2:41
-          _3 = move _4 as i8 (Transmute);  // scope 1 at $DIR/combine_transmutes.rs:+2:18: +2:42
-          StorageDead(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:41: +2:42
+          StorageLive(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:29: +2:54
+          _4 = Wrapping::<i16>(const 0_i16); // scope 1 at $DIR/combine_transmutes.rs:+2:29: +2:54
+-         _3 = move _4 as i16 (Transmute); // scope 1 at $DIR/combine_transmutes.rs:+2:19: +2:55
++         _3 = move (_4.0: i16);           // scope 1 at $DIR/combine_transmutes.rs:+2:19: +2:55
+          StorageDead(_4);                 // scope 1 at $DIR/combine_transmutes.rs:+2:54: +2:55
           StorageLive(_5);                 // scope 2 at $DIR/combine_transmutes.rs:+3:9: +3:11
-          StorageLive(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:31: +3:47
-          _6 = EnumReprIsize::A;           // scope 2 at $DIR/combine_transmutes.rs:+3:31: +3:47
-          _5 = move _6 as usize (Transmute); // scope 2 at $DIR/combine_transmutes.rs:+3:21: +3:48
-          StorageDead(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:47: +3:48
+          StorageLive(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:29: +3:54
+          _6 = Wrapping::<i16>(const 0_i16); // scope 2 at $DIR/combine_transmutes.rs:+3:29: +3:54
+          _5 = move _6 as u16 (Transmute); // scope 2 at $DIR/combine_transmutes.rs:+3:19: +3:55
+          StorageDead(_6);                 // scope 2 at $DIR/combine_transmutes.rs:+3:54: +3:55
           StorageLive(_7);                 // scope 3 at $DIR/combine_transmutes.rs:+4:9: +4:11
-          StorageLive(_8);                 // scope 3 at $DIR/combine_transmutes.rs:+4:31: +4:47
-          _8 = EnumReprIsize::B;           // scope 3 at $DIR/combine_transmutes.rs:+4:31: +4:47
--         _7 = move _8 as isize (Transmute); // scope 3 at $DIR/combine_transmutes.rs:+4:21: +4:48
-+         _7 = discriminant(_8);           // scope 3 at $DIR/combine_transmutes.rs:+4:21: +4:48
+          StorageLive(_8);                 // scope 3 at $DIR/combine_transmutes.rs:+4:29: +4:47
+          _8 = Union32 { u32: const 0_i32 }; // scope 3 at $DIR/combine_transmutes.rs:+4:29: +4:47
+          _7 = move _8 as u32 (Transmute); // scope 3 at $DIR/combine_transmutes.rs:+4:19: +4:48
           StorageDead(_8);                 // scope 3 at $DIR/combine_transmutes.rs:+4:47: +4:48
           StorageLive(_9);                 // scope 4 at $DIR/combine_transmutes.rs:+5:9: +5:11
-          StorageLive(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:28: +5:52
-          _10 = Less;                      // scope 4 at $DIR/combine_transmutes.rs:+5:28: +5:52
-          _9 = move _10 as u8 (Transmute); // scope 4 at $DIR/combine_transmutes.rs:+5:18: +5:53
-          StorageDead(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:52: +5:53
+          StorageLive(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:29: +5:47
+          _10 = Union32 { u32: const 0_u32 }; // scope 4 at $DIR/combine_transmutes.rs:+5:29: +5:47
+          _9 = move _10 as i32 (Transmute); // scope 4 at $DIR/combine_transmutes.rs:+5:19: +5:48
+          StorageDead(_10);                // scope 4 at $DIR/combine_transmutes.rs:+5:47: +5:48
           StorageLive(_11);                // scope 5 at $DIR/combine_transmutes.rs:+6:9: +6:11
-          StorageLive(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:28: +6:52
-          _12 = Less;                      // scope 5 at $DIR/combine_transmutes.rs:+6:28: +6:52
--         _11 = move _12 as i8 (Transmute); // scope 5 at $DIR/combine_transmutes.rs:+6:18: +6:53
-+         _11 = discriminant(_12);         // scope 5 at $DIR/combine_transmutes.rs:+6:18: +6:53
-          StorageDead(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:52: +6:53
-          StorageLive(_13);                // scope 6 at $DIR/combine_transmutes.rs:+7:9: +7:11
-          StorageLive(_14);                // scope 6 at $DIR/combine_transmutes.rs:+7:28: +7:58
-          _14 = Option::<NonZeroU8>::Some(const _); // scope 6 at $DIR/combine_transmutes.rs:+7:28: +7:58
-                                           // mir::Constant
-                                           // + span: $DIR/combine_transmutes.rs:41:33: 41:57
-                                           // + literal: Const { ty: NonZeroU8, val: Unevaluated(NonZeroU8::MAX, [], None) }
-          _13 = move _14 as u8 (Transmute); // scope 6 at $DIR/combine_transmutes.rs:+7:18: +7:59
-          StorageDead(_14);                // scope 6 at $DIR/combine_transmutes.rs:+7:58: +7:59
-          StorageLive(_15);                // scope 7 at $DIR/combine_transmutes.rs:+8:9: +8:11
-          StorageLive(_16);                // scope 7 at $DIR/combine_transmutes.rs:+8:29: +8:54
-          _16 = Wrapping::<i16>(const 0_i16); // scope 7 at $DIR/combine_transmutes.rs:+8:29: +8:54
--         _15 = move _16 as i16 (Transmute); // scope 7 at $DIR/combine_transmutes.rs:+8:19: +8:55
-+         _15 = move (_16.0: i16);         // scope 7 at $DIR/combine_transmutes.rs:+8:19: +8:55
-          StorageDead(_16);                // scope 7 at $DIR/combine_transmutes.rs:+8:54: +8:55
-          StorageLive(_17);                // scope 8 at $DIR/combine_transmutes.rs:+9:9: +9:11
-          StorageLive(_18);                // scope 8 at $DIR/combine_transmutes.rs:+9:29: +9:54
-          _18 = Wrapping::<i16>(const 0_i16); // scope 8 at $DIR/combine_transmutes.rs:+9:29: +9:54
-          _17 = move _18 as u16 (Transmute); // scope 8 at $DIR/combine_transmutes.rs:+9:19: +9:55
-          StorageDead(_18);                // scope 8 at $DIR/combine_transmutes.rs:+9:54: +9:55
-          StorageLive(_19);                // scope 9 at $DIR/combine_transmutes.rs:+10:9: +10:11
-          StorageLive(_20);                // scope 9 at $DIR/combine_transmutes.rs:+10:29: +10:47
-          _20 = Union32 { u32: const 0_i32 }; // scope 9 at $DIR/combine_transmutes.rs:+10:29: +10:47
-          _19 = move _20 as u32 (Transmute); // scope 9 at $DIR/combine_transmutes.rs:+10:19: +10:48
-          StorageDead(_20);                // scope 9 at $DIR/combine_transmutes.rs:+10:47: +10:48
-          StorageLive(_21);                // scope 10 at $DIR/combine_transmutes.rs:+11:9: +11:11
-          StorageLive(_22);                // scope 10 at $DIR/combine_transmutes.rs:+11:29: +11:47
-          _22 = Union32 { u32: const 0_u32 }; // scope 10 at $DIR/combine_transmutes.rs:+11:29: +11:47
-          _21 = move _22 as i32 (Transmute); // scope 10 at $DIR/combine_transmutes.rs:+11:19: +11:48
-          StorageDead(_22);                // scope 10 at $DIR/combine_transmutes.rs:+11:47: +11:48
-          StorageLive(_23);                // scope 11 at $DIR/combine_transmutes.rs:+12:9: +12:11
-          StorageLive(_24);                // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
-          _24 = MaybeUninit::<String>::uninit() -> [return: bb1, unwind unreachable]; // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
+          StorageLive(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:46: +6:77
+          _12 = MaybeUninit::<String>::uninit() -> [return: bb1, unwind unreachable]; // scope 5 at $DIR/combine_transmutes.rs:+6:46: +6:77
                                            // mir::Constant
-                                           // + span: $DIR/combine_transmutes.rs:46:46: 46:75
-                                           // + user_ty: UserType(23)
+                                           // + span: $DIR/combine_transmutes.rs:40:46: 40:75
+                                           // + user_ty: UserType(11)
                                            // + literal: Const { ty: fn() -> MaybeUninit<String> {MaybeUninit::<String>::uninit}, val: Value(<ZST>) }
       }
   
       bb1: {
--         _23 = move _24 as std::mem::ManuallyDrop<std::string::String> (Transmute); // scope 11 at $DIR/combine_transmutes.rs:+12:36: +12:78
-+         _23 = move (_24.1: std::mem::ManuallyDrop<std::string::String>); // scope 11 at $DIR/combine_transmutes.rs:+12:36: +12:78
-          StorageDead(_24);                // scope 11 at $DIR/combine_transmutes.rs:+12:77: +12:78
-          _0 = const ();                   // scope 0 at $DIR/combine_transmutes.rs:+0:32: +13:2
-          StorageDead(_23);                // scope 11 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_21);                // scope 10 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_19);                // scope 9 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_17);                // scope 8 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_15);                // scope 7 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_13);                // scope 6 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_11);                // scope 5 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_9);                 // scope 4 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_7);                 // scope 3 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_5);                 // scope 2 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          StorageDead(_1);                 // scope 0 at $DIR/combine_transmutes.rs:+13:1: +13:2
-          return;                          // scope 0 at $DIR/combine_transmutes.rs:+13:2: +13:2
+-         _11 = move _12 as std::mem::ManuallyDrop<std::string::String> (Transmute); // scope 5 at $DIR/combine_transmutes.rs:+6:36: +6:78
++         _11 = move (_12.1: std::mem::ManuallyDrop<std::string::String>); // scope 5 at $DIR/combine_transmutes.rs:+6:36: +6:78
+          StorageDead(_12);                // scope 5 at $DIR/combine_transmutes.rs:+6:77: +6:78
+          _0 = const ();                   // scope 0 at $DIR/combine_transmutes.rs:+0:32: +7:2
+          StorageDead(_11);                // scope 5 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_9);                 // scope 4 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_7);                 // scope 3 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_5);                 // scope 2 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          StorageDead(_1);                 // scope 0 at $DIR/combine_transmutes.rs:+7:1: +7:2
+          return;                          // scope 0 at $DIR/combine_transmutes.rs:+7:2: +7:2
       }
   }
   
diff --git a/tests/mir-opt/combine_transmutes.rs b/tests/mir-opt/combine_transmutes.rs
index 7088488c1b8..403f9356ce2 100644
--- a/tests/mir-opt/combine_transmutes.rs
+++ b/tests/mir-opt/combine_transmutes.rs
@@ -32,12 +32,6 @@ pub unsafe fn integer_transmutes() {
 
 // EMIT_MIR combine_transmutes.adt_transmutes.InstSimplify.diff
 pub unsafe fn adt_transmutes() {
-    let _a: u8 = transmute(EnumNoRepr::A);
-    let _a: i8 = transmute(EnumNoRepr::B);
-    let _a: usize = transmute(EnumReprIsize::A);
-    let _a: isize = transmute(EnumReprIsize::B);
-    let _a: u8 = transmute(std::cmp::Ordering::Less);
-    let _a: i8 = transmute(std::cmp::Ordering::Less);
     let _a: u8 = transmute(Some(std::num::NonZeroU8::MAX));
     let _a: i16 = transmute(std::num::Wrapping(0_i16));
     let _a: u16 = transmute(std::num::Wrapping(0_i16));
@@ -46,20 +40,4 @@ pub unsafe fn adt_transmutes() {
     let _a: ManuallyDrop<String> = transmute(MaybeUninit::<String>::uninit());
 }
 
-#[inline(always)]
-#[custom_mir(dialect = "runtime", phase = "initial")]
-const unsafe fn mir_transmute<T, U>(x: T) -> U {
-    mir!{
-        {
-            RET = CastTransmute(x);
-            Return()
-        }
-    }
-}
-
-pub enum EnumNoRepr { A, B, C }
-
-#[repr(isize)]
-pub enum EnumReprIsize { A, B, C }
-
 pub union Union32 { u32: u32, i32: i32 }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff
index bc41b5d0813..5258d75bdf7 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.32bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_box() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _2 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: Box<Never>, val: Value(Scalar(0x00000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff
index c4376e6e17a..7e57e06a5cf 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_box.ConstProp.64bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_box() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: std::boxed::Box<Never>;      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _2 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _1 = const Box::<Never>(Unique::<Never> {{ pointer: NonNull::<Never> {{ pointer: {0x1 as *const Never} }}, _marker: PhantomData::<Never> }}, std::alloc::Global); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: Box<Never>, val: Value(Scalar(0x0000000000000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff
index 81b7b368993..032681f230b 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.32bit.diff
@@ -3,22 +3,19 @@
   
   fn unreachable_direct() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:39: +0:40
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:41: +3:2
-      let _2: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:15
+      let _1: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:41: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _3 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _2 = move _3 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _2 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _1 = move _2 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
           unreachable;                     // scope 2 at $DIR/transmute.rs:+1:29: +1:42
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff
index 81b7b368993..032681f230b 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_direct.ConstProp.64bit.diff
@@ -3,22 +3,19 @@
   
   fn unreachable_direct() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:39: +0:40
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:41: +3:2
-      let _2: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:15
+      let _1: Never;                       // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: ();                      // in scope 0 at $DIR/transmute.rs:+1:39: +1:41
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:41: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _3 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
-          _2 = move _3 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _2 = ();                         // scope 2 at $DIR/transmute.rs:+1:39: +1:41
+          _1 = move _2 as Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:29: +1:42
           unreachable;                     // scope 2 at $DIR/transmute.rs:+1:29: +1:42
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff
index 47f023cd93d..ec8a62bd62c 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.32bit.diff
@@ -3,28 +3,24 @@
   
   fn unreachable_mut() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
--         _3 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _3 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+-         _2 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _2 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &mut Never, val: Value(Scalar(0x00000001)) }
-          _2 = &mut (*_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
-          StorageDead(_3);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
-          StorageLive(_4);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
+          _1 = &mut (*_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+          StorageDead(_2);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff
index 62300d2e313..288da6e56c5 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_mut.ConstProp.64bit.diff
@@ -3,28 +3,24 @@
   
   fn unreachable_mut() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
-      let mut _4: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &mut Never;                  // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
+      let mut _2: &mut Never;              // in scope 0 at $DIR/transmute.rs:+1:34: +1:52
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
-          StorageLive(_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
--         _3 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
-+         _3 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+-         _2 = const 1_usize as &mut Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:34: +1:52
++         _2 = const {0x1 as &mut Never};  // scope 2 at $DIR/transmute.rs:+1:34: +1:52
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &mut Never, val: Value(Scalar(0x0000000000000001)) }
-          _2 = &mut (*_3);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
-          StorageDead(_3);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
-          StorageLive(_4);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
+          _1 = &mut (*_2);                 // scope 0 at $DIR/transmute.rs:+1:34: +1:52
+          StorageDead(_2);                 // scope 0 at $DIR/transmute.rs:+1:54: +1:55
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff
index 8578f898a7e..dcca0fca619 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.32bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_ref() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
-+         _2 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
++         _1 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &Never, val: Value(Scalar(0x00000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff
index 8b11cea9365..3a0b967e66f 100644
--- a/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.unreachable_ref.ConstProp.64bit.diff
@@ -3,24 +3,20 @@
   
   fn unreachable_ref() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/transmute.rs:+0:36: +0:37
-      let mut _1: !;                       // in scope 0 at $DIR/transmute.rs:+0:38: +3:2
-      let _2: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/transmute.rs:+2:5: +2:16
+      let _1: &Never;                      // in scope 0 at $DIR/transmute.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/transmute.rs:+1:9: +1:10
       }
       scope 2 {
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+0:38: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
--         _2 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
-+         _2 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
+          StorageLive(_1);                 // scope 0 at $DIR/transmute.rs:+1:9: +1:10
+-         _1 = const 1_usize as &Never (Transmute); // scope 2 at $DIR/transmute.rs:+1:30: +1:48
++         _1 = const {0x1 as &Never};      // scope 2 at $DIR/transmute.rs:+1:30: +1:48
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: &Never, val: Value(Scalar(0x0000000000000001)) }
-          StorageLive(_3);                 // scope 1 at $DIR/transmute.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/transmute.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff
new file mode 100644
index 00000000000..745f2bb193a
--- /dev/null
+++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff
@@ -0,0 +1,50 @@
+- // MIR for `caller` before Inline
++ // MIR for `caller` after Inline
+  
+  fn caller(_1: Box<[i32]>) -> () {
+      debug x => _1;                       // in scope 0 at $DIR/unsized_argument.rs:+0:11: +0:12
+      let mut _0: ();                      // return place in scope 0 at $DIR/unsized_argument.rs:+0:26: +0:26
+      let _2: ();                          // in scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+      let mut _3: std::boxed::Box<[i32]>;  // in scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+      let mut _4: ();                      // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+      let mut _5: ();                      // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+      let mut _6: ();                      // in scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+      let mut _7: *const [i32];            // in scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+          StorageLive(_3);                 // scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+          _3 = move _1;                    // scope 0 at $DIR/unsized_argument.rs:+1:13: +1:14
+          _7 = (((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>).0: *const [i32]); // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+          _2 = callee(move (*_7)) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/unsized_argument.rs:+1:5: +1:15
+                                           // mir::Constant
+                                           // + span: $DIR/unsized_argument.rs:9:5: 9:11
+                                           // + literal: Const { ty: fn([i32]) {callee}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_3);                 // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+          StorageDead(_2);                 // scope 0 at $DIR/unsized_argument.rs:+1:15: +1:16
+          _0 = const ();                   // scope 0 at $DIR/unsized_argument.rs:+0:26: +2:2
+          return;                          // scope 0 at $DIR/unsized_argument.rs:+2:2: +2:2
+      }
+  
+      bb2 (cleanup): {
+          resume;                          // scope 0 at $DIR/unsized_argument.rs:+0:1: +2:2
+      }
+  
+      bb3: {
+          _4 = alloc::alloc::box_free::<[i32], std::alloc::Global>(move (_3.0: std::ptr::Unique<[i32]>), move (_3.1: std::alloc::Global)) -> bb1; // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+                                           // mir::Constant
+                                           // + span: $DIR/unsized_argument.rs:9:14: 9:15
+                                           // + literal: Const { ty: unsafe fn(Unique<[i32]>, std::alloc::Global) {alloc::alloc::box_free::<[i32], std::alloc::Global>}, val: Value(<ZST>) }
+      }
+  
+      bb4 (cleanup): {
+          _6 = alloc::alloc::box_free::<[i32], std::alloc::Global>(move (_3.0: std::ptr::Unique<[i32]>), move (_3.1: std::alloc::Global)) -> [return: bb2, unwind terminate]; // scope 0 at $DIR/unsized_argument.rs:+1:14: +1:15
+                                           // mir::Constant
+                                           // + span: $DIR/unsized_argument.rs:9:14: 9:15
+                                           // + literal: Const { ty: unsafe fn(Unique<[i32]>, std::alloc::Global) {alloc::alloc::box_free::<[i32], std::alloc::Global>}, val: Value(<ZST>) }
+      }
+  }
+  
diff --git a/tests/mir-opt/inline/unsized_argument.rs b/tests/mir-opt/inline/unsized_argument.rs
new file mode 100644
index 00000000000..b2c51407fd5
--- /dev/null
+++ b/tests/mir-opt/inline/unsized_argument.rs
@@ -0,0 +1,15 @@
+// needs-unwind
+#![feature(unsized_fn_params)]
+
+#[inline(always)]
+fn callee(y: [i32]) {}
+
+// EMIT_MIR unsized_argument.caller.Inline.diff
+fn caller(x: Box<[i32]>) {
+    callee(*x);
+}
+
+fn main() {
+    let b = Box::new([1]);
+    caller(b);
+}
diff --git a/tests/mir-opt/issue_72181_1.f.built.after.mir b/tests/mir-opt/issue_72181_1.f.built.after.mir
index 4086da52011..25f47225113 100644
--- a/tests/mir-opt/issue_72181_1.f.built.after.mir
+++ b/tests/mir-opt/issue_72181_1.f.built.after.mir
@@ -3,27 +3,13 @@
 fn f(_1: Void) -> ! {
     debug v => _1;                       // in scope 0 at $DIR/issue_72181_1.rs:+0:6: +0:7
     let mut _0: !;                       // return place in scope 0 at $DIR/issue_72181_1.rs:+0:18: +0:19
-    let mut _2: !;                       // in scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2
-    let mut _3: !;                       // in scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2
-        StorageLive(_3);                 // scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/issue_72181_1.rs:+1:11: +1:12
         unreachable;                     // scope 0 at $DIR/issue_72181_1.rs:+1:11: +1:12
     }
 
     bb1: {
-        unreachable;                     // scope 0 at $DIR/issue_72181_1.rs:+1:5: +1:15
-    }
-
-    bb2: {
-        StorageDead(_3);                 // scope 0 at $DIR/issue_72181_1.rs:+1:14: +1:15
-        unreachable;                     // scope 0 at $DIR/issue_72181_1.rs:+0:20: +2:2
-    }
-
-    bb3: {
-        StorageDead(_2);                 // scope 0 at $DIR/issue_72181_1.rs:+2:1: +2:2
         return;                          // scope 0 at $DIR/issue_72181_1.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
index 8735a750060..aa5d9619d10 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
@@ -3,26 +3,22 @@
   
   fn transmute_to_box_uninhabited() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-      let _2: std::boxed::Box<Never>;      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      let _1: std::boxed::Box<Never>;      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _1 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:70:25: 70:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> Box<Never> {transmute::<usize, Box<Never>>}, val: Value(<ZST>) }
-+         _2 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
++         _1 = const 1_usize as std::boxed::Box<Never> (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
       }
   
       bb1: {
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
index a772132770c..5fafd45fe85 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
@@ -3,26 +3,22 @@
   
   fn transmute_to_mut_uninhabited() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-      let _2: &mut Never;                  // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      let _1: &mut Never;                  // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _1 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:64:25: 64:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &mut Never {transmute::<usize, &mut Never>}, val: Value(<ZST>) }
-+         _2 = const 1_usize as &mut Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
++         _1 = const 1_usize as &mut Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
       }
   
       bb1: {
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
index c4d53d4e8c7..08dead13211 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
@@ -3,26 +3,22 @@
   
   fn transmute_to_ref_uninhabited() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:49: +0:50
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-      let _2: &Never;                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:16
+      let _1: &Never;                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       scope 1 {
-          debug x => _2;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+          debug x => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+1:9: +1:10
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
+-         _1 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:58:21: 58:40
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &Never {transmute::<usize, &Never>}, val: Value(<ZST>) }
-+         _2 = const 1_usize as &Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
++         _1 = const 1_usize as &Never (Transmute); // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
 +         goto -> bb1;                     // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
       }
   
       bb1: {
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:5: +2:16
           unreachable;                     // scope 1 at $DIR/lower_intrinsics.rs:+2:11: +2:13
       }
   }
diff --git a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
index c0cc698c481..28e45909c33 100644
--- a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
@@ -3,16 +3,15 @@
   
   fn unreachable() -> ! {
       let mut _0: !;                       // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:25: +0:26
-      let mut _1: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+0:27: +2:2
-      let _2: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
-      let mut _3: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+      let _1: ();                          // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+      let mut _2: !;                       // in scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:45
       scope 1 {
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:47
-          StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
--         _3 = std::intrinsics::unreachable() -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+          StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:47
+          StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+-         _2 = std::intrinsics::unreachable() -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:31:14: 31:43
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(<ZST>) }
diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/run-make-fulldeps/obtain-borrowck/driver.rs
index 12cbb5a5f12..d342b2ff6d9 100644
--- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs
+++ b/tests/run-make-fulldeps/obtain-borrowck/driver.rs
@@ -24,7 +24,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_interface::interface::Compiler;
 use rustc_interface::{Config, Queries};
-use rustc_middle::query::query_values::mir_borrowck;
+use rustc_middle::query::queries::mir_borrowck::ProvidedValue;
 use rustc_middle::query::{ExternProviders, Providers};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
@@ -126,7 +126,7 @@ thread_local! {
         RefCell::new(HashMap::new());
 }
 
-fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> mir_borrowck<'tcx> {
+fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ProvidedValue<'tcx> {
     let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(tcx, def_id);
     // SAFETY: The reader casts the 'static lifetime to 'tcx before using it.
     let body_with_facts: BodyWithBorrowckFacts<'static> =
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/Makefile b/tests/run-make/CURRENT_RUSTC_VERSION/Makefile
new file mode 100644
index 00000000000..7940dae207b
--- /dev/null
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/Makefile
@@ -0,0 +1,6 @@
+include ../tools.mk
+
+all:
+	$(RUSTC) --emit=metadata --crate-type lib stable.rs
+	$(RUSTC) --emit=metadata --extern stable=$(TMPDIR)/libstable.rmeta main.rs 2>&1 >/dev/null \
+		| $(CGREP) -e "stable since $$(cat $(S)/src/version)(-[a-zA-Z]+)?"
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/main.rs b/tests/run-make/CURRENT_RUSTC_VERSION/main.rs
new file mode 100644
index 00000000000..466aaa82bd4
--- /dev/null
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/main.rs
@@ -0,0 +1,4 @@
+#![feature(foo)]
+extern crate stable;
+
+fn main() {}
diff --git a/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs b/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs
new file mode 100644
index 00000000000..2fd09aded60
--- /dev/null
+++ b/tests/run-make/CURRENT_RUSTC_VERSION/stable.rs
@@ -0,0 +1,5 @@
+#![feature(staged_api)]
+#![stable(since = "1.0.0", feature = "rust1")]
+
+#[stable(since = "CURRENT_RUSTC_VERSION", feature = "foo")]
+pub fn foo() {}
diff --git a/tests/run-make/debugger-visualizer-dep-info/Makefile b/tests/run-make/debugger-visualizer-dep-info/Makefile
new file mode 100644
index 00000000000..0877998a74f
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/Makefile
@@ -0,0 +1,9 @@
+include ../tools.mk
+
+# This test makes sure that files referenced via #[debugger_visualizer] are
+# included in `--emit dep-info` output.
+
+all:
+	$(RUSTC) --emit dep-info main.rs
+	$(CGREP) "foo.py" < $(TMPDIR)/main.d
+	$(CGREP) "my_visualizers/bar.natvis" < $(TMPDIR)/main.d
diff --git a/tests/run-make/debugger-visualizer-dep-info/foo.py b/tests/run-make/debugger-visualizer-dep-info/foo.py
new file mode 100644
index 00000000000..1bb8bf6d7fd
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/foo.py
@@ -0,0 +1 @@
+# empty
diff --git a/tests/run-make/debugger-visualizer-dep-info/main.rs b/tests/run-make/debugger-visualizer-dep-info/main.rs
new file mode 100644
index 00000000000..3aede2215ea
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/main.rs
@@ -0,0 +1,12 @@
+#![debugger_visualizer(gdb_script_file = "foo.py")]
+
+fn main() {
+    const _UNUSED: u32 = {
+        mod inner {
+            #![debugger_visualizer(natvis_file = "my_visualizers/bar.natvis")]
+            pub const XYZ: u32 = 123;
+        }
+
+        inner::XYZ + 1
+    };
+}
diff --git a/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis b/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis
new file mode 100644
index 00000000000..c341a403902
--- /dev/null
+++ b/tests/run-make/debugger-visualizer-dep-info/my_visualizers/bar.natvis
@@ -0,0 +1 @@
+<!-- empty -->
diff --git a/tests/run-make/incremental-debugger-visualizer/Makefile b/tests/run-make/incremental-debugger-visualizer/Makefile
new file mode 100644
index 00000000000..8cfe41597ad
--- /dev/null
+++ b/tests/run-make/incremental-debugger-visualizer/Makefile
@@ -0,0 +1,49 @@
+include ../tools.mk
+
+# This test makes sure that changes to files referenced via #[debugger_visualizer]
+# are picked up when compiling incrementally.
+
+# We have to copy the source to $(TMPDIR) because Github CI mounts the source
+# directory as readonly. We need to apply modifications to some of the source
+# file.
+SRC_DIR := $(TMPDIR)/src
+INCR_CACHE_DIR := $(TMPDIR)/incremental
+
+all:
+	rm -rf $(TMPDIR)/*
+	mkdir $(SRC_DIR)
+	cp ./foo.rs $(SRC_DIR)
+	echo "GDB script v1" > $(SRC_DIR)/foo.py
+	echo "Natvis v1" > $(SRC_DIR)/foo.natvis
+	$(RUSTC) $(SRC_DIR)/foo.rs \
+	  --crate-type=rlib \
+	  --emit metadata \
+	  -C incremental=$(INCR_CACHE_DIR) \
+	  -Z incremental-verify-ich
+	$(CGREP) "GDB script v1" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) "Natvis v1" < $(TMPDIR)/libfoo.rmeta
+
+	# Change only the GDB script and check that the change has been picked up
+	echo "GDB script v2" > $(SRC_DIR)/foo.py
+	$(RUSTC) $(SRC_DIR)/foo.rs \
+	  --crate-type=rlib \
+	  --emit metadata \
+	  -C incremental=$(INCR_CACHE_DIR) \
+	  -Z incremental-verify-ich
+
+	$(CGREP) "GDB script v2" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) -v "GDB script v1" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) "Natvis v1" < $(TMPDIR)/libfoo.rmeta
+
+	# Now change the Natvis version and check that the change has been picked up
+	echo "Natvis v2" > $(SRC_DIR)/foo.natvis
+	$(RUSTC) $(SRC_DIR)/foo.rs \
+	  --crate-type=rlib \
+	  --emit metadata \
+	  -C incremental=$(INCR_CACHE_DIR) \
+	  -Z incremental-verify-ich
+
+	$(CGREP) "GDB script v2" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) -v "GDB script v1" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) "Natvis v2" < $(TMPDIR)/libfoo.rmeta
+	$(CGREP) -v "Natvis v1" < $(TMPDIR)/libfoo.rmeta
diff --git a/tests/run-make/incremental-debugger-visualizer/foo.rs b/tests/run-make/incremental-debugger-visualizer/foo.rs
new file mode 100644
index 00000000000..8daa36a12d3
--- /dev/null
+++ b/tests/run-make/incremental-debugger-visualizer/foo.rs
@@ -0,0 +1,6 @@
+#![debugger_visualizer(natvis_file = "./foo.natvis")]
+#![debugger_visualizer(gdb_script_file = "./foo.py")]
+
+pub struct Foo {
+    pub x: u32,
+}
diff --git a/tests/run-make/issue-83045/Makefile b/tests/run-make/issue-83045/Makefile
index 7053da00f6b..b76e184b610 100644
--- a/tests/run-make/issue-83045/Makefile
+++ b/tests/run-make/issue-83045/Makefile
@@ -29,5 +29,5 @@ all:
 				  --crate-type=rlib \
 				  --edition=2018 \
 				  c.rs 2>&1 | tee $(TMPDIR)/output.txt || exit 0
-	$(CGREP) E0519 < $(TMPDIR)/output.txt
+	$(CGREP) E0463 < $(TMPDIR)/output.txt
 	$(CGREP) -v "internal compiler error" < $(TMPDIR)/output.txt
diff --git a/tests/run-make/print-native-static-libs/Makefile b/tests/run-make/print-native-static-libs/Makefile
new file mode 100644
index 00000000000..98e72d7696f
--- /dev/null
+++ b/tests/run-make/print-native-static-libs/Makefile
@@ -0,0 +1,15 @@
+include ../tools.mk
+
+# ignore-cross-compile
+# ignore-wasm
+
+all:
+	$(RUSTC) --crate-type rlib -lbar_cli bar.rs
+	$(RUSTC) foo.rs -lfoo_cli --crate-type staticlib --print native-static-libs 2>&1 \
+		| grep 'note: native-static-libs: ' \
+		| sed 's/note: native-static-libs: \(.*\)/\1/' > $(TMPDIR)/libs.txt
+
+	cat $(TMPDIR)/libs.txt | grep -F "glib-2.0" # in bar.rs
+	cat $(TMPDIR)/libs.txt | grep -F "systemd" # in foo.rs
+	cat $(TMPDIR)/libs.txt | grep -F "bar_cli"
+	cat $(TMPDIR)/libs.txt | grep -F "foo_cli"
diff --git a/tests/run-make/print-native-static-libs/bar.rs b/tests/run-make/print-native-static-libs/bar.rs
new file mode 100644
index 00000000000..a563bbc2a22
--- /dev/null
+++ b/tests/run-make/print-native-static-libs/bar.rs
@@ -0,0 +1,13 @@
+#[no_mangle]
+pub extern "C" fn my_bar_add(left: i32, right: i32) -> i32 {
+    // Obviously makes no sense but...
+    unsafe {
+        g_free(std::ptr::null_mut());
+    }
+    left + right
+}
+
+#[link(name = "glib-2.0")]
+extern "C" {
+    fn g_free(p: *mut ());
+}
diff --git a/tests/run-make/print-native-static-libs/foo.rs b/tests/run-make/print-native-static-libs/foo.rs
new file mode 100644
index 00000000000..6acaee20ed4
--- /dev/null
+++ b/tests/run-make/print-native-static-libs/foo.rs
@@ -0,0 +1,15 @@
+extern crate bar;
+
+#[no_mangle]
+pub extern "C" fn my_foo_add(left: i32, right: i32) -> i32 {
+    // Obviously makes no sense but...
+    unsafe {
+        init(std::ptr::null_mut());
+    }
+    bar::my_bar_add(left, right)
+}
+
+#[link(name = "systemd")]
+extern "C" {
+    fn init(p: *mut ());
+}
diff --git a/tests/run-make/short-ice/Makefile b/tests/run-make/short-ice/Makefile
new file mode 100644
index 00000000000..4f33d590237
--- /dev/null
+++ b/tests/run-make/short-ice/Makefile
@@ -0,0 +1,9 @@
+include ../tools.mk
+
+# ignore-windows
+
+export RUSTC := $(RUSTC_ORIGINAL)
+export TMPDIR := $(TMPDIR)
+
+all:
+	bash check.sh
diff --git a/tests/run-make/short-ice/check.sh b/tests/run-make/short-ice/check.sh
new file mode 100644
index 00000000000..96cd8fe86bc
--- /dev/null
+++ b/tests/run-make/short-ice/check.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+RUST_BACKTRACE=1 $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-1.log 2>&1
+RUST_BACKTRACE=full $RUSTC src/lib.rs -Z treat-err-as-bug=1 1>$TMPDIR/rust-test-2.log 2>&1
+
+short=$(cat $TMPDIR/rust-test-1.log | wc -l)
+full=$(cat $TMPDIR/rust-test-2.log | wc -l)
+rustc_query_count=$(cat $TMPDIR/rust-test-1.log | grep rustc_query_ | wc -l)
+rustc_query_count_full=$(cat $TMPDIR/rust-test-2.log | grep rustc_query_ | wc -l)
+
+begin_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_begin_short_backtrace | wc -l)
+end_count=$(cat $TMPDIR/rust-test-2.log | grep __rust_end_short_backtrace | wc -l)
+
+cat $TMPDIR/rust-test-1.log
+echo "====================="
+cat $TMPDIR/rust-test-2.log
+echo "====================="
+
+echo "short backtrace: $short"
+echo "full  backtrace: $full"
+echo "begin_count: $begin_count"
+echo "end_count  : $end_count"
+echo "rustc_query_count: $rustc_query_count"
+echo "rustc_query_count_full: $rustc_query_count_full"
+
+## backtraces to vary a bit depending on platform and configuration options,
+## here we make sure that the short backtrace of rustc_query is shorter than the full,
+## and marks are in pairs.
+if [ $short -lt $full ] &&
+    [ $begin_count -eq $end_count ] &&
+    [ $(($rustc_query_count + 10)) -lt $rustc_query_count_full ] &&
+    [ $rustc_query_count_full -gt 10 ]; then
+    exit 0
+else
+    exit 1
+fi
diff --git a/tests/run-make/short-ice/src/lib.rs b/tests/run-make/short-ice/src/lib.rs
new file mode 100644
index 00000000000..b23b7f830d7
--- /dev/null
+++ b/tests/run-make/short-ice/src/lib.rs
@@ -0,0 +1,7 @@
+fn func(s: &str) {
+    println!("{}", s);
+}
+
+fn main() {
+    func(1);
+}
diff --git a/tests/rustdoc-gui/anchors.goml b/tests/rustdoc-gui/anchors.goml
index 0904aa90e1b..e9b77296917 100644
--- a/tests/rustdoc-gui/anchors.goml
+++ b/tests/rustdoc-gui/anchors.goml
@@ -75,35 +75,35 @@ call-function: (
     "check-colors",
     {
         "theme": "ayu",
-        "main_color": "rgb(197, 197, 197)",
-        "title_color": "rgb(255, 255, 255)",
-        "main_heading_color": "rgb(255, 255, 255)",
-        "main_heading_type_color": "rgb(255, 160, 165)",
-        "src_link_color": "rgb(57, 175, 215)",
-        "sidebar_link_color": "rgb(83, 177, 219)",
+        "main_color": "#c5c5c5",
+        "title_color": "#fff",
+        "main_heading_color": "#fff",
+        "main_heading_type_color": "#ffa0a5",
+        "src_link_color": "#39afd7",
+        "sidebar_link_color": "#53b1db",
     },
 )
 call-function: (
     "check-colors",
     {
         "theme": "dark",
-        "main_color": "rgb(221, 221, 221)",
-        "title_color": "rgb(221, 221, 221)",
-        "main_heading_color": "rgb(221, 221, 221)",
-        "main_heading_type_color": "rgb(45, 191, 184)",
-        "src_link_color": "rgb(210, 153, 29)",
-        "sidebar_link_color": "rgb(253, 191, 53)",
+        "main_color": "#ddd",
+        "title_color": "#ddd",
+        "main_heading_color": "#ddd",
+        "main_heading_type_color": "#2dbfb8",
+        "src_link_color": "#d2991d",
+        "sidebar_link_color": "#fdbf35",
     },
 )
 call-function: (
     "check-colors",
     {
         "theme": "light",
-        "main_color": "rgb(0, 0, 0)",
-        "title_color": "rgb(0, 0, 0)",
-        "main_heading_color": "rgb(0, 0, 0)",
-        "main_heading_type_color": "rgb(173, 55, 138)",
-        "src_link_color": "rgb(56, 115, 173)",
-        "sidebar_link_color": "rgb(53, 109, 164)",
+        "main_color": "black",
+        "title_color": "black",
+        "main_heading_color": "black",
+        "main_heading_type_color": "#ad378a",
+        "src_link_color": "#3873ad",
+        "sidebar_link_color": "#356da4",
     },
 )
diff --git a/tests/rustdoc-gui/codeblock-tooltip.goml b/tests/rustdoc-gui/codeblock-tooltip.goml
index 2ed0579d314..e1c81ed79e4 100644
--- a/tests/rustdoc-gui/codeblock-tooltip.goml
+++ b/tests/rustdoc-gui/codeblock-tooltip.goml
@@ -109,19 +109,19 @@ define-function: (
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "background": "rgb(15, 20, 25)",
-    "color": "rgb(197, 197, 197)",
-    "border": "rgb(92, 103, 115)",
+    "background": "#0f1419",
+    "color": "#c5c5c5",
+    "border": "#5c6773",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "background": "rgb(53, 53, 53)",
-    "color": "rgb(221, 221, 221)",
-    "border": "rgb(224, 224, 224)",
+    "background": "#353535",
+    "color": "#ddd",
+    "border": "#e0e0e0",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "background": "rgb(255, 255, 255)",
-    "color": "rgb(0, 0, 0)",
-    "border": "rgb(224, 224, 224)",
+    "background": "white",
+    "color": "black",
+    "border": "#e0e0e0",
 })
diff --git a/tests/rustdoc-gui/jump-to-def-background.goml b/tests/rustdoc-gui/jump-to-def-background.goml
index 3a7d48284d7..6adc36b0edb 100644
--- a/tests/rustdoc-gui/jump-to-def-background.goml
+++ b/tests/rustdoc-gui/jump-to-def-background.goml
@@ -17,6 +17,6 @@ define-function: (
     },
 )
 
-call-function: ("check-background-color", ("ayu", "rgb(51, 51, 51)"))
-call-function: ("check-background-color", ("dark", "rgb(51, 51, 51)"))
-call-function: ("check-background-color", ("light", "rgb(238, 238, 238)"))
+call-function: ("check-background-color", ("ayu", "#333"))
+call-function: ("check-background-color", ("dark", "#333"))
+call-function: ("check-background-color", ("light", "#eee"))
diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml
index 8ddb06fccfc..0052d18dc56 100644
--- a/tests/rustdoc-gui/scrape-examples-color.goml
+++ b/tests/rustdoc-gui/scrape-examples-color.goml
@@ -33,30 +33,30 @@ define-function: (
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "highlight": "rgb(91, 59, 1)",
-    "highlight_focus": "rgb(124, 75, 15)",
-    "help_border": "rgb(170, 170, 170)",
-    "help_color": "rgb(238, 238, 238)",
-    "help_hover_border": "rgb(255, 255, 255)",
-    "help_hover_color": "rgb(255, 255, 255)",
+    "highlight": "#5b3b01",
+    "highlight_focus": "#7c4b0f",
+    "help_border": "#aaa",
+    "help_color": "#eee",
+    "help_hover_border": "#fff",
+    "help_hover_color": "#fff",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "highlight": "rgb(91, 59, 1)",
-    "highlight_focus": "rgb(124, 75, 15)",
-    "help_border": "rgb(170, 170, 170)",
-    "help_color": "rgb(238, 238, 238)",
-    "help_hover_border": "rgb(255, 255, 255)",
-    "help_hover_color": "rgb(255, 255, 255)",
+    "highlight": "#5b3b01",
+    "highlight_focus": "#7c4b0f",
+    "help_border": "#aaa",
+    "help_color": "#eee",
+    "help_hover_border": "#fff",
+    "help_hover_color": "#fff",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "highlight": "rgb(252, 255, 214)",
-    "highlight_focus": "rgb(246, 253, 176)",
-    "help_border": "rgb(85, 85, 85)",
-    "help_color": "rgb(51, 51, 51)",
-    "help_hover_border": "rgb(0, 0, 0)",
-    "help_hover_color": "rgb(0, 0, 0)",
+    "highlight": "#fcffd6",
+    "highlight_focus": "#f6fdb0",
+    "help_border": "#555",
+    "help_color": "#333",
+    "help_hover_border": "#000",
+    "help_hover_color": "#000",
 })
 
 // Now testing the top and bottom background in case there is only one scraped examples.
@@ -81,16 +81,16 @@ define-function: (
 
 call-function: ("check-background", {
     "theme": "ayu",
-    "background_color_start": "rgb(15, 20, 25)",
+    "background_color_start": "rgba(15, 20, 25, 1)",
     "background_color_end": "rgba(15, 20, 25, 0)",
 })
 call-function: ("check-background", {
     "theme": "dark",
-    "background_color_start": "rgb(53, 53, 53)",
+    "background_color_start": "rgba(53, 53, 53, 1)",
     "background_color_end": "rgba(53, 53, 53, 0)",
 })
 call-function: ("check-background", {
     "theme": "light",
-    "background_color_start": "rgb(255, 255, 255)",
+    "background_color_start": "rgba(255, 255, 255, 1)",
     "background_color_end": "rgba(255, 255, 255, 0)",
 })
diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml
index bf1fe7be910..c37d969324c 100644
--- a/tests/rustdoc-gui/settings.goml
+++ b/tests/rustdoc-gui/settings.goml
@@ -301,7 +301,7 @@ wait-for-css: ("#help-button .popover", {"display": "block"})
 // Now we go to the settings page to check that the CSS is loaded as expected.
 go-to: "file://" + |DOC_PATH| + "/settings.html"
 wait-for: "#settings"
-assert-css: (".setting-line", {"position": "relative"})
+assert-css: (".setting-radio", {"cursor": "pointer"})
 
 assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS)
 compare-elements-position: (".sub form", "#settings", ("x"))
@@ -322,4 +322,4 @@ reload:
 set-window-size: (300, 1000)
 click: "#settings-menu"
 wait-for: "#settings"
-assert-css: (".setting-line", {"position": "relative"})
+assert-css: (".setting-radio", {"cursor": "pointer"})
diff --git a/tests/rustdoc-gui/source-code-page.goml b/tests/rustdoc-gui/source-code-page.goml
index 5c795928bdc..d5dd511b1d3 100644
--- a/tests/rustdoc-gui/source-code-page.goml
+++ b/tests/rustdoc-gui/source-code-page.goml
@@ -40,24 +40,24 @@ define-function: (
 
 call-function: ("check-colors", {
     "theme": "ayu",
-    "color": "rgb(92, 103, 115)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(112, 128, 144)",
+    "color": "#5c6773",
+    "background_color": "transparent",
+    "highlight_color": "#708090",
     "highlight_background_color": "rgba(255, 236, 164, 0.06)",
 })
 call-function: ("check-colors", {
     "theme": "dark",
-    "color": "rgb(59, 145, 226)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(59, 145, 226)",
-    "highlight_background_color": "rgb(10, 4, 47)",
+    "color": "#3b91e2",
+    "background_color": "transparent",
+    "highlight_color": "#3b91e2",
+    "highlight_background_color": "#0a042f",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "color": "rgb(198, 126, 45)",
-    "background_color": "rgba(0, 0, 0, 0)",
-    "highlight_color": "rgb(198, 126, 45)",
-    "highlight_background_color": "rgb(253, 255, 211)",
+    "color": "#c67e2d",
+    "background_color": "transparent",
+    "highlight_color": "#c67e2d",
+    "highlight_background_color": "#fdffd3",
 })
 
 // This is to ensure that the content is correctly align with the line numbers.
diff --git a/tests/rustdoc-json/assoc_items.rs b/tests/rustdoc-json/assoc_items.rs
index 6d7f6bb969f..05c2d428393 100644
--- a/tests/rustdoc-json/assoc_items.rs
+++ b/tests/rustdoc-json/assoc_items.rs
@@ -3,35 +3,32 @@
 pub struct Simple;
 
 impl Simple {
-    // @is "$.index[*][?(@.name=='CONSTANT')].kind" \"assoc_const\"
+    // @has "$.index[*][?(@.name=='CONSTANT')].inner.assoc_const"
     pub const CONSTANT: usize = 0;
 }
 
 pub trait EasyToImpl {
-    // @is "$.index[*][?(@.docs=='ToDeclare trait')].kind" \"assoc_type\"
-    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.default" null
-    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.bounds" []
+    // @has "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type"
+    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.default" null
+    // @is "$.index[*][?(@.docs=='ToDeclare trait')].inner.assoc_type.bounds" []
     /// ToDeclare trait
     type ToDeclare;
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].kind" \"assoc_const\"
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.default" null
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.type.kind" '"primitive"'
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.type.inner" '"usize"'
+    // @has "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const"
+    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.default" null
+    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE trait')].inner.assoc_const.type.primitive" '"usize"'
     /// AN_ATTRIBUTE trait
     const AN_ATTRIBUTE: usize;
 }
 
 impl EasyToImpl for Simple {
-    // @is "$.index[*][?(@.docs=='ToDeclare impl')].kind" '"assoc_type"'
-    // @is "$.index[*][?(@.docs=='ToDeclare impl')].inner.default.kind" \"primitive\"
-    // @is "$.index[*][?(@.docs=='ToDeclare impl')].inner.default.inner" \"usize\"
+    // @has "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type"
+    // @is "$.index[*][?(@.docs=='ToDeclare impl')].inner.assoc_type.default.primitive" \"usize\"
     /// ToDeclare impl
     type ToDeclare = usize;
 
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].kind" '"assoc_const"'
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.type.kind" \"primitive\"
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.type.inner" \"usize\"
-    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.default" \"12\"
+    // @has "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const"
+    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.type.primitive" \"usize\"
+    // @is "$.index[*][?(@.docs=='AN_ATTRIBUTE impl')].inner.assoc_const.default" \"12\"
     /// AN_ATTRIBUTE impl
     const AN_ATTRIBUTE: usize = 12;
 }
diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs
index c5cc87ca1eb..a2a5c4a7146 100644
--- a/tests/rustdoc-json/blanket_impls.rs
+++ b/tests/rustdoc-json/blanket_impls.rs
@@ -2,7 +2,7 @@
 
 #![no_std]
 
-// @has "$.index[*][?(@.name=='Error')].kind" \"assoc_type\"
-// @has "$.index[*][?(@.name=='Error')].inner.default.kind" \"resolved_path\"
-// @has "$.index[*][?(@.name=='Error')].inner.default.inner.name" \"Infallible\"
+// @has "$.index[*][?(@.name=='Error')].inner.assoc_type"
+// @has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path"
+// @has "$.index[*][?(@.name=='Error')].inner.assoc_type.default.resolved_path.name" \"Infallible\"
 pub struct ForBlanketTryFromImpl;
diff --git a/tests/rustdoc-json/enums/discriminant/basic.rs b/tests/rustdoc-json/enums/discriminant/basic.rs
index 06906df3b2c..dbfc5c2cf6b 100644
--- a/tests/rustdoc-json/enums/discriminant/basic.rs
+++ b/tests/rustdoc-json/enums/discriminant/basic.rs
@@ -1,12 +1,12 @@
 #[repr(i8)]
 pub enum Ordering {
-    // @is "$.index[*][?(@.name=='Less')].inner.discriminant.expr" '"-1"'
-    // @is "$.index[*][?(@.name=='Less')].inner.discriminant.value" '"-1"'
+    // @is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.expr" '"-1"'
+    // @is "$.index[*][?(@.name=='Less')].inner.variant.discriminant.value" '"-1"'
     Less = -1,
-    // @is "$.index[*][?(@.name=='Equal')].inner.discriminant.expr" '"0"'
-    // @is "$.index[*][?(@.name=='Equal')].inner.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.expr" '"0"'
+    // @is "$.index[*][?(@.name=='Equal')].inner.variant.discriminant.value" '"0"'
     Equal = 0,
-    // @is "$.index[*][?(@.name=='Greater')].inner.discriminant.expr" '"1"'
-    // @is "$.index[*][?(@.name=='Greater')].inner.discriminant.value" '"1"'
+    // @is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.expr" '"1"'
+    // @is "$.index[*][?(@.name=='Greater')].inner.variant.discriminant.value" '"1"'
     Greater = 1,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/expr.rs b/tests/rustdoc-json/enums/discriminant/expr.rs
index e639965e79b..ddcad58a550 100644
--- a/tests/rustdoc-json/enums/discriminant/expr.rs
+++ b/tests/rustdoc-json/enums/discriminant/expr.rs
@@ -1,30 +1,30 @@
 pub enum Foo {
-    // @is "$.index[*][?(@.name=='Addition')].inner.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='Addition')].inner.discriminant.expr" '"{ _ }"'
+    // @is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='Addition')].inner.variant.discriminant.expr" '"{ _ }"'
     Addition = 0 + 0,
-    // @is "$.index[*][?(@.name=='Bin')].inner.discriminant.value" '"1"'
-    // @is "$.index[*][?(@.name=='Bin')].inner.discriminant.expr" '"0b1"'
+    // @is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.value" '"1"'
+    // @is "$.index[*][?(@.name=='Bin')].inner.variant.discriminant.expr" '"0b1"'
     Bin = 0b1,
-    // @is "$.index[*][?(@.name=='Oct')].inner.discriminant.value" '"2"'
-    // @is "$.index[*][?(@.name=='Oct')].inner.discriminant.expr" '"0o2"'
+    // @is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.value" '"2"'
+    // @is "$.index[*][?(@.name=='Oct')].inner.variant.discriminant.expr" '"0o2"'
     Oct = 0o2,
-    // @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.value" '"3"'
-    // @is "$.index[*][?(@.name=='PubConst')].inner.discriminant.expr" '"THREE"'
+    // @is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.value" '"3"'
+    // @is "$.index[*][?(@.name=='PubConst')].inner.variant.discriminant.expr" '"THREE"'
     PubConst = THREE,
-    // @is "$.index[*][?(@.name=='Hex')].inner.discriminant.value" '"4"'
-    // @is "$.index[*][?(@.name=='Hex')].inner.discriminant.expr" '"0x4"'
+    // @is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.value" '"4"'
+    // @is "$.index[*][?(@.name=='Hex')].inner.variant.discriminant.expr" '"0x4"'
     Hex = 0x4,
-    // @is "$.index[*][?(@.name=='Cast')].inner.discriminant.value" '"5"'
-    // @is "$.index[*][?(@.name=='Cast')].inner.discriminant.expr" '"{ _ }"'
+    // @is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.value" '"5"'
+    // @is "$.index[*][?(@.name=='Cast')].inner.variant.discriminant.expr" '"{ _ }"'
     Cast = 5 as isize,
-    // @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.value" '"6"'
-    // @is "$.index[*][?(@.name=='PubCall')].inner.discriminant.expr" '"{ _ }"'
+    // @is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.value" '"6"'
+    // @is "$.index[*][?(@.name=='PubCall')].inner.variant.discriminant.expr" '"{ _ }"'
     PubCall = six(),
-    // @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.value" '"7"'
-    // @is "$.index[*][?(@.name=='PrivCall')].inner.discriminant.expr" '"{ _ }"'
+    // @is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.value" '"7"'
+    // @is "$.index[*][?(@.name=='PrivCall')].inner.variant.discriminant.expr" '"{ _ }"'
     PrivCall = seven(),
-    // @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.value" '"8"'
-    // @is "$.index[*][?(@.name=='PrivConst')].inner.discriminant.expr" '"EIGHT"'
+    // @is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.value" '"8"'
+    // @is "$.index[*][?(@.name=='PrivConst')].inner.variant.discriminant.expr" '"EIGHT"'
     PrivConst = EIGHT,
 }
 
diff --git a/tests/rustdoc-json/enums/discriminant/limits.rs b/tests/rustdoc-json/enums/discriminant/limits.rs
index e56d5594f2f..47fb7040896 100644
--- a/tests/rustdoc-json/enums/discriminant/limits.rs
+++ b/tests/rustdoc-json/enums/discriminant/limits.rs
@@ -4,40 +4,40 @@
 
 #[repr(u64)]
 pub enum U64 {
-    // @is "$.index[*][?(@.name=='U64Min')].inner.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='U64Min')].inner.discriminant.expr" '"u64::MIN"'
+    // @is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='U64Min')].inner.variant.discriminant.expr" '"u64::MIN"'
     U64Min = u64::MIN,
-    // @is "$.index[*][?(@.name=='U64Max')].inner.discriminant.value" '"18446744073709551615"'
-    // @is "$.index[*][?(@.name=='U64Max')].inner.discriminant.expr" '"u64::MAX"'
+    // @is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.value" '"18446744073709551615"'
+    // @is "$.index[*][?(@.name=='U64Max')].inner.variant.discriminant.expr" '"u64::MAX"'
     U64Max = u64::MAX,
 }
 
 #[repr(i64)]
 pub enum I64 {
-    // @is "$.index[*][?(@.name=='I64Min')].inner.discriminant.value" '"-9223372036854775808"'
-    // @is "$.index[*][?(@.name=='I64Min')].inner.discriminant.expr" '"i64::MIN"'
+    // @is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.value" '"-9223372036854775808"'
+    // @is "$.index[*][?(@.name=='I64Min')].inner.variant.discriminant.expr" '"i64::MIN"'
     I64Min = i64::MIN,
-    // @is "$.index[*][?(@.name=='I64Max')].inner.discriminant.value" '"9223372036854775807"'
-    // @is "$.index[*][?(@.name=='I64Max')].inner.discriminant.expr" '"i64::MAX"'
+    // @is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.value" '"9223372036854775807"'
+    // @is "$.index[*][?(@.name=='I64Max')].inner.variant.discriminant.expr" '"i64::MAX"'
     I64Max = i64::MAX,
 }
 
 #[repr(u128)]
 pub enum U128 {
-    // @is "$.index[*][?(@.name=='U128Min')].inner.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='U128Min')].inner.discriminant.expr" '"u128::MIN"'
+    // @is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='U128Min')].inner.variant.discriminant.expr" '"u128::MIN"'
     U128Min = u128::MIN,
-    // @is "$.index[*][?(@.name=='U128Max')].inner.discriminant.value" '"340282366920938463463374607431768211455"'
-    // @is "$.index[*][?(@.name=='U128Max')].inner.discriminant.expr" '"u128::MAX"'
+    // @is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.value" '"340282366920938463463374607431768211455"'
+    // @is "$.index[*][?(@.name=='U128Max')].inner.variant.discriminant.expr" '"u128::MAX"'
     U128Max = u128::MAX,
 }
 
 #[repr(i128)]
 pub enum I128 {
-    // @is "$.index[*][?(@.name=='I128Min')].inner.discriminant.value" '"-170141183460469231731687303715884105728"'
-    // @is "$.index[*][?(@.name=='I128Min')].inner.discriminant.expr" '"i128::MIN"'
+    // @is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.value" '"-170141183460469231731687303715884105728"'
+    // @is "$.index[*][?(@.name=='I128Min')].inner.variant.discriminant.expr" '"i128::MIN"'
     I128Min = i128::MIN,
-    // @is "$.index[*][?(@.name=='I128Max')].inner.discriminant.value" '"170141183460469231731687303715884105727"'
-    // @is "$.index[*][?(@.name=='I128Max')].inner.discriminant.expr" '"i128::MAX"'
+    // @is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.value" '"170141183460469231731687303715884105727"'
+    // @is "$.index[*][?(@.name=='I128Max')].inner.variant.discriminant.expr" '"i128::MAX"'
     I128Max = i128::MAX,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
index 6889b305ffb..9c3db81c663 100644
--- a/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
+++ b/tests/rustdoc-json/enums/discriminant/num_underscore_and_suffix.rs
@@ -1,15 +1,17 @@
+// ignore-tidy-linelength
+
 #[repr(u32)]
 pub enum Foo {
-    // @is "$.index[*][?(@.name=='Basic')].inner.discriminant.value" '"0"'
-    // @is "$.index[*][?(@.name=='Basic')].inner.discriminant.expr" '"0"'
+    // @is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.value" '"0"'
+    // @is "$.index[*][?(@.name=='Basic')].inner.variant.discriminant.expr" '"0"'
     Basic = 0,
-    // @is "$.index[*][?(@.name=='Suffix')].inner.discriminant.value" '"10"'
-    // @is "$.index[*][?(@.name=='Suffix')].inner.discriminant.expr" '"10u32"'
+    // @is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.value" '"10"'
+    // @is "$.index[*][?(@.name=='Suffix')].inner.variant.discriminant.expr" '"10u32"'
     Suffix = 10u32,
-    // @is "$.index[*][?(@.name=='Underscore')].inner.discriminant.value" '"100"'
-    // @is "$.index[*][?(@.name=='Underscore')].inner.discriminant.expr" '"1_0_0"'
+    // @is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.value" '"100"'
+    // @is "$.index[*][?(@.name=='Underscore')].inner.variant.discriminant.expr" '"1_0_0"'
     Underscore = 1_0_0,
-    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.discriminant.value" '"1000"'
-    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.discriminant.expr" '"1_0_0_0u32"'
+    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.value" '"1000"'
+    // @is "$.index[*][?(@.name=='SuffixUnderscore')].inner.variant.discriminant.expr" '"1_0_0_0u32"'
     SuffixUnderscore = 1_0_0_0u32,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
index 6a4f54de617..38ba1caf140 100644
--- a/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
+++ b/tests/rustdoc-json/enums/discriminant/only_some_have_discriminant.rs
@@ -1,10 +1,12 @@
+// ignore-tidy-linelength
+
 pub enum Foo {
-    // @is "$.index[*][?(@.name=='Has')].inner.discriminant" '{"expr":"0", "value":"0"}'
+    // @is "$.index[*][?(@.name=='Has')].inner.variant.discriminant" '{"expr":"0", "value":"0"}'
     Has = 0,
-    // @is "$.index[*][?(@.name=='Doesnt')].inner.discriminant" null
+    // @is "$.index[*][?(@.name=='Doesnt')].inner.variant.discriminant" null
     Doesnt,
-    // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.discriminant" null
+    // @is "$.index[*][?(@.name=='AlsoDoesnt')].inner.variant.discriminant" null
     AlsoDoesnt,
-    // @is "$.index[*][?(@.name=='AlsoHas')].inner.discriminant" '{"expr":"44", "value":"44"}'
+    // @is "$.index[*][?(@.name=='AlsoHas')].inner.variant.discriminant" '{"expr":"44", "value":"44"}'
     AlsoHas = 44,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs
index e91a632a3b3..c4b087c3635 100644
--- a/tests/rustdoc-json/enums/discriminant/struct.rs
+++ b/tests/rustdoc-json/enums/discriminant/struct.rs
@@ -3,13 +3,13 @@
 #[repr(i32)]
 // @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(i32)]"]'
 pub enum Foo {
-    // @is    "$.index[*][?(@.name=='Struct')].inner.discriminant" null
-    // @count "$.index[*][?(@.name=='Struct')].inner.kind.struct.fields[*]" 0
+    // @is    "$.index[*][?(@.name=='Struct')].inner.variant.discriminant" null
+    // @count "$.index[*][?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0
     Struct {},
-    // @is    "$.index[*][?(@.name=='StructWithDiscr')].inner.discriminant" '{"expr": "42", "value": "42"}'
-    // @count "$.index[*][?(@.name=='StructWithDiscr')].inner.kind.struct.fields[*]" 1
+    // @is    "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.discriminant" '{"expr": "42", "value": "42"}'
+    // @count "$.index[*][?(@.name=='StructWithDiscr')].inner.variant.kind.struct.fields[*]" 1
     StructWithDiscr { x: i32 } = 42,
-    // @is    "$.index[*][?(@.name=='StructWithHexDiscr')].inner.discriminant"  '{"expr": "0x42", "value": "66"}'
-    // @count "$.index[*][?(@.name=='StructWithHexDiscr')].inner.kind.struct.fields[*]" 2
+    // @is    "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.discriminant"  '{"expr": "0x42", "value": "66"}'
+    // @count "$.index[*][?(@.name=='StructWithHexDiscr')].inner.variant.kind.struct.fields[*]" 2
     StructWithHexDiscr { x: i32, y: bool } = 0x42,
 }
diff --git a/tests/rustdoc-json/enums/discriminant/tuple.rs b/tests/rustdoc-json/enums/discriminant/tuple.rs
index b94d5739eab..7da82ec8ea4 100644
--- a/tests/rustdoc-json/enums/discriminant/tuple.rs
+++ b/tests/rustdoc-json/enums/discriminant/tuple.rs
@@ -3,13 +3,13 @@
 #[repr(u32)]
 // @is "$.index[*][?(@.name=='Foo')].attrs" '["#[repr(u32)]"]'
 pub enum Foo {
-    // @is    "$.index[*][?(@.name=='Tuple')].inner.discriminant" null
-    // @count "$.index[*][?(@.name=='Tuple')].inner.kind.tuple[*]" 0
+    // @is    "$.index[*][?(@.name=='Tuple')].inner.variant.discriminant" null
+    // @count "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0
     Tuple(),
-    // @is    "$.index[*][?(@.name=='TupleWithDiscr')].inner.discriminant" '{"expr": "1", "value": "1"}'
-    // @count "$.index[*][?(@.name=='TupleWithDiscr')].inner.kind.tuple[*]" 1
+    // @is    "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.discriminant" '{"expr": "1", "value": "1"}'
+    // @count "$.index[*][?(@.name=='TupleWithDiscr')].inner.variant.kind.tuple[*]" 1
     TupleWithDiscr(i32) = 1,
-    // @is    "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.discriminant" '{"expr": "0b10", "value": "2"}'
-    // @count "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.discriminant" '{"expr": "0b10", "value": "2"}'
+    // @count "$.index[*][?(@.name=='TupleWithBinDiscr')].inner.variant.kind.tuple[*]" 2
     TupleWithBinDiscr(i32, i32) = 0b10,
 }
diff --git a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs
index 470b195a292..b00156124fc 100644
--- a/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs
+++ b/tests/rustdoc-json/enums/doc_link_to_foreign_variant.rs
@@ -5,7 +5,7 @@
 extern crate color;
 use color::Color::Red;
 
-// @set red = "$.index[*][?(@.inner.is_crate == true)].links.Red"
+// @set red = "$.index[*][?(@.inner.module.is_crate)].links.Red"
 
 // @!has "$.index[*][?(@.name == 'Red')]"
 // @!has "$.index[*][?(@.name == 'Color')]"
diff --git a/tests/rustdoc-json/enums/field_hidden.rs b/tests/rustdoc-json/enums/field_hidden.rs
index 78a05431472..5c0d0ffd3df 100644
--- a/tests/rustdoc-json/enums/field_hidden.rs
+++ b/tests/rustdoc-json/enums/field_hidden.rs
@@ -5,8 +5,8 @@
 
 // @has "$.index[*][?(@.name=='ParseError')]"
 // @has "$.index[*][?(@.name=='UnexpectedEndTag')]"
-// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.kind.tuple" [null]
-// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.discriminant" null
+// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.kind.tuple" [null]
+// @is "$.index[*][?(@.name=='UnexpectedEndTag')].inner.variant.discriminant" null
 
 pub enum ParseError {
     UnexpectedEndTag(#[doc(hidden)] u32),
diff --git a/tests/rustdoc-json/enums/kind.rs b/tests/rustdoc-json/enums/kind.rs
index 1787a859c8b..e283c074006 100644
--- a/tests/rustdoc-json/enums/kind.rs
+++ b/tests/rustdoc-json/enums/kind.rs
@@ -5,28 +5,28 @@
 
 pub enum Foo {
     // @set Unit = "$.index[*][?(@.name=='Unit')].id"
-    // @is "$.index[*][?(@.name=='Unit')].inner.kind" '"plain"'
+    // @is "$.index[*][?(@.name=='Unit')].inner.variant.kind" '"plain"'
     Unit,
     // @set Named = "$.index[*][?(@.name=='Named')].id"
-    // @is "$.index[*][?(@.name=='Named')].inner.kind.struct" '{"fields": [], "fields_stripped": false}'
+    // @is "$.index[*][?(@.name=='Named')].inner.variant.kind.struct" '{"fields": [], "fields_stripped": false}'
     Named {},
     // @set Tuple = "$.index[*][?(@.name=='Tuple')].id"
-    // @is "$.index[*][?(@.name=='Tuple')].inner.kind.tuple" []
+    // @is "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple" []
     Tuple(),
     // @set NamedField = "$.index[*][?(@.name=='NamedField')].id"
-    // @set x = "$.index[*][?(@.name=='x' && @.kind=='struct_field')].id"
-    // @is "$.index[*][?(@.name=='NamedField')].inner.kind.struct.fields[*]" $x
-    // @is "$.index[*][?(@.name=='NamedField')].inner.kind.struct.fields_stripped" false
+    // @set x = "$.index[*][?(@.name=='x' && @.inner.struct_field)].id"
+    // @is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields[*]" $x
+    // @is "$.index[*][?(@.name=='NamedField')].inner.variant.kind.struct.fields_stripped" false
     NamedField { x: i32 },
     // @set TupleField = "$.index[*][?(@.name=='TupleField')].id"
-    // @set tup_field = "$.index[*][?(@.name=='0' && @.kind=='struct_field')].id"
-    // @is "$.index[*][?(@.name=='TupleField')].inner.kind.tuple[*]" $tup_field
+    // @set tup_field = "$.index[*][?(@.name=='0' && @.inner.struct_field)].id"
+    // @is "$.index[*][?(@.name=='TupleField')].inner.variant.kind.tuple[*]" $tup_field
     TupleField(i32),
 }
 
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[0]" $Unit
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[1]" $Named
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[2]" $Tuple
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[3]" $NamedField
-// @is    "$.index[*][?(@.name=='Foo')].inner.variants[4]" $TupleField
-// @count "$.index[*][?(@.name=='Foo')].inner.variants[*]" 5
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[0]" $Unit
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[1]" $Named
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[2]" $Tuple
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[3]" $NamedField
+// @is    "$.index[*][?(@.name=='Foo')].inner.enum.variants[4]" $TupleField
+// @count "$.index[*][?(@.name=='Foo')].inner.enum.variants[*]" 5
diff --git a/tests/rustdoc-json/enums/struct_field_hidden.rs b/tests/rustdoc-json/enums/struct_field_hidden.rs
index de939cde2e7..2676c4e4157 100644
--- a/tests/rustdoc-json/enums/struct_field_hidden.rs
+++ b/tests/rustdoc-json/enums/struct_field_hidden.rs
@@ -9,8 +9,8 @@ pub enum Foo {
         // @set y = "$.index[*][?(@.name=='y')].id"
         y: i32,
     },
-    // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields_stripped" true
-    // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[0]" $b
-    // @is "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[1]" $y
-    // @count "$.index[*][?(@.name=='Variant')].inner.kind.struct.fields[*]" 2
+    // @is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields_stripped" true
+    // @is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[0]" $b
+    // @is "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[1]" $y
+    // @count "$.index[*][?(@.name=='Variant')].inner.variant.kind.struct.fields[*]" 2
 }
diff --git a/tests/rustdoc-json/enums/tuple_fields_hidden.rs b/tests/rustdoc-json/enums/tuple_fields_hidden.rs
index 70bfbb81826..3aeb0356420 100644
--- a/tests/rustdoc-json/enums/tuple_fields_hidden.rs
+++ b/tests/rustdoc-json/enums/tuple_fields_hidden.rs
@@ -14,47 +14,47 @@
 // @set 3.3.1 = "$.index[*][?(@.docs=='3.3.1')].id"
 
 pub enum EnumWithStrippedTupleVariants {
-    // @count "$.index[*][?(@.name=='None')].inner.kind.tuple[*]" 0
+    // @count "$.index[*][?(@.name=='None')].inner.variant.kind.tuple[*]" 0
     None(),
 
-    // @count "$.index[*][?(@.name=='One')].inner.kind.tuple[*]" 1
-    // @is    "$.index[*][?(@.name=='One')].inner.kind.tuple[0]" $1.1.0
+    // @count "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[*]" 1
+    // @is    "$.index[*][?(@.name=='One')].inner.variant.kind.tuple[0]" $1.1.0
     One(/** 1.1.0*/ bool),
-    // @count "$.index[*][?(@.name=='OneHidden')].inner.kind.tuple[*]" 1
-    // @is    "$.index[*][?(@.name=='OneHidden')].inner.kind.tuple[0]" null
+    // @count "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[*]" 1
+    // @is    "$.index[*][?(@.name=='OneHidden')].inner.variant.kind.tuple[0]" null
     OneHidden(#[doc(hidden)] bool),
 
-    // @count "$.index[*][?(@.name=='Two')].inner.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='Two')].inner.kind.tuple[0]" $2.1.0
-    // @is    "$.index[*][?(@.name=='Two')].inner.kind.tuple[1]" $2.1.1
+    // @count "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[0]" $2.1.0
+    // @is    "$.index[*][?(@.name=='Two')].inner.variant.kind.tuple[1]" $2.1.1
     Two(/** 2.1.0*/ bool, /** 2.1.1*/ bool),
-    // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[0]" null
-    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.kind.tuple[1]" $2.2.1
+    // @count "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[0]" null
+    // @is    "$.index[*][?(@.name=='TwoLeftHidden')].inner.variant.kind.tuple[1]" $2.2.1
     TwoLeftHidden(#[doc(hidden)] bool, /** 2.2.1*/ bool),
-    // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[0]" $2.3.0
-    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.kind.tuple[1]" null
+    // @count "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[0]" $2.3.0
+    // @is    "$.index[*][?(@.name=='TwoRightHidden')].inner.variant.kind.tuple[1]" null
     TwoRightHidden(/** 2.3.0*/ bool, #[doc(hidden)] bool),
-    // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[*]" 2
-    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[0]" null
-    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.kind.tuple[1]" null
+    // @count "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[*]" 2
+    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[0]" null
+    // @is    "$.index[*][?(@.name=='TwoBothHidden')].inner.variant.kind.tuple[1]" null
     TwoBothHidden(#[doc(hidden)] bool, #[doc(hidden)] bool),
 
-    // @count "$.index[*][?(@.name=='Three1')].inner.kind.tuple[*]" 3
-    // @is    "$.index[*][?(@.name=='Three1')].inner.kind.tuple[0]" null
-    // @is    "$.index[*][?(@.name=='Three1')].inner.kind.tuple[1]" $3.1.1
-    // @is    "$.index[*][?(@.name=='Three1')].inner.kind.tuple[2]" $3.1.2
+    // @count "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[*]" 3
+    // @is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[0]" null
+    // @is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[1]" $3.1.1
+    // @is    "$.index[*][?(@.name=='Three1')].inner.variant.kind.tuple[2]" $3.1.2
     Three1(#[doc(hidden)] bool, /** 3.1.1*/ bool, /** 3.1.2*/ bool),
-    // @count "$.index[*][?(@.name=='Three2')].inner.kind.tuple[*]" 3
-    // @is    "$.index[*][?(@.name=='Three2')].inner.kind.tuple[0]" $3.2.0
-    // @is    "$.index[*][?(@.name=='Three2')].inner.kind.tuple[1]" null
-    // @is    "$.index[*][?(@.name=='Three2')].inner.kind.tuple[2]" $3.2.2
+    // @count "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[*]" 3
+    // @is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[0]" $3.2.0
+    // @is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[1]" null
+    // @is    "$.index[*][?(@.name=='Three2')].inner.variant.kind.tuple[2]" $3.2.2
     Three2(/** 3.2.0*/ bool, #[doc(hidden)] bool, /** 3.2.2*/ bool),
-    // @count "$.index[*][?(@.name=='Three3')].inner.kind.tuple[*]" 3
-    // @is    "$.index[*][?(@.name=='Three3')].inner.kind.tuple[0]" $3.3.0
-    // @is    "$.index[*][?(@.name=='Three3')].inner.kind.tuple[1]" $3.3.1
-    // @is    "$.index[*][?(@.name=='Three3')].inner.kind.tuple[2]" null
+    // @count "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[*]" 3
+    // @is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[0]" $3.3.0
+    // @is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[1]" $3.3.1
+    // @is    "$.index[*][?(@.name=='Three3')].inner.variant.kind.tuple[2]" null
     Three3(/** 3.3.0*/ bool, /** 3.3.1*/ bool, #[doc(hidden)] bool),
 }
 
@@ -70,14 +70,14 @@ pub enum EnumWithStrippedTupleVariants {
 // @is "$.index[*][?(@.docs=='3.3.0')].name" '"0"'
 // @is "$.index[*][?(@.docs=='3.3.1')].name" '"1"'
 
-// @is "$.index[*][?(@.docs=='1.1.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='2.1.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='2.1.1')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='2.2.1')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='2.3.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.1.1')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.1.2')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.2.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.2.2')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.3.0')].inner" '{"kind": "primitive", "inner": "bool"}'
-// @is "$.index[*][?(@.docs=='3.3.1')].inner" '{"kind": "primitive", "inner": "bool"}'
+// @is "$.index[*][?(@.docs=='1.1.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='2.1.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='2.1.1')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='2.2.1')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='2.3.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.1.1')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.1.2')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.2.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.2.2')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.3.0')].inner.struct_field" '{"primitive": "bool"}'
+// @is "$.index[*][?(@.docs=='3.3.1')].inner.struct_field" '{"primitive": "bool"}'
diff --git a/tests/rustdoc-json/enums/use_glob.rs b/tests/rustdoc-json/enums/use_glob.rs
index 62b8b832afd..49990ec5331 100644
--- a/tests/rustdoc-json/enums/use_glob.rs
+++ b/tests/rustdoc-json/enums/use_glob.rs
@@ -10,9 +10,9 @@ pub enum Color {
     Blue,
 }
 
-// @set use_Color = "$.index[*][?(@.kind == 'import')].id"
-// @is "$.index[*][?(@.kind == 'import')].inner.id" $Color
-// @is "$.index[*][?(@.kind == 'import')].inner.glob" true
+// @set use_Color = "$.index[*][?(@.inner.import)].id"
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $Color
+// @is "$.index[*][?(@.inner.import)].inner.import.glob" true
 pub use Color::*;
 
-// @ismany "$.index[*][?(@.name == 'use_glob')].inner.items[*]" $Color $use_Color
+// @ismany "$.index[*][?(@.name == 'use_glob')].inner.module.items[*]" $Color $use_Color
diff --git a/tests/rustdoc-json/enums/use_variant.rs b/tests/rustdoc-json/enums/use_variant.rs
index 5f0d2b9b1ec..8190e1cbe81 100644
--- a/tests/rustdoc-json/enums/use_variant.rs
+++ b/tests/rustdoc-json/enums/use_variant.rs
@@ -6,10 +6,10 @@ pub enum AlwaysNone {
     // @set None = "$.index[*][?(@.name == 'None')].id"
     None,
 }
-// @is "$.index[*][?(@.name == 'AlwaysNone')].inner.variants[*]" $None
+// @is "$.index[*][?(@.name == 'AlwaysNone')].inner.enum.variants[*]" $None
 
-// @set use_None = "$.index[*][?(@.kind == 'import')].id"
-// @is "$.index[*][?(@.kind == 'import')].inner.id" $None
+// @set use_None = "$.index[*][?(@.inner.import)].id"
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $None
 pub use AlwaysNone::None;
 
-// @ismany "$.index[*][?(@.name == 'use_variant')].inner.items[*]" $AlwaysNone $use_None
+// @ismany "$.index[*][?(@.name == 'use_variant')].inner.module.items[*]" $AlwaysNone $use_None
diff --git a/tests/rustdoc-json/enums/use_variant_foreign.rs b/tests/rustdoc-json/enums/use_variant_foreign.rs
index 11bb6ce1f3a..a79e899d85f 100644
--- a/tests/rustdoc-json/enums/use_variant_foreign.rs
+++ b/tests/rustdoc-json/enums/use_variant_foreign.rs
@@ -2,7 +2,7 @@
 
 extern crate color;
 
-// @is "$.index[*][?(@.inner.name == 'Red')].kind" '"import"'
+// @has "$.index[*].inner.import[?(@.name == 'Red')]"
 pub use color::Color::Red;
 
 // @!has "$.index[*][?(@.name == 'Red')]"
diff --git a/tests/rustdoc-json/enums/variant_struct.rs b/tests/rustdoc-json/enums/variant_struct.rs
index bc870c502a0..fe40f1a5d5d 100644
--- a/tests/rustdoc-json/enums/variant_struct.rs
+++ b/tests/rustdoc-json/enums/variant_struct.rs
@@ -1,10 +1,10 @@
 // @is "$.index[*][?(@.name=='EnumStruct')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='EnumStruct')].kind" \"enum\"
+// @has "$.index[*][?(@.name=='EnumStruct')].inner.enum"
 pub enum EnumStruct {
-    // @is "$.index[*][?(@.name=='x')].kind" \"struct_field\"
+    // @has "$.index[*][?(@.name=='x')].inner.struct_field"
     // @set x = "$.index[*][?(@.name=='x')].id"
-    // @is "$.index[*][?(@.name=='y')].kind" \"struct_field\"
+    // @has "$.index[*][?(@.name=='y')].inner.struct_field"
     // @set y = "$.index[*][?(@.name=='y')].id"
-    // @ismany "$.index[*][?(@.name=='VariantS')].inner.kind.struct.fields[*]" $x $y
+    // @ismany "$.index[*][?(@.name=='VariantS')].inner.variant.kind.struct.fields[*]" $x $y
     VariantS { x: u32, y: String },
 }
diff --git a/tests/rustdoc-json/enums/variant_tuple_struct.rs b/tests/rustdoc-json/enums/variant_tuple_struct.rs
index d1207bbfb18..358fc1079cb 100644
--- a/tests/rustdoc-json/enums/variant_tuple_struct.rs
+++ b/tests/rustdoc-json/enums/variant_tuple_struct.rs
@@ -1,10 +1,10 @@
 // @is "$.index[*][?(@.name=='EnumTupleStruct')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='EnumTupleStruct')].kind" \"enum\"
+// @has "$.index[*][?(@.name=='EnumTupleStruct')].inner.enum"
 pub enum EnumTupleStruct {
-    // @is "$.index[*][?(@.name=='0')].kind" \"struct_field\"
+    // @has "$.index[*][?(@.name=='0')].inner.struct_field"
     // @set f0 = "$.index[*][?(@.name=='0')].id"
-    // @is "$.index[*][?(@.name=='1')].kind" \"struct_field\"
+    // @has "$.index[*][?(@.name=='1')].inner.struct_field"
     // @set f1 = "$.index[*][?(@.name=='1')].id"
-    // @ismany "$.index[*][?(@.name=='VariantA')].inner.kind.tuple[*]" $f0 $f1
+    // @ismany "$.index[*][?(@.name=='VariantA')].inner.variant.kind.tuple[*]" $f0 $f1
     VariantA(u32, String),
 }
diff --git a/tests/rustdoc-json/fn_pointer/abi.rs b/tests/rustdoc-json/fn_pointer/abi.rs
index 6a30acc2cc3..77c0e82330f 100644
--- a/tests/rustdoc-json/fn_pointer/abi.rs
+++ b/tests/rustdoc-json/fn_pointer/abi.rs
@@ -2,23 +2,23 @@
 
 #![feature(abi_vectorcall)]
 
-// @is "$.index[*][?(@.name=='AbiRust')].inner.type.inner.header.abi" \"Rust\"
+// @is "$.index[*][?(@.name=='AbiRust')].inner.typedef.type.function_pointer.header.abi" \"Rust\"
 pub type AbiRust = fn();
 
-// @is "$.index[*][?(@.name=='AbiC')].inner.type.inner.header.abi" '{"C": {"unwind": false}}'
+// @is "$.index[*][?(@.name=='AbiC')].inner.typedef.type.function_pointer.header.abi" '{"C": {"unwind": false}}'
 pub type AbiC = extern "C" fn();
 
-// @is "$.index[*][?(@.name=='AbiSystem')].inner.type.inner.header.abi" '{"System": {"unwind": false}}'
+// @is "$.index[*][?(@.name=='AbiSystem')].inner.typedef.type.function_pointer.header.abi" '{"System": {"unwind": false}}'
 pub type AbiSystem = extern "system" fn();
 
-// @is "$.index[*][?(@.name=='AbiCUnwind')].inner.type.inner.header.abi" '{"C": {"unwind": true}}'
+// @is "$.index[*][?(@.name=='AbiCUnwind')].inner.typedef.type.function_pointer.header.abi" '{"C": {"unwind": true}}'
 pub type AbiCUnwind = extern "C-unwind" fn();
 
-// @is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.type.inner.header.abi" '{"System": {"unwind": true}}'
+// @is "$.index[*][?(@.name=='AbiSystemUnwind')].inner.typedef.type.function_pointer.header.abi" '{"System": {"unwind": true}}'
 pub type AbiSystemUnwind = extern "system-unwind" fn();
 
-// @is "$.index[*][?(@.name=='AbiVecorcall')].inner.type.inner.header.abi.Other" '"\"vectorcall\""'
+// @is "$.index[*][?(@.name=='AbiVecorcall')].inner.typedef.type.function_pointer.header.abi.Other" '"\"vectorcall\""'
 pub type AbiVecorcall = extern "vectorcall" fn();
 
-// @is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.type.inner.header.abi.Other" '"\"vectorcall-unwind\""'
+// @is "$.index[*][?(@.name=='AbiVecorcallUnwind')].inner.typedef.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""'
 pub type AbiVecorcallUnwind = extern "vectorcall-unwind" fn();
diff --git a/tests/rustdoc-json/fn_pointer/generics.rs b/tests/rustdoc-json/fn_pointer/generics.rs
index a93b01ac2c4..48672f12da1 100644
--- a/tests/rustdoc-json/fn_pointer/generics.rs
+++ b/tests/rustdoc-json/fn_pointer/generics.rs
@@ -3,12 +3,11 @@
 #![feature(no_core)]
 #![no_core]
 
-// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][0]" '"val"'
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.inputs[0][1].inner.lifetime" \"\'c\"
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.decl.output" '{ "kind": "primitive", "inner": "i32" }'
-// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[*]" 1
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].name" \"\'c\"
-// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.type.inner.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.inputs[*]" 1
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.inputs[0][0]" '"val"'
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.inputs[0][1].borrowed_ref.lifetime" \"\'c\"
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.decl.output.primitive" \"i32\"
+// @count "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.generic_params[*]" 1
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.generic_params[0].name" \"\'c\"
+// @is "$.index[*][?(@.name=='WithHigherRankTraitBounds')].inner.typedef.type.function_pointer.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
 pub type WithHigherRankTraitBounds = for<'c> fn(val: &'c i32) -> i32;
diff --git a/tests/rustdoc-json/fn_pointer/qualifiers.rs b/tests/rustdoc-json/fn_pointer/qualifiers.rs
index bd65bb3eefe..0ab776c21ed 100644
--- a/tests/rustdoc-json/fn_pointer/qualifiers.rs
+++ b/tests/rustdoc-json/fn_pointer/qualifiers.rs
@@ -1,9 +1,11 @@
-// @is "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.unsafe" false
-// @is "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.const" false
-// @is "$.index[*][?(@.name=='FnPointer')].inner.type.inner.header.async" false
+// ignore-tidy-linelength
+
+// @is "$.index[*][?(@.name=='FnPointer')].inner.typedef.type.function_pointer.header.unsafe" false
+// @is "$.index[*][?(@.name=='FnPointer')].inner.typedef.type.function_pointer.header.const" false
+// @is "$.index[*][?(@.name=='FnPointer')].inner.typedef.type.function_pointer.header.async" false
 pub type FnPointer = fn();
 
-// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.unsafe" true
-// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.const" false
-// @is "$.index[*][?(@.name=='UnsafePointer')].inner.type.inner.header.async" false
+// @is "$.index[*][?(@.name=='UnsafePointer')].inner.typedef.type.function_pointer.header.unsafe" true
+// @is "$.index[*][?(@.name=='UnsafePointer')].inner.typedef.type.function_pointer.header.const" false
+// @is "$.index[*][?(@.name=='UnsafePointer')].inner.typedef.type.function_pointer.header.async" false
 pub type UnsafePointer = unsafe fn();
diff --git a/tests/rustdoc-json/fns/abi.rs b/tests/rustdoc-json/fns/abi.rs
index 7a5dbee730c..d7b98b5924b 100644
--- a/tests/rustdoc-json/fns/abi.rs
+++ b/tests/rustdoc-json/fns/abi.rs
@@ -2,23 +2,23 @@
 
 #![feature(abi_vectorcall)]
 
-// @is "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\"
+// @is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\"
 pub fn abi_rust() {}
 
-// @is "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
+// @is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
 pub extern "C" fn abi_c() {}
 
-// @is "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
+// @is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
 pub extern "system" fn abi_system() {}
 
-// @is "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
+// @is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
 pub extern "C-unwind" fn abi_c_unwind() {}
 
-// @is "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
+// @is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
 pub extern "system-unwind" fn abi_system_unwind() {}
 
-// @is "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
+// @is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
 pub extern "vectorcall" fn abi_vectorcall() {}
 
-// @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
+// @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
 pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs
index b89781ca92d..8192f2e6ae6 100644
--- a/tests/rustdoc-json/fns/async_return.rs
+++ b/tests/rustdoc-json/fns/async_return.rs
@@ -5,32 +5,30 @@
 
 use std::future::Future;
 
-// @is "$.index[*][?(@.name=='get_int')].inner.decl.output" '{"inner": "i32", "kind": "primitive"}'
-// @is "$.index[*][?(@.name=='get_int')].inner.header.async" false
+// @is "$.index[*][?(@.name=='get_int')].inner.function.decl.output.primitive" \"i32\"
+// @is "$.index[*][?(@.name=='get_int')].inner.function.header.async" false
 pub fn get_int() -> i32 {
     42
 }
 
-// @is "$.index[*][?(@.name=='get_int_async')].inner.decl.output" '{"inner": "i32", "kind": "primitive"}'
-// @is "$.index[*][?(@.name=='get_int_async')].inner.header.async" true
+// @is "$.index[*][?(@.name=='get_int_async')].inner.function.decl.output.primitive" \"i32\"
+// @is "$.index[*][?(@.name=='get_int_async')].inner.function.header.async" true
 pub async fn get_int_async() -> i32 {
     42
 }
 
-// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.kind" '"impl_trait"'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.name" '"Future"'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type" '{"inner": "i32", "kind": "primitive"}'
-// @is "$.index[*][?(@.name=='get_int_future')].inner.header.async" false
+// @is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+// @is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
+// @is "$.index[*][?(@.name=='get_int_future')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive"  \"i32\"
+// @is "$.index[*][?(@.name=='get_int_future')].inner.function.header.async" false
 pub fn get_int_future() -> impl Future<Output = i32> {
     async { 42 }
 }
 
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.kind" '"impl_trait"'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.name" '"Future"'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.decl.output.inner[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type" '{"inner": "i32", "kind": "primitive"}'
-// @is "$.index[*][?(@.name=='get_int_future_async')].inner.header.async" true
+// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.name" '"Future"'
+// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].name" '"Output"'
+// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.decl.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.bindings[0].binding.equality.type.primitive" \"i32\"
+// @is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.async" true
 pub async fn get_int_future_async() -> impl Future<Output = i32> {
     async { 42 }
 }
diff --git a/tests/rustdoc-json/fns/extern_c_variadic.rs b/tests/rustdoc-json/fns/extern_c_variadic.rs
index 33bebbab5e0..d6ea343b991 100644
--- a/tests/rustdoc-json/fns/extern_c_variadic.rs
+++ b/tests/rustdoc-json/fns/extern_c_variadic.rs
@@ -2,8 +2,8 @@
 #![no_core]
 
 extern "C" {
-    // @is "$.index[*][?(@.name == 'not_variadic')].inner.decl.c_variadic" false
+    // @is "$.index[*][?(@.name == 'not_variadic')].inner.function.decl.c_variadic" false
     pub fn not_variadic(_: i32);
-    // @is "$.index[*][?(@.name == 'variadic')].inner.decl.c_variadic" true
+    // @is "$.index[*][?(@.name == 'variadic')].inner.function.decl.c_variadic" true
     pub fn variadic(_: i32, ...);
 }
diff --git a/tests/rustdoc-json/fns/generic_args.rs b/tests/rustdoc-json/fns/generic_args.rs
index eec295efec0..539d17f831e 100644
--- a/tests/rustdoc-json/fns/generic_args.rs
+++ b/tests/rustdoc-json/fns/generic_args.rs
@@ -9,59 +9,55 @@ pub trait Foo {}
 // @set generic_foo = "$.index[*][?(@.name=='GenericFoo')].id"
 pub trait GenericFoo<'a> {}
 
-// @is "$.index[*][?(@.name=='generics')].inner.generics.where_predicates" "[]"
-// @count "$.index[*][?(@.name=='generics')].inner.generics.params[*]" 1
-// @is "$.index[*][?(@.name=='generics')].inner.generics.params[0].name" '"F"'
-// @is "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.default" 'null'
-// @count "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[*]" 1
-// @is "$.index[*][?(@.name=='generics')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
-// @count "$.index[*][?(@.name=='generics')].inner.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][0]" '"f"'
-// @is "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].kind" '"generic"'
-// @is "$.index[*][?(@.name=='generics')].inner.decl.inputs[0][1].inner" '"F"'
+// @is "$.index[*][?(@.name=='generics')].inner.function.generics.where_predicates" "[]"
+// @count "$.index[*][?(@.name=='generics')].inner.function.generics.params[*]" 1
+// @is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].name" '"F"'
+// @is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.default" 'null'
+// @count "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[*]" 1
+// @is "$.index[*][?(@.name=='generics')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" '$foo'
+// @count "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[*]" 1
+// @is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][0]" '"f"'
+// @is "$.index[*][?(@.name=='generics')].inner.function.decl.inputs[0][1].generic" '"F"'
 pub fn generics<F: Foo>(f: F) {}
 
-// @is "$.index[*][?(@.name=='impl_trait')].inner.generics.where_predicates" "[]"
-// @count "$.index[*][?(@.name=='impl_trait')].inner.generics.params[*]" 1
-// @is "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].name" '"impl Foo"'
-// @is "$.index[*][?(@.name=='impl_trait')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
-// @count "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[*]" 1
-// @is "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][0]" '"f"'
-// @is "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].kind" '"impl_trait"'
-// @count "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[*]" 1
-// @is "$.index[*][?(@.name=='impl_trait')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $foo
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.where_predicates" "[]"
+// @count "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[*]" 1
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].name" '"impl Foo"'
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $foo
+// @count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[*]" 1
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][0]" '"f"'
+// @count "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[*]" 1
+// @is "$.index[*][?(@.name=='impl_trait')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $foo
 pub fn impl_trait(f: impl Foo) {}
 
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.params[*]" 3
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].name" '"F"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
-// @count "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[*]" 3
-// @is "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][0]" '"f"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].kind" '"generic"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.decl.inputs[0][1].inner" '"F"'
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[*]" 3
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[*]" 3
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].name" '"F"'
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.params[0].kind" '{"type": {"bounds": [], "default": null, "synthetic": false}}'
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[*]" 3
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][0]" '"f"'
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.decl.inputs[0][1].generic" '"F"'
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[*]" 3
 
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F", "kind": "generic"}'
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.type.generic" \"F\"
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[0].bound_predicate.bounds[0].trait_bound.trait.id" $foo
 
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.type" '{"inner": "G", "kind": "generic"}'
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[1].bound_predicate.generic_params" "[]"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.type.generic" \"G\"
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.trait.id" $generic_foo
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].name" \"\'a\"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.bounds[0].trait_bound.generic_params[0].kind.lifetime.outlives" "[]"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[1].bound_predicate.generic_params" "[]"
 
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.lifetime" \"\'b\"
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.type.inner.type" '{"inner": "H", "kind": "generic"}'
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
-// @count "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
-// @is "$.index[*][?(@.name=='where_clase')].inner.generics.where_predicates[2].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.lifetime" \"\'b\"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.type.borrowed_ref.type.generic" \"H\"
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.trait.id" $foo
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.bounds[0].trait_bound.generic_params" "[]"
+// @count "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[*]" 1
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].name" \"\'b\"
+// @is "$.index[*][?(@.name=='where_clase')].inner.function.generics.where_predicates[2].bound_predicate.generic_params[0].kind.lifetime.outlives" "[]"
 pub fn where_clase<F, G, H>(f: F, g: G, h: H)
 where
     F: Foo,
diff --git a/tests/rustdoc-json/fns/generic_returns.rs b/tests/rustdoc-json/fns/generic_returns.rs
index a9bc2d5d727..27d842066f4 100644
--- a/tests/rustdoc-json/fns/generic_returns.rs
+++ b/tests/rustdoc-json/fns/generic_returns.rs
@@ -3,15 +3,14 @@
 #![feature(no_core)]
 #![no_core]
 
-// @count "$.index[*][?(@.name=='generic_returns')].inner.items[*]" 2
+// @count "$.index[*][?(@.name=='generic_returns')].inner.module.items[*]" 2
 
 // @set foo = "$.index[*][?(@.name=='Foo')].id"
 pub trait Foo {}
 
-// @is "$.index[*][?(@.name=='get_foo')].inner.decl.inputs" []
-// @is "$.index[*][?(@.name=='get_foo')].inner.decl.output.kind" '"impl_trait"'
-// @count "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[*]" 1
-// @is "$.index[*][?(@.name=='get_foo')].inner.decl.output.inner[0].trait_bound.trait.id" $foo
+// @is "$.index[*][?(@.name=='get_foo')].inner.function.decl.inputs" []
+// @count "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[*]" 1
+// @is "$.index[*][?(@.name=='get_foo')].inner.function.decl.output.impl_trait[0].trait_bound.trait.id" $foo
 pub fn get_foo() -> impl Foo {
     Fooer {}
 }
diff --git a/tests/rustdoc-json/fns/generics.rs b/tests/rustdoc-json/fns/generics.rs
index 7b70ff1df6b..5239a6f21f5 100644
--- a/tests/rustdoc-json/fns/generics.rs
+++ b/tests/rustdoc-json/fns/generics.rs
@@ -6,21 +6,20 @@
 // @set wham_id = "$.index[*][?(@.name=='Wham')].id"
 pub trait Wham {}
 
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.where_predicates" []
-// @count "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[*]" 1
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].name" '"T"'
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" false
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.decl.inputs" '[["w", {"inner": "T", "kind": "generic"}]]'
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.where_predicates" []
+// @count "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[*]" 1
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].name" '"T"'
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" false
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
+// @is    "$.index[*][?(@.name=='one_generic_param_fn')].inner.function.decl.inputs" '[["w", {"generic": "T"}]]'
 pub fn one_generic_param_fn<T: Wham>(w: T) {}
 
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.where_predicates" []
-// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[*]" 1
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].name" '"impl Wham"'
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.synthetic" true
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
-// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[*]" 1
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][0]" '"w"'
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].kind" '"impl_trait"'
-// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $wham_id
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.where_predicates" []
+// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[*]" 1
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].name" '"impl Wham"'
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.synthetic" true
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $wham_id
+// @count "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[*]" 1
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][0]" '"w"'
+// @is    "$.index[*][?(@.name=='one_synthetic_generic_param_fn')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $wham_id
 pub fn one_synthetic_generic_param_fn(w: impl Wham) {}
diff --git a/tests/rustdoc-json/fns/pattern_arg.rs b/tests/rustdoc-json/fns/pattern_arg.rs
index 32b7da0fae4..55f24797ac0 100644
--- a/tests/rustdoc-json/fns/pattern_arg.rs
+++ b/tests/rustdoc-json/fns/pattern_arg.rs
@@ -1,7 +1,7 @@
-// @is "$.index[*][?(@.name=='fst')].inner.decl.inputs[0][0]" '"(x, _)"'
+// @is "$.index[*][?(@.name=='fst')].inner.function.decl.inputs[0][0]" '"(x, _)"'
 pub fn fst<X, Y>((x, _): (X, Y)) -> X {
     x
 }
 
-// @is "$.index[*][?(@.name=='drop_int')].inner.decl.inputs[0][0]" '"_"'
+// @is "$.index[*][?(@.name=='drop_int')].inner.function.decl.inputs[0][0]" '"_"'
 pub fn drop_int(_: i32) {}
diff --git a/tests/rustdoc-json/fns/qualifiers.rs b/tests/rustdoc-json/fns/qualifiers.rs
index 7ff54290042..643865a3f07 100644
--- a/tests/rustdoc-json/fns/qualifiers.rs
+++ b/tests/rustdoc-json/fns/qualifiers.rs
@@ -1,33 +1,33 @@
 // edition:2018
 
-// @is "$.index[*][?(@.name=='nothing_fn')].inner.header.async" false
-// @is "$.index[*][?(@.name=='nothing_fn')].inner.header.const"  false
-// @is "$.index[*][?(@.name=='nothing_fn')].inner.header.unsafe" false
+// @is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.async" false
+// @is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.const"  false
+// @is "$.index[*][?(@.name=='nothing_fn')].inner.function.header.unsafe" false
 pub fn nothing_fn() {}
 
-// @is "$.index[*][?(@.name=='unsafe_fn')].inner.header.async"  false
-// @is "$.index[*][?(@.name=='unsafe_fn')].inner.header.const"  false
-// @is "$.index[*][?(@.name=='unsafe_fn')].inner.header.unsafe" true
+// @is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.async"  false
+// @is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.const"  false
+// @is "$.index[*][?(@.name=='unsafe_fn')].inner.function.header.unsafe" true
 pub unsafe fn unsafe_fn() {}
 
-// @is "$.index[*][?(@.name=='const_fn')].inner.header.async"  false
-// @is "$.index[*][?(@.name=='const_fn')].inner.header.const"  true
-// @is "$.index[*][?(@.name=='const_fn')].inner.header.unsafe" false
+// @is "$.index[*][?(@.name=='const_fn')].inner.function.header.async"  false
+// @is "$.index[*][?(@.name=='const_fn')].inner.function.header.const"  true
+// @is "$.index[*][?(@.name=='const_fn')].inner.function.header.unsafe" false
 pub const fn const_fn() {}
 
-// @is "$.index[*][?(@.name=='async_fn')].inner.header.async"  true
-// @is "$.index[*][?(@.name=='async_fn')].inner.header.const"  false
-// @is "$.index[*][?(@.name=='async_fn')].inner.header.unsafe" false
+// @is "$.index[*][?(@.name=='async_fn')].inner.function.header.async"  true
+// @is "$.index[*][?(@.name=='async_fn')].inner.function.header.const"  false
+// @is "$.index[*][?(@.name=='async_fn')].inner.function.header.unsafe" false
 pub async fn async_fn() {}
 
-// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.async"  true
-// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.const"  false
-// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.header.unsafe" true
+// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.async"  true
+// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.const"  false
+// @is "$.index[*][?(@.name=='async_unsafe_fn')].inner.function.header.unsafe" true
 pub async unsafe fn async_unsafe_fn() {}
 
-// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.async"  false
-// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.const"  true
-// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.header.unsafe" true
+// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.async"  false
+// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.const"  true
+// @is "$.index[*][?(@.name=='const_unsafe_fn')].inner.function.header.unsafe" true
 pub const unsafe fn const_unsafe_fn() {}
 
 // It's impossible for a function to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/fns/return_type_alias.rs b/tests/rustdoc-json/fns/return_type_alias.rs
index 2578bb49ad3..e8a7dce8b0a 100644
--- a/tests/rustdoc-json/fns/return_type_alias.rs
+++ b/tests/rustdoc-json/fns/return_type_alias.rs
@@ -3,8 +3,7 @@
 /// @set foo = "$.index[*][?(@.name=='Foo')].id"
 pub type Foo = i32;
 
-// @is "$.index[*][?(@.name=='demo')].inner.decl.output.kind" '"resolved_path"'
-// @is "$.index[*][?(@.name=='demo')].inner.decl.output.inner.id" $foo
+// @is "$.index[*][?(@.name=='demo')].inner.function.decl.output.resolved_path.id" $foo
 pub fn demo() -> Foo {
     42
 }
diff --git a/tests/rustdoc-json/generic-associated-types/gats.rs b/tests/rustdoc-json/generic-associated-types/gats.rs
index e5809783aec..99c57ff6540 100644
--- a/tests/rustdoc-json/generic-associated-types/gats.rs
+++ b/tests/rustdoc-json/generic-associated-types/gats.rs
@@ -9,34 +9,32 @@ pub trait Sized {}
 pub trait Display {}
 
 pub trait LendingIterator {
-    // @count "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*]" 1
-    // @is "$.index[*][?(@.name=='LendingItem')].inner.generics.params[*].name" \"\'a\"
-    // @count "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*]" 1
-    // @is "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.type.inner" \"Self\"
-    // @is "$.index[*][?(@.name=='LendingItem')].inner.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\"
-    // @count "$.index[*][?(@.name=='LendingItem')].inner.bounds[*]" 1
+    // @count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*]" 1
+    // @is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.params[*].name" \"\'a\"
+    // @count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*]" 1
+    // @is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.type.generic" \"Self\"
+    // @is "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.generics.where_predicates[*].bound_predicate.bounds[*].outlives" \"\'a\"
+    // @count "$.index[*][?(@.name=='LendingItem')].inner.assoc_type.bounds[*]" 1
     type LendingItem<'a>: Display
     where
         Self: 'a;
 
-    // @is "$.index[*][?(@.name=='lending_next')].inner.decl.output.kind" \"qualified_path\"
-    // @count "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 1
-    // @count "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0
-    // @is "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.self_type.inner" \"Self\"
-    // @is "$.index[*][?(@.name=='lending_next')].inner.decl.output.inner.name" \"LendingItem\"
+    // @count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 1
+    // @count "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    // @is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
+    // @is "$.index[*][?(@.name=='lending_next')].inner.function.decl.output.qualified_path.name" \"LendingItem\"
     fn lending_next<'a>(&'a self) -> Self::LendingItem<'a>;
 }
 
 pub trait Iterator {
-    // @count "$.index[*][?(@.name=='Item')].inner.generics.params[*]" 0
-    // @count "$.index[*][?(@.name=='Item')].inner.generics.where_predicates[*]" 0
-    // @count "$.index[*][?(@.name=='Item')].inner.bounds[*]" 1
+    // @count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.params[*]" 0
+    // @count "$.index[*][?(@.name=='Item')].inner.assoc_type.generics.where_predicates[*]" 0
+    // @count "$.index[*][?(@.name=='Item')].inner.assoc_type.bounds[*]" 1
     type Item: Display;
 
-    // @is "$.index[*][?(@.name=='next')].inner.decl.output.kind" \"qualified_path\"
-    // @count "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.args[*]" 0
-    // @count "$.index[*][?(@.name=='next')].inner.decl.output.inner.args.angle_bracketed.bindings[*]" 0
-    // @is "$.index[*][?(@.name=='next')].inner.decl.output.inner.self_type.inner" \"Self\"
-    // @is "$.index[*][?(@.name=='next')].inner.decl.output.inner.name" \"Item\"
+    // @count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.args[*]" 0
+    // @count "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.args.angle_bracketed.bindings[*]" 0
+    // @is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.self_type.generic" \"Self\"
+    // @is "$.index[*][?(@.name=='next')].inner.function.decl.output.qualified_path.name" \"Item\"
     fn next<'a>(&'a self) -> Self::Item;
 }
diff --git a/tests/rustdoc-json/glob_import.rs b/tests/rustdoc-json/glob_import.rs
index 00051b12199..f37ce0abb41 100644
--- a/tests/rustdoc-json/glob_import.rs
+++ b/tests/rustdoc-json/glob_import.rs
@@ -5,7 +5,7 @@
 #![no_core]
 
 // @has "$.index[*][?(@.name=='glob')]"
-// @has "$.index[*][?(@.kind=='import')].inner.name" \"*\"
+// @has "$.index[*][?(@.inner.import)].inner.import.name" \"*\"
 
 
 mod m1 {
diff --git a/tests/rustdoc-json/impls/auto.rs b/tests/rustdoc-json/impls/auto.rs
index 50d85241427..ace37e5b3df 100644
--- a/tests/rustdoc-json/impls/auto.rs
+++ b/tests/rustdoc-json/impls/auto.rs
@@ -12,7 +12,8 @@ impl Foo {
 }
 
 // Testing spans, so all tests below code
-// @is "$.index[*][?(@.kind=='impl' && @.inner.synthetic==true)].span" null
 // @is "$.index[*][?(@.docs=='has span')].span.begin" "[10, 0]"
 // @is "$.index[*][?(@.docs=='has span')].span.end" "[12, 1]"
+// FIXME: this doesn't work due to https://github.com/freestrings/jsonpath/issues/91
+// is "$.index[*][?(@.inner.impl.synthetic==true)].span" null
 pub struct Foo;
diff --git a/tests/rustdoc-json/impls/foreign_for_local.rs b/tests/rustdoc-json/impls/foreign_for_local.rs
index 290c2d571e8..20e1cecd778 100644
--- a/tests/rustdoc-json/impls/foreign_for_local.rs
+++ b/tests/rustdoc-json/impls/foreign_for_local.rs
@@ -3,7 +3,7 @@ extern crate foreign_trait;
 
 /// ForeignTrait id hack
 pub use foreign_trait::ForeignTrait as _;
-// @set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.id"
+// @set ForeignTrait = "$.index[*][?(@.docs=='ForeignTrait id hack')].inner.import.id"
 
 pub struct LocalStruct;
 // @set LocalStruct = "$.index[*][?(@.name=='LocalStruct')].id"
@@ -12,7 +12,7 @@ pub struct LocalStruct;
 impl foreign_trait::ForeignTrait for LocalStruct {}
 
 // @set impl = "$.index[*][?(@.docs=='foreign for local')].id"
-// @is "$.index[*][?(@.docs=='foreign for local')].inner.for.inner.id" $LocalStruct
-// @is "$.index[*][?(@.docs=='foreign for local')].inner.trait.id" $ForeignTrait
+// @is "$.index[*][?(@.docs=='foreign for local')].inner.impl.for.resolved_path.id" $LocalStruct
+// @is "$.index[*][?(@.docs=='foreign for local')].inner.impl.trait.id" $ForeignTrait
 
-// @has "$.index[*][?(@.name=='LocalStruct')].inner.impls[*]" $impl
+// @has "$.index[*][?(@.name=='LocalStruct')].inner.struct.impls[*]" $impl
diff --git a/tests/rustdoc-json/impls/impl_item_visibility.rs b/tests/rustdoc-json/impls/impl_item_visibility.rs
new file mode 100644
index 00000000000..efa54d91dca
--- /dev/null
+++ b/tests/rustdoc-json/impls/impl_item_visibility.rs
@@ -0,0 +1,26 @@
+#![feature(no_core)]
+#![no_core]
+
+pub struct Foo;
+
+/// impl Foo priv
+impl Foo {
+    fn baz() {}
+}
+// @!has '$.index[*][?(@.docs=="impl Foo priv")]'
+
+
+/// impl Foo pub
+impl Foo {
+    pub fn qux() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+
+
+/// impl Foo hidden
+impl Foo {
+    #[doc(hidden)]
+    pub fn __quazl(){}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs
new file mode 100644
index 00000000000..3c6fefc4ca2
--- /dev/null
+++ b/tests/rustdoc-json/impls/impl_item_visibility_show_hidden.rs
@@ -0,0 +1,28 @@
+// compile-flags: --document-hidden-items
+#![feature(no_core)]
+#![no_core]
+
+pub struct Foo;
+
+/// impl Foo priv
+impl Foo {
+    fn baz() {}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
+
+
+/// impl Foo pub
+impl Foo {
+    pub fn qux() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+
+
+/// impl Foo hidden
+impl Foo {
+    #[doc(hidden)]
+    pub fn __quazl(){}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs
new file mode 100644
index 00000000000..b98d1e4167c
--- /dev/null
+++ b/tests/rustdoc-json/impls/impl_item_visibility_show_private.rs
@@ -0,0 +1,27 @@
+// compile-flags: --document-private-items
+#![feature(no_core)]
+#![no_core]
+
+pub struct Foo;
+
+/// impl Foo priv
+impl Foo {
+    fn baz() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo priv")].visibility' '"default"'
+
+
+/// impl Foo pub
+impl Foo {
+    pub fn qux() {}
+}
+// @is '$.index[*][?(@.docs=="impl Foo pub")].visibility' '"default"'
+
+
+/// impl Foo hidden
+impl Foo {
+    #[doc(hidden)]
+    pub fn __quazl(){}
+}
+// FIXME(#111564): Is this the right behaviour?
+// @is '$.index[*][?(@.docs=="impl Foo hidden")].visibility' '"default"'
diff --git a/tests/rustdoc-json/impls/import_from_private.rs b/tests/rustdoc-json/impls/import_from_private.rs
index fa88b6113a5..d2b0665dcaf 100644
--- a/tests/rustdoc-json/impls/import_from_private.rs
+++ b/tests/rustdoc-json/impls/import_from_private.rs
@@ -4,19 +4,19 @@
 #![no_core]
 
 mod bar {
-    // @set baz = "$.index[*][?(@.kind=='struct')].id"
+    // @set baz = "$.index[*][?(@.inner.struct)].id"
     pub struct Baz;
-    // @set impl = "$.index[*][?(@.kind=='impl')].id"
+    // @set impl = "$.index[*][?(@.inner.impl)].id"
     impl Baz {
-        // @set doit = "$.index[*][?(@.kind=='function')].id"
+        // @set doit = "$.index[*][?(@.inner.function)].id"
         pub fn doit() {}
     }
 }
 
-// @set import = "$.index[*][?(@.kind=='import')].id"
+// @set import = "$.index[*][?(@.inner.import)].id"
 pub use bar::Baz;
 
-// @is "$.index[*][?(@.kind=='module')].inner.items[*]" $import
-// @is "$.index[*][?(@.kind=='import')].inner.id" $baz
-// @is "$.index[*][?(@.kind=='struct')].inner.impls[*]" $impl
-// @is "$.index[*][?(@.kind=='impl')].inner.items[*]" $doit
+// @is "$.index[*].inner.module.items[*]" $import
+// @is "$.index[*].inner.import.id" $baz
+// @is "$.index[*].inner.struct.impls[*]" $impl
+// @is "$.index[*].inner.impl.items[*]" $doit
diff --git a/tests/rustdoc-json/impls/local_for_foreign.rs b/tests/rustdoc-json/impls/local_for_foreign.rs
index 74f2f08b5a4..72352ce88da 100644
--- a/tests/rustdoc-json/impls/local_for_foreign.rs
+++ b/tests/rustdoc-json/impls/local_for_foreign.rs
@@ -3,7 +3,7 @@ extern crate foreign_struct;
 
 /// ForeignStruct id hack
 pub use foreign_struct::ForeignStruct as _;
-// @set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.id"
+// @set ForeignStruct = "$.index[*][?(@.docs=='ForeignStruct id hack')].inner.import.id"
 
 pub trait LocalTrait {}
 // @set LocalTrait = "$.index[*][?(@.name=='LocalTrait')].id"
@@ -12,7 +12,7 @@ pub trait LocalTrait {}
 impl LocalTrait for foreign_struct::ForeignStruct {}
 
 // @set impl = "$.index[*][?(@.docs=='local for foreign')].id"
-// @is "$.index[*][?(@.docs=='local for foreign')].inner.trait.id" $LocalTrait
-// @is "$.index[*][?(@.docs=='local for foreign')].inner.for.inner.id" $ForeignStruct
+// @is "$.index[*][?(@.docs=='local for foreign')].inner.impl.trait.id" $LocalTrait
+// @is "$.index[*][?(@.docs=='local for foreign')].inner.impl.for.resolved_path.id" $ForeignStruct
 
-// @is "$.index[*][?(@.name=='LocalTrait')].inner.implementations[*]" $impl
+// @is "$.index[*][?(@.name=='LocalTrait')].inner.trait.implementations[*]" $impl
diff --git a/tests/rustdoc-json/impls/local_for_local.rs b/tests/rustdoc-json/impls/local_for_local.rs
index 93dedb7ec92..37a72000329 100644
--- a/tests/rustdoc-json/impls/local_for_local.rs
+++ b/tests/rustdoc-json/impls/local_for_local.rs
@@ -9,7 +9,7 @@ pub trait Trait {}
 /// impl
 impl Trait for Struct {}
 
-// @is "$.index[*][?(@.name=='Struct')].inner.impls[*]" $impl
-// @is "$.index[*][?(@.name=='Trait')].inner.implementations[*]" $impl
-// @is "$.index[*][?(@.docs=='impl')].inner.trait.id" $trait
-// @is "$.index[*][?(@.docs=='impl')].inner.for.inner.id" $struct
+// @is "$.index[*][?(@.name=='Struct')].inner.struct.impls[*]" $impl
+// @is "$.index[*][?(@.name=='Trait')].inner.trait.implementations[*]" $impl
+// @is "$.index[*][?(@.docs=='impl')].inner.impl.trait.id" $trait
+// @is "$.index[*][?(@.docs=='impl')].inner.impl.for.resolved_path.id" $struct
diff --git a/tests/rustdoc-json/impls/local_for_local_primitive.rs b/tests/rustdoc-json/impls/local_for_local_primitive.rs
index 8383dcc0482..769dd3f0a2c 100644
--- a/tests/rustdoc-json/impls/local_for_local_primitive.rs
+++ b/tests/rustdoc-json/impls/local_for_local_primitive.rs
@@ -5,14 +5,13 @@
 // @set Local = "$.index[*][?(@.name=='Local')].id"
 pub trait Local {}
 
-// @is "$.index[*][?(@.docs=='Local for bool')].inner.trait.id" $Local
-// @is "$.index[*][?(@.docs=='Local for bool')].inner.for.kind" '"primitive"'
-// @is "$.index[*][?(@.docs=='Local for bool')].inner.for.inner" '"bool"'
+// @is "$.index[*][?(@.docs=='Local for bool')].inner.impl.trait.id" $Local
+// @is "$.index[*][?(@.docs=='Local for bool')].inner.impl.for.primitive" '"bool"'
 /// Local for bool
 impl Local for bool {}
 
 // @set impl =  "$.index[*][?(@.docs=='Local for bool')].id"
-// @is "$.index[*][?(@.name=='Local')].inner.implementations[*]" $impl
+// @is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl
 
 // FIXME(#101695): Test bool's `impls` include "Local for bool"
 // @has "$.index[*][?(@.name=='bool')]"
diff --git a/tests/rustdoc-json/impls/local_for_primitive.rs b/tests/rustdoc-json/impls/local_for_primitive.rs
index 7702a526fd8..85278c0e08c 100644
--- a/tests/rustdoc-json/impls/local_for_primitive.rs
+++ b/tests/rustdoc-json/impls/local_for_primitive.rs
@@ -2,6 +2,6 @@
 pub trait Local {}
 
 // @set impl = "$.index[*][?(@.docs=='local for bool')].id"
-// @is "$.index[*][?(@.name=='Local')].inner.implementations[*]" $impl
+// @is "$.index[*][?(@.name=='Local')].inner.trait.implementations[*]" $impl
 /// local for bool
 impl Local for bool {}
diff --git a/tests/rustdoc-json/lifetime/longest.rs b/tests/rustdoc-json/lifetime/longest.rs
index 326dab8e57a..dc28258a8b6 100644
--- a/tests/rustdoc-json/lifetime/longest.rs
+++ b/tests/rustdoc-json/lifetime/longest.rs
@@ -3,30 +3,27 @@
 #![feature(no_core)]
 #![no_core]
 
-// @is "$.index[*][?(@.name=='longest')].inner.generics.params[0].name"  \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
-// @is "$.index[*][?(@.name=='longest')].inner.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
-// @count "$.index[*][?(@.name=='longest')].inner.generics.params[*]" 1
-// @is "$.index[*][?(@.name=='longest')].inner.generics.where_predicates" []
+// @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].name"  \"\'a\"
+// @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
+// @is "$.index[*][?(@.name=='longest')].inner.function.generics.params[0].kind"  '{"lifetime": {"outlives": []}}'
+// @count "$.index[*][?(@.name=='longest')].inner.function.generics.params[*]" 1
+// @is "$.index[*][?(@.name=='longest')].inner.function.generics.where_predicates" []
 
-// @count "$.index[*][?(@.name=='longest')].inner.decl.inputs[*]" 2
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][0]" '"l"'
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][0]" '"r"'
+// @count "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[*]" 2
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][0]" '"l"'
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][0]" '"r"'
 
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.mutable" false
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[0][1].inner.type" '{"inner": "str", "kind": "primitive"}'
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[0][1].borrowed_ref.type.primitive" \"str\"
 
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.mutable" false
-// @is "$.index[*][?(@.name=='longest')].inner.decl.inputs[1][1].inner.type" '{"inner": "str", "kind": "primitive"}'
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.lifetime" \"\'a\"
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.inputs[1][1].borrowed_ref.type.primitive" \"str\"
 
-// @is "$.index[*][?(@.name=='longest')].inner.decl.output.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='longest')].inner.decl.output.inner.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='longest')].inner.decl.output.inner.mutable" false
-// @is "$.index[*][?(@.name=='longest')].inner.decl.output.inner.type" '{"inner": "str", "kind": "primitive"}'
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.lifetime" \"\'a\"
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='longest')].inner.function.decl.output.borrowed_ref.type.primitive" \"str\"
 
 pub fn longest<'a>(l: &'a str, r: &'a str) -> &'a str {
     if l.len() > r.len() { l } else { r }
diff --git a/tests/rustdoc-json/lifetime/outlives.rs b/tests/rustdoc-json/lifetime/outlives.rs
index e15a533efdc..6e105b382b0 100644
--- a/tests/rustdoc-json/lifetime/outlives.rs
+++ b/tests/rustdoc-json/lifetime/outlives.rs
@@ -3,21 +3,19 @@
 #![feature(no_core)]
 #![no_core]
 
-// @count "$.index[*][?(@.name=='foo')].inner.generics.params[*]" 3
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates" []
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[1].name" \"\'b\"
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[2].name" '"T"'
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[0].kind.lifetime.outlives" []
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[1].kind.lifetime.outlives" [\"\'a\"]
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.default" null
-// @count "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[*]" 1
-// @is "$.index[*][?(@.name=='foo')].inner.generics.params[2].kind.type.bounds[0].outlives" \"\'b\"
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.lifetime" \"\'a\"
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.mutable" false
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.lifetime" \"\'b\"
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.mutable" false
-// @is "$.index[*][?(@.name=='foo')].inner.decl.inputs[0][1].inner.type.inner.type" '{"inner": "T", "kind": "generic"}'
+// @count "$.index[*][?(@.name=='foo')].inner.function.generics.params[*]" 3
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates" []
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].name" \"\'a\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].name" \"\'b\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].name" '"T"'
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[0].kind.lifetime.outlives" []
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[1].kind.lifetime.outlives" [\"\'a\"]
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.default" null
+// @count "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[*]" 1
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.params[2].kind.type.bounds[0].outlives" \"\'b\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.lifetime" \"\'a\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.lifetime" \"\'b\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.mutable" false
+// @is "$.index[*][?(@.name=='foo')].inner.function.decl.inputs[0][1].borrowed_ref.type.borrowed_ref.type.generic" \"T\"
 pub fn foo<'a, 'b: 'a, T: 'b>(_: &'a &'b T) {}
diff --git a/tests/rustdoc-json/methods/abi.rs b/tests/rustdoc-json/methods/abi.rs
index fd03d92d65b..b8279298c1e 100644
--- a/tests/rustdoc-json/methods/abi.rs
+++ b/tests/rustdoc-json/methods/abi.rs
@@ -8,47 +8,47 @@
 pub struct Foo;
 
 impl Foo {
-    // @is "$.index[*][?(@.name=='abi_rust')].inner.header.abi" \"Rust\"
+    // @is "$.index[*][?(@.name=='abi_rust')].inner.function.header.abi" \"Rust\"
     pub fn abi_rust() {}
 
-    // @is "$.index[*][?(@.name=='abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
+    // @is "$.index[*][?(@.name=='abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
     pub extern "C" fn abi_c() {}
 
-    // @is "$.index[*][?(@.name=='abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
+    // @is "$.index[*][?(@.name=='abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
     pub extern "system" fn abi_system() {}
 
-    // @is "$.index[*][?(@.name=='abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
+    // @is "$.index[*][?(@.name=='abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
     pub extern "C-unwind" fn abi_c_unwind() {}
 
-    // @is "$.index[*][?(@.name=='abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
+    // @is "$.index[*][?(@.name=='abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
     pub extern "system-unwind" fn abi_system_unwind() {}
 
-    // @is "$.index[*][?(@.name=='abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
+    // @is "$.index[*][?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
     pub extern "vectorcall" fn abi_vectorcall() {}
 
-    // @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
+    // @is "$.index[*][?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
     pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {}
 }
 
 pub trait Bar {
-    // @is "$.index[*][?(@.name=='trait_abi_rust')].inner.header.abi" \"Rust\"
+    // @is "$.index[*][?(@.name=='trait_abi_rust')].inner.function.header.abi" \"Rust\"
     fn trait_abi_rust() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_c')].inner.header.abi" '{"C": {"unwind": false}}'
+    // @is "$.index[*][?(@.name=='trait_abi_c')].inner.function.header.abi" '{"C": {"unwind": false}}'
     extern "C" fn trait_abi_c() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_system')].inner.header.abi" '{"System": {"unwind": false}}'
+    // @is "$.index[*][?(@.name=='trait_abi_system')].inner.function.header.abi" '{"System": {"unwind": false}}'
     extern "system" fn trait_abi_system() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.header.abi" '{"C": {"unwind": true}}'
+    // @is "$.index[*][?(@.name=='trait_abi_c_unwind')].inner.function.header.abi" '{"C": {"unwind": true}}'
     extern "C-unwind" fn trait_abi_c_unwind() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.header.abi" '{"System": {"unwind": true}}'
+    // @is "$.index[*][?(@.name=='trait_abi_system_unwind')].inner.function.header.abi" '{"System": {"unwind": true}}'
     extern "system-unwind" fn trait_abi_system_unwind() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.header.abi.Other" '"\"vectorcall\""'
+    // @is "$.index[*][?(@.name=='trait_abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""'
     extern "vectorcall" fn trait_abi_vectorcall() {}
 
-    // @is "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.header.abi.Other" '"\"vectorcall-unwind\""'
+    // @is "$.index[*][?(@.name=='trait_abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""'
     extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {}
 }
diff --git a/tests/rustdoc-json/methods/qualifiers.rs b/tests/rustdoc-json/methods/qualifiers.rs
index b9a5e56012e..65977bc826f 100644
--- a/tests/rustdoc-json/methods/qualifiers.rs
+++ b/tests/rustdoc-json/methods/qualifiers.rs
@@ -3,34 +3,34 @@
 pub struct Foo;
 
 impl Foo {
-    // @is "$.index[*][?(@.name=='const_meth')].inner.header.async" false
-    // @is "$.index[*][?(@.name=='const_meth')].inner.header.const"  true
-    // @is "$.index[*][?(@.name=='const_meth')].inner.header.unsafe" false
+    // @is "$.index[*][?(@.name=='const_meth')].inner.function.header.async" false
+    // @is "$.index[*][?(@.name=='const_meth')].inner.function.header.const"  true
+    // @is "$.index[*][?(@.name=='const_meth')].inner.function.header.unsafe" false
     pub const fn const_meth() {}
 
-    // @is "$.index[*][?(@.name=='nothing_meth')].inner.header.async"  false
-    // @is "$.index[*][?(@.name=='nothing_meth')].inner.header.const"  false
-    // @is "$.index[*][?(@.name=='nothing_meth')].inner.header.unsafe" false
+    // @is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.async"  false
+    // @is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.const"  false
+    // @is "$.index[*][?(@.name=='nothing_meth')].inner.function.header.unsafe" false
     pub fn nothing_meth() {}
 
-    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.header.async"  false
-    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.header.const"  false
-    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.header.unsafe" true
+    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.async"  false
+    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.const"  false
+    // @is "$.index[*][?(@.name=='unsafe_meth')].inner.function.header.unsafe" true
     pub unsafe fn unsafe_meth() {}
 
-    // @is "$.index[*][?(@.name=='async_meth')].inner.header.async"  true
-    // @is "$.index[*][?(@.name=='async_meth')].inner.header.const"  false
-    // @is "$.index[*][?(@.name=='async_meth')].inner.header.unsafe" false
+    // @is "$.index[*][?(@.name=='async_meth')].inner.function.header.async"  true
+    // @is "$.index[*][?(@.name=='async_meth')].inner.function.header.const"  false
+    // @is "$.index[*][?(@.name=='async_meth')].inner.function.header.unsafe" false
     pub async fn async_meth() {}
 
-    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.async"  true
-    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.const"  false
-    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.header.unsafe" true
+    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.async"  true
+    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.const"  false
+    // @is "$.index[*][?(@.name=='async_unsafe_meth')].inner.function.header.unsafe" true
     pub async unsafe fn async_unsafe_meth() {}
 
-    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.async"  false
-    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.const"  true
-    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.header.unsafe" true
+    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.async"  false
+    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.const"  true
+    // @is "$.index[*][?(@.name=='const_unsafe_meth')].inner.function.header.unsafe" true
     pub const unsafe fn const_unsafe_meth() {}
 
     // It's impossible for a method to be both const and async, so no test for that
diff --git a/tests/rustdoc-json/nested.rs b/tests/rustdoc-json/nested.rs
index ee2d2efa960..e012cfc5014 100644
--- a/tests/rustdoc-json/nested.rs
+++ b/tests/rustdoc-json/nested.rs
@@ -2,30 +2,31 @@
 // compile-flags: --crate-version 1.0.0
 
 // @is "$.crate_version" \"1.0.0\"
-// @is "$.index[*][?(@.name=='nested')].kind" \"module\"
-// @is "$.index[*][?(@.name=='nested')].inner.is_crate" true
+// @has "$.index[*][?(@.name=='nested')].inner.module"
+// @is "$.index[*][?(@.name=='nested')].inner.module.is_crate" true
 
 // @set l1_id = "$.index[*][?(@.name=='l1')].id"
-// @ismany "$.index[*][?(@.name=='nested')].inner.items[*]" $l1_id
+// @ismany "$.index[*][?(@.name=='nested')].inner.module.items[*]" $l1_id
 
-// @is "$.index[*][?(@.name=='l1')].kind" \"module\"
-// @is "$.index[*][?(@.name=='l1')].inner.is_crate" false
+// @has "$.index[*][?(@.name=='l1')].inner.module"
+// @is "$.index[*][?(@.name=='l1')].inner.module.is_crate" false
 pub mod l1 {
-    // @is "$.index[*][?(@.name=='l3')].kind" \"module\"
-    // @is "$.index[*][?(@.name=='l3')].inner.is_crate" false
+    // @has "$.index[*][?(@.name=='l3')].inner.module"
+    // @is "$.index[*][?(@.name=='l3')].inner.module.is_crate" false
     // @set l3_id = "$.index[*][?(@.name=='l3')].id"
     pub mod l3 {
 
-        // @is "$.index[*][?(@.name=='L4')].kind" \"struct\"
-        // @is "$.index[*][?(@.name=='L4')].inner.kind" \"unit\"
+        // @has "$.index[*][?(@.name=='L4')].inner.struct"
+        // @is "$.index[*][?(@.name=='L4')].inner.struct.kind" '"unit"'
         // @set l4_id = "$.index[*][?(@.name=='L4')].id"
-        // @ismany "$.index[*][?(@.name=='l3')].inner.items[*]" $l4_id
+        // @ismany "$.index[*][?(@.name=='l3')].inner.module.items[*]" $l4_id
         pub struct L4;
     }
-    // @is "$.index[*][?(@.inner.source=='l3::L4')].kind" \"import\"
-    // @is "$.index[*][?(@.inner.source=='l3::L4')].inner.glob" false
-    // @is "$.index[*][?(@.inner.source=='l3::L4')].inner.id" $l4_id
-    // @set l4_use_id = "$.index[*][?(@.inner.source=='l3::L4')].id"
+    // @is "$.index[*][?(@.inner.import)].inner.import.glob" false
+    // @is "$.index[*][?(@.inner.import)].inner.import.source" '"l3::L4"'
+    // @is "$.index[*][?(@.inner.import)].inner.import.glob" false
+    // @is "$.index[*][?(@.inner.import)].inner.import.id" $l4_id
+    // @set l4_use_id = "$.index[*][?(@.inner.import)].id"
     pub use l3::L4;
 }
-// @ismany "$.index[*][?(@.name=='l1')].inner.items[*]" $l3_id $l4_use_id
+// @ismany "$.index[*][?(@.name=='l1')].inner.module.items[*]" $l3_id $l4_use_id
diff --git a/tests/rustdoc-json/non_lifetime_binders.rs b/tests/rustdoc-json/non_lifetime_binders.rs
index ca5a008344a..cabee0b1caa 100644
--- a/tests/rustdoc-json/non_lifetime_binders.rs
+++ b/tests/rustdoc-json/non_lifetime_binders.rs
@@ -16,9 +16,9 @@ struct PhantomData<T_>;
 
 pub struct Wrapper<T_>(PhantomData<T_>);
 
-// @count "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[*]" 2
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\"
-// @is "$.index[*][?(@.name=='foo')].inner.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }'
+// @count "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[*]" 2
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].name" \"\'a\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[0].kind" '{ "lifetime": { "outlives": [] } }'
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].name" \"T\"
+// @is "$.index[*][?(@.name=='foo')].inner.function.generics.where_predicates[0].bound_predicate.generic_params[1].kind" '{ "type": { "bounds": [], "default": null, "synthetic": false } }'
 pub fn foo() where for<'a, T> &'a Wrapper<T>: Trait {}
diff --git a/tests/rustdoc-json/primitives/local_primitive.rs b/tests/rustdoc-json/primitives/local_primitive.rs
index 0cf479faf29..562c7e4d79b 100644
--- a/tests/rustdoc-json/primitives/local_primitive.rs
+++ b/tests/rustdoc-json/primitives/local_primitive.rs
@@ -14,7 +14,7 @@ mod prim_i32 {}
 // @set local_i32 = "$.index[*][?(@.name=='i32')].id"
 
 // @has "$.index[*][?(@.name=='local_primitive')]"
-// @ismany "$.index[*][?(@.name=='local_primitive')].inner.items[*]" $local_i32
+// @ismany "$.index[*][?(@.name=='local_primitive')].inner.module.items[*]" $local_i32
 // @is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32
 
 // Let's ensure the `prim_i32` module isn't present in the output JSON:
diff --git a/tests/rustdoc-json/primitives/primitive_impls.rs b/tests/rustdoc-json/primitives/primitive_impls.rs
index 85d179ee45f..4b7b7646b89 100644
--- a/tests/rustdoc-json/primitives/primitive_impls.rs
+++ b/tests/rustdoc-json/primitives/primitive_impls.rs
@@ -15,7 +15,7 @@ impl i32 {
         self
     }
 
-    // @is "$.index[*][?(@.docs=='Only core can do this')].inner.items[*]" $identity
+    // @is "$.index[*][?(@.docs=='Only core can do this')].inner.impl.items[*]" $identity
 }
 
 // @set Trait = "$.index[*][?(@.name=='Trait')].id"
@@ -30,5 +30,5 @@ mod prim_i32 {}
 
 // @set i32 = "$.index[*][?(@.docs=='i32')].id"
 // @is "$.index[*][?(@.docs=='i32')].name" '"i32"'
-// @is "$.index[*][?(@.docs=='i32')].inner.name" '"i32"'
-// @ismany "$.index[*][?(@.docs=='i32')].inner.impls[*]" $impl_i32 $impl_trait_for_i32
+// @is "$.index[*][?(@.docs=='i32')].inner.primitive.name" '"i32"'
+// @ismany "$.index[*][?(@.docs=='i32')].inner.primitive.impls[*]" $impl_i32 $impl_trait_for_i32
diff --git a/tests/rustdoc-json/primitives/primitive_type.rs b/tests/rustdoc-json/primitives/primitive_type.rs
index 8024044bc05..5f251b3b890 100644
--- a/tests/rustdoc-json/primitives/primitive_type.rs
+++ b/tests/rustdoc-json/primitives/primitive_type.rs
@@ -1,22 +1,17 @@
 #![feature(never_type)]
 
 // @is "$.index[*][?(@.name=='PrimNever')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='PrimNever')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimNever')].inner.type.inner" \"never\"
+// @is "$.index[*][?(@.name=='PrimNever')].inner.typedef.type.primitive" \"never\"
 pub type PrimNever = !;
 
-// @is "$.index[*][?(@.name=='PrimStr')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimStr')].inner.type.inner" \"str\"
+// @is "$.index[*][?(@.name=='PrimStr')].inner.typedef.type.primitive" \"str\"
 pub type PrimStr = str;
 
-// @is "$.index[*][?(@.name=='PrimBool')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimBool')].inner.type.inner" \"bool\"
+// @is "$.index[*][?(@.name=='PrimBool')].inner.typedef.type.primitive" \"bool\"
 pub type PrimBool = bool;
 
-// @is "$.index[*][?(@.name=='PrimChar')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimChar')].inner.type.inner" \"char\"
+// @is "$.index[*][?(@.name=='PrimChar')].inner.typedef.type.primitive" \"char\"
 pub type PrimChar = char;
 
-// @is "$.index[*][?(@.name=='PrimU8')].inner.type.kind" \"primitive\"
-// @is "$.index[*][?(@.name=='PrimU8')].inner.type.inner" \"u8\"
+// @is "$.index[*][?(@.name=='PrimU8')].inner.typedef.type.primitive" \"u8\"
 pub type PrimU8 = u8;
diff --git a/tests/rustdoc-json/primitives/use_primitive.rs b/tests/rustdoc-json/primitives/use_primitive.rs
index 5180a804f07..f8118b82094 100644
--- a/tests/rustdoc-json/primitives/use_primitive.rs
+++ b/tests/rustdoc-json/primitives/use_primitive.rs
@@ -13,8 +13,8 @@ mod usize {}
 // @!is "$.index[*][?(@.name=='checked_add')]" $local_crate_id
 // @!has "$.index[*][?(@.name=='is_ascii_uppercase')]"
 
-// @is "$.index[*][?(@.kind=='import' && @.inner.name=='my_i32')].inner.id" null
+// @is "$.index[*].inner.import[?(@.name=='my_i32')].id" null
 pub use i32 as my_i32;
 
-// @is "$.index[*][?(@.kind=='import' && @.inner.name=='u32')].inner.id" null
+// @is "$.index[*].inner.import[?(@.name=='u32')].id" null
 pub use u32;
diff --git a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
index 40b681d7dbb..1c5fed8c6b2 100644
--- a/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
+++ b/tests/rustdoc-json/reexport/doc_inline_external_crate.rs
@@ -1,10 +1,11 @@
 // Regression Test for https://github.com/rust-lang/rust/issues/110138
 // aux-build: enum_with_discriminant.rs
+// ignore-tidy-linelength
 
 #[doc(inline)]
 pub extern crate enum_with_discriminant;
 
 // @!has '$.index[*][?(@.docs == "Should not be inlined")]'
-// @is '$.index[*][?(@.name == "enum_with_discriminant")].kind' '"extern_crate"'
+// @has '$.index[*][?(@.name == "enum_with_discriminant")].inner.extern_crate'
 // @set enum_with_discriminant = '$.index[*][?(@.name == "enum_with_discriminant")].id'
-// @is '$.index[*][?(@.name == "doc_inline_external_crate")].inner.items[*]' $enum_with_discriminant
+// @is '$.index[*][?(@.name == "doc_inline_external_crate")].inner.module.items[*]' $enum_with_discriminant
diff --git a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
index f076feb7185..37ca279b352 100644
--- a/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
+++ b/tests/rustdoc-json/reexport/export_extern_crate_as_self.rs
@@ -7,5 +7,5 @@
 
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.kind=='module')].name" \"export_extern_crate_as_self\"
+// @is "$.index[*][?(@.inner.module)].name" \"export_extern_crate_as_self\"
 pub extern crate self as export_extern_crate_as_self; // Must be the same name as the crate already has
diff --git a/tests/rustdoc-json/reexport/extern_crate_glob.rs b/tests/rustdoc-json/reexport/extern_crate_glob.rs
index 8efb94fd3f1..553ee79b44e 100644
--- a/tests/rustdoc-json/reexport/extern_crate_glob.rs
+++ b/tests/rustdoc-json/reexport/extern_crate_glob.rs
@@ -6,5 +6,6 @@ extern crate enum_with_discriminant;
 pub use enum_with_discriminant::*;
 
 // @!has '$.index[*][?(@.docs == "Should not be inlined")]'
-// @set use = '$.index[*][?(@.inner.name == "enum_with_discriminant")].id'
-// @is '$.index[*][?(@.name == "extern_crate_glob")].inner.items[*]' $use
+// @is '$.index[*][?(@.inner.import)].inner.import.name' \"enum_with_discriminant\"
+// @set use = '$.index[*][?(@.inner.import)].id'
+// @is '$.index[*][?(@.name == "extern_crate_glob")].inner.module.items[*]' $use
diff --git a/tests/rustdoc-json/reexport/glob_collision.rs b/tests/rustdoc-json/reexport/glob_collision.rs
index f91144dbfad..dee35ba78dc 100644
--- a/tests/rustdoc-json/reexport/glob_collision.rs
+++ b/tests/rustdoc-json/reexport/glob_collision.rs
@@ -3,26 +3,28 @@
 #![feature(no_core)]
 #![no_core]
 
-// @set m1 = "$.index[*][?(@.name == 'm1' && @.kind == 'module')].id"
-// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.items" []
-// @is "$.index[*][?(@.name == 'm1' && @.kind == 'module')].inner.is_stripped" true
+// @set m1 = "$.index[*][?(@.name == 'm1' && @.inner.module)].id"
+// @is "$.index[*][?(@.name == 'm1')].inner.module.items" []
+// @is "$.index[*][?(@.name == 'm1')].inner.module.is_stripped" true
 mod m1 {
     pub fn f() {}
 }
-// @set m2 = "$.index[*][?(@.name == 'm2' && @.kind == 'module')].id"
-// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.items" []
-// @is "$.index[*][?(@.name == 'm2' && @.kind == 'module')].inner.is_stripped" true
+// @set m2 = "$.index[*][?(@.name == 'm2' && @.inner.module)].id"
+// @is "$.index[*][?(@.name == 'm2')].inner.module.items" []
+// @is "$.index[*][?(@.name == 'm2')].inner.module.is_stripped" true
 mod m2 {
     pub fn f(_: u8) {}
 }
 
-// @set m1_use = "$.index[*][?(@.inner.name=='m1')].id"
-// @is "$.index[*][?(@.inner.name=='m1')].inner.id" $m1
-// @is "$.index[*][?(@.inner.name=='m1')].inner.glob" true
+// @set m1_use = "$.index[*][?(@.docs=='m1 re-export')].id"
+// @is "$.index[*].inner.import[?(@.name=='m1')].id" $m1
+// @is "$.index[*].inner.import[?(@.name=='m1')].glob" true
+/// m1 re-export
 pub use m1::*;
-// @set m2_use = "$.index[*][?(@.inner.name=='m2')].id"
-// @is "$.index[*][?(@.inner.name=='m2')].inner.id" $m2
-// @is "$.index[*][?(@.inner.name=='m2')].inner.glob" true
+// @set m2_use = "$.index[*][?(@.docs=='m2 re-export')].id"
+// @is "$.index[*].inner.import[?(@.name=='m2')].id" $m2
+// @is "$.index[*].inner.import[?(@.name=='m2')].glob" true
+/// m2 re-export
 pub use m2::*;
 
-// @ismany "$.index[*][?(@.inner.is_crate==true)].inner.items[*]" $m1_use $m2_use
+// @ismany "$.index[*].inner.module[?(@.is_crate==true)].items[*]" $m1_use $m2_use
diff --git a/tests/rustdoc-json/reexport/glob_empty_mod.rs b/tests/rustdoc-json/reexport/glob_empty_mod.rs
index da68228352c..8b7150c8fd7 100644
--- a/tests/rustdoc-json/reexport/glob_empty_mod.rs
+++ b/tests/rustdoc-json/reexport/glob_empty_mod.rs
@@ -1,8 +1,8 @@
 // Regression test for https://github.com/rust-lang/rust/issues/100973
 
-// @is "$.index[*][?(@.name=='m1' && @.kind == 'module')].inner.is_stripped" true
+// @is "$.index[*][?(@.name=='m1' && @.inner.module)].inner.module.is_stripped" true
 // @set m1 = "$.index[*][?(@.name=='m1')].id"
 mod m1 {}
 
-// @is "$.index[*][?(@.inner.name=='m1' && @.kind=='import')].inner.id" $m1
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $m1
 pub use m1::*;
diff --git a/tests/rustdoc-json/reexport/glob_extern.rs b/tests/rustdoc-json/reexport/glob_extern.rs
index 7a1e8c11ffa..78edfaf0aa8 100644
--- a/tests/rustdoc-json/reexport/glob_extern.rs
+++ b/tests/rustdoc-json/reexport/glob_extern.rs
@@ -3,8 +3,7 @@
 #![no_core]
 #![feature(no_core)]
 
-// @is "$.index[*][?(@.name=='mod1')].kind" \"module\"
-// @is "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
+// @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true"
 mod mod1 {
     extern "C" {
         // @set public_fn_id = "$.index[*][?(@.name=='public_fn')].id"
@@ -12,12 +11,12 @@ mod mod1 {
         // @!has "$.index[*][?(@.name=='private_fn')]"
         fn private_fn();
     }
-    // @ismany "$.index[*][?(@.name=='mod1')].inner.items[*]" $public_fn_id
+    // @ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $public_fn_id
     // @set mod1_id = "$.index[*][?(@.name=='mod1')].id"
 }
 
-// @is "$.index[*][?(@.kind=='import')].inner.glob" true
-// @is "$.index[*][?(@.kind=='import')].inner.id" $mod1_id
-// @set use_id = "$.index[*][?(@.kind=='import')].id"
-// @ismany "$.index[*][?(@.name=='glob_extern')].inner.items[*]" $use_id
+// @is "$.index[*][?(@.inner.import)].inner.import.glob" true
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $mod1_id
+// @set use_id = "$.index[*][?(@.inner.import)].id"
+// @ismany "$.index[*][?(@.name=='glob_extern')].inner.module.items[*]" $use_id
 pub use mod1::*;
diff --git a/tests/rustdoc-json/reexport/glob_private.rs b/tests/rustdoc-json/reexport/glob_private.rs
index 3a83a20818b..ae4e87d23bc 100644
--- a/tests/rustdoc-json/reexport/glob_private.rs
+++ b/tests/rustdoc-json/reexport/glob_private.rs
@@ -3,11 +3,9 @@
 #![no_core]
 #![feature(no_core)]
 
-// @is "$.index[*][?(@.name=='mod1')].kind" \"module\"
-// @is "$.index[*][?(@.name=='mod1')].inner.is_stripped" "true"
+// @is "$.index[*][?(@.name=='mod1')].inner.module.is_stripped" "true"
 mod mod1 {
-    // @is "$.index[*][?(@.name=='mod2')].kind" \"module\"
-    // @is "$.index[*][?(@.name=='mod2')].inner.is_stripped" "true"
+    // @is "$.index[*][?(@.name=='mod2')].inner.module.is_stripped" "true"
     mod mod2 {
         // @set m2pub_id = "$.index[*][?(@.name=='Mod2Public')].id"
         pub struct Mod2Public;
@@ -16,7 +14,9 @@ mod mod1 {
         struct Mod2Private;
     }
 
-    // @set mod2_use_id = "$.index[*][?(@.kind=='import' && @.inner.name=='mod2')].id"
+    // @set mod2_use_id = "$.index[*][?(@.docs=='Mod2 re-export')].id"
+    // @is "$.index[*][?(@.docs=='Mod2 re-export')].inner.import.name" \"mod2\"
+    /// Mod2 re-export
     pub use self::mod2::*;
 
     // @set m1pub_id = "$.index[*][?(@.name=='Mod1Public')].id"
@@ -25,9 +25,11 @@ mod mod1 {
     struct Mod1Private;
 }
 
-// @set mod1_use_id = "$.index[*][?(@.kind=='import' && @.inner.name=='mod1')].id"
+// @set mod1_use_id = "$.index[*][?(@.docs=='Mod1 re-export')].id"
+// @is "$.index[*][?(@.docs=='Mod1 re-export')].inner.import.name" \"mod1\"
+/// Mod1 re-export
 pub use mod1::*;
 
-// @ismany "$.index[*][?(@.name=='mod2')].inner.items[*]" $m2pub_id
-// @ismany "$.index[*][?(@.name=='mod1')].inner.items[*]" $m1pub_id $mod2_use_id
-// @ismany "$.index[*][?(@.name=='glob_private')].inner.items[*]" $mod1_use_id
+// @ismany "$.index[*][?(@.name=='mod2')].inner.module.items[*]" $m2pub_id
+// @ismany "$.index[*][?(@.name=='mod1')].inner.module.items[*]" $m1pub_id $mod2_use_id
+// @ismany "$.index[*][?(@.name=='glob_private')].inner.module.items[*]" $mod1_use_id
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod.rs b/tests/rustdoc-json/reexport/in_root_and_mod.rs
index 7b97ebf2129..f81445bd48d 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod.rs
@@ -7,10 +7,10 @@ mod foo {
     pub struct Foo;
 }
 
-// @has "$.index[*][?(@.kind=='import' && @.inner.source=='foo::Foo')]"
+// @has "$.index[*].inner[?(@.import.source=='foo::Foo')]"
 pub use foo::Foo;
 
 pub mod bar {
-    // @has "$.index[*][?(@.kind=='import' && @.inner.source=='crate::foo::Foo')]"
+    // @has "$.index[*].inner[?(@.import.source=='crate::foo::Foo')]"
     pub use crate::foo::Foo;
 }
diff --git a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
index f6d932d927b..c5c41b25f7e 100644
--- a/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
+++ b/tests/rustdoc-json/reexport/in_root_and_mod_pub.rs
@@ -3,18 +3,20 @@
 
 pub mod foo {
     // @set bar_id = "$.index[*][?(@.name=='Bar')].id"
-    // @ismany "$.index[*][?(@.name=='foo')].inner.items[*]" $bar_id
+    // @ismany "$.index[*][?(@.name=='foo')].inner.module.items[*]" $bar_id
     pub struct Bar;
 }
 
-// @set root_import_id = "$.index[*][?(@.inner.source=='foo::Bar')].id"
-// @is "$.index[*][?(@.inner.source=='foo::Bar')].inner.id" $bar_id
-// @has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.items[*]" $root_import_id
+// @set root_import_id = "$.index[*][?(@.docs=='Outer re-export')].id"
+// @is "$.index[*].inner[?(@.import.source=='foo::Bar')].import.id" $bar_id
+// @has "$.index[*][?(@.name=='in_root_and_mod_pub')].inner.module.items[*]" $root_import_id
+/// Outer re-export
 pub use foo::Bar;
 
 pub mod baz {
-    // @set baz_import_id = "$.index[*][?(@.inner.source=='crate::foo::Bar')].id"
-    // @is "$.index[*][?(@.inner.source=='crate::foo::Bar')].inner.id" $bar_id
-    // @ismany "$.index[*][?(@.name=='baz')].inner.items[*]" $baz_import_id
+    // @set baz_import_id = "$.index[*][?(@.docs=='Inner re-export')].id"
+    // @is "$.index[*].inner[?(@.import.source=='crate::foo::Bar')].import.id" $bar_id
+    // @ismany "$.index[*][?(@.name=='baz')].inner.module.items[*]" $baz_import_id
+    /// Inner re-export
     pub use crate::foo::Bar;
 }
diff --git a/tests/rustdoc-json/reexport/macro.rs b/tests/rustdoc-json/reexport/macro.rs
index b4882100f06..ac0632b98a9 100644
--- a/tests/rustdoc-json/reexport/macro.rs
+++ b/tests/rustdoc-json/reexport/macro.rs
@@ -9,7 +9,8 @@ macro_rules! repro {
     () => {};
 }
 
-// @set repro2_id = "$.index[*][?(@.inner.name=='repro2')].id"
+// @set repro2_id = "$.index[*][?(@.docs=='Re-export')].id"
+/// Re-export
 pub use crate::repro as repro2;
 
-// @ismany "$.index[*][?(@.name=='macro')].inner.items[*]" $repro_id $repro2_id
+// @ismany "$.index[*][?(@.name=='macro')].inner.module.items[*]" $repro_id $repro2_id
diff --git a/tests/rustdoc-json/reexport/mod_not_included.rs b/tests/rustdoc-json/reexport/mod_not_included.rs
index 7b7600ef20f..1c49f213d1a 100644
--- a/tests/rustdoc-json/reexport/mod_not_included.rs
+++ b/tests/rustdoc-json/reexport/mod_not_included.rs
@@ -9,6 +9,6 @@ mod m1 {
 
 pub use m1::x;
 
-// @has "$.index[*][?(@.name=='x' && @.kind=='function')]"
-// @has "$.index[*][?(@.kind=='import' && @.inner.name=='x')].inner.source" '"m1::x"'
+// @has "$.index[*][?(@.name=='x' && @.inner.function)]"
+// @has "$.index[*].inner[?(@.import.name=='x')].import.source" '"m1::x"'
 // @!has "$.index[*][?(@.name=='m1')]"
diff --git a/tests/rustdoc-json/reexport/private_twice_one_inline.rs b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
index 687a3b2ac8b..8c8152bd16c 100644
--- a/tests/rustdoc-json/reexport/private_twice_one_inline.rs
+++ b/tests/rustdoc-json/reexport/private_twice_one_inline.rs
@@ -11,18 +11,18 @@ extern crate pub_struct as foo;
 #[doc(inline)]
 
 // @set crate_use_id = "$.index[*][?(@.docs=='Hack A')].id"
-// @set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.id"
+// @set foo_id = "$.index[*][?(@.docs=='Hack A')].inner.import.id"
 /// Hack A
 pub use foo::Foo;
 
 // @set bar_id = "$.index[*][?(@.name=='bar')].id"
 pub mod bar {
-    // @is "$.index[*][?(@.docs=='Hack B')].inner.id" $foo_id
+    // @is "$.index[*][?(@.docs=='Hack B')].inner.import.id" $foo_id
     // @set bar_use_id = "$.index[*][?(@.docs=='Hack B')].id"
-    // @ismany "$.index[*][?(@.name=='bar')].inner.items[*]" $bar_use_id
+    // @ismany "$.index[*][?(@.name=='bar')].inner.module.items[*]" $bar_use_id
     /// Hack B
     pub use foo::Foo;
 }
 
-// @ismany "$.index[*][?(@.kind=='import')].id" $crate_use_id $bar_use_id
-// @ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.items[*]" $bar_id $crate_use_id
+// @ismany "$.index[*][?(@.inner.import)].id" $crate_use_id $bar_use_id
+// @ismany "$.index[*][?(@.name=='private_twice_one_inline')].inner.module.items[*]" $bar_id $crate_use_id
diff --git a/tests/rustdoc-json/reexport/private_two_names.rs b/tests/rustdoc-json/reexport/private_two_names.rs
index 9858538a9d0..cdcbf2a2bc8 100644
--- a/tests/rustdoc-json/reexport/private_two_names.rs
+++ b/tests/rustdoc-json/reexport/private_two_names.rs
@@ -8,15 +8,19 @@
 
 // @!has "$.index[*][?(@.name=='style')]"
 mod style {
-    // @set color_struct_id = "$.index[*][?(@.kind=='struct' && @.name=='Color')].id"
+    // @set color_struct_id = "$.index[*][?(@.inner.struct && @.name=='Color')].id"
     pub struct Color;
 }
 
-// @is "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].inner.id" $color_struct_id
-// @set color_export_id = "$.index[*][?(@.kind=='import' && @.inner.name=='Color')].id"
+// @is "$.index[*][?(@.docs=='First re-export')].inner.import.id" $color_struct_id
+// @is "$.index[*][?(@.docs=='First re-export')].inner.import.name" \"Color\"
+// @set color_export_id = "$.index[*][?(@.docs=='First re-export')].id"
+/// First re-export
 pub use style::Color;
-// @is "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].inner.id" $color_struct_id
-// @set colour_export_id = "$.index[*][?(@.kind=='import' && @.inner.name=='Colour')].id"
+// @is "$.index[*][?(@.docs=='Second re-export')].inner.import.id" $color_struct_id
+// @is "$.index[*][?(@.docs=='Second re-export')].inner.import.name" \"Colour\"
+// @set colour_export_id = "$.index[*][?(@.docs=='Second re-export')].id"
+/// Second re-export
 pub use style::Color as Colour;
 
-// @ismany "$.index[*][?(@.name=='private_two_names')].inner.items[*]" $color_export_id $colour_export_id
+// @ismany "$.index[*][?(@.name=='private_two_names')].inner.module.items[*]" $color_export_id $colour_export_id
diff --git a/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs b/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs
index 239b1a23b43..61075088af9 100644
--- a/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs
+++ b/tests/rustdoc-json/reexport/reexport_method_from_private_module.rs
@@ -1,9 +1,9 @@
 // Regression test for <https://github.com/rust-lang/rust/issues/102583>.
 
 // @set impl_S = "$.index[*][?(@.docs=='impl S')].id"
-// @has "$.index[*][?(@.name=='S')].inner.impls[*]" $impl_S
+// @has "$.index[*][?(@.name=='S')].inner.struct.impls[*]" $impl_S
 // @set is_present = "$.index[*][?(@.name=='is_present')].id"
-// @is "$.index[*][?(@.docs=='impl S')].inner.items[*]" $is_present
+// @is "$.index[*][?(@.docs=='impl S')].inner.impl.items[*]" $is_present
 // @!has "$.index[*][?(@.name=='hidden_impl')]"
 // @!has "$.index[*][?(@.name=='hidden_fn')]"
 
diff --git a/tests/rustdoc-json/reexport/rename_private.rs b/tests/rustdoc-json/reexport/rename_private.rs
index 8fd850f9b13..9114460231d 100644
--- a/tests/rustdoc-json/reexport/rename_private.rs
+++ b/tests/rustdoc-json/reexport/rename_private.rs
@@ -3,11 +3,11 @@
 #![no_core]
 #![feature(no_core)]
 
-// @!has "$.index[*][?(@.kind=='inner')]"
+// @!has "$.index[*][?(@.name=='inner')]"
 mod inner {
     // @has "$.index[*][?(@.name=='Public')]"
     pub struct Public;
 }
 
-// @is "$.index[*][?(@.kind=='import')].inner.name" \"NewName\"
+// @is "$.index[*][?(@.inner.import)].inner.import.name" \"NewName\"
 pub use inner::Public as NewName;
diff --git a/tests/rustdoc-json/reexport/rename_public.rs b/tests/rustdoc-json/reexport/rename_public.rs
index e30907fe256..d0fd314bd8c 100644
--- a/tests/rustdoc-json/reexport/rename_public.rs
+++ b/tests/rustdoc-json/reexport/rename_public.rs
@@ -6,12 +6,13 @@
 // @set inner_id = "$.index[*][?(@.name=='inner')].id"
 pub mod inner {
     // @set public_id = "$.index[*][?(@.name=='Public')].id"
-    // @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+    // @ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id
     pub struct Public;
 }
-// @set import_id = "$.index[*][?(@.inner.name=='NewName')].id"
-// @!has "$.index[*][?(@.inner.name=='Public')]"
-// @is "$.index[*][?(@.inner.name=='NewName')].inner.source" \"inner::Public\"
+// @set import_id = "$.index[*][?(@.docs=='Re-export')].id"
+// @!has "$.index[*].inner[?(@.import.name=='Public')]"
+// @is "$.index[*].inner[?(@.import.name=='NewName')].import.source" \"inner::Public\"
+/// Re-export
 pub use inner::Public as NewName;
 
-// @ismany "$.index[*][?(@.name=='rename_public')].inner.items[*]" $inner_id $import_id
+// @ismany "$.index[*][?(@.name=='rename_public')].inner.module.items[*]" $inner_id $import_id
diff --git a/tests/rustdoc-json/reexport/same_name_different_types.rs b/tests/rustdoc-json/reexport/same_name_different_types.rs
index 2314a4eb909..6a765b73301 100644
--- a/tests/rustdoc-json/reexport/same_name_different_types.rs
+++ b/tests/rustdoc-json/reexport/same_name_different_types.rs
@@ -16,10 +16,10 @@ pub mod nested {
     pub fn Foo() {}
 }
 
-// @ismany "$.index[*][?(@.inner.name == 'Foo' && @.kind == 'import')].inner.id" $foo_fn $foo_struct
-// @ismany "$.index[*][?(@.inner.name == 'Bar' && @.kind == 'import')].inner.id" $foo_fn $foo_struct
+// @ismany "$.index[*].inner[?(@.import.name == 'Foo')].import.id" $foo_fn $foo_struct
+// @ismany "$.index[*].inner[?(@.import.name == 'Bar')].import.id" $foo_fn $foo_struct
 
-// @count "$.index[*][?(@.inner.name == 'Foo' && @.kind == 'import')]" 2
+// @count "$.index[*].inner[?(@.import.name == 'Foo')]" 2
 pub use nested::Foo;
-// @count "$.index[*][?(@.inner.name == 'Bar' && @.kind == 'import')]" 2
+// @count "$.index[*].inner[?(@.import.name == 'Bar')]" 2
 pub use Foo as Bar;
diff --git a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
index 880dbdc4416..a00547dc348 100644
--- a/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
+++ b/tests/rustdoc-json/reexport/same_type_reexported_more_than_once.rs
@@ -11,11 +11,13 @@ mod inner {
     pub trait Trait {}
 }
 
-// @set export_id = "$.index[*][?(@.inner.name=='Trait')].id"
-// @is "$.index[*][?(@.inner.name=='Trait')].inner.id" $trait_id
+// @set export_id = "$.index[*][?(@.docs=='First re-export')].id"
+// @is "$.index[*].inner[?(@.import.name=='Trait')].import.id" $trait_id
+/// First re-export
 pub use inner::Trait;
-// @set reexport_id = "$.index[*][?(@.inner.name=='Reexport')].id"
-// @is "$.index[*][?(@.inner.name=='Reexport')].inner.id" $trait_id
+// @set reexport_id = "$.index[*][?(@.docs=='Second re-export')].id"
+// @is "$.index[*].inner[?(@.import.name=='Reexport')].import.id" $trait_id
+/// Second re-export
 pub use inner::Trait as Reexport;
 
-// @ismany "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.items[*]" $reexport_id $export_id
+// @ismany "$.index[*][?(@.name=='same_type_reexported_more_than_once')].inner.module.items[*]" $reexport_id $export_id
diff --git a/tests/rustdoc-json/reexport/simple_private.rs b/tests/rustdoc-json/reexport/simple_private.rs
index d058ce0598d..462efee51bf 100644
--- a/tests/rustdoc-json/reexport/simple_private.rs
+++ b/tests/rustdoc-json/reexport/simple_private.rs
@@ -8,9 +8,9 @@ mod inner {
     pub struct Public;
 }
 
-// @is "$.index[*][?(@.kind=='import')].inner.name" \"Public\"
-// @is "$.index[*][?(@.kind=='import')].inner.id" $pub_id
-// @set use_id = "$.index[*][?(@.kind=='import')].id"
+// @is "$.index[*][?(@.inner.import)].inner.import.name" \"Public\"
+// @is "$.index[*][?(@.inner.import)].inner.import.id" $pub_id
+// @set use_id = "$.index[*][?(@.inner.import)].id"
 pub use inner::Public;
 
-// @ismany "$.index[*][?(@.name=='simple_private')].inner.items[*]" $use_id
+// @ismany "$.index[*][?(@.name=='simple_private')].inner.module.items[*]" $use_id
diff --git a/tests/rustdoc-json/reexport/simple_public.rs b/tests/rustdoc-json/reexport/simple_public.rs
index e64a0dcb769..1373f96f87f 100644
--- a/tests/rustdoc-json/reexport/simple_public.rs
+++ b/tests/rustdoc-json/reexport/simple_public.rs
@@ -7,12 +7,13 @@
 pub mod inner {
 
     // @set public_id = "$.index[*][?(@.name=='Public')].id"
-    // @ismany "$.index[*][?(@.name=='inner')].inner.items[*]" $public_id
+    // @ismany "$.index[*][?(@.name=='inner')].inner.module.items[*]" $public_id
     pub struct Public;
 }
 
-// @set import_id = "$.index[*][?(@.inner.name=='Public')].id"
-// @is "$.index[*][?(@.inner.name=='Public')].inner.source" \"inner::Public\"
+// @set import_id = "$.index[*][?(@.docs=='Outer')].id"
+// @is "$.index[*][?(@.docs=='Outer')].inner.import.source" \"inner::Public\"
+/// Outer
 pub use inner::Public;
 
-// @ismany "$.index[*][?(@.name=='simple_public')].inner.items[*]" $import_id $inner_id
+// @ismany "$.index[*][?(@.name=='simple_public')].inner.module.items[*]" $import_id $inner_id
diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs
index a8d1fae30df..0ce81b5e59f 100644
--- a/tests/rustdoc-json/return_private.rs
+++ b/tests/rustdoc-json/return_private.rs
@@ -8,8 +8,8 @@ mod secret {
     pub struct Secret;
 }
 
-// @is "$.index[*][?(@.name=='get_secret')].kind" \"function\"
-// @is "$.index[*][?(@.name=='get_secret')].inner.decl.output.inner.name" \"secret::Secret\"
+// @has "$.index[*][?(@.name=='get_secret')].inner.function"
+// @is "$.index[*][?(@.name=='get_secret')].inner.function.decl.output.resolved_path.name" \"secret::Secret\"
 pub fn get_secret() -> secret::Secret {
     secret::Secret
 }
diff --git a/tests/rustdoc-json/structs/plain_all_pub.rs b/tests/rustdoc-json/structs/plain_all_pub.rs
index b86ab93c264..777260100d6 100644
--- a/tests/rustdoc-json/structs/plain_all_pub.rs
+++ b/tests/rustdoc-json/structs/plain_all_pub.rs
@@ -5,7 +5,7 @@ pub struct Demo {
 
 // @set x = "$.index[*][?(@.name=='x')].id"
 // @set y = "$.index[*][?(@.name=='y')].id"
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[1]" $y
-// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 2
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" false
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[1]" $y
+// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 2
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" false
diff --git a/tests/rustdoc-json/structs/plain_doc_hidden.rs b/tests/rustdoc-json/structs/plain_doc_hidden.rs
index 7800b55a481..1ff4489ef6b 100644
--- a/tests/rustdoc-json/structs/plain_doc_hidden.rs
+++ b/tests/rustdoc-json/structs/plain_doc_hidden.rs
@@ -6,6 +6,6 @@ pub struct Demo {
 
 // @set x = "$.index[*][?(@.name=='x')].id"
 // @!has "$.index[*][?(@.name=='y')].id"
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
-// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
+// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
diff --git a/tests/rustdoc-json/structs/plain_empty.rs b/tests/rustdoc-json/structs/plain_empty.rs
index 1d01b8bc14a..c037c0251b9 100644
--- a/tests/rustdoc-json/structs/plain_empty.rs
+++ b/tests/rustdoc-json/structs/plain_empty.rs
@@ -1,5 +1,5 @@
 // @is "$.index[*][?(@.name=='PlainEmpty')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='PlainEmpty')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields_stripped" false
-// @is "$.index[*][?(@.name=='PlainEmpty')].inner.kind.plain.fields" []
+// @has "$.index[*][?(@.name=='PlainEmpty')].inner.struct"
+// @is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields_stripped" false
+// @is "$.index[*][?(@.name=='PlainEmpty')].inner.struct.kind.plain.fields" []
 pub struct PlainEmpty {}
diff --git a/tests/rustdoc-json/structs/plain_pub_priv.rs b/tests/rustdoc-json/structs/plain_pub_priv.rs
index 9b771224d97..ff061be62d1 100644
--- a/tests/rustdoc-json/structs/plain_pub_priv.rs
+++ b/tests/rustdoc-json/structs/plain_pub_priv.rs
@@ -4,6 +4,6 @@ pub struct Demo {
 }
 
 // @set x = "$.index[*][?(@.name=='x')].id"
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[0]" $x
-// @count "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields[*]" 1
-// @is "$.index[*][?(@.name=='Demo')].inner.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[0]" $x
+// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields[*]" 1
+// @is "$.index[*][?(@.name=='Demo')].inner.struct.kind.plain.fields_stripped" true
diff --git a/tests/rustdoc-json/structs/tuple.rs b/tests/rustdoc-json/structs/tuple.rs
index 6bdb753ee01..16ab95ed271 100644
--- a/tests/rustdoc-json/structs/tuple.rs
+++ b/tests/rustdoc-json/structs/tuple.rs
@@ -1,4 +1,4 @@
 // @is "$.index[*][?(@.name=='Tuple')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='Tuple')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='Tuple')].inner.kind.tuple" '[null, null]'
+// @has "$.index[*][?(@.name=='Tuple')].inner.struct"
+// @is "$.index[*][?(@.name=='Tuple')].inner.struct.kind.tuple" '[null, null]'
 pub struct Tuple(u32, String);
diff --git a/tests/rustdoc-json/structs/tuple_empty.rs b/tests/rustdoc-json/structs/tuple_empty.rs
index 0ad6a89547f..4d4af8558bb 100644
--- a/tests/rustdoc-json/structs/tuple_empty.rs
+++ b/tests/rustdoc-json/structs/tuple_empty.rs
@@ -1,2 +1,2 @@
-// @is "$.index[*][?(@.name=='TupleUnit')].inner.kind.tuple" []
+// @is "$.index[*][?(@.name=='TupleUnit')].inner.struct.kind.tuple" []
 pub struct TupleUnit();
diff --git a/tests/rustdoc-json/structs/tuple_pub_priv.rs b/tests/rustdoc-json/structs/tuple_pub_priv.rs
index 9d5a1d1c8be..a669ba1dfcc 100644
--- a/tests/rustdoc-json/structs/tuple_pub_priv.rs
+++ b/tests/rustdoc-json/structs/tuple_pub_priv.rs
@@ -7,7 +7,7 @@ pub struct Demo(
 
 // @set field = "$.index[*][?(@.docs=='field')].id"
 
-// @is    "$.index[*][?(@.name=='Demo')].inner.kind.tuple[0]" null
-// @is    "$.index[*][?(@.name=='Demo')].inner.kind.tuple[1]" $field
-// @is    "$.index[*][?(@.name=='Demo')].inner.kind.tuple[2]" null
-// @count "$.index[*][?(@.name=='Demo')].inner.kind.tuple[*]" 3
+// @is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[0]" null
+// @is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[1]" $field
+// @is    "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[2]" null
+// @count "$.index[*][?(@.name=='Demo')].inner.struct.kind.tuple[*]" 3
diff --git a/tests/rustdoc-json/structs/unit.rs b/tests/rustdoc-json/structs/unit.rs
index 26570971721..640d3fb7865 100644
--- a/tests/rustdoc-json/structs/unit.rs
+++ b/tests/rustdoc-json/structs/unit.rs
@@ -1,4 +1,4 @@
 // @is "$.index[*][?(@.name=='Unit')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='Unit')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='Unit')].inner.kind" \"unit\"
+// @has "$.index[*][?(@.name=='Unit')].inner.struct"
+// @is "$.index[*][?(@.name=='Unit')].inner.struct.kind" \"unit\"
 pub struct Unit;
diff --git a/tests/rustdoc-json/structs/with_generics.rs b/tests/rustdoc-json/structs/with_generics.rs
index 00474800a0e..d721cbdbe25 100644
--- a/tests/rustdoc-json/structs/with_generics.rs
+++ b/tests/rustdoc-json/structs/with_generics.rs
@@ -1,13 +1,13 @@
 use std::collections::HashMap;
 
 // @is "$.index[*][?(@.name=='WithGenerics')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='WithGenerics')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].name" \"T\"
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[0].kind.type.bounds" []
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].name" \"U\"
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.generics.params[1].kind.type.bounds" []
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields_stripped" true
-// @is "$.index[*][?(@.name=='WithGenerics')].inner.kind.plain.fields" []
+// @has "$.index[*][?(@.name=='WithGenerics')].inner.struct"
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].name" \"T\"
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[0].kind.type.bounds" []
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].name" \"U\"
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.generics.params[1].kind.type.bounds" []
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='WithGenerics')].inner.struct.kind.plain.fields" []
 pub struct WithGenerics<T, U> {
     stuff: Vec<T>,
     things: HashMap<U, U>,
diff --git a/tests/rustdoc-json/structs/with_primitives.rs b/tests/rustdoc-json/structs/with_primitives.rs
index 9c5a37f3957..e0285a9e688 100644
--- a/tests/rustdoc-json/structs/with_primitives.rs
+++ b/tests/rustdoc-json/structs/with_primitives.rs
@@ -1,9 +1,11 @@
+// ignore-tidy-linelength
+
 // @is "$.index[*][?(@.name=='WithPrimitives')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='WithPrimitives')].kind" \"struct\"
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].name" \"\'a\"
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.generics.params[0].kind.lifetime.outlives" []
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields_stripped" true
-// @is "$.index[*][?(@.name=='WithPrimitives')].inner.kind.plain.fields" []
+// @has "$.index[*][?(@.name=='WithPrimitives')].inner.struct"
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].name" \"\'a\"
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.generics.params[0].kind.lifetime.outlives" []
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields_stripped" true
+// @is "$.index[*][?(@.name=='WithPrimitives')].inner.struct.kind.plain.fields" []
 pub struct WithPrimitives<'a> {
     num: u32,
     s: &'a str,
diff --git a/tests/rustdoc-json/traits/has_body.rs b/tests/rustdoc-json/traits/has_body.rs
index a57cb97d4a6..219e2d9bc54 100644
--- a/tests/rustdoc-json/traits/has_body.rs
+++ b/tests/rustdoc-json/traits/has_body.rs
@@ -1,21 +1,21 @@
 // @has "$.index[*][?(@.name=='Foo')]"
 pub trait Foo {
-    // @is "$.index[*][?(@.name=='no_self')].inner.has_body" false
+    // @is "$.index[*][?(@.name=='no_self')].inner.function.has_body" false
     fn no_self();
-    // @is "$.index[*][?(@.name=='move_self')].inner.has_body" false
+    // @is "$.index[*][?(@.name=='move_self')].inner.function.has_body" false
     fn move_self(self);
-    // @is "$.index[*][?(@.name=='ref_self')].inner.has_body" false
+    // @is "$.index[*][?(@.name=='ref_self')].inner.function.has_body" false
     fn ref_self(&self);
 
-    // @is "$.index[*][?(@.name=='no_self_def')].inner.has_body" true
+    // @is "$.index[*][?(@.name=='no_self_def')].inner.function.has_body" true
     fn no_self_def() {}
-    // @is "$.index[*][?(@.name=='move_self_def')].inner.has_body" true
+    // @is "$.index[*][?(@.name=='move_self_def')].inner.function.has_body" true
     fn move_self_def(self) {}
-    // @is "$.index[*][?(@.name=='ref_self_def')].inner.has_body" true
+    // @is "$.index[*][?(@.name=='ref_self_def')].inner.function.has_body" true
     fn ref_self_def(&self) {}
 }
 
 pub trait Bar: Clone {
-    // @is "$.index[*][?(@.name=='method')].inner.has_body" false
+    // @is "$.index[*][?(@.name=='method')].inner.function.has_body" false
     fn method(&self, param: usize);
 }
diff --git a/tests/rustdoc-json/traits/implementors.rs b/tests/rustdoc-json/traits/implementors.rs
index db3fe5df739..7d351ad61be 100644
--- a/tests/rustdoc-json/traits/implementors.rs
+++ b/tests/rustdoc-json/traits/implementors.rs
@@ -2,18 +2,18 @@
 #![no_core]
 
 // @set wham = "$.index[*][?(@.name=='Wham')].id"
-// @count "$.index[*][?(@.name=='Wham')].inner.implementations[*]" 1
-// @set gmWham = "$.index[*][?(@.name=='Wham')].inner.implementations[0]"
+// @count "$.index[*][?(@.name=='Wham')].inner.trait.implementations[*]" 1
+// @set gmWham = "$.index[*][?(@.name=='Wham')].inner.trait.implementations[0]"
 pub trait Wham {}
 
-// @count "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[*]" 1
-// @is "$.index[*][?(@.name=='GeorgeMichael')].inner.impls[0]" $gmWham
+// @count "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[*]" 1
+// @is "$.index[*][?(@.name=='GeorgeMichael')].inner.struct.impls[0]" $gmWham
 // @set gm = "$.index[*][?(@.name=='Wham')].id"
 
 // jsonpath_lib isnt expressive enough (for now) to get the "impl" item, so we
 // just check it isn't pointing to the type, but when you port to jsondocck-ng
 // check what the impl item is
-// @!is "$.index[*][?(@.name=='Wham')].inner.implementations[0]" $gm
+// @!is "$.index[*][?(@.name=='Wham')].inner.trait.implementations[0]" $gm
 pub struct GeorgeMichael {}
 
 impl Wham for GeorgeMichael {}
diff --git a/tests/rustdoc-json/traits/supertrait.rs b/tests/rustdoc-json/traits/supertrait.rs
index 4048fdd74b4..2123ac40427 100644
--- a/tests/rustdoc-json/traits/supertrait.rs
+++ b/tests/rustdoc-json/traits/supertrait.rs
@@ -8,19 +8,19 @@
 pub trait Loud {}
 
 // @set very_loud_id = "$.index[*][?(@.name=='VeryLoud')].id"
-// @count "$.index[*][?(@.name=='VeryLoud')].inner.bounds[*]" 1
-// @is    "$.index[*][?(@.name=='VeryLoud')].inner.bounds[0].trait_bound.trait.id" $loud_id
+// @count "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[*]" 1
+// @is    "$.index[*][?(@.name=='VeryLoud')].inner.trait.bounds[0].trait_bound.trait.id" $loud_id
 pub trait VeryLoud: Loud {}
 
 // @set sounds_good_id = "$.index[*][?(@.name=='SoundsGood')].id"
 pub trait SoundsGood {}
 
-// @count "$.index[*][?(@.name=='MetalBand')].inner.bounds[*]" 2
-// @is    "$.index[*][?(@.name=='MetalBand')].inner.bounds[0].trait_bound.trait.id" $very_loud_id
-// @is    "$.index[*][?(@.name=='MetalBand')].inner.bounds[1].trait_bound.trait.id" $sounds_good_id
+// @count "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[*]" 2
+// @is    "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[0].trait_bound.trait.id" $very_loud_id
+// @is    "$.index[*][?(@.name=='MetalBand')].inner.trait.bounds[1].trait_bound.trait.id" $sounds_good_id
 pub trait MetalBand: VeryLoud + SoundsGood {}
 
-// @count "$.index[*][?(@.name=='DnabLatem')].inner.bounds[*]" 2
-// @is    "$.index[*][?(@.name=='DnabLatem')].inner.bounds[1].trait_bound.trait.id" $very_loud_id
-// @is    "$.index[*][?(@.name=='DnabLatem')].inner.bounds[0].trait_bound.trait.id" $sounds_good_id
+// @count "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[*]" 2
+// @is    "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[1].trait_bound.trait.id" $very_loud_id
+// @is    "$.index[*][?(@.name=='DnabLatem')].inner.trait.bounds[0].trait_bound.trait.id" $sounds_good_id
 pub trait DnabLatem: SoundsGood + VeryLoud {}
diff --git a/tests/rustdoc-json/traits/trait_alias.rs b/tests/rustdoc-json/traits/trait_alias.rs
index 35db9296cdd..4fcc26f7de2 100644
--- a/tests/rustdoc-json/traits/trait_alias.rs
+++ b/tests/rustdoc-json/traits/trait_alias.rs
@@ -4,24 +4,24 @@
 #![feature(trait_alias)]
 
 // @set Orig = "$.index[*][?(@.name == 'Orig')].id"
-// @is "$.index[*][?(@.name == 'Orig')].kind" '"trait"'
+// @has "$.index[*][?(@.name == 'Orig')].inner.trait"
 pub trait Orig<T> {}
 
 // @set Alias = "$.index[*][?(@.name == 'Alias')].id"
-// @is "$.index[*][?(@.name == 'Alias')].kind" '"trait_alias"'
-// @is "$.index[*][?(@.name == 'Alias')].inner.generics" '{"params": [], "where_predicates": []}'
-// @count "$.index[*][?(@.name == 'Alias')].inner.params[*]" 1
-// @is "$.index[*][?(@.name == 'Alias')].inner.params[0].trait_bound.trait.id" $Orig
-// @is "$.index[*][?(@.name == 'Alias')].inner.params[0].trait_bound.trait.args.angle_bracketed.args[0].type.inner" '"i32"'
+// @has "$.index[*][?(@.name == 'Alias')].inner.trait_alias"
+// @is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.generics" '{"params": [], "where_predicates": []}'
+// @count "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[*]" 1
+// @is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.id" $Orig
+// @is "$.index[*][?(@.name == 'Alias')].inner.trait_alias.params[0].trait_bound.trait.args.angle_bracketed.args[0].type.primitive" '"i32"'
 pub trait Alias = Orig<i32>;
 
 pub struct Struct;
 
 impl Orig<i32> for Struct {}
 
-// @is "$.index[*][?(@.name=='takes_alias')].inner.decl.inputs[0][1].kind" '"impl_trait"'
-// @is "$.index[*][?(@.name=='takes_alias')].inner.decl.inputs[0][1].inner[0].trait_bound.trait.id" $Alias
-// @is "$.index[*][?(@.name=='takes_alias')].inner.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias
+// @has "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait"
+// @is "$.index[*][?(@.name=='takes_alias')].inner.function.decl.inputs[0][1].impl_trait[0].trait_bound.trait.id" $Alias
+// @is "$.index[*][?(@.name=='takes_alias')].inner.function.generics.params[0].kind.type.bounds[0].trait_bound.trait.id" $Alias
 pub fn takes_alias(_: impl Alias) {}
 // FIXME: Should the trait be mentioned in both the decl and generics?
 
diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs
index eaf249252e3..e5ee60fad59 100644
--- a/tests/rustdoc-json/type/dyn.rs
+++ b/tests/rustdoc-json/type/dyn.rs
@@ -1,46 +1,46 @@
 // ignore-tidy-linelength
 use std::fmt::Debug;
 
-// @count "$.index[*][?(@.name=='dyn')].inner.items[*]" 3
+// @count "$.index[*][?(@.name=='dyn')].inner.module.items[*]" 3
 // @set sync_int_gen = "$.index[*][?(@.name=='SyncIntGen')].id"
 // @set ref_fn       = "$.index[*][?(@.name=='RefFn')].id"
 // @set weird_order  = "$.index[*][?(@.name=='WeirdOrder')].id"
-// @ismany "$.index[*][?(@.name=='dyn')].inner.items[*]" $sync_int_gen $ref_fn $weird_order
+// @ismany "$.index[*][?(@.name=='dyn')].inner.module.items[*]" $sync_int_gen $ref_fn $weird_order
 
-// @is    "$.index[*][?(@.name=='SyncIntGen')].kind" \"typedef\"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.generics" '{"params": [], "where_predicates": []}'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.kind" \"resolved_path\"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.name" \"Box\"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.bindings" []
-// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args" 1
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"dyn_trait\"
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.lifetime" \"\'static\"
-// @count "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[*]" 3
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].generic_params" []
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].generic_params" []
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].generic_params" []
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Fn"'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Send"'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[2].trait.name" '"Sync"'
-// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"inner": "i32","kind": "primitive"}}}'
+// @has    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef"
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.generics" '{"params": [], "where_predicates": []}'
+// @has    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path"
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.name" \"Box\"
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.bindings" []
+// @count "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args" 1
+// @has    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait"
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.lifetime" \"\'static\"
+// @count "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[*]" 3
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" []
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" []
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" []
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Fn"'
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Send"'
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.name" '"Sync"'
+// @is    "$.index[*][?(@.name=='SyncIntGen')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}'
 pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>;
 
-// @is "$.index[*][?(@.name=='RefFn')].kind" \"typedef\"
-// @is "$.index[*][?(@.name=='RefFn')].inner.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.mutable" 'false'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.lifetime" "\"'a\""
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.kind" '"dyn_trait"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.lifetime" null
-// @count "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[*]" 1
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.name" '"Fn"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.inputs[0].inner.lifetime" "\"'b\""
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='RefFn')].inner.type.inner.type.inner.traits[0].trait.args.parenthesized.output.inner.lifetime" "\"'b\""
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.generics" '{"params": [{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"}],"where_predicates": []}'
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.mutable" 'false'
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.lifetime" "\"'a\""
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.lifetime" null
+// @count "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[*]" 1
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\""
+// @has "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref"
+// @is "$.index[*][?(@.name=='RefFn')].inner.typedef.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\""
 pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32;
 
-// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[0].trait.name" '"Send"'
-// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.type.inner.args.angle_bracketed.args[0].type.inner.traits[1].trait.name" '"Debug"'
+// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Send"'
+// @is    "$.index[*][?(@.name=='WeirdOrder')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Debug"'
 pub type WeirdOrder = Box<dyn Send + Debug>;
diff --git a/tests/rustdoc-json/type/extern.rs b/tests/rustdoc-json/type/extern.rs
index d287d5ebec5..c30146ce9e0 100644
--- a/tests/rustdoc-json/type/extern.rs
+++ b/tests/rustdoc-json/type/extern.rs
@@ -6,5 +6,4 @@ extern {
 }
 
 // @is "$.index[*][?(@.docs=='No inner information')].name" '"Foo"'
-// @is "$.index[*][?(@.docs=='No inner information')].kind" '"foreign_type"'
-// @!has "$.index[*][?(@.docs=='No inner information')].inner"
+// @is "$.index[*][?(@.docs=='No inner information')].inner" \"foreign_type\"
diff --git a/tests/rustdoc-json/type/fn_lifetime.rs b/tests/rustdoc-json/type/fn_lifetime.rs
index d7216ec7675..424c5dce273 100644
--- a/tests/rustdoc-json/type/fn_lifetime.rs
+++ b/tests/rustdoc-json/type/fn_lifetime.rs
@@ -1,27 +1,26 @@
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.name=='GenericFn')].kind" \"typedef\"
+// @has "$.index[*][?(@.name=='GenericFn')].inner.typedef"
 
-// @ismany "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].name" \"\'a\"
-// @has    "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime"
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.generics.params[*].kind.lifetime.outlives[*]" 0
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.generics.where_predicates[*]" 0
-// @is     "$.index[*][?(@.name=='GenericFn')].inner.type.kind" \"function_pointer\"
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.type.inner.generic_params[*]" 0
-// @count  "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*]" 1
-// @is     "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
-// @is     "$.index[*][?(@.name=='GenericFn')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"
+// @ismany "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.params[*].name" \"\'a\"
+// @has    "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.params[*].kind.lifetime"
+// @count  "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.params[*].kind.lifetime.outlives[*]" 0
+// @count  "$.index[*][?(@.name=='GenericFn')].inner.typedef.generics.where_predicates[*]" 0
+// @count  "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.generic_params[*]" 0
+// @count  "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.decl.inputs[*]" 1
+// @is     "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+// @is     "$.index[*][?(@.name=='GenericFn')].inner.typedef.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
 
 pub type GenericFn<'a> = fn(&'a i32) -> &'a i32;
 
-// @is    "$.index[*][?(@.name=='ForAll')].kind" \"typedef\"
-// @count "$.index[*][?(@.name=='ForAll')].inner.generics.params[*]" 0
-// @count "$.index[*][?(@.name=='ForAll')].inner.generics.where_predicates[*]" 0
-// @count "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*]" 1
-// @is    "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].name" \"\'a\"
-// @has   "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime"
-// @count "$.index[*][?(@.name=='ForAll')].inner.type.inner.generic_params[*].kind.lifetime.outlives[*]" 0
-// @count "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*]" 1
-// @is    "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.inputs[*][1].inner.lifetime" \"\'a\"
-// @is    "$.index[*][?(@.name=='ForAll')].inner.type.inner.decl.output.inner.lifetime" \"\'a\"
+// @has    "$.index[*][?(@.name=='ForAll')].inner.typedef"
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.generics.params[*]" 0
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.generics.where_predicates[*]" 0
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*]" 1
+// @is    "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*].name" \"\'a\"
+// @has   "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*].kind.lifetime"
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.generic_params[*].kind.lifetime.outlives[*]" 0
+// @count "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.decl.inputs[*]" 1
+// @is    "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.decl.inputs[*][1].borrowed_ref.lifetime" \"\'a\"
+// @is    "$.index[*][?(@.name=='ForAll')].inner.typedef.type.function_pointer.decl.output.borrowed_ref.lifetime" \"\'a\"
 pub type ForAll = for<'a> fn(&'a i32) -> &'a i32;
diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs
index 9c6d4540bfb..b4642874532 100644
--- a/tests/rustdoc-json/type/generic_default.rs
+++ b/tests/rustdoc-json/type/generic_default.rs
@@ -9,25 +9,25 @@ pub enum Result<T, E> {
 // @set my_error = "$.index[*][?(@.name=='MyError')].id"
 pub struct MyError {}
 
-// @is    "$.index[*][?(@.name=='MyResult')].kind" \"typedef\"
-// @count "$.index[*][?(@.name=='MyResult')].inner.generics.where_predicates[*]" 0
-// @count "$.index[*][?(@.name=='MyResult')].inner.generics.params[*]" 2
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].name" \"T\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].name" \"E\"
-// @has   "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type"
-// @has   "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type"
-// @count "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.bounds[*]" 0
-// @count "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.bounds[*]" 0
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[0].kind.type.default" null
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.kind" \"resolved_path\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.id" $my_error
-// @is    "$.index[*][?(@.name=='MyResult')].inner.generics.params[1].kind.type.default.inner.name" \"MyError\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.kind" \"resolved_path\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.id" $result
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.name" \"Result\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.bindings" []
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.kind" \"generic\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.kind" \"generic\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[0].type.inner" \"T\"
-// @is    "$.index[*][?(@.name=='MyResult')].inner.type.inner.args.angle_bracketed.args[1].type.inner" \"E\"
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef"
+// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.where_predicates[*]" 0
+// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[*]" 2
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].name" \"T\"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].name" \"E\"
+// @has   "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].kind.type"
+// @has   "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type"
+// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].kind.type.bounds[*]" 0
+// @count "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.bounds[*]" 0
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[0].kind.type.default" null
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.default.resolved_path"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.default.resolved_path.id" $my_error
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.generics.params[1].kind.type.default.resolved_path.name" \"MyError\"
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.id" $result
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.name" \"Result\"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.bindings" []
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.generic"
+// @has    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[1].type.generic"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[0].type.generic" \"T\"
+// @is    "$.index[*][?(@.name=='MyResult')].inner.typedef.type.resolved_path.args.angle_bracketed.args[1].type.generic" \"E\"
 pub type MyResult<T, E = MyError> = Result<T, E>;
diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs
index 2c4ee00d468..f7ac878ceaa 100644
--- a/tests/rustdoc-json/type/hrtb.rs
+++ b/tests/rustdoc-json/type/hrtb.rs
@@ -1,7 +1,7 @@
 // ignore-tidy-linelength
 
-// @is "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.type" '{"inner": "F","kind": "generic"}'
-// @is "$.index[*][?(@.name=='genfn')].inner.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+// @is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.type" '{"generic": "F"}'
+// @is "$.index[*][?(@.name=='genfn')].inner.function.generics.where_predicates[0].bound_predicate.generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
 pub fn genfn<F>(f: F)
 where
     for<'a, 'b> F: Fn(&'a i32, &'b i32),
@@ -10,14 +10,12 @@ where
     f(&zero, &zero);
 }
 
-// @is "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}'
-// @is "$.index[*][?(@.name=='dynfn')].inner.generics" '{"params": [], "where_predicates": []}'
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].kind" '"borrowed_ref"'
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.kind" '"dyn_trait"'
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.lifetime" null
-// @count "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[*]" 1
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
-// @is "$.index[*][?(@.name=='dynfn')].inner.decl.inputs[0][1].inner.type.inner.traits[0].trait.name" '"Fn"'
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.generics" '{"params": [], "where_predicates": []}'
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null
+// @count "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]'
+// @is "$.index[*][?(@.name=='dynfn')].inner.function.decl.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"'
 pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) {
     let zero = 0;
     f(&zero, &zero);
diff --git a/tests/rustdoc-json/type/inherent_associated_type.rs b/tests/rustdoc-json/type/inherent_associated_type.rs
index ed63def93df..64c6c53ce47 100644
--- a/tests/rustdoc-json/type/inherent_associated_type.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type.rs
@@ -12,11 +12,9 @@ pub struct Owner;
 pub fn create() -> Owner::Metadata {
     OwnerMetadata
 }
-// @is '$.index[*][?(@.name=="create")].inner.decl.output.kind' '"qualified_path"'
-// @is '$.index[*][?(@.name=="create")].inner.decl.output.inner.name' '"Metadata"'
-// @is '$.index[*][?(@.name=="create")].inner.decl.output.inner.trait' null
-// @is '$.index[*][?(@.name=="create")].inner.decl.output.inner.self_type.kind' '"resolved_path"'
-// @is '$.index[*][?(@.name=="create")].inner.decl.output.inner.self_type.inner.id' $Owner
+// @is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.name' '"Metadata"'
+// @is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.trait' null
+// @is '$.index[*][?(@.name=="create")].inner.function.decl.output.qualified_path.self_type.resolved_path.id' $Owner
 
 /// impl
 impl Owner {
@@ -24,6 +22,5 @@ impl Owner {
     pub type Metadata = OwnerMetadata;
 }
 // @set iat = '$.index[*][?(@.docs=="iat")].id'
-// @is '$.index[*][?(@.docs=="impl")].inner.items[*]' $iat
-// @is '$.index[*][?(@.docs=="iat")].kind' '"assoc_type"'
-// @is '$.index[*][?(@.docs=="iat")].inner.default.inner.id' $OwnerMetadata
+// @is '$.index[*][?(@.docs=="impl")].inner.impl.items[*]' $iat
+// @is '$.index[*][?(@.docs=="iat")].inner.assoc_type.default.resolved_path.id' $OwnerMetadata
diff --git a/tests/rustdoc-json/type/inherent_associated_type_bound.rs b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
index a089600b692..2e9b13d0cac 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_bound.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_bound.rs
@@ -5,14 +5,12 @@
 // @set Carrier = '$.index[*][?(@.name=="Carrier")].id'
 pub struct Carrier<'a>(&'a ());
 
-// @is '$.index[*][?(@.name=="User")].inner.type.kind' '"function_pointer"'
-// @is '$.index[*][?(@.name=="User")].inner.type.inner.generic_params[*].name' \""'b"\"
-// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].kind' '"qualified_path"'
-// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.self_type.inner.id' $Carrier
-// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.self_type.inner.args.angle_bracketed.args[0].lifetime' \""'b"\"
-// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.name' '"Focus"'
-// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.trait' null
-// @is '$.index[*][?(@.name=="User")].inner.type.inner.decl.inputs[0][1].inner.args.angle_bracketed.args[0].type.inner' '"i32"'
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.generic_params[*].name' \""'b"\"
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.id' $Carrier
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].lifetime' \""'b"\"
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.name' '"Focus"'
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.trait' null
+// @is '$.index[*][?(@.name=="User")].inner.typedef.type.function_pointer.decl.inputs[0][1].qualified_path.args.angle_bracketed.args[0].type.primitive' '"i32"'
 
 pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
 
diff --git a/tests/rustdoc-json/type/inherent_associated_type_projections.rs b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
index 30c68bfe56c..942e323efca 100644
--- a/tests/rustdoc-json/type/inherent_associated_type_projections.rs
+++ b/tests/rustdoc-json/type/inherent_associated_type_projections.rs
@@ -5,11 +5,10 @@
 // @set Parametrized = '$.index[*][?(@.name=="Parametrized")].id'
 pub struct Parametrized<T>(T);
 
-// @is '$.index[*][?(@.name=="Test")].inner.type.kind' '"qualified_path"'
-// @is '$.index[*][?(@.name=="Test")].inner.type.inner.self_type.inner.id' $Parametrized
-// @is '$.index[*][?(@.name=="Test")].inner.type.inner.self_type.inner.args.angle_bracketed.args[0].type' '{"inner": "i32", "kind": "primitive"}'
-// @is '$.index[*][?(@.name=="Test")].inner.type.inner.name' '"Proj"'
-// @is '$.index[*][?(@.name=="Test")].inner.type.inner.trait' null
+// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.id' $Parametrized
+// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.self_type.resolved_path.args.angle_bracketed.args[0].type.primitive' \"i32\"
+// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.name' '"Proj"'
+// @is '$.index[*][?(@.name=="Test")].inner.typedef.type.qualified_path.trait' null
 pub type Test = Parametrized<i32>::Proj;
 
 /// param_bool
@@ -29,5 +28,5 @@ impl Parametrized<i32> {
 // @set param_bool_proj = '$.index[*][?(@.docs=="param_bool_proj")].id'
 // @set param_i32_proj = '$.index[*][?(@.docs=="param_i32_proj")].id'
 
-// @is '$.index[*][?(@.docs=="param_bool")].inner.items[*]' $param_bool_proj
-// @is '$.index[*][?(@.docs=="param_i32")].inner.items[*]' $param_i32_proj
+// @is '$.index[*][?(@.docs=="param_bool")].inner.impl.items[*]' $param_bool_proj
+// @is '$.index[*][?(@.docs=="param_i32")].inner.impl.items[*]' $param_i32_proj
diff --git a/tests/rustdoc-json/unions/impl.rs b/tests/rustdoc-json/unions/impl.rs
index 4454a69ecd1..7456892df1b 100644
--- a/tests/rustdoc-json/unions/impl.rs
+++ b/tests/rustdoc-json/unions/impl.rs
@@ -1,15 +1,15 @@
 #![no_std]
 
 // @is "$.index[*][?(@.name=='Ux')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='Ux')].kind" \"union\"
+// @has "$.index[*][?(@.name=='Ux')].inner.union"
 pub union Ux {
     a: u32,
     b: u64
 }
 
 // @is "$.index[*][?(@.name=='Num')].visibility" \"public\"
-// @is "$.index[*][?(@.name=='Num')].kind" \"trait\"
+// @has "$.index[*][?(@.name=='Num')].inner.trait"
 pub trait Num {}
 
-// @count "$.index[*][?(@.name=='Ux')].inner.impls" 1
+// @count "$.index[*][?(@.name=='Ux')].inner.union.impls" 1
 impl Num for Ux {}
diff --git a/tests/rustdoc-json/unions/union.rs b/tests/rustdoc-json/unions/union.rs
index c9df2b81c4b..22b70e1ce8c 100644
--- a/tests/rustdoc-json/unions/union.rs
+++ b/tests/rustdoc-json/unions/union.rs
@@ -1,6 +1,6 @@
 // @has "$.index[*][?(@.name=='Union')].visibility" \"public\"
-// @has "$.index[*][?(@.name=='Union')].kind" \"union\"
-// @!has "$.index[*][?(@.name=='Union')].inner.struct_type"
+// @has "$.index[*][?(@.name=='Union')].inner.union"
+// @!has "$.index[*][?(@.name=='Union')].inner.union.struct_type"
 // @set Union = "$.index[*][?(@.name=='Union')].id"
 pub union Union {
     int: i32,
@@ -8,8 +8,8 @@ pub union Union {
 }
 
 
-// @is "$.index[*][?(@.name=='make_int_union')].inner.decl.output.kind" '"resolved_path"'
-// @is "$.index[*][?(@.name=='make_int_union')].inner.decl.output.inner.id" $Union
+// @has "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path"
+// @is "$.index[*][?(@.name=='make_int_union')].inner.function.decl.output.resolved_path.id" $Union
 pub fn make_int_union(int: i32) -> Union {
     Union { int }
 }
diff --git a/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs
new file mode 100644
index 00000000000..4e74278dc7b
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.rs
@@ -0,0 +1,10 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/111189>.
+// This test ensures that it doesn't crash.
+
+#![deny(warnings)]
+
+/// #[rustfmt::skip]
+//~^ ERROR unresolved link to `rustfmt::skip`
+/// #[clippy::whatever]
+//~^ ERROR unresolved link to `clippy::whatever`
+pub fn foo() {}
diff --git a/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr
new file mode 100644
index 00000000000..edd3dfa7d7e
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/issue-111189-resolution-ice.stderr
@@ -0,0 +1,21 @@
+error: unresolved link to `rustfmt::skip`
+  --> $DIR/issue-111189-resolution-ice.rs:6:7
+   |
+LL | /// #[rustfmt::skip]
+   |       ^^^^^^^^^^^^^ no item named `rustfmt` in scope
+   |
+note: the lint level is defined here
+  --> $DIR/issue-111189-resolution-ice.rs:4:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
+
+error: unresolved link to `clippy::whatever`
+  --> $DIR/issue-111189-resolution-ice.rs:8:7
+   |
+LL | /// #[clippy::whatever]
+   |       ^^^^^^^^^^^^^^^^ no item named `clippy` in scope
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/rustdoc/strikethrough-in-summary.rs b/tests/rustdoc/strikethrough-in-summary.rs
new file mode 100644
index 00000000000..cb6cd0e7ba6
--- /dev/null
+++ b/tests/rustdoc/strikethrough-in-summary.rs
@@ -0,0 +1,6 @@
+#![crate_name = "foo"]
+
+// @has foo/index.html '//del' 'strike'
+
+/// ~~strike~~
+pub fn strike() {}
diff --git a/tests/ui/associated-inherent-types/inference.rs b/tests/ui/associated-inherent-types/inference.rs
index 7d6d26003f6..ebd8e1d5594 100644
--- a/tests/ui/associated-inherent-types/inference.rs
+++ b/tests/ui/associated-inherent-types/inference.rs
@@ -3,7 +3,7 @@
 
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::convert::identity;
 
diff --git a/tests/ui/associated-inherent-types/issue-111879-0.rs b/tests/ui/associated-inherent-types/issue-111879-0.rs
new file mode 100644
index 00000000000..e37f7d34ab5
--- /dev/null
+++ b/tests/ui/associated-inherent-types/issue-111879-0.rs
@@ -0,0 +1,14 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that we don't crash when printing inherent projections in diagnostics.
+
+pub struct Carrier<'a>(&'a ());
+
+pub type User = for<'b> fn(Carrier<'b>::Focus<i32>);
+
+impl<'a> Carrier<'a> {
+    pub type Focus<T> = &'a mut User; //~ ERROR overflow evaluating associated type
+}
+
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-111879-0.stderr b/tests/ui/associated-inherent-types/issue-111879-0.stderr
new file mode 100644
index 00000000000..7bdbad44017
--- /dev/null
+++ b/tests/ui/associated-inherent-types/issue-111879-0.stderr
@@ -0,0 +1,8 @@
+error: overflow evaluating associated type `Carrier<'b>::Focus<i32>`
+  --> $DIR/issue-111879-0.rs:11:25
+   |
+LL |     pub type Focus<T> = &'a mut User;
+   |                         ^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/associated-inherent-types/issue-111879-1.rs b/tests/ui/associated-inherent-types/issue-111879-1.rs
new file mode 100644
index 00000000000..7acc4f94505
--- /dev/null
+++ b/tests/ui/associated-inherent-types/issue-111879-1.rs
@@ -0,0 +1,12 @@
+#![feature(inherent_associated_types)]
+#![allow(incomplete_features)]
+
+// Check that we don't crash when printing inherent projections in diagnostics.
+
+struct Foo<T>(T);
+
+impl<'a> Foo<fn(&'a ())> {
+    type Assoc = &'a ();
+}
+
+fn main(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {} //~ ERROR `main` function has wrong type
diff --git a/tests/ui/associated-inherent-types/issue-111879-1.stderr b/tests/ui/associated-inherent-types/issue-111879-1.stderr
new file mode 100644
index 00000000000..689b45e09aa
--- /dev/null
+++ b/tests/ui/associated-inherent-types/issue-111879-1.stderr
@@ -0,0 +1,12 @@
+error[E0580]: `main` function has wrong type
+  --> $DIR/issue-111879-1.rs:12:1
+   |
+LL | fn main(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters
+   |
+   = note: expected fn pointer `fn()`
+              found fn pointer `fn(for<'a> fn(Foo<fn(&'a ())>::Assoc))`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0580`.
diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.rs b/tests/ui/async-await/return-type-notation/supertrait-bound.rs
new file mode 100644
index 00000000000..19bcfe3046b
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/supertrait-bound.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(return_position_impl_trait_in_trait, return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete and may not be safe to use
+
+trait IntFactory {
+    fn stream(&self) -> impl Iterator<Item = i32>;
+}
+trait SendIntFactory: IntFactory<stream(): Send> + Send {}
+
+fn main() {}
diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.stderr b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr
new file mode 100644
index 00000000000..c8cec4946b4
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/supertrait-bound.rs:3:49
+   |
+LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)]
+   |                                                 ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
index 9163c8ed6fb..60128c9419d 100644
--- a/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
+++ b/tests/ui/borrowck/borrowck-closures-slice-patterns-ok.rs
@@ -1,7 +1,7 @@
 // Check that closure captures for slice patterns are inferred correctly
 
 #![allow(unused_variables)]
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 // run-pass
 
diff --git a/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs b/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs
index a88b323e0bf..78e965cc4bc 100644
--- a/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs
+++ b/tests/ui/borrowck/borrowck-field-sensitivity-rpass.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(unused_mut)]
 #![allow(unused_variables)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 // pretty-expanded FIXME #23616
 
 struct A { a: isize, b: Box<isize> }
diff --git a/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs b/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs
index 40c6bfeeb43..9acb1ec5e43 100644
--- a/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs
+++ b/tests/ui/borrowck/borrowck-use-mut-borrow-rpass.rs
@@ -1,7 +1,7 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 struct A { a: isize, b: Box<isize> }
 
diff --git a/tests/ui/cfg/cfg-stmt-recovery.rs b/tests/ui/cfg/cfg-stmt-recovery.rs
new file mode 100644
index 00000000000..2e0839d2a15
--- /dev/null
+++ b/tests/ui/cfg/cfg-stmt-recovery.rs
@@ -0,0 +1,13 @@
+// Verify that we do not ICE when failing to parse a statement in `cfg_eval`.
+
+#![feature(cfg_eval)]
+#![feature(stmt_expr_attributes)]
+
+#[cfg_eval]
+fn main() {
+    #[cfg_eval]
+    let _ = #[cfg(FALSE)] 0;
+    //~^ ERROR removing an expression is not supported in this position
+    //~| ERROR expected expression, found `;`
+    //~| ERROR removing an expression is not supported in this position
+}
diff --git a/tests/ui/cfg/cfg-stmt-recovery.stderr b/tests/ui/cfg/cfg-stmt-recovery.stderr
new file mode 100644
index 00000000000..cb15e21fac6
--- /dev/null
+++ b/tests/ui/cfg/cfg-stmt-recovery.stderr
@@ -0,0 +1,20 @@
+error: removing an expression is not supported in this position
+  --> $DIR/cfg-stmt-recovery.rs:9:13
+   |
+LL |     let _ = #[cfg(FALSE)] 0;
+   |             ^^^^^^^^^^^^^
+
+error: expected expression, found `;`
+  --> $DIR/cfg-stmt-recovery.rs:9:28
+   |
+LL |     let _ = #[cfg(FALSE)] 0;
+   |                            ^ expected expression
+
+error: removing an expression is not supported in this position
+  --> $DIR/cfg-stmt-recovery.rs:9:13
+   |
+LL |     let _ = #[cfg(FALSE)] 0;
+   |             ^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
index bc7295a0826..98f8d5d4733 100644
--- a/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
+++ b/tests/ui/closures/2229_closure_analysis/migrations/issue-78720.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 #![warn(rust_2021_incompatible_closure_captures)]
-#![allow(drop_ref, drop_copy)]
+#![allow(dropping_references, dropping_copy_types)]
 
 fn main() {
     if let a = "" {
diff --git a/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs b/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
index 0f15f664e75..5496d0e5fc7 100644
--- a/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
+++ b/tests/ui/closures/2229_closure_analysis/optimization/edge_case_run_pass.rs
@@ -3,7 +3,7 @@
 
 #![allow(unused)]
 #![allow(dead_code)]
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Int(i32);
 struct B<'a>(&'a i32);
diff --git a/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs b/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
index a097424a021..b5e97ec1c1b 100644
--- a/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
+++ b/tests/ui/closures/2229_closure_analysis/run_pass/drop_then_use_fake_reads.rs
@@ -2,7 +2,7 @@
 // check-pass
 
 #![feature(rustc_attrs)]
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 fn main() {
     let mut x = 1;
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
index a1b711a3024..87ae83dd966 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs
@@ -11,6 +11,13 @@ struct S<T> {
 
 impl<T: ConstParamTy> ConstParamTy for S<T> {}
 
+#[derive(PartialEq, Eq, ConstParamTy)]
+struct D<T> {
+    field: u8,
+    gen: T,
+}
+
+
 fn check<T: ConstParamTy + ?Sized>() {}
 
 fn main() {
@@ -39,5 +46,8 @@ fn main() {
     check::<S<u8>>();
     check::<S<[&[bool]; 8]>>();
 
+    check::<D<u8>>();
+    check::<D<[&[bool]; 8]>>();
+
     // FIXME: test tuples
 }
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
index 07fd243737e..74283a37afc 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs
@@ -10,4 +10,8 @@ struct CantParam(NotParam);
 impl std::marker::ConstParamTy for CantParam {}
 //~^ error: the trait `ConstParamTy` cannot be implemented for this type
 
+#[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+//~^ error: the trait `ConstParamTy` cannot be implemented for this type
+struct CantParamDerive(NotParam);
+
 fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
index c8e065848b1..52b65d6061a 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr
@@ -7,6 +7,17 @@ LL |
 LL | impl std::marker::ConstParamTy for CantParam {}
    |                                    ^^^^^^^^^
 
-error: aborting due to previous error
+error[E0204]: the trait `ConstParamTy` cannot be implemented for this type
+  --> $DIR/const_param_ty_impl_bad_field.rs:13:10
+   |
+LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
+LL | struct CantParamDerive(NotParam);
+   |                        -------- this field does not implement `ConstParamTy`
+   |
+   = note: this error originates in the derive macro `std::marker::ConstParamTy` (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 E0204`.
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
index 17ef396164e..37986de481f 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs
@@ -10,6 +10,10 @@ struct CantParam(ImplementsConstParamTy);
 impl std::marker::ConstParamTy for CantParam {}
 //~^ error: the type `CantParam` does not `#[derive(Eq)]`
 
+#[derive(std::marker::ConstParamTy)]
+//~^ error: the type `CantParamDerive` does not `#[derive(Eq)]`
+struct CantParamDerive(ImplementsConstParamTy);
+
 fn check<T: std::marker::ConstParamTy>() {}
 
 fn main() {
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
index ca5abf5e254..52701d55914 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr
@@ -7,6 +7,16 @@ LL | impl std::marker::ConstParamTy for CantParam {}
 note: required by a bound in `ConstParamTy`
   --> $SRC_DIR/core/src/marker.rs:LL:COL
 
-error: aborting due to previous error
+error[E0277]: the type `CantParamDerive` does not `#[derive(Eq)]`
+  --> $DIR/const_param_ty_impl_no_structural_eq.rs:13:10
+   |
+LL | #[derive(std::marker::ConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParamDerive`
+   |
+note: required by a bound in `ConstParamTy`
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+   = note: this error originates in the derive macro `std::marker::ConstParamTy` (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 E0277`.
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
new file mode 100644
index 00000000000..d70377a20c1
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.rs
@@ -0,0 +1,33 @@
+#![allow(incomplete_features)]
+#![feature(adt_const_params, structural_match)]
+
+union Union {
+    a: u8,
+}
+
+impl PartialEq for Union {
+    fn eq(&self, other: &Union) -> bool {
+        true
+    }
+}
+impl Eq for Union {}
+impl std::marker::StructuralEq for Union {}
+
+impl std::marker::ConstParamTy for Union {}
+
+#[derive(std::marker::ConstParamTy)]
+//~^ ERROR this trait cannot be derived for unions
+union UnionDerive {
+    a: u8,
+}
+
+impl PartialEq for UnionDerive {
+    fn eq(&self, other: &UnionDerive) -> bool {
+        true
+    }
+}
+impl Eq for UnionDerive {}
+impl std::marker::StructuralEq for UnionDerive {}
+
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
new file mode 100644
index 00000000000..29370304605
--- /dev/null
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_union.stderr
@@ -0,0 +1,8 @@
+error: this trait cannot be derived for unions
+  --> $DIR/const_param_ty_impl_union.rs:18:10
+   |
+LL | #[derive(std::marker::ConstParamTy)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/consts/const_forget.rs b/tests/ui/consts/const_forget.rs
index acdd6a54cf4..f06149f2cb9 100644
--- a/tests/ui/consts/const_forget.rs
+++ b/tests/ui/consts/const_forget.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![allow(forget_copy)]
+#![allow(forgetting_copy_types)]
 
 use std::mem::forget;
 
diff --git a/tests/ui/consts/issue-104155.rs b/tests/ui/consts/issue-104155.rs
index b3821f467b6..7b375dc0566 100644
--- a/tests/ui/consts/issue-104155.rs
+++ b/tests/ui/consts/issue-104155.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![allow(forget_copy)]
+#![allow(forgetting_copy_types)]
 
 const _: () = core::mem::forget(Box::<u32>::default);
 const _: () = core::mem::forget(|| Box::<u32>::default());
diff --git a/tests/ui/crate-leading-sep.rs b/tests/ui/crate-leading-sep.rs
index 8d1d0b4fcdf..fce97d9ba23 100644
--- a/tests/ui/crate-leading-sep.rs
+++ b/tests/ui/crate-leading-sep.rs
@@ -1,7 +1,7 @@
 // run-pass
 // pretty-expanded FIXME #23616
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 fn main() {
     use ::std::mem;
diff --git a/tests/ui/drop/issue-110682.rs b/tests/ui/drop/issue-110682.rs
new file mode 100644
index 00000000000..35f9c7e8d9b
--- /dev/null
+++ b/tests/ui/drop/issue-110682.rs
@@ -0,0 +1,92 @@
+// build-pass
+// compile-flags: -Zmir-opt-level=3
+
+use std::fmt::Debug;
+use std::mem::ManuallyDrop;
+use std::ptr;
+
+pub trait BitRegister {}
+
+macro_rules! register {
+    ($($t:ty),+ $(,)?) => { $(
+        impl BitRegister for $t {
+        }
+    )* };
+}
+
+register!(u8, u16, u32);
+
+pub trait BitStore: Sized + Debug {
+    /// The register type that the implementor describes.
+    type Mem: BitRegister + Into<Self>;
+}
+
+macro_rules! store {
+    ($($t:ty),+ $(,)?) => { $(
+        impl BitStore for $t {
+            type Mem = Self;
+        }
+    )+ };
+}
+
+store!(u8, u16, u32,);
+
+#[repr(C)]
+pub struct BitVec<T>
+where
+    T: BitStore,
+{
+    /// Region pointer describing the live portion of the owned buffer.
+    pointer: ptr::NonNull<T>,
+    /// Allocated capacity, in elements `T`, of the owned buffer.
+    capacity: usize,
+}
+
+impl<T> BitVec<T>
+where
+    T: BitStore,
+{
+    pub fn new() -> Self {
+        let pointer = ptr::NonNull::<T>::new(ptr::null_mut()).unwrap();
+
+        BitVec { pointer, capacity: 10 }
+    }
+
+    pub fn clear(&mut self) {
+        unsafe {
+            self.set_len(0);
+        }
+    }
+
+    #[inline]
+    pub unsafe fn set_len(&mut self, new_len: usize) {}
+
+    fn with_vec<F, R>(&mut self, func: F) -> R
+    where
+        F: FnOnce(&mut ManuallyDrop<Vec<T::Mem>>) -> R,
+    {
+        let cap = self.capacity;
+        let elts = 10;
+        let mut vec = ManuallyDrop::new(unsafe { Vec::from_raw_parts(ptr::null_mut(), elts, cap) });
+        let out = func(&mut vec);
+
+        out
+    }
+}
+
+impl<T> Drop for BitVec<T>
+where
+    T: BitStore,
+{
+    #[inline]
+    fn drop(&mut self) {
+        //  The buffer elements do not have destructors.
+        self.clear();
+        //  Run the `Vec` destructor to deällocate the buffer.
+        self.with_vec(|vec| unsafe { ManuallyDrop::drop(vec) });
+    }
+}
+
+fn main() {
+    let bitvec = BitVec::<u32>::new();
+}
diff --git a/tests/ui/drop/repeat-drop.rs b/tests/ui/drop/repeat-drop.rs
index 659d35db657..0afb4bb11bc 100644
--- a/tests/ui/drop/repeat-drop.rs
+++ b/tests/ui/drop/repeat-drop.rs
@@ -1,7 +1,7 @@
 // run-pass
 // needs-unwind
 
-#![allow(drop_ref, drop_copy)]
+#![allow(dropping_references, dropping_copy_types)]
 
 static mut CHECK: usize = 0;
 
diff --git a/tests/ui/dyn-star/param-env-infer.current.stderr b/tests/ui/dyn-star/param-env-infer.current.stderr
new file mode 100644
index 00000000000..d0785c887d8
--- /dev/null
+++ b/tests/ui/dyn-star/param-env-infer.current.stderr
@@ -0,0 +1,18 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/param-env-infer.rs:5:12
+   |
+LL | #![feature(dyn_star, pointer_like_trait)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0282]: type annotations needed
+  --> $DIR/param-env-infer.rs:12:10
+   |
+LL |     t as _
+   |          ^ cannot infer type
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/dyn-star/param-env-infer.next.stderr b/tests/ui/dyn-star/param-env-infer.next.stderr
new file mode 100644
index 00000000000..d0785c887d8
--- /dev/null
+++ b/tests/ui/dyn-star/param-env-infer.next.stderr
@@ -0,0 +1,18 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/param-env-infer.rs:5:12
+   |
+LL | #![feature(dyn_star, pointer_like_trait)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0282]: type annotations needed
+  --> $DIR/param-env-infer.rs:12:10
+   |
+LL |     t as _
+   |          ^ cannot infer type
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/dyn-star/param-env-infer.rs b/tests/ui/dyn-star/param-env-infer.rs
new file mode 100644
index 00000000000..9039dde5e93
--- /dev/null
+++ b/tests/ui/dyn-star/param-env-infer.rs
@@ -0,0 +1,16 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+// incremental
+
+#![feature(dyn_star, pointer_like_trait)]
+//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+
+use std::fmt::Debug;
+use std::marker::PointerLike;
+
+fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
+    t as _
+    //~^ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/tests/ui/error-codes/E0746.fixed b/tests/ui/error-codes/E0746.fixed
deleted file mode 100644
index ca8319aa020..00000000000
--- a/tests/ui/error-codes/E0746.fixed
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-rustfix
-#![allow(dead_code)]
-struct Struct;
-trait Trait {}
-impl Trait for Struct {}
-impl Trait for u32 {}
-
-fn foo() -> impl Trait { Struct }
-//~^ ERROR E0746
-
-fn bar() -> impl Trait { //~ ERROR E0746
-    if true {
-        return 0;
-    }
-    42
-}
-
-fn main() {}
diff --git a/tests/ui/error-codes/E0746.rs b/tests/ui/error-codes/E0746.rs
index bf5ba8fff56..86b5b7444d1 100644
--- a/tests/ui/error-codes/E0746.rs
+++ b/tests/ui/error-codes/E0746.rs
@@ -1,5 +1,5 @@
-// run-rustfix
 #![allow(dead_code)]
+
 struct Struct;
 trait Trait {}
 impl Trait for Struct {}
diff --git a/tests/ui/error-codes/E0746.stderr b/tests/ui/error-codes/E0746.stderr
index 2153b59ad18..9fe90ab7bec 100644
--- a/tests/ui/error-codes/E0746.stderr
+++ b/tests/ui/error-codes/E0746.stderr
@@ -4,11 +4,14 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn foo() -> dyn Trait { Struct }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn foo() -> impl Trait { Struct }
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL | fn foo() -> Box<dyn Trait> { Box::new(Struct) }
+   |             ++++         +   +++++++++      +
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/E0746.rs:11:13
@@ -16,11 +19,18 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bar() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn bar() -> impl Trait {
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bar() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         return Box::new(0);
+LL |     }
+LL ~     Box::new(42)
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed
index 0bc4feed329..bb093a4af4a 100644
--- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed
+++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Foo {
     x: isize
diff --git a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs
index 26ae6698d66..1a9f89c054f 100644
--- a/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs
+++ b/tests/ui/explicit/explicit-call-to-supertrait-dtor.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Foo {
     x: isize
diff --git a/tests/ui/generator/drop-env.rs b/tests/ui/generator/drop-env.rs
index cb46953dac3..137a407931a 100644
--- a/tests/ui/generator/drop-env.rs
+++ b/tests/ui/generator/drop-env.rs
@@ -4,7 +4,7 @@
 //[nomiropt]compile-flags: -Z mir-opt-level=0
 
 #![feature(generators, generator_trait)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::ops::Generator;
 use std::pin::Pin;
diff --git a/tests/ui/generator/issue-57017.rs b/tests/ui/generator/issue-57017.rs
index 918d233bf4e..381897c77a5 100644
--- a/tests/ui/generator/issue-57017.rs
+++ b/tests/ui/generator/issue-57017.rs
@@ -5,7 +5,7 @@
 // [drop_tracking_mir] build-pass
 
 #![feature(generators, negative_impls)]
-#![allow(drop_ref, drop_copy)]
+#![allow(dropping_references, dropping_copy_types)]
 
 macro_rules! type_combinations {
     (
diff --git a/tests/ui/generator/non-static-is-unpin.rs b/tests/ui/generator/non-static-is-unpin.rs
index adba800e25a..a5dde3912cc 100644
--- a/tests/ui/generator/non-static-is-unpin.rs
+++ b/tests/ui/generator/non-static-is-unpin.rs
@@ -3,7 +3,7 @@
 // run-pass
 
 #![feature(generators, generator_trait)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::marker::{PhantomPinned, Unpin};
 
diff --git a/tests/ui/generator/resume-arg-size.rs b/tests/ui/generator/resume-arg-size.rs
index 19618f8d0aa..195166f975b 100644
--- a/tests/ui/generator/resume-arg-size.rs
+++ b/tests/ui/generator/resume-arg-size.rs
@@ -1,5 +1,5 @@
 #![feature(generators)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 // run-pass
 
diff --git a/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs b/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs
index 214267372bf..721bb7281c0 100644
--- a/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs
+++ b/tests/ui/hygiene/stdlib-prelude-from-opaque-late.rs
@@ -1,7 +1,7 @@
 // check-pass
 
 #![feature(decl_macro)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 macro mac() {
     mod m {
diff --git a/tests/ui/illegal-ufcs-drop.fixed b/tests/ui/illegal-ufcs-drop.fixed
index 8783682dec4..c088c82791b 100644
--- a/tests/ui/illegal-ufcs-drop.fixed
+++ b/tests/ui/illegal-ufcs-drop.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Foo;
 
diff --git a/tests/ui/illegal-ufcs-drop.rs b/tests/ui/illegal-ufcs-drop.rs
index 29774306ec6..1389b112188 100644
--- a/tests/ui/illegal-ufcs-drop.rs
+++ b/tests/ui/illegal-ufcs-drop.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 struct Foo;
 
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
index cbf1daabe2b..af368203de0 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.rs
@@ -26,7 +26,7 @@ fn bax() -> dyn Trait { //~ ERROR E0746
     if true {
         Struct
     } else {
-        42 //~ ERROR `if` and `else` have incompatible types
+        42
     }
 }
 fn bam() -> Box<dyn Trait> {
diff --git a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
index dc1e40ea560..ed9261d0de5 100644
--- a/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
+++ b/tests/ui/impl-trait/dyn-trait-return-should-be-impl-trait.stderr
@@ -46,11 +46,10 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bap() -> Trait { Struct }
    |             ^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL | fn bap() -> impl Trait { Struct }
-   |             ~~~~~~~~~~
+LL | fn bap() -> Box<Trait> { Box::new(Struct) }
+   |             ++++     +   +++++++++      +
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:15:13
@@ -58,11 +57,14 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn ban() -> dyn Trait { Struct }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `Struct`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn ban() -> impl Trait { Struct }
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL | fn ban() -> Box<dyn Trait> { Box::new(Struct) }
+   |             ++++         +   +++++++++      +
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:17:13
@@ -70,14 +72,14 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bak() -> dyn Trait { unimplemented!() }
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: use `impl Trait` as the return type if all return paths have the same type but you want to expose only the trait in the signature
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn bak() -> impl Trait { unimplemented!() }
-   |             ~~~~~~~~~~
-help: use a boxed trait object if all return paths implement trait `Trait`
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL | fn bak() -> Box<dyn Trait> { unimplemented!() }
-   |             ++++         +
+LL | fn bak() -> Box<dyn Trait> { Box::new(unimplemented!()) }
+   |             ++++         +   +++++++++                +
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:19:13
@@ -85,34 +87,18 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bal() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl Trait` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | fn bal() -> Box<dyn Trait> {
-   |             ++++         +
-help: ... and box this value
+LL | fn bal() -> impl Trait {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL |         return Box::new(Struct);
-   |                +++++++++      +
-help: ... and box this value
+LL ~ fn bal() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         return Box::new(Struct);
+LL |     }
+LL ~     Box::new(42)
    |
-LL |     Box::new(42)
-   |     +++++++++  +
-
-error[E0308]: `if` and `else` have incompatible types
-  --> $DIR/dyn-trait-return-should-be-impl-trait.rs:29:9
-   |
-LL | /     if true {
-LL | |         Struct
-   | |         ------ expected because of this
-LL | |     } else {
-LL | |         42
-   | |         ^^ expected `Struct`, found integer
-LL | |     }
-   | |_____- `if` and `else` have incompatible types
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:25:13
@@ -120,22 +106,18 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bax() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl Trait` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | fn bax() -> Box<dyn Trait> {
-   |             ++++         +
-help: ... and box this value
+LL | fn bax() -> impl Trait {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL |         Box::new(Struct)
-   |         +++++++++      +
-help: ... and box this value
+LL ~ fn bax() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         Box::new(Struct)
+LL |     } else {
+LL ~         Box::new(42)
    |
-LL |         Box::new(42)
-   |         +++++++++  +
 
 error[E0308]: mismatched types
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:34:16
@@ -279,11 +261,18 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bat() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn bat() -> impl Trait {
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bat() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         return Box::new(0);
+LL |     }
+LL ~     Box::new(42)
+   |
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/dyn-trait-return-should-be-impl-trait.rs:66:13
@@ -291,13 +280,20 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn bay() -> dyn Trait {
    |             ^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Trait` as the return type, as all return paths are of type `{integer}`, which implements `Trait`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn bay() -> impl Trait {
-   |             ~~~~~~~~~~
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL ~ fn bay() -> Box<dyn Trait> {
+LL |     if true {
+LL ~         Box::new(0)
+LL |     } else {
+LL ~         Box::new(42)
+   |
 
-error: aborting due to 20 previous errors
+error: aborting due to 19 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0746.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
index fa7664a83ee..a8a6288eb56 100644
--- a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
+++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.rs
@@ -77,7 +77,7 @@ fn hat() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed
 fn pug() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed trait object
     match 13 {
         0 => 0i32,
-        1 => 1u32, //~ ERROR `match` arms have incompatible types
+        1 => 1u32,
         _ => 2u32,
     }
 }
@@ -86,7 +86,7 @@ fn man() -> dyn std::fmt::Display { //~ ERROR return type cannot have an unboxed
     if false {
         0i32
     } else {
-        1u32 //~ ERROR `if` and `else` have incompatible types
+        1u32
     }
 }
 
diff --git a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
index 3c65fd998c5..9205d74504f 100644
--- a/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
+++ b/tests/ui/impl-trait/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -171,39 +171,20 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn hat() -> dyn std::fmt::Display {
    |             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
-   |
-LL | fn hat() -> Box<dyn std::fmt::Display> {
-   |             ++++                     +
-help: ... and box this value
-   |
-LL |             return Box::new(0i32);
-   |                    +++++++++    +
-help: ... and box this value
-   |
-LL |             Box::new(1u32)
-   |             +++++++++    +
-
-error[E0308]: `match` arms have incompatible types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:80:14
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | /     match 13 {
-LL | |         0 => 0i32,
-   | |              ---- this is found to be of type `i32`
-LL | |         1 => 1u32,
-   | |              ^^^^ expected `i32`, found `u32`
-LL | |         _ => 2u32,
-LL | |     }
-   | |_____- `match` arms have incompatible types
+LL | fn hat() -> impl std::fmt::Display {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-help: change the type of the numeric literal from `u32` to `i32`
+LL ~ fn hat() -> Box<dyn std::fmt::Display> {
+LL |     match 13 {
+LL |         0 => {
+LL ~             return Box::new(0i32);
+LL |         }
+LL |         _ => {
+LL ~             Box::new(1u32)
    |
-LL |         1 => 1i32,
-   |               ~~~
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13
@@ -211,43 +192,18 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn pug() -> dyn std::fmt::Display {
    |             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
-   |
-LL | fn pug() -> Box<dyn std::fmt::Display> {
-   |             ++++                     +
-help: ... and box this value
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL |         0 => Box::new(0i32),
-   |              +++++++++    +
-help: ... and box this value
-   |
-LL |         1 => Box::new(1u32),
-   |              +++++++++    +
-help: ... and box this value
-   |
-LL |         _ => Box::new(2u32),
-   |              +++++++++    +
-
-error[E0308]: `if` and `else` have incompatible types
-  --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:89:9
+LL | fn pug() -> impl std::fmt::Display {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL | /     if false {
-LL | |         0i32
-   | |         ---- expected because of this
-LL | |     } else {
-LL | |         1u32
-   | |         ^^^^ expected `i32`, found `u32`
-LL | |     }
-   | |_____- `if` and `else` have incompatible types
-   |
-help: change the type of the numeric literal from `u32` to `i32`
+LL ~ fn pug() -> Box<dyn std::fmt::Display> {
+LL |     match 13 {
+LL ~         0 => Box::new(0i32),
+LL ~         1 => Box::new(1u32),
+LL ~         _ => Box::new(2u32),
    |
-LL |         1i32
-   |          ~~~
 
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13
@@ -255,24 +211,20 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn man() -> dyn std::fmt::Display {
    |             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl std::fmt::Display` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
-LL | fn man() -> Box<dyn std::fmt::Display> {
-   |             ++++                     +
-help: ... and box this value
+LL | fn man() -> impl std::fmt::Display {
+   |             ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL |         Box::new(0i32)
-   |         +++++++++    +
-help: ... and box this value
+LL ~ fn man() -> Box<dyn std::fmt::Display> {
+LL |     if false {
+LL ~         Box::new(0i32)
+LL |     } else {
+LL ~         Box::new(1u32)
    |
-LL |         Box::new(1u32)
-   |         +++++++++    +
 
-error: aborting due to 14 previous errors
+error: aborting due to 12 previous errors
 
 Some errors have detailed explanations: E0308, E0746.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/imports/issue-109148.rs b/tests/ui/imports/issue-109148.rs
new file mode 100644
index 00000000000..694cb494a15
--- /dev/null
+++ b/tests/ui/imports/issue-109148.rs
@@ -0,0 +1,15 @@
+// edition: 2021
+
+// https://github.com/rust-lang/rust/pull/111761#issuecomment-1557777314
+macro_rules! m {
+    () => {
+        extern crate core as std;
+        //~^ ERROR macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+    }
+}
+
+m!();
+
+use std::mem;
+
+fn main() {}
diff --git a/tests/ui/imports/issue-109148.stderr b/tests/ui/imports/issue-109148.stderr
new file mode 100644
index 00000000000..6cc1221cfe9
--- /dev/null
+++ b/tests/ui/imports/issue-109148.stderr
@@ -0,0 +1,13 @@
+error: macro-expanded `extern crate` items cannot shadow names passed with `--extern`
+  --> $DIR/issue-109148.rs:6:9
+   |
+LL |         extern crate core as std;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | m!();
+   | ---- in this macro invocation
+   |
+   = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/imports/issue-109343.rs b/tests/ui/imports/issue-109343.rs
new file mode 100644
index 00000000000..0c10259bcd7
--- /dev/null
+++ b/tests/ui/imports/issue-109343.rs
@@ -0,0 +1,10 @@
+#![crate_type = "lib"]
+
+pub mod f {}
+pub use unresolved::f;
+//~^ ERROR unresolved import `unresolved`
+
+/// [g]
+pub use f as g;
+
+fn main() {}
diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr
new file mode 100644
index 00000000000..8d9a3aee980
--- /dev/null
+++ b/tests/ui/imports/issue-109343.stderr
@@ -0,0 +1,11 @@
+error[E0432]: unresolved import `unresolved`
+  --> $DIR/issue-109343.rs:4:9
+   |
+LL | pub use unresolved::f;
+   |         ^^^^^^^^^^ maybe a missing crate `unresolved`?
+   |
+   = help: consider adding `extern crate unresolved` to use the `unresolved` crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/invalid/foo.natvis.xml b/tests/ui/invalid/foo.natvis.xml
new file mode 100644
index 00000000000..c341a403902
--- /dev/null
+++ b/tests/ui/invalid/foo.natvis.xml
@@ -0,0 +1 @@
+<!-- empty -->
diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.rs b/tests/ui/invalid/invalid-debugger-visualizer-target.rs
index f9dd20dbfed..1efb9555c24 100644
--- a/tests/ui/invalid/invalid-debugger-visualizer-target.rs
+++ b/tests/ui/invalid/invalid-debugger-visualizer-target.rs
@@ -1,2 +1,2 @@
-#[debugger_visualizer(natvis_file = "../foo.natvis")] //~ ERROR attribute should be applied to a module
+#[debugger_visualizer(natvis_file = "./foo.natvis.xml")] //~ ERROR attribute should be applied to a module
 fn main() {}
diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr
index 7944f751859..c8a4d681379 100644
--- a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr
+++ b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr
@@ -1,8 +1,8 @@
 error: attribute should be applied to a module
   --> $DIR/invalid-debugger-visualizer-target.rs:1:1
    |
-LL | #[debugger_visualizer(natvis_file = "../foo.natvis")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[debugger_visualizer(natvis_file = "./foo.natvis.xml")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/tests/ui/issues/issue-18107.stderr b/tests/ui/issues/issue-18107.stderr
index 1669b550a9b..cf4e06316a7 100644
--- a/tests/ui/issues/issue-18107.stderr
+++ b/tests/ui/issues/issue-18107.stderr
@@ -4,14 +4,18 @@ error[E0746]: return type cannot have an unboxed trait object
 LL |     dyn AbstractRenderer
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-help: use `impl AbstractRenderer` as the return type if all return paths have the same type but you want to expose only the trait in the signature
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL |     impl AbstractRenderer
+   |     ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-help: use a boxed trait object if all return paths implement trait `AbstractRenderer`
+LL ~     Box<dyn AbstractRenderer>
+LL |
+LL | {
+LL |     match 0 {
+LL ~         _ => Box::new(unimplemented!())
    |
-LL |     Box<dyn AbstractRenderer>
-   |     ++++                    +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/iterators/collect-into-slice.rs b/tests/ui/iterators/collect-into-slice.rs
index 5a8aacb1a6d..045d40a6f71 100644
--- a/tests/ui/iterators/collect-into-slice.rs
+++ b/tests/ui/iterators/collect-into-slice.rs
@@ -14,4 +14,10 @@ fn main() {
     //~| NOTE doesn't have a size known at compile-time
     //~| NOTE doesn't have a size known at compile-time
     process_slice(&some_generated_vec);
+
+    let some_generated_vec = (0..10).collect();
+    //~^ ERROR a slice of type `&[i32]` cannot be built since we need to store the elements somewhere
+    //~| NOTE try explicitly collecting into a `Vec<{integer}>`
+    //~| NOTE required by a bound in `collect`
+    process_slice(some_generated_vec);
 }
diff --git a/tests/ui/iterators/collect-into-slice.stderr b/tests/ui/iterators/collect-into-slice.stderr
index 29fff8c51c6..07dc561f06a 100644
--- a/tests/ui/iterators/collect-into-slice.stderr
+++ b/tests/ui/iterators/collect-into-slice.stderr
@@ -28,6 +28,16 @@ LL |     let some_generated_vec = (0..10).collect();
 note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
-error: aborting due to 3 previous errors
+error[E0277]: a slice of type `&[i32]` cannot be built since we need to store the elements somewhere
+  --> $DIR/collect-into-slice.rs:18:38
+   |
+LL |     let some_generated_vec = (0..10).collect();
+   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
+   |
+   = help: the trait `FromIterator<{integer}>` is not implemented for `&[i32]`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/lint/drop_copy.rs b/tests/ui/lint/dropping_copy_types.rs
index 0adcd34505f..2937320e5d8 100644
--- a/tests/ui/lint/drop_copy.rs
+++ b/tests/ui/lint/dropping_copy_types.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![warn(drop_copy)]
+#![warn(dropping_copy_types)]
 
 use std::mem::drop;
 use std::vec::Vec;
diff --git a/tests/ui/lint/drop_copy.stderr b/tests/ui/lint/dropping_copy_types.stderr
index db8e89ad295..b6291aa5ed6 100644
--- a/tests/ui/lint/drop_copy.stderr
+++ b/tests/ui/lint/dropping_copy_types.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:34:5
+  --> $DIR/dropping_copy_types.rs:34:5
    |
 LL |     drop(s1);
    |     ^^^^^--^
@@ -8,13 +8,13 @@ LL |     drop(s1);
    |
    = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
-  --> $DIR/drop_copy.rs:3:9
+  --> $DIR/dropping_copy_types.rs:3:9
    |
-LL | #![warn(drop_copy)]
-   |         ^^^^^^^^^
+LL | #![warn(dropping_copy_types)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:35:5
+  --> $DIR/dropping_copy_types.rs:35:5
    |
 LL |     drop(s2);
    |     ^^^^^--^
@@ -24,7 +24,7 @@ LL |     drop(s2);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_copy.rs:36:5
+  --> $DIR/dropping_copy_types.rs:36:5
    |
 LL |     drop(s3);
    |     ^^^^^--^
@@ -32,10 +32,10 @@ LL |     drop(s3);
    |          argument has type `&SomeStruct`
    |
    = note: use `let _ = ...` to ignore the expression or result
-   = note: `#[warn(drop_ref)]` on by default
+   = note: `#[warn(dropping_references)]` on by default
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:37:5
+  --> $DIR/dropping_copy_types.rs:37:5
    |
 LL |     drop(s4);
    |     ^^^^^--^
@@ -45,7 +45,7 @@ LL |     drop(s4);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_copy.rs:38:5
+  --> $DIR/dropping_copy_types.rs:38:5
    |
 LL |     drop(s5);
    |     ^^^^^--^
@@ -55,7 +55,7 @@ LL |     drop(s5);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_copy.rs:50:5
+  --> $DIR/dropping_copy_types.rs:50:5
    |
 LL |     drop(a2);
    |     ^^^^^--^
@@ -65,7 +65,7 @@ LL |     drop(a2);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_copy.rs:52:5
+  --> $DIR/dropping_copy_types.rs:52:5
    |
 LL |     drop(a4);
    |     ^^^^^--^
@@ -75,7 +75,7 @@ LL |     drop(a4);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:71:13
+  --> $DIR/dropping_copy_types.rs:71:13
    |
 LL |             drop(println_and(13));
    |             ^^^^^---------------^
@@ -85,7 +85,7 @@ LL |             drop(println_and(13));
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:74:14
+  --> $DIR/dropping_copy_types.rs:74:14
    |
 LL |         3 if drop(println_and(14)) == () => (),
    |              ^^^^^---------------^
@@ -95,7 +95,7 @@ LL |         3 if drop(println_and(14)) == () => (),
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
-  --> $DIR/drop_copy.rs:76:14
+  --> $DIR/dropping_copy_types.rs:76:14
    |
 LL |         4 => drop(2),
    |              ^^^^^-^
diff --git a/tests/ui/lint/drop_ref.rs b/tests/ui/lint/dropping_references.rs
index db4f7569f6f..0d5d484f451 100644
--- a/tests/ui/lint/drop_ref.rs
+++ b/tests/ui/lint/dropping_references.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![warn(drop_ref)]
+#![warn(dropping_references)]
 
 struct SomeStruct;
 
diff --git a/tests/ui/lint/drop_ref.stderr b/tests/ui/lint/dropping_references.stderr
index 04c988fe99d..7e25a46216e 100644
--- a/tests/ui/lint/drop_ref.stderr
+++ b/tests/ui/lint/dropping_references.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:8:5
+  --> $DIR/dropping_references.rs:8:5
    |
 LL |     drop(&SomeStruct);
    |     ^^^^^-----------^
@@ -8,13 +8,13 @@ LL |     drop(&SomeStruct);
    |
    = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
-  --> $DIR/drop_ref.rs:3:9
+  --> $DIR/dropping_references.rs:3:9
    |
-LL | #![warn(drop_ref)]
-   |         ^^^^^^^^
+LL | #![warn(dropping_references)]
+   |         ^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:11:5
+  --> $DIR/dropping_references.rs:11:5
    |
 LL |     drop(&owned1);
    |     ^^^^^-------^
@@ -24,7 +24,7 @@ LL |     drop(&owned1);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:12:5
+  --> $DIR/dropping_references.rs:12:5
    |
 LL |     drop(&&owned1);
    |     ^^^^^--------^
@@ -34,7 +34,7 @@ LL |     drop(&&owned1);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:13:5
+  --> $DIR/dropping_references.rs:13:5
    |
 LL |     drop(&mut owned1);
    |     ^^^^^-----------^
@@ -44,7 +44,7 @@ LL |     drop(&mut owned1);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:17:5
+  --> $DIR/dropping_references.rs:17:5
    |
 LL |     drop(reference1);
    |     ^^^^^----------^
@@ -54,7 +54,7 @@ LL |     drop(reference1);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:20:5
+  --> $DIR/dropping_references.rs:20:5
    |
 LL |     drop(reference2);
    |     ^^^^^----------^
@@ -64,7 +64,7 @@ LL |     drop(reference2);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:23:5
+  --> $DIR/dropping_references.rs:23:5
    |
 LL |     drop(reference3);
    |     ^^^^^----------^
@@ -74,7 +74,7 @@ LL |     drop(reference3);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:28:5
+  --> $DIR/dropping_references.rs:28:5
    |
 LL |     drop(&val);
    |     ^^^^^----^
@@ -84,7 +84,7 @@ LL |     drop(&val);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:36:5
+  --> $DIR/dropping_references.rs:36:5
    |
 LL |     std::mem::drop(&SomeStruct);
    |     ^^^^^^^^^^^^^^^-----------^
@@ -94,7 +94,7 @@ LL |     std::mem::drop(&SomeStruct);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:91:13
+  --> $DIR/dropping_references.rs:91:13
    |
 LL |             drop(println_and(&13));
    |             ^^^^^----------------^
@@ -104,7 +104,7 @@ LL |             drop(println_and(&13));
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:94:14
+  --> $DIR/dropping_references.rs:94:14
    |
 LL |         3 if drop(println_and(&14)) == () => (),
    |              ^^^^^----------------^
@@ -114,7 +114,7 @@ LL |         3 if drop(println_and(&14)) == () => (),
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::drop` with a reference instead of an owned value does nothing
-  --> $DIR/drop_ref.rs:96:14
+  --> $DIR/dropping_references.rs:96:14
    |
 LL |         4 => drop(&2),
    |              ^^^^^--^
diff --git a/tests/ui/lint/forget_copy.rs b/tests/ui/lint/forgetting_copy_types.rs
index a6b17b76971..224c7bcd5f6 100644
--- a/tests/ui/lint/forget_copy.rs
+++ b/tests/ui/lint/forgetting_copy_types.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![warn(forget_copy)]
+#![warn(forgetting_copy_types)]
 
 use std::mem::forget;
 use std::vec::Vec;
diff --git a/tests/ui/lint/forget_copy.stderr b/tests/ui/lint/forgetting_copy_types.stderr
index 37bc8a8854e..36d1ef5c53e 100644
--- a/tests/ui/lint/forget_copy.stderr
+++ b/tests/ui/lint/forgetting_copy_types.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
-  --> $DIR/forget_copy.rs:34:5
+  --> $DIR/forgetting_copy_types.rs:34:5
    |
 LL |     forget(s1);
    |     ^^^^^^^--^
@@ -8,13 +8,13 @@ LL |     forget(s1);
    |
    = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
-  --> $DIR/forget_copy.rs:3:9
+  --> $DIR/forgetting_copy_types.rs:3:9
    |
-LL | #![warn(forget_copy)]
-   |         ^^^^^^^^^^^
+LL | #![warn(forgetting_copy_types)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
-  --> $DIR/forget_copy.rs:35:5
+  --> $DIR/forgetting_copy_types.rs:35:5
    |
 LL |     forget(s2);
    |     ^^^^^^^--^
@@ -24,7 +24,7 @@ LL |     forget(s2);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:36:5
+  --> $DIR/forgetting_copy_types.rs:36:5
    |
 LL |     forget(s3);
    |     ^^^^^^^--^
@@ -32,10 +32,10 @@ LL |     forget(s3);
    |            argument has type `&SomeStruct`
    |
    = note: use `let _ = ...` to ignore the expression or result
-   = note: `#[warn(forget_ref)]` on by default
+   = note: `#[warn(forgetting_references)]` on by default
 
 warning: calls to `std::mem::forget` with a value that implements `Copy` does nothing
-  --> $DIR/forget_copy.rs:37:5
+  --> $DIR/forgetting_copy_types.rs:37:5
    |
 LL |     forget(s4);
    |     ^^^^^^^--^
@@ -45,7 +45,7 @@ LL |     forget(s4);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:38:5
+  --> $DIR/forgetting_copy_types.rs:38:5
    |
 LL |     forget(s5);
    |     ^^^^^^^--^
@@ -55,7 +55,7 @@ LL |     forget(s5);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:50:5
+  --> $DIR/forgetting_copy_types.rs:50:5
    |
 LL |     forget(a2);
    |     ^^^^^^^--^
@@ -65,7 +65,7 @@ LL |     forget(a2);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:52:5
+  --> $DIR/forgetting_copy_types.rs:52:5
    |
 LL |     forget(a3);
    |     ^^^^^^^--^
@@ -75,7 +75,7 @@ LL |     forget(a3);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_copy.rs:53:5
+  --> $DIR/forgetting_copy_types.rs:53:5
    |
 LL |     forget(a4);
    |     ^^^^^^^--^
diff --git a/tests/ui/lint/forget_ref.rs b/tests/ui/lint/forgetting_references.rs
index 13f6d4be3d1..bd51e980031 100644
--- a/tests/ui/lint/forget_ref.rs
+++ b/tests/ui/lint/forgetting_references.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![warn(forget_ref)]
+#![warn(forgetting_references)]
 
 use std::mem::forget;
 
diff --git a/tests/ui/lint/forget_ref.stderr b/tests/ui/lint/forgetting_references.stderr
index 63fc7791980..5624b690789 100644
--- a/tests/ui/lint/forget_ref.stderr
+++ b/tests/ui/lint/forgetting_references.stderr
@@ -1,5 +1,5 @@
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:10:5
+  --> $DIR/forgetting_references.rs:10:5
    |
 LL |     forget(&SomeStruct);
    |     ^^^^^^^-----------^
@@ -8,13 +8,13 @@ LL |     forget(&SomeStruct);
    |
    = note: use `let _ = ...` to ignore the expression or result
 note: the lint level is defined here
-  --> $DIR/forget_ref.rs:3:9
+  --> $DIR/forgetting_references.rs:3:9
    |
-LL | #![warn(forget_ref)]
-   |         ^^^^^^^^^^
+LL | #![warn(forgetting_references)]
+   |         ^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:13:5
+  --> $DIR/forgetting_references.rs:13:5
    |
 LL |     forget(&owned);
    |     ^^^^^^^------^
@@ -24,7 +24,7 @@ LL |     forget(&owned);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:14:5
+  --> $DIR/forgetting_references.rs:14:5
    |
 LL |     forget(&&owned);
    |     ^^^^^^^-------^
@@ -34,7 +34,7 @@ LL |     forget(&&owned);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:15:5
+  --> $DIR/forgetting_references.rs:15:5
    |
 LL |     forget(&mut owned);
    |     ^^^^^^^----------^
@@ -44,7 +44,7 @@ LL |     forget(&mut owned);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:19:5
+  --> $DIR/forgetting_references.rs:19:5
    |
 LL |     forget(&*reference1);
    |     ^^^^^^^------------^
@@ -54,7 +54,7 @@ LL |     forget(&*reference1);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:22:5
+  --> $DIR/forgetting_references.rs:22:5
    |
 LL |     forget(reference2);
    |     ^^^^^^^----------^
@@ -64,7 +64,7 @@ LL |     forget(reference2);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:25:5
+  --> $DIR/forgetting_references.rs:25:5
    |
 LL |     forget(reference3);
    |     ^^^^^^^----------^
@@ -74,7 +74,7 @@ LL |     forget(reference3);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:30:5
+  --> $DIR/forgetting_references.rs:30:5
    |
 LL |     forget(&val);
    |     ^^^^^^^----^
@@ -84,7 +84,7 @@ LL |     forget(&val);
    = note: use `let _ = ...` to ignore the expression or result
 
 warning: calls to `std::mem::forget` with a reference instead of an owned value does nothing
-  --> $DIR/forget_ref.rs:38:5
+  --> $DIR/forgetting_references.rs:38:5
    |
 LL |     std::mem::forget(&SomeStruct);
    |     ^^^^^^^^^^^^^^^^^-----------^
diff --git a/tests/ui/lint/unused/auxiliary/must-use-foreign.rs b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs
new file mode 100644
index 00000000000..f773f09c382
--- /dev/null
+++ b/tests/ui/lint/unused/auxiliary/must-use-foreign.rs
@@ -0,0 +1,12 @@
+// edition:2021
+
+use std::future::Future;
+
+pub struct Manager;
+
+impl Manager {
+    #[must_use]
+    pub async fn new() -> (Self, impl Future<Output = ()>) {
+        (Manager, async {})
+    }
+}
diff --git a/tests/ui/lint/unused/must-use-foreign.rs b/tests/ui/lint/unused/must-use-foreign.rs
new file mode 100644
index 00000000000..21a11058562
--- /dev/null
+++ b/tests/ui/lint/unused/must-use-foreign.rs
@@ -0,0 +1,15 @@
+// edition:2021
+// aux-build:must-use-foreign.rs
+// check-pass
+
+extern crate must_use_foreign;
+
+use must_use_foreign::Manager;
+
+async fn async_main() {
+    Manager::new().await.1.await;
+}
+
+fn main() {
+    let _ = async_main();
+}
diff --git a/tests/ui/lint/unused/unused-async.rs b/tests/ui/lint/unused/unused-async.rs
index 4be93aa155a..6355f47f037 100644
--- a/tests/ui/lint/unused/unused-async.rs
+++ b/tests/ui/lint/unused/unused-async.rs
@@ -33,7 +33,7 @@ async fn test() {
     foo().await; //~ ERROR unused output of future returned by `foo` that must be used
     bar(); //~ ERROR unused return value of `bar` that must be used
     //~^ ERROR unused implementer of `Future` that must be used
-    bar().await; //~ ERROR unused output of future returned by `bar` that must be used
+    bar().await; // ok, it's not an async fn
     baz(); //~ ERROR unused implementer of `Future` that must be used
     baz().await; // ok
 }
diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr
index 1c3702ba265..e93a40658f3 100644
--- a/tests/ui/lint/unused/unused-async.stderr
+++ b/tests/ui/lint/unused/unused-async.stderr
@@ -52,17 +52,6 @@ help: use `let _ = ...` to ignore the resulting value
 LL |     let _ = bar();
    |     +++++++
 
-error: unused output of future returned by `bar` that must be used
-  --> $DIR/unused-async.rs:36:5
-   |
-LL |     bar().await;
-   |     ^^^^^^^^^^^
-   |
-help: use `let _ = ...` to ignore the resulting value
-   |
-LL |     let _ = bar().await;
-   |     +++++++
-
 error: unused implementer of `Future` that must be used
   --> $DIR/unused-async.rs:37:5
    |
@@ -71,5 +60,5 @@ LL |     baz();
    |
    = note: futures do nothing unless you `.await` or poll them
 
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/ui/liveness/liveness-unused.rs b/tests/ui/liveness/liveness-unused.rs
index 8ef6ab1b6ff..ba635e6638c 100644
--- a/tests/ui/liveness/liveness-unused.rs
+++ b/tests/ui/liveness/liveness-unused.rs
@@ -1,7 +1,7 @@
 #![warn(unused)]
 #![deny(unused_variables)]
 #![deny(unused_assignments)]
-#![allow(dead_code, non_camel_case_types, trivial_numeric_casts, drop_copy)]
+#![allow(dead_code, non_camel_case_types, trivial_numeric_casts, dropping_copy_types)]
 
 use std::ops::AddAssign;
 
diff --git a/tests/ui/macros/issue-111749.rs b/tests/ui/macros/issue-111749.rs
new file mode 100644
index 00000000000..6c45e4e8cd7
--- /dev/null
+++ b/tests/ui/macros/issue-111749.rs
@@ -0,0 +1,12 @@
+macro_rules! cbor_map {
+    ($key:expr) => {
+        $key.signum();
+    };
+}
+
+fn main() {
+    cbor_map! { #[test(test)] 4};
+    //~^ ERROR removing an expression is not supported in this position
+    //~| ERROR attribute must be of the form `#[test]`
+    //~| WARNING this was previously accepted by the compiler but is being phased out
+}
diff --git a/tests/ui/macros/issue-111749.stderr b/tests/ui/macros/issue-111749.stderr
new file mode 100644
index 00000000000..7db2b8e6ad1
--- /dev/null
+++ b/tests/ui/macros/issue-111749.stderr
@@ -0,0 +1,18 @@
+error: removing an expression is not supported in this position
+  --> $DIR/issue-111749.rs:8:17
+   |
+LL |     cbor_map! { #[test(test)] 4};
+   |                 ^^^^^^^^^^^^^
+
+error: attribute must be of the form `#[test]`
+  --> $DIR/issue-111749.rs:8:17
+   |
+LL |     cbor_map! { #[test(test)] 4};
+   |                 ^^^^^^^^^^^^^
+   |
+   = warning: 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 #57571 <https://github.com/rust-lang/rust/issues/57571>
+   = note: `#[deny(ill_formed_attribute_input)]` on by default
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/macros/panic-temporaries-2018.rs b/tests/ui/macros/panic-temporaries-2018.rs
new file mode 100644
index 00000000000..d914df38062
--- /dev/null
+++ b/tests/ui/macros/panic-temporaries-2018.rs
@@ -0,0 +1,55 @@
+// check-pass
+// edition:2018
+
+#![allow(non_fmt_panics, unreachable_code)]
+
+use std::fmt::{self, Display};
+use std::marker::PhantomData;
+
+struct NotSend {
+    marker: PhantomData<*const u8>,
+}
+
+const NOT_SEND: NotSend = NotSend { marker: PhantomData };
+
+impl Display for NotSend {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("this value does not implement Send")
+    }
+}
+
+async fn f(_: u8) {}
+
+// Exercises this matcher in panic_2015:
+// ($fmt:expr, $($arg:tt)+) => $crate::panicking::panic_fmt(...)
+async fn panic_fmt() {
+    // Panic returns `!`, so the await is never reached, and in particular the
+    // temporaries inside the formatting machinery are not still alive at the
+    // await point.
+    let todo = "...";
+    f(panic!("not yet implemented: {}", todo)).await;
+}
+
+// Exercises ("{}", $arg:expr) => $crate::panicking::panic_display(&$arg)
+async fn panic_display() {
+    f(panic!("{}", NOT_SEND)).await;
+}
+
+// Exercises ($msg:expr) => $crate::panicking::panic_str($msg)
+async fn panic_str() {
+    f(panic!((NOT_SEND, "...").1)).await;
+}
+
+// Exercises ($msg:expr) => $crate::panicking::unreachable_display(&$msg)
+async fn unreachable_display() {
+    f(unreachable!(NOT_SEND)).await;
+}
+
+fn require_send(_: impl Send) {}
+
+fn main() {
+    require_send(panic_fmt());
+    require_send(panic_display());
+    require_send(panic_str());
+    require_send(unreachable_display());
+}
diff --git a/tests/ui/macros/panic-temporaries.rs b/tests/ui/macros/panic-temporaries.rs
index 5b5b8b7c2d9..db65601fb73 100644
--- a/tests/ui/macros/panic-temporaries.rs
+++ b/tests/ui/macros/panic-temporaries.rs
@@ -3,17 +3,41 @@
 
 #![allow(unreachable_code)]
 
+use std::fmt::{self, Display};
+use std::marker::PhantomData;
+
+struct NotSend {
+    marker: PhantomData<*const u8>,
+}
+
+const NOT_SEND: NotSend = NotSend { marker: PhantomData };
+
+impl Display for NotSend {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("this value does not implement Send")
+    }
+}
+
 async fn f(_: u8) {}
 
-async fn g() {
-    // Todo returns `!`, so the await is never reached, and in particular the
+// Exercises this matcher in panic_2021:
+// ($($t:tt)+) => $crate::panicking::panic_fmt(...)
+async fn panic_fmt() {
+    // Panic returns `!`, so the await is never reached, and in particular the
     // temporaries inside the formatting machinery are not still alive at the
     // await point.
-    f(todo!("...")).await;
+    let todo = "...";
+    f(panic!("not yet implemented: {}", todo)).await;
+}
+
+// Exercises ("{}", $arg:expr) => $crate::panicking::panic_display(&$arg)
+async fn panic_display() {
+    f(panic!("{}", NOT_SEND)).await;
 }
 
 fn require_send(_: impl Send) {}
 
 fn main() {
-    require_send(g());
+    require_send(panic_fmt());
+    require_send(panic_display());
 }
diff --git a/tests/ui/macros/parse-complex-macro-invoc-op.rs b/tests/ui/macros/parse-complex-macro-invoc-op.rs
index c50dfdf0116..10810388d20 100644
--- a/tests/ui/macros/parse-complex-macro-invoc-op.rs
+++ b/tests/ui/macros/parse-complex-macro-invoc-op.rs
@@ -4,7 +4,7 @@
 #![allow(unused_assignments)]
 #![allow(unused_variables)]
 #![allow(stable_features)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 // Test parsing binary operators after macro invocations.
 
diff --git a/tests/ui/never_type/never-assign-dead-code.rs b/tests/ui/never_type/never-assign-dead-code.rs
index e95a992d780..39df7de5a7f 100644
--- a/tests/ui/never_type/never-assign-dead-code.rs
+++ b/tests/ui/never_type/never-assign-dead-code.rs
@@ -3,7 +3,7 @@
 // check-pass
 
 #![feature(never_type)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 #![warn(unused)]
 
 fn main() {
diff --git a/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs b/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
index 73ceaeeb875..2e9eff59386 100644
--- a/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
+++ b/tests/ui/nll/relate_tys/hr-fn-aba-as-aaa.rs
@@ -5,7 +5,7 @@
 // check-pass
 // compile-flags:-Zno-leak-check
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 fn make_it() -> for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 {
     panic!()
diff --git a/tests/ui/nll/ty-outlives/projection-body.rs b/tests/ui/nll/ty-outlives/projection-body.rs
index bff9058a507..722d6747102 100644
--- a/tests/ui/nll/ty-outlives/projection-body.rs
+++ b/tests/ui/nll/ty-outlives/projection-body.rs
@@ -3,7 +3,7 @@
 //
 // check-pass
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 trait MyTrait<'a> {
     type Output;
diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs
index 5e66e33f8a2..31de45bc756 100644
--- a/tests/ui/offset-of/offset-of-arg-count.rs
+++ b/tests/ui/offset-of/offset-of-arg-count.rs
@@ -12,6 +12,11 @@ fn main() {
     offset_of!(S, f.,); //~ ERROR expected identifier
     offset_of!(S, f..); //~ ERROR no rules expected the token
     offset_of!(S, f..,); //~ ERROR no rules expected the token
+    offset_of!(Lt<'static>, bar); // issue #111657
+    offset_of!(Lt<'_>, bar); // issue #111678
 }
 
 struct S { f: u8, }
+struct Lt<'a> {
+    bar: &'a (),
+}
diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs
index a0269ca2d12..3b8dc0b84a4 100644
--- a/tests/ui/offset-of/offset-of-dst-field.rs
+++ b/tests/ui/offset-of/offset-of-dst-field.rs
@@ -26,8 +26,24 @@ struct Gamma {
     z: Extern,
 }
 
+struct Delta<T: ?Sized> {
+    x: u8,
+    y: u16,
+    z: T,
+}
+
 fn main() {
     offset_of!(Alpha, z); //~ ERROR the size for values of type
     offset_of!(Beta, z); //~ ERROR the size for values of type
     offset_of!(Gamma, z); //~ ERROR the size for values of type
 }
+
+fn delta() {
+    offset_of!(Delta<Alpha>, z); //~ ERROR the size for values of type
+    offset_of!(Delta<Extern>, z); //~ ERROR the size for values of type
+    offset_of!(Delta<dyn Trait>, z); //~ ERROR the size for values of type
+}
+
+fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+    offset_of!(Delta<T>, z) //~ ERROR the size for values of type
+}
diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr
index e6e0f499236..128c783d5dd 100644
--- a/tests/ui/offset-of/offset-of-dst-field.stderr
+++ b/tests/ui/offset-of/offset-of-dst-field.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:30:5
+  --> $DIR/offset-of-dst-field.rs:36:5
    |
 LL |     offset_of!(Alpha, z);
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -8,7 +8,7 @@ LL |     offset_of!(Alpha, z);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:31:5
+  --> $DIR/offset-of-dst-field.rs:37:5
    |
 LL |     offset_of!(Beta, z);
    |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -17,7 +17,7 @@ LL |     offset_of!(Beta, z);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the size for values of type `Extern` cannot be known at compilation time
-  --> $DIR/offset-of-dst-field.rs:32:5
+  --> $DIR/offset-of-dst-field.rs:38:5
    |
 LL |     offset_of!(Gamma, z);
    |     ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -25,6 +25,53 @@ LL |     offset_of!(Gamma, z);
    = help: the trait `Sized` is not implemented for `Extern`
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 3 previous errors
+error[E0277]: the size for values of type `Extern` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:43:5
+   |
+LL |     offset_of!(Delta<Extern>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `Extern`
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:44:5
+   |
+LL |     offset_of!(Delta<dyn Trait>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `dyn Trait`
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:42:5
+   |
+LL |     offset_of!(Delta<Alpha>, z);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]`
+note: required because it appears within the type `Alpha`
+  --> $DIR/offset-of-dst-field.rs:5:8
+   |
+LL | struct Alpha {
+   |        ^^^^^
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: the size for values of type `T` cannot be known at compilation time
+  --> $DIR/offset-of-dst-field.rs:48:5
+   |
+LL | fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+   |                             - this type parameter needs to be `std::marker::Sized`
+LL |     offset_of!(Delta<T>, z)
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider removing the `?Sized` bound to make the type parameter `Sized`
+   |
+LL - fn generic_with_maybe_sized<T: ?Sized>() -> usize {
+LL + fn generic_with_maybe_sized<T>() -> usize {
+   |
+
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/offset-of/offset-of-inference.rs b/tests/ui/offset-of/offset-of-inference.rs
new file mode 100644
index 00000000000..ba87574eae0
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-inference.rs
@@ -0,0 +1,11 @@
+// Test that inference types in `offset_of!` don't ICE.
+
+#![feature(offset_of)]
+
+struct Foo<T> {
+    x: T,
+}
+
+fn main() {
+    let _ = core::mem::offset_of!(Foo<_>, x); //~ ERROR: type annotations needed
+}
diff --git a/tests/ui/offset-of/offset-of-inference.stderr b/tests/ui/offset-of/offset-of-inference.stderr
new file mode 100644
index 00000000000..2a520f6f906
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-inference.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/offset-of-inference.rs:10:35
+   |
+LL |     let _ = core::mem::offset_of!(Foo<_>, x);
+   |                                   ^^^^^^ cannot infer type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/offset-of/offset-of-output-type.rs b/tests/ui/offset-of/offset-of-output-type.rs
new file mode 100644
index 00000000000..50c2e93841f
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-output-type.rs
@@ -0,0 +1,20 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+struct S {
+    v: u8,
+    w: u16,
+}
+
+
+fn main() {
+    let _: u8 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u16 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u32 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: u64 = offset_of!(S, v); //~ ERROR mismatched types
+    let _: isize = offset_of!(S, v); //~ ERROR mismatched types
+    let _: usize = offset_of!(S, v);
+
+    offset_of!(S, v) //~ ERROR mismatched types
+}
diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr
new file mode 100644
index 00000000000..6f8c9475029
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-output-type.stderr
@@ -0,0 +1,64 @@
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:12:17
+   |
+LL |     let _: u8 = offset_of!(S, v);
+   |            --   ^^^^^^^^^^^^^^^^ expected `u8`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:13:18
+   |
+LL |     let _: u16 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u16`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:14:18
+   |
+LL |     let _: u32 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u32`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:15:18
+   |
+LL |     let _: u64 = offset_of!(S, v);
+   |            ---   ^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:16:20
+   |
+LL |     let _: isize = offset_of!(S, v);
+   |            -----   ^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
+   |            |
+   |            expected due to this
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0308]: mismatched types
+  --> $DIR/offset-of-output-type.rs:19:5
+   |
+LL | fn main() {
+   |           - expected `()` because of default return type
+...
+LL |     offset_of!(S, v)
+   |     ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+   |
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs
index 0291b7825ca..6b1a16ba62b 100644
--- a/tests/ui/offset-of/offset-of-private.rs
+++ b/tests/ui/offset-of/offset-of-private.rs
@@ -8,9 +8,21 @@ mod m {
         pub public: u8,
         private: u8,
     }
+    #[repr(C)]
+    pub struct FooTuple(pub u8, u8);
+    #[repr(C)]
+    struct Bar {
+        pub public: u8,
+        private: u8,
+    }
 }
 
 fn main() {
     offset_of!(m::Foo, public);
     offset_of!(m::Foo, private); //~ ERROR field `private` of struct `Foo` is private
+    offset_of!(m::FooTuple, 0);
+    offset_of!(m::FooTuple, 1); //~ ERROR field `1` of struct `FooTuple` is private
+    offset_of!(m::Bar, public); //~ ERROR struct `Bar` is private
+    offset_of!(m::Bar, private); //~ ERROR struct `Bar` is private
+    //~| ERROR field `private` of struct `Bar` is private
 }
diff --git a/tests/ui/offset-of/offset-of-private.stderr b/tests/ui/offset-of/offset-of-private.stderr
index 8a186dd5a02..0674b58f860 100644
--- a/tests/ui/offset-of/offset-of-private.stderr
+++ b/tests/ui/offset-of/offset-of-private.stderr
@@ -1,9 +1,46 @@
+error[E0603]: struct `Bar` is private
+  --> $DIR/offset-of-private.rs:25:19
+   |
+LL |     offset_of!(m::Bar, public);
+   |                   ^^^ private struct
+   |
+note: the struct `Bar` is defined here
+  --> $DIR/offset-of-private.rs:14:5
+   |
+LL |     struct Bar {
+   |     ^^^^^^^^^^
+
+error[E0603]: struct `Bar` is private
+  --> $DIR/offset-of-private.rs:26:19
+   |
+LL |     offset_of!(m::Bar, private);
+   |                   ^^^ private struct
+   |
+note: the struct `Bar` is defined here
+  --> $DIR/offset-of-private.rs:14:5
+   |
+LL |     struct Bar {
+   |     ^^^^^^^^^^
+
 error[E0616]: field `private` of struct `Foo` is private
-  --> $DIR/offset-of-private.rs:15:24
+  --> $DIR/offset-of-private.rs:22:24
    |
 LL |     offset_of!(m::Foo, private);
    |                        ^^^^^^^ private field
 
-error: aborting due to previous error
+error[E0616]: field `1` of struct `FooTuple` is private
+  --> $DIR/offset-of-private.rs:24:29
+   |
+LL |     offset_of!(m::FooTuple, 1);
+   |                             ^ private field
+
+error[E0616]: field `private` of struct `Bar` is private
+  --> $DIR/offset-of-private.rs:26:24
+   |
+LL |     offset_of!(m::Bar, private);
+   |                        ^^^^^^^ private field
+
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0616`.
+Some errors have detailed explanations: E0603, E0616.
+For more information about an error, try `rustc --explain E0603`.
diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs
new file mode 100644
index 00000000000..dbeef0e74dc
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-self.rs
@@ -0,0 +1,58 @@
+#![feature(offset_of)]
+
+use std::mem::offset_of;
+
+struct C<T> {
+    v: T,
+    w: T,
+}
+
+struct S {
+    v: u8,
+    w: u16,
+}
+
+impl S {
+    fn v_offs() -> usize {
+        offset_of!(Self, v)
+    }
+    fn v_offs_wrong_syntax() {
+        offset_of!(Self, Self::v); //~ ERROR no rules expected the token `::`
+        offset_of!(S, Self); //~ ERROR expected identifier, found keyword `Self`
+        //~| no field `Self` on type `S`
+    }
+    fn offs_in_c() -> usize {
+        offset_of!(C<Self>, w)
+    }
+    fn offs_in_c_colon() -> usize {
+        offset_of!(C::<Self>, w)
+    }
+}
+
+mod m {
+    use std::mem::offset_of;
+    fn off() {
+        offset_of!(self::S, v); //~ ERROR cannot find type `S` in module
+        offset_of!(super::S, v);
+        offset_of!(crate::S, v);
+    }
+    impl super::n::T {
+        fn v_offs_self() -> usize {
+            offset_of!(Self, v) //~ ERROR field `v` of struct `T` is private
+        }
+    }
+}
+
+mod n {
+    pub struct T { v: u8, }
+}
+
+fn main() {
+    offset_of!(self::S, v);
+    offset_of!(Self, v); //~ ERROR cannot find type `Self` in this scope
+
+    offset_of!(S, self); //~ ERROR expected identifier, found keyword `self`
+    //~| no field `self` on type `S`
+    offset_of!(S, v.self); //~ ERROR expected identifier, found keyword `self`
+    //~| no field `self` on type `u8`
+}
diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr
new file mode 100644
index 00000000000..df555463f98
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-self.stderr
@@ -0,0 +1,79 @@
+error: no rules expected the token `::`
+  --> $DIR/offset-of-self.rs:20:30
+   |
+LL |         offset_of!(Self, Self::v);
+   |                              ^^ no rules expected this token in macro call
+   |
+   = note: while trying to match sequence start
+
+error: expected identifier, found keyword `Self`
+  --> $DIR/offset-of-self.rs:21:23
+   |
+LL |         offset_of!(S, Self);
+   |                       ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `self`
+  --> $DIR/offset-of-self.rs:54:19
+   |
+LL |     offset_of!(S, self);
+   |                   ^^^^ expected identifier, found keyword
+
+error: expected identifier, found keyword `self`
+  --> $DIR/offset-of-self.rs:56:21
+   |
+LL |     offset_of!(S, v.self);
+   |                     ^^^^ expected identifier, found keyword
+
+error[E0412]: cannot find type `S` in module `self`
+  --> $DIR/offset-of-self.rs:35:26
+   |
+LL |         offset_of!(self::S, v);
+   |                          ^ not found in `self`
+   |
+help: consider importing this struct
+   |
+LL +     use S;
+   |
+help: if you import `S`, refer to it directly
+   |
+LL -         offset_of!(self::S, v);
+LL +         offset_of!(S, v);
+   |
+
+error[E0411]: cannot find type `Self` in this scope
+  --> $DIR/offset-of-self.rs:52:16
+   |
+LL | fn main() {
+   |    ---- `Self` not allowed in a function
+LL |     offset_of!(self::S, v);
+LL |     offset_of!(Self, v);
+   |                ^^^^ `Self` is only available in impls, traits, and type definitions
+
+error[E0609]: no field `Self` on type `S`
+  --> $DIR/offset-of-self.rs:21:23
+   |
+LL |         offset_of!(S, Self);
+   |                       ^^^^
+
+error[E0616]: field `v` of struct `T` is private
+  --> $DIR/offset-of-self.rs:41:30
+   |
+LL |             offset_of!(Self, v)
+   |                              ^ private field
+
+error[E0609]: no field `self` on type `S`
+  --> $DIR/offset-of-self.rs:54:19
+   |
+LL |     offset_of!(S, self);
+   |                   ^^^^
+
+error[E0609]: no field `self` on type `u8`
+  --> $DIR/offset-of-self.rs:56:21
+   |
+LL |     offset_of!(S, v.self);
+   |                     ^^^^
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0411, E0412, E0609, E0616.
+For more information about an error, try `rustc --explain E0411`.
diff --git a/tests/ui/or-patterns/or-patterns-default-binding-modes.rs b/tests/ui/or-patterns/or-patterns-default-binding-modes.rs
index c138d99d303..df6aab0e6a8 100644
--- a/tests/ui/or-patterns/or-patterns-default-binding-modes.rs
+++ b/tests/ui/or-patterns/or-patterns-default-binding-modes.rs
@@ -3,8 +3,8 @@
 // check-pass
 
 #![allow(irrefutable_let_patterns)]
-#![allow(drop_copy)]
-#![allow(drop_ref)]
+#![allow(dropping_copy_types)]
+#![allow(dropping_references)]
 
 fn main() {
     // A regression test for a mistake we made at one point:
diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr
index ddbfc4e7f3a..815ce4dd015 100644
--- a/tests/ui/panics/default-backtrace-ice.stderr
+++ b/tests/ui/panics/default-backtrace-ice.stderr
@@ -8,6 +8,8 @@ LL | fn main() { missing_ident; }
 stack backtrace:
 (end_short_backtrace)
 (begin_short_backtrace)
+(end_short_backtrace)
+(begin_short_backtrace)
 
 error: the compiler unexpectedly panicked. this is a bug.
 
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.rs b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
new file mode 100644
index 00000000000..38a80f8b670
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
@@ -0,0 +1,61 @@
+// compile-flags:-Cstrip=none
+// run-fail
+// check-run-results
+// exec-env:RUST_BACKTRACE=1
+// ignore-android FIXME #17520
+// ignore-wasm no panic support
+// ignore-openbsd no support for libbacktrace without filename
+// ignore-emscripten no panic
+// ignore-sgx Backtraces not symbolized
+// ignore-fuchsia Backtraces not symbolized
+// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
+
+/// This test case make sure that we can have multiple pairs of `__rust_{begin,end}_short_backtrace`
+
+#[inline(never)]
+fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+#[inline(never)]
+fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+fn first() {
+    __rust_end_short_backtrace(|| second());
+}
+
+fn second() {
+    third(); // won't show up
+}
+
+fn third() {
+    fourth(); // won't show up
+}
+
+fn fourth() {
+    __rust_begin_short_backtrace(|| fifth());
+}
+
+fn fifth() {
+    __rust_end_short_backtrace(|| sixth());
+}
+
+fn sixth() {
+    seven(); // won't show up
+}
+
+fn seven() {
+    __rust_begin_short_backtrace(|| eight());
+}
+
+fn eight() {
+    panic!("debug!!!");
+}
+
+fn main() {
+    first();
+}
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
new file mode 100644
index 00000000000..2592b747918
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
@@ -0,0 +1,11 @@
+thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames-2.rs:56:5
+stack backtrace:
+   0: std::panicking::begin_panic
+   1: short_ice_remove_middle_frames_2::eight
+   2: short_ice_remove_middle_frames_2::seven::{{closure}}
+   3: short_ice_remove_middle_frames_2::fifth
+   4: short_ice_remove_middle_frames_2::fourth::{{closure}}
+   5: short_ice_remove_middle_frames_2::first
+   6: short_ice_remove_middle_frames_2::main
+   7: core::ops::function::FnOnce::call_once
+note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.rs b/tests/ui/panics/short-ice-remove-middle-frames.rs
new file mode 100644
index 00000000000..c872084f033
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames.rs
@@ -0,0 +1,57 @@
+// compile-flags:-Cstrip=none
+// run-fail
+// check-run-results
+// exec-env:RUST_BACKTRACE=1
+// ignore-android FIXME #17520
+// ignore-wasm no panic support
+// ignore-openbsd no support for libbacktrace without filename
+// ignore-emscripten no panic
+// ignore-sgx Backtraces not symbolized
+// ignore-fuchsia Backtraces not symbolized
+// ignore-msvc the `__rust_{begin,end}_short_backtrace` symbols aren't reliable.
+
+
+#[inline(never)]
+fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+#[inline(never)]
+fn __rust_end_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+    let result = f();
+    std::hint::black_box(result)
+}
+
+fn first() {
+    __rust_end_short_backtrace(|| second());
+    // do not take effect since we already has a inner call of __rust_end_short_backtrace
+}
+
+fn second() {
+    __rust_end_short_backtrace(|| third());
+}
+
+fn third() {
+    fourth(); // won't show up in backtrace
+}
+
+fn fourth() {
+    fifth(); // won't show up in backtrace
+}
+
+fn fifth() {
+    __rust_begin_short_backtrace(|| sixth());
+}
+
+fn sixth() {
+    seven();
+}
+
+fn seven() {
+    panic!("debug!!!");
+}
+
+fn main() {
+    first();
+}
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
new file mode 100644
index 00000000000..9c15f2e08fe
--- /dev/null
+++ b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
@@ -0,0 +1,12 @@
+thread 'main' panicked at 'debug!!!', $DIR/short-ice-remove-middle-frames.rs:52:5
+stack backtrace:
+   0: std::panicking::begin_panic
+   1: short_ice_remove_middle_frames::seven
+   2: short_ice_remove_middle_frames::sixth
+   3: short_ice_remove_middle_frames::fifth::{{closure}}
+   4: short_ice_remove_middle_frames::second
+   5: short_ice_remove_middle_frames::first::{{closure}}
+   6: short_ice_remove_middle_frames::first
+   7: short_ice_remove_middle_frames::main
+   8: core::ops::function::FnOnce::call_once
+note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
index 965204bf240..43b53b7cf1f 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs
@@ -2,8 +2,8 @@
 
 // Test `@` patterns combined with `box` patterns.
 
-#![allow(drop_ref)]
-#![allow(drop_copy)]
+#![allow(dropping_references)]
+#![allow(dropping_copy_types)]
 
 #![feature(box_patterns)]
 
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
index 3eb5d2cbf54..1df51c0edd9 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs
@@ -2,7 +2,7 @@
 
 // Test `Copy` bindings in the rhs of `@` patterns.
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 #[derive(Copy, Clone)]
 struct C;
diff --git a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
index 0550238549e..204cd3e6657 100644
--- a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
+++ b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 fn main() {}
 
diff --git a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
index 788975d960a..4de1f653db0 100644
--- a/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
+++ b/tests/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 fn main() {
     struct U;
diff --git a/tests/ui/print_type_sizes/async.rs b/tests/ui/print_type_sizes/async.rs
index c73268dc46a..f38a6e674da 100644
--- a/tests/ui/print_type_sizes/async.rs
+++ b/tests/ui/print_type_sizes/async.rs
@@ -3,7 +3,7 @@
 // build-pass
 // ignore-pass
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 async fn wait() {}
 
diff --git a/tests/ui/print_type_sizes/generator_discr_placement.rs b/tests/ui/print_type_sizes/generator_discr_placement.rs
index a77a03f0a8a..6adc14f9b99 100644
--- a/tests/ui/print_type_sizes/generator_discr_placement.rs
+++ b/tests/ui/print_type_sizes/generator_discr_placement.rs
@@ -6,7 +6,7 @@
 
 // Avoid emitting panic handlers, like the rest of these tests...
 #![feature(generators)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 pub fn foo() {
     let a = || {
diff --git a/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs b/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs
index af2bb09805a..0c1e9314441 100644
--- a/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs
+++ b/tests/ui/regions/type-param-outlives-reempty-issue-74429.rs
@@ -3,7 +3,7 @@
 
 // check-pass
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 use std::marker::PhantomData;
 
diff --git a/tests/ui/resolve/issue-111312.rs b/tests/ui/resolve/issue-111312.rs
new file mode 100644
index 00000000000..acea37b358b
--- /dev/null
+++ b/tests/ui/resolve/issue-111312.rs
@@ -0,0 +1,11 @@
+// edition: 2021
+
+trait Has {
+    fn has() {}
+}
+
+trait HasNot {}
+
+fn main() {
+    HasNot::has(); //~ ERROR
+}
diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr
new file mode 100644
index 00000000000..4c864029c98
--- /dev/null
+++ b/tests/ui/resolve/issue-111312.stderr
@@ -0,0 +1,15 @@
+error[E0599]: no function or associated item named `has` found for trait `HasNot`
+  --> $DIR/issue-111312.rs:10:13
+   |
+LL |     HasNot::has();
+   |             ^^^ function or associated item not found in `HasNot`
+   |
+note: `Has` defines an item `has`
+  --> $DIR/issue-111312.rs:3:1
+   |
+LL | trait Has {
+   | ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/resolve/issue-111727.rs b/tests/ui/resolve/issue-111727.rs
new file mode 100644
index 00000000000..36f3081211d
--- /dev/null
+++ b/tests/ui/resolve/issue-111727.rs
@@ -0,0 +1,5 @@
+// edition: 2021
+
+fn main() {
+    std::any::Any::create(); //~ ERROR
+}
diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr
new file mode 100644
index 00000000000..bd748211ed3
--- /dev/null
+++ b/tests/ui/resolve/issue-111727.stderr
@@ -0,0 +1,9 @@
+error[E0599]: no function or associated item named `create` found for trait `Any`
+  --> $DIR/issue-111727.rs:4:20
+   |
+LL |     std::any::Any::create();
+   |                    ^^^^^^ function or associated item not found in `Any`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
index 8f45b989f13..b9ff24c7624 100644
--- a/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
+++ b/tests/ui/rfc-2008-non-exhaustive/borrowck-exhaustive.rs
@@ -3,7 +3,7 @@
 
 // check-pass
 
-#![allow(drop_ref)]
+#![allow(dropping_references)]
 
 // aux-build:monovariants.rs
 extern crate monovariants;
diff --git a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
index 4c1562790d5..542be3942b7 100644
--- a/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
+++ b/tests/ui/rfc-2361-dbg-macro/dbg-macro-expected-behavior.rs
@@ -4,7 +4,7 @@
 // Tests ensuring that `dbg!(expr)` has the expected run-time behavior.
 // as well as some compile time properties we expect.
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 #[derive(Copy, Clone, Debug)]
 struct Unit;
diff --git a/tests/ui/rust-2018/remove-extern-crate.fixed b/tests/ui/rust-2018/remove-extern-crate.fixed
index 4ed4d610025..209b91af1dd 100644
--- a/tests/ui/rust-2018/remove-extern-crate.fixed
+++ b/tests/ui/rust-2018/remove-extern-crate.fixed
@@ -5,7 +5,7 @@
 // compile-flags:--extern remove_extern_crate
 
 #![warn(rust_2018_idioms)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
  //~ WARNING unused extern crate
 // Shouldn't suggest changing to `use`, as `another_name`
diff --git a/tests/ui/rust-2018/remove-extern-crate.rs b/tests/ui/rust-2018/remove-extern-crate.rs
index 5dafdb2b7b7..ef3c2db696a 100644
--- a/tests/ui/rust-2018/remove-extern-crate.rs
+++ b/tests/ui/rust-2018/remove-extern-crate.rs
@@ -5,7 +5,7 @@
 // compile-flags:--extern remove_extern_crate
 
 #![warn(rust_2018_idioms)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 extern crate core; //~ WARNING unused extern crate
 // Shouldn't suggest changing to `use`, as `another_name`
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.rs b/tests/ui/self/arbitrary-self-from-method-substs.rs
new file mode 100644
index 00000000000..0f911a20842
--- /dev/null
+++ b/tests/ui/self/arbitrary-self-from-method-substs.rs
@@ -0,0 +1,16 @@
+#![feature(arbitrary_self_types)]
+
+use std::ops::Deref;
+
+struct Foo(u32);
+impl Foo {
+    fn get<R: Deref<Target=Self>>(self: R) -> u32 {
+        self.0
+    }
+}
+
+fn main() {
+    let mut foo = Foo(1);
+    foo.get::<&Foo>();
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/self/arbitrary-self-from-method-substs.stderr b/tests/ui/self/arbitrary-self-from-method-substs.stderr
new file mode 100644
index 00000000000..6c252fadf46
--- /dev/null
+++ b/tests/ui/self/arbitrary-self-from-method-substs.stderr
@@ -0,0 +1,9 @@
+error[E0308]: mismatched types
+  --> $DIR/arbitrary-self-from-method-substs.rs:14:5
+   |
+LL |     foo.get::<&Foo>();
+   |     ^^^ expected `&Foo`, found `Foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/self/self-ctor-inner-const.rs b/tests/ui/self/self-ctor-inner-const.rs
deleted file mode 100644
index b015397a5bc..00000000000
--- a/tests/ui/self/self-ctor-inner-const.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Verify that we ban usage of `Self` as constructor from inner items.
-
-struct S0<T>(T);
-
-impl<T> S0<T> {
-    fn foo() {
-        const C: S0<u8> = Self(0);
-        //~^ ERROR can't use generic parameters from outer function
-        fn bar() -> Self {
-            //~^ ERROR can't use generic parameters from outer function
-            Self(0)
-            //~^ ERROR can't use generic parameters from outer function
-        }
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/self/self-ctor-inner-const.stderr b/tests/ui/self/self-ctor-inner-const.stderr
deleted file mode 100644
index 7287c64c659..00000000000
--- a/tests/ui/self/self-ctor-inner-const.stderr
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/self-ctor-inner-const.rs:7:27
-   |
-LL |         const C: S0<u8> = Self(0);
-   |                           ^^^^
-   |                           |
-   |                           use of generic parameter from outer function
-   |                           can't use `Self` here
-
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/self-ctor-inner-const.rs:9:21
-   |
-LL | impl<T> S0<T> {
-   | ---- `Self` type implicitly declared here, by this `impl`
-...
-LL |         fn bar() -> Self {
-   |                     ^^^^
-   |                     |
-   |                     use of generic parameter from outer function
-   |                     use a type here instead
-
-error[E0401]: can't use generic parameters from outer function
-  --> $DIR/self-ctor-inner-const.rs:11:13
-   |
-LL |             Self(0)
-   |             ^^^^
-   |             |
-   |             use of generic parameter from outer function
-   |             can't use `Self` here
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0401`.
diff --git a/tests/ui/self/self-ctor-nongeneric.rs b/tests/ui/self/self-ctor-nongeneric.rs
new file mode 100644
index 00000000000..0ae7f8da4b4
--- /dev/null
+++ b/tests/ui/self/self-ctor-nongeneric.rs
@@ -0,0 +1,15 @@
+// `Self` as a constructor is currently allowed when the outer item is not generic.
+// check-pass
+
+struct S0(usize);
+
+impl S0 {
+    fn foo() {
+        const C: S0 = Self(0);
+        fn bar() -> S0 {
+            Self(0)
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/statics/issue-91050-1.rs b/tests/ui/statics/issue-91050-1.rs
index f59bcf0b803..c6268dba567 100644
--- a/tests/ui/statics/issue-91050-1.rs
+++ b/tests/ui/statics/issue-91050-1.rs
@@ -12,7 +12,7 @@
 //
 // In regular builds, the bad cast was UB, like "Invalid LLVMRustVisibility value!"
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 pub mod before {
     #[no_mangle]
diff --git a/tests/ui/suggestions/issue-109854.rs b/tests/ui/suggestions/issue-109854.rs
new file mode 100644
index 00000000000..dd4542dd71f
--- /dev/null
+++ b/tests/ui/suggestions/issue-109854.rs
@@ -0,0 +1,12 @@
+fn generate_setter() {
+    String::with_capacity(
+    //~^ ERROR this function takes 1 argument but 3 arguments were supplied
+    generate_setter,
+    r#"
+pub(crate) struct Person<T: Clone> {}
+"#,
+     r#""#,
+    );
+}
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-109854.stderr b/tests/ui/suggestions/issue-109854.stderr
new file mode 100644
index 00000000000..621a3897165
--- /dev/null
+++ b/tests/ui/suggestions/issue-109854.stderr
@@ -0,0 +1,31 @@
+error[E0061]: this function takes 1 argument but 3 arguments were supplied
+  --> $DIR/issue-109854.rs:2:5
+   |
+LL |       String::with_capacity(
+   |       ^^^^^^^^^^^^^^^^^^^^^
+...
+LL | /     r#"
+LL | | pub(crate) struct Person<T: Clone> {}
+LL | | "#,
+   | |__- unexpected argument of type `&'static str`
+LL |        r#""#,
+   |        ----- unexpected argument of type `&'static str`
+   |
+note: expected `usize`, found fn item
+  --> $DIR/issue-109854.rs:4:5
+   |
+LL |     generate_setter,
+   |     ^^^^^^^^^^^^^^^
+   = note: expected type `usize`
+           found fn item `fn() {generate_setter}`
+note: associated function defined here
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
+help: remove the extra arguments
+   |
+LL -     generate_setter,
+LL +     /* usize */,
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/suggestions/issue-94171.rs b/tests/ui/suggestions/issue-94171.rs
new file mode 100644
index 00000000000..cbb9f9cec72
--- /dev/null
+++ b/tests/ui/suggestions/issue-94171.rs
@@ -0,0 +1,5 @@
+fn L(]{match
+(; {`
+//~^^ ERROR mismatched closing delimiter
+//~^^ ERROR unknown start of token
+//~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/suggestions/issue-94171.stderr b/tests/ui/suggestions/issue-94171.stderr
new file mode 100644
index 00000000000..b3440e46e8a
--- /dev/null
+++ b/tests/ui/suggestions/issue-94171.stderr
@@ -0,0 +1,36 @@
+error: unknown start of token: `
+  --> $DIR/issue-94171.rs:2:5
+   |
+LL | (; {`
+   |     ^
+   |
+help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not
+   |
+LL | (; {'
+   |     ~
+
+error: mismatched closing delimiter: `]`
+  --> $DIR/issue-94171.rs:1:5
+   |
+LL | fn L(]{match
+   |     ^^ mismatched closing delimiter
+   |     |
+   |     unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-94171.rs:5:52
+   |
+LL | fn L(]{match
+   |      -- unclosed delimiter
+   |      |
+   |      missing open `[` for this delimiter
+LL | (; {`
+   | -  - unclosed delimiter
+   | |
+   | unclosed delimiter
+...
+LL |
+   |                                                    ^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/traits/copy-guessing.rs b/tests/ui/traits/copy-guessing.rs
index 558303c2e40..af25010e3bd 100644
--- a/tests/ui/traits/copy-guessing.rs
+++ b/tests/ui/traits/copy-guessing.rs
@@ -1,7 +1,5 @@
-// run-pass
-
 #![allow(dead_code)]
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 // "guessing" in trait selection can affect `copy_or_move`. Check that this
 // is correctly handled. I am not sure what is the "correct" behaviour,
@@ -20,6 +18,7 @@ fn assert_impls_fn<R,T: Fn()->R>(_: &T){}
 
 fn main() {
     let n = None;
+    //~^ ERROR type annotations needed for `Option<T>`
     let e = S(&n);
     let f = || {
         // S being copy is critical for this to work
diff --git a/tests/ui/traits/copy-guessing.stderr b/tests/ui/traits/copy-guessing.stderr
new file mode 100644
index 00000000000..568b7e5a64a
--- /dev/null
+++ b/tests/ui/traits/copy-guessing.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed for `Option<T>`
+  --> $DIR/copy-guessing.rs:20:9
+   |
+LL |     let n = None;
+   |         ^
+   |
+help: consider giving `n` an explicit type, where the type for type parameter `T` is specified
+   |
+LL |     let n: Option<T> = None;
+   |          +++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr
index 2ff16b4af38..aee41c43aef 100644
--- a/tests/ui/traits/cycle-cache-err-60010.stderr
+++ b/tests/ui/traits/cycle-cache-err-60010.stderr
@@ -1,9 +1,25 @@
-error[E0275]: overflow evaluating the requirement `RootDatabase: RefUnwindSafe`
+error[E0275]: overflow evaluating the requirement `SalsaStorage: RefUnwindSafe`
   --> $DIR/cycle-cache-err-60010.rs:27:13
    |
 LL |     _parse: <ParseQuery as Query<RootDatabase>>::Data,
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+note: required because it appears within the type `PhantomData<SalsaStorage>`
+  --> $SRC_DIR/core/src/marker.rs:LL:COL
+note: required because it appears within the type `Unique<SalsaStorage>`
+  --> $SRC_DIR/core/src/ptr/unique.rs:LL:COL
+note: required because it appears within the type `Box<SalsaStorage>`
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+note: required because it appears within the type `Runtime<RootDatabase>`
+  --> $DIR/cycle-cache-err-60010.rs:23:8
+   |
+LL | struct Runtime<DB: Database> {
+   |        ^^^^^^^
+note: required because it appears within the type `RootDatabase`
+  --> $DIR/cycle-cache-err-60010.rs:20:8
+   |
+LL | struct RootDatabase {
+   |        ^^^^^^^^^^^^
 note: required for `RootDatabase` to implement `SourceDatabase`
   --> $DIR/cycle-cache-err-60010.rs:44:9
    |
diff --git a/tests/ui/traits/impl-evaluation-order.rs b/tests/ui/traits/impl-evaluation-order.rs
index 256ce992eef..2ce0b6b0df8 100644
--- a/tests/ui/traits/impl-evaluation-order.rs
+++ b/tests/ui/traits/impl-evaluation-order.rs
@@ -6,7 +6,7 @@
 
 // check-pass
 
-#![allow(drop_copy)]
+#![allow(dropping_copy_types)]
 
 trait A {
     type B;
diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs
index 7064a39d21e..b174669545a 100644
--- a/tests/ui/traits/issue-106072.rs
+++ b/tests/ui/traits/issue-106072.rs
@@ -1,5 +1,4 @@
 #[derive(Clone)] //~  trait objects must include the `dyn` keyword
-                 //~| trait objects must include the `dyn` keyword
 struct Foo;
 trait Foo {} //~ the name `Foo` is defined multiple times
 fn main() {}
diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr
index f9b7b814663..1037603ceb7 100644
--- a/tests/ui/traits/issue-106072.stderr
+++ b/tests/ui/traits/issue-106072.stderr
@@ -1,5 +1,5 @@
 error[E0428]: the name `Foo` is defined multiple times
-  --> $DIR/issue-106072.rs:4:1
+  --> $DIR/issue-106072.rs:3:1
    |
 LL | struct Foo;
    | ----------- previous definition of the type `Foo` here
@@ -16,15 +16,7 @@ LL | #[derive(Clone)]
    |
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0782]: trait objects must include the `dyn` keyword
-  --> $DIR/issue-106072.rs:1:10
-   |
-LL | #[derive(Clone)]
-   |          ^^^^^
-   |
-   = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0428, E0782.
 For more information about an error, try `rustc --explain E0428`.
diff --git a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
index f115e143318..e311a4af2f4 100644
--- a/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
+++ b/tests/ui/traits/new-solver/auto-with-drop_tracking_mir.rs
@@ -14,7 +14,7 @@ async fn foo() {
     #[cfg(fail)]
     let x = &NotSync;
     bar().await;
-    #[allow(drop_ref)]
+    #[allow(dropping_references)]
     drop(x);
 }
 
diff --git a/tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs b/tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs
new file mode 100644
index 00000000000..d70534feb07
--- /dev/null
+++ b/tests/ui/traits/new-solver/normalize-rcvr-for-inherent.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+// Verify that we can assemble inherent impl candidates on a possibly
+// unnormalized self type.
+
+trait Foo {
+    type Assoc;
+}
+impl Foo for i32 {
+    type Assoc = Bar;
+}
+
+struct Bar;
+impl Bar {
+    fn method(&self) {}
+}
+
+fn build<T: Foo>(_: T) -> T::Assoc {
+    todo!()
+}
+
+fn main() {
+    build(1i32).method();
+}
diff --git a/tests/ui/traits/new-solver/structural-resolve-field.rs b/tests/ui/traits/new-solver/structural-resolve-field.rs
new file mode 100644
index 00000000000..01899c9ad64
--- /dev/null
+++ b/tests/ui/traits/new-solver/structural-resolve-field.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+#[derive(Default)]
+struct Foo {
+    x: i32,
+}
+
+fn main() {
+    let mut xs = <[Foo; 1]>::default();
+    xs[0].x = 1;
+    (&mut xs[0]).x = 2;
+}
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
new file mode 100644
index 00000000000..d37943b929a
--- /dev/null
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.rs
@@ -0,0 +1,34 @@
+//~ ERROR overflow
+// A regression test for #111729 checking that we correctly
+// track recursion depth for obligations returned by confirmation.
+use std::panic::RefUnwindSafe;
+
+trait Database {
+    type Storage;
+}
+trait Query<DB> {
+    type Data;
+}
+struct ParseQuery;
+struct RootDatabase {
+    _runtime: Runtime<RootDatabase>,
+}
+
+impl<T: RefUnwindSafe> Database for T {
+    type Storage = SalsaStorage;
+}
+impl Database for RootDatabase {
+    type Storage = SalsaStorage;
+}
+
+struct Runtime<DB: Database> {
+    _storage: Box<DB::Storage>,
+}
+struct SalsaStorage {
+    _parse: <ParseQuery as Query<RootDatabase>>::Data,
+}
+
+impl<DB: Database> Query<DB> for ParseQuery {
+    type Data = RootDatabase;
+}
+fn main() {}
diff --git a/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
new file mode 100644
index 00000000000..8f9ce3ef1e9
--- /dev/null
+++ b/tests/ui/traits/solver-cycles/cycle-via-builtin-auto-trait-impl.stderr
@@ -0,0 +1,24 @@
+error[E0275]: overflow evaluating the requirement `Runtime<RootDatabase>: RefUnwindSafe`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_via_builtin_auto_trait_impl`)
+note: required because it appears within the type `RootDatabase`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:13:8
+   |
+LL | struct RootDatabase {
+   |        ^^^^^^^^^^^^
+note: required for `RootDatabase` to implement `Database`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:17:24
+   |
+LL | impl<T: RefUnwindSafe> Database for T {
+   |         -------------  ^^^^^^^^     ^
+   |         |
+   |         unsatisfied trait bound introduced here
+note: required because it appears within the type `Runtime<RootDatabase>`
+  --> $DIR/cycle-via-builtin-auto-trait-impl.rs:24:8
+   |
+LL | struct Runtime<DB: Database> {
+   |        ^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
index 6ed7667115a..f98c3164d7e 100644
--- a/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
+++ b/tests/ui/trivial-bounds/trivial-bounds-inconsistent-copy.rs
@@ -2,7 +2,7 @@
 // Check tautalogically false `Copy` bounds
 
 #![feature(trivial_bounds)]
-#![allow(drop_ref, drop_copy)]
+#![allow(dropping_references, dropping_copy_types)]
 
 fn copy_string(t: String) -> String where String: Copy { //~ WARNING trivial_bounds
     is_copy(&t);
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
new file mode 100644
index 00000000000..e5bfbfdae91
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+
+type Tait<'a> = impl Sized + 'a;
+
+fn foo<'a, 'b>() {
+    if false {
+        if { return } {
+            let y: Tait<'b> = 1i32;
+            //~^ ERROR concrete type differs from previous defining opaque type use
+        }
+    }
+    let x: Tait<'a> = ();
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
new file mode 100644
index 00000000000..f2eb7bc4dc7
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/different_defining_uses_never_type-2.rs:8:31
+   |
+LL |             let y: Tait<'b> = 1i32;
+   |                               ^^^^ expected `()`, got `i32`
+   |
+note: previous use here
+  --> $DIR/different_defining_uses_never_type-2.rs:12:23
+   |
+LL |     let x: Tait<'a> = ();
+   |                       ^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
new file mode 100644
index 00000000000..2b30a9cd57c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
@@ -0,0 +1,15 @@
+#![feature(type_alias_impl_trait)]
+
+type Tait<T> = impl Sized;
+
+fn foo<T, U>() {
+    if false {
+        if { return } {
+            let y: Tait<U> = 1i32;
+            //~^ ERROR concrete type differs from previous defining opaque type use
+        }
+    }
+    let x: Tait<T> = ();
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
new file mode 100644
index 00000000000..8fc2e22848c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/different_defining_uses_never_type-3.rs:8:30
+   |
+LL |             let y: Tait<U> = 1i32;
+   |                              ^^^^ expected `()`, got `i32`
+   |
+note: previous use here
+  --> $DIR/different_defining_uses_never_type-3.rs:12:22
+   |
+LL |     let x: Tait<T> = ();
+   |                      ^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
index da845e86147..9ae2c34b935 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
@@ -8,6 +8,7 @@ type X<A, B> = impl Into<&'static A>;
 
 fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
     //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
+    //~| ERROR concrete type differs from previous defining opaque type use
     (a, a)
 }
 
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
index 66a6b0bbf74..0d24d42ba62 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
@@ -10,6 +10,15 @@ help: consider introducing a `where` clause, but there might be an alternative b
 LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> {
    |                                                                ++++++++++++++++++++++++++
 
-error: aborting due to previous error
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/multiple-def-uses-in-one-fn.rs:9:45
+   |
+LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
+   |                                             ^^^^^^^^^^^^^^^^^^
+   |                                             |
+   |                                             expected `&B`, got `&A`
+   |                                             this expression supplies two conflicting concrete types for the same opaque type
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/underscore-imports/issue-110164.rs b/tests/ui/underscore-imports/issue-110164.rs
new file mode 100644
index 00000000000..6fd13414500
--- /dev/null
+++ b/tests/ui/underscore-imports/issue-110164.rs
@@ -0,0 +1,19 @@
+use self::*;
+//~^ ERROR unresolved import `self::*`
+use crate::*;
+//~^ ERROR unresolved import `crate::*`
+use _::a;
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR unresolved import `_`
+use _::*;
+//~^ ERROR expected identifier, found reserved identifier `_`
+//~| ERROR unresolved import `_`
+
+fn main() {
+    use _::a;
+    //~^ ERROR expected identifier, found reserved identifier `_`
+    //~| ERROR unresolved import `_`
+    use _::*;
+    //~^ ERROR expected identifier, found reserved identifier `_`
+    //~| ERROR unresolved import `_`
+}
diff --git a/tests/ui/underscore-imports/issue-110164.stderr b/tests/ui/underscore-imports/issue-110164.stderr
new file mode 100644
index 00000000000..5016c41e8a5
--- /dev/null
+++ b/tests/ui/underscore-imports/issue-110164.stderr
@@ -0,0 +1,71 @@
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:5:5
+   |
+LL | use _::a;
+   |     ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:8:5
+   |
+LL | use _::*;
+   |     ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:13:9
+   |
+LL |     use _::a;
+   |         ^ expected identifier, found reserved identifier
+
+error: expected identifier, found reserved identifier `_`
+  --> $DIR/issue-110164.rs:16:9
+   |
+LL |     use _::*;
+   |         ^ expected identifier, found reserved identifier
+
+error[E0432]: unresolved import `self::*`
+  --> $DIR/issue-110164.rs:1:5
+   |
+LL | use self::*;
+   |     ^^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `crate::*`
+  --> $DIR/issue-110164.rs:3:5
+   |
+LL | use crate::*;
+   |     ^^^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:8:5
+   |
+LL | use _::*;
+   |     ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:5:5
+   |
+LL | use _::a;
+   |     ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:13:9
+   |
+LL |     use _::a;
+   |         ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error[E0432]: unresolved import `_`
+  --> $DIR/issue-110164.rs:16:9
+   |
+LL |     use _::*;
+   |         ^ maybe a missing crate `_`?
+   |
+   = help: consider adding `extern crate _` to use the `_` crate
+
+error: aborting due to 10 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/unsized-locals/issue-67981.rs b/tests/ui/unsized-locals/issue-67981.rs
new file mode 100644
index 00000000000..3eb6498e9dc
--- /dev/null
+++ b/tests/ui/unsized-locals/issue-67981.rs
@@ -0,0 +1,9 @@
+#![feature(unsized_fn_params)]
+
+fn main() {
+    let f: fn([u8]) = |_| {};
+    //~^ERROR the size for values of type `[u8]` cannot be known at compilation time
+    let slice: Box<[u8]> = Box::new([1; 8]);
+
+    f(*slice);
+}
diff --git a/tests/ui/unsized-locals/issue-67981.stderr b/tests/ui/unsized-locals/issue-67981.stderr
new file mode 100644
index 00000000000..a4b179ae2fd
--- /dev/null
+++ b/tests/ui/unsized-locals/issue-67981.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/issue-67981.rs:4:24
+   |
+LL |     let f: fn([u8]) = |_| {};
+   |                        ^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     let f: fn([u8]) = |&_| {};
+   |                        +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.rs b/tests/ui/unsized/box-instead-of-dyn-fn.rs
index 2fa741bc1c5..321c2ebf5a1 100644
--- a/tests/ui/unsized/box-instead-of-dyn-fn.rs
+++ b/tests/ui/unsized/box-instead-of-dyn-fn.rs
@@ -8,7 +8,6 @@ fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a {
         move || println!("{a}")
     } else {
         Box::new(move || println!("{}", b))
-        //~^ ERROR `if` and `else` have incompatible types
     }
 }
 
diff --git a/tests/ui/unsized/box-instead-of-dyn-fn.stderr b/tests/ui/unsized/box-instead-of-dyn-fn.stderr
index bfb7c3957f4..6087f5c5465 100644
--- a/tests/ui/unsized/box-instead-of-dyn-fn.stderr
+++ b/tests/ui/unsized/box-instead-of-dyn-fn.stderr
@@ -1,42 +1,21 @@
-error[E0308]: `if` and `else` have incompatible types
-  --> $DIR/box-instead-of-dyn-fn.rs:10:9
-   |
-LL | /     if a % 2 == 0 {
-LL | |         move || println!("{a}")
-   | |         -----------------------
-   | |         |
-   | |         the expected closure
-   | |         expected because of this
-LL | |     } else {
-LL | |         Box::new(move || println!("{}", b))
-   | |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected closure, found `Box<[closure@box-instead-of-dyn-fn.rs:10:18]>`
-LL | |
-LL | |     }
-   | |_____- `if` and `else` have incompatible types
-   |
-   = note: expected closure `[closure@$DIR/box-instead-of-dyn-fn.rs:8:9: 8:16]`
-               found struct `Box<[closure@$DIR/box-instead-of-dyn-fn.rs:10:18: 10:25]>`
-
 error[E0746]: return type cannot have an unboxed trait object
   --> $DIR/box-instead-of-dyn-fn.rs:5:56
    |
 LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> dyn Fn() + 'a {
    |                                                        ^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on trait objects, see <https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types>
-   = note: if all the returned values were of the same type you could use `impl Fn() + 'a` as the return type
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-   = note: you can create a new `enum` with a variant for each returned type
-help: return a boxed trait object instead
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
+   |
+LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> impl Fn() + 'a {
+   |                                                        ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL | fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> Box<dyn Fn() + 'a> {
-   |                                                        ++++             +
-help: ... and box this value
+LL ~ fn print_on_or_the_other<'a>(a: i32, b: &'a String) -> Box<dyn Fn() + 'a> {
+LL |
+LL |     if a % 2 == 0 {
+LL ~         Box::new(move || println!("{a}"))
    |
-LL |         Box::new(move || println!("{a}"))
-   |         +++++++++                       +
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0746.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0746`.
diff --git a/tests/ui/unsized/issue-91801.stderr b/tests/ui/unsized/issue-91801.stderr
index 8795aa1687f..da5c4322403 100644
--- a/tests/ui/unsized/issue-91801.stderr
+++ b/tests/ui/unsized/issue-91801.stderr
@@ -4,11 +4,10 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Validator<'a> {
    |                                                                             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a` as the return type, as all return paths are of type `Box<[closure@$DIR/issue-91801.rs:10:21: 10:70]>`, which implements `Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a`
+help: box the return type, and wrap all of the returned values in `Box::new`
    |
-LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> impl Fn(&'a Something) -> Result<(), ()> + Send + Sync + 'a {
-   |                                                                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | fn or<'a>(first: &'static Validator<'a>, second: &'static Validator<'a>) -> Box<Validator<'a>> {
+   |                                                                             ++++             +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/unsized/issue-91803.stderr b/tests/ui/unsized/issue-91803.stderr
index 2dad9e89294..a43b8d0741f 100644
--- a/tests/ui/unsized/issue-91803.stderr
+++ b/tests/ui/unsized/issue-91803.stderr
@@ -4,11 +4,14 @@ error[E0746]: return type cannot have an unboxed trait object
 LL | fn or<'a>(first: &'static dyn Foo<'a>) -> dyn Foo<'a> {
    |                                           ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
-   = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Foo<'a>` as the return type, as all return paths are of type `Box<_>`, which implements `Foo<'a>`
+help: return an `impl Trait` instead of a `dyn Trait`, if all returned values are the same type
    |
 LL | fn or<'a>(first: &'static dyn Foo<'a>) -> impl Foo<'a> {
-   |                                           ~~~~~~~~~~~~
+   |                                           ~~~~
+help: box the return type, and wrap all of the returned values in `Box::new`
+   |
+LL | fn or<'a>(first: &'static dyn Foo<'a>) -> Box<dyn Foo<'a>> {
+   |                                           ++++           +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/use/use-self-type.stderr b/tests/ui/use/use-self-type.stderr
index e6153941151..3da04a851f6 100644
--- a/tests/ui/use/use-self-type.stderr
+++ b/tests/ui/use/use-self-type.stderr
@@ -8,7 +8,7 @@ error[E0432]: unresolved import `Self`
   --> $DIR/use-self-type.rs:6:13
    |
 LL |         use Self::f;
-   |             ^^^^ `Self` is only available in impls, traits, and type definitions
+   |             ^^^^ `Self` cannot be used in imports
 
 error: aborting due to 2 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index a5152434d89..d7cd3ea1275 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -371,31 +371,6 @@ cc = ["@GuillaumeGomez"]
 message = "Some changes might have occurred in exhaustiveness checking"
 cc = ["@Nadrieril"]
 
-[mentions."library"]
-message = """
-Hey! It looks like you've submitted a new PR for the library teams!
-
-If this PR contains changes to any `rust-lang/rust` public library APIs then \
-please comment with `@rustbot label +T-libs-api -T-libs` to tag it \
-appropriately. If this PR contains changes to any unstable APIs please edit \
-the PR description to add a link to the relevant [API Change \
-Proposal](https://std-dev-guide.rust-lang.org/feature-lifecycle/api-change-proposals.html) \
-or [create one](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29) \
-if you haven't already. If you're unsure where your change falls no worries, \
-just leave it as is and the reviewer will take a look and make a decision to \
-forward on if necessary.
-
-Examples of `T-libs-api` changes:
-
-* Stabilizing library features
-* Introducing insta-stable changes such as new implementations of existing \
-  stable traits on existing stable types
-* Introducing new or changing existing unstable library APIs (excluding \
-  permanently unstable features / features without a tracking issue)
-* Changing public documentation in ways that create new stability guarantees
-* Changing observable runtime behavior of library APIs
-"""
-
 [mentions."src/librustdoc/clean/types.rs"]
 cc = ["@camelid"]
 
@@ -507,7 +482,6 @@ compiler-team = [
     "@petrochenkov",
     "@davidtwco",
     "@oli-obk",
-    "@lcnr",
     "@wesleywiser",
 ]
 compiler-team-contributors = [
@@ -618,6 +592,7 @@ style-team = [
 "/compiler/rustc_llvm" =                     ["@cuviper"]
 "/compiler/rustc_middle/src/mir" =           ["compiler", "mir"]
 "/compiler/rustc_middle/src/traits" =        ["compiler", "types"]
+"/compiler/rustc_middle/src/ty" =            ["compiler", "types"]
 "/compiler/rustc_const_eval/src/interpret" = ["compiler", "mir"]
 "/compiler/rustc_const_eval/src/transform" = ["compiler", "mir-opt"]
 "/compiler/rustc_mir_build/src/build" =      ["compiler", "mir"]