about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock17
-rw-r--r--compiler/rustc_ast_passes/messages.ftl7
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs33
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs14
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl146
-rw-r--r--compiler/rustc_builtin_macros/src/alloc_error_handler.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/assert.rs28
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs21
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_accessible.rs18
-rw-r--r--compiler/rustc_builtin_macros/src/compile_error.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/concat.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/concat_bytes.rs77
-rw-r--r--compiler/rustc_builtin_macros/src/concat_idents.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/derive.rs40
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs124
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs30
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs553
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs175
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_gcc/example/alloc_system.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0449.md29
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs1
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs26
-rw-r--r--compiler/rustc_errors/src/lib.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs8
-rw-r--r--compiler/rustc_infer/messages.ftl44
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs389
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs448
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs208
-rw-r--r--compiler/rustc_llvm/build.rs1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp7
-rw-r--r--compiler/rustc_llvm/src/lib.rs8
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs24
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs232
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs21
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs32
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs3
-rw-r--r--compiler/rustc_resolve/messages.ftl10
-rw-r--r--compiler/rustc_resolve/src/errors.rs27
-rw-r--r--compiler/rustc_resolve/src/macros.rs30
-rw-r--r--compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs17
-rw-r--r--compiler/rustc_target/src/spec/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs10
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs21
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs107
-rw-r--r--config.example.toml2
-rw-r--r--library/core/src/macros/mod.rs4
-rw-r--r--library/core/src/num/uint_macros.rs9
-rw-r--r--library/std/src/env.rs18
-rw-r--r--library/std/src/os/linux/raw.rs1
-rw-r--r--library/std/src/personality/gcc.rs3
-rw-r--r--library/std/src/sys/common/alloc.rs1
-rw-r--r--library/unwind/src/libunwind.rs3
-rw-r--r--src/bootstrap/bootstrap.py1
-rw-r--r--src/bootstrap/compile.rs6
-rw-r--r--src/bootstrap/lib.rs3
-rw-r--r--src/bootstrap/llvm.rs2
-rw-r--r--src/bootstrap/test.rs5
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
m---------src/doc/book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md1
-rw-r--r--src/doc/rustc/src/platform-support/loongarch-linux.md92
-rwxr-xr-xsrc/etc/rust-gdb4
-rwxr-xr-xsrc/etc/rust-gdbgui6
-rw-r--r--src/librustdoc/clean/cfg.rs1
-rw-r--r--src/librustdoc/clean/mod.rs3
-rw-r--r--src/librustdoc/clean/types.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/.cargo/config.toml3
-rw-r--r--src/tools/clippy/.editorconfig1
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml2
-rw-r--r--src/tools/clippy/.github/workflows/remark.yml2
-rw-r--r--src/tools/clippy/CHANGELOG.md7
-rw-r--r--src/tools/clippy/README.md6
-rw-r--r--src/tools/clippy/book/src/README.md2
-rw-r--r--src/tools/clippy/book/src/SUMMARY.md1
-rw-r--r--src/tools/clippy/book/src/configuration.md29
-rw-r--r--src/tools/clippy/book/src/development/README.md2
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md32
-rw-r--r--src/tools/clippy/book/src/development/basics.md6
-rw-r--r--src/tools/clippy/book/src/development/common_tools_writing_lints.md14
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/book.md4
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/changelog_update.md2
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/release.md2
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/sync.md13
-rw-r--r--src/tools/clippy/book/src/development/proposals/README.md2
-rw-r--r--src/tools/clippy/book/src/development/proposals/roadmap-2021.md6
-rw-r--r--src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md28
-rw-r--r--src/tools/clippy/book/src/development/type_checking.md144
-rw-r--r--src/tools/clippy/book/src/installation.md4
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md18
-rw-r--r--src/tools/clippy/book/src/lints.md10
-rw-r--r--src/tools/clippy/book/src/usage.md4
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs8
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs14
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml1
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs42
-rw-r--r--src/tools/clippy/clippy_lints/src/collection_is_never_read.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/explicit_write.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs177
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs91
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs224
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs60
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/items_after_statements.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/large_futures.rs87
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs100
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs93
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs71
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clear_with_drain.rs53
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_async_block.rs145
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/single_component_path_imports.rs59
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_doc_comments.rs94
-rw-r--r--src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs71
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs120
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs79
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs14
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs39
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs72
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs800
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs22
-rw-r--r--src/tools/clippy/etc/relicense/RELICENSE_DOCUMENTATION.md4
-rw-r--r--src/tools/clippy/lintcheck/README.md2
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/src/driver.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr6
-rw-r--r--src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr22
-rw-r--r--src/tools/clippy/tests/ui-toml/extra_unused_type_parameters/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs9
-rw-r--r--src/tools/clippy/tests/ui-toml/large_futures/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/large_futures/large_futures.rs27
-rw-r--r--src/tools/clippy/tests/ui-toml/large_futures/large_futures.stderr10
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr1
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs4
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr14
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macros.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast.rs6
-rw-r--r--src/tools/clippy/tests/ui/cast.stderr112
-rw-r--r--src/tools/clippy/tests/ui/clear_with_drain.fixed358
-rw-r--r--src/tools/clippy/tests/ui/clear_with_drain.rs358
-rw-r--r--src/tools/clippy/tests/ui/clear_with_drain.stderr130
-rw-r--r--src/tools/clippy/tests/ui/collection_is_never_read.rs31
-rw-r--r--src/tools/clippy/tests/ui/collection_is_never_read.stderr34
-rw-r--r--src/tools/clippy/tests/ui/double_must_use.rs11
-rw-r--r--src/tools/clippy/tests/ui/double_must_use.stderr10
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed105
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.rs11
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr79
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters_unfixable.rs24
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters_unfixable.stderr27
-rw-r--r--src/tools/clippy/tests/ui/format_args_unfixable.rs44
-rw-r--r--src/tools/clippy/tests/ui/format_args_unfixable.stderr36
-rw-r--r--src/tools/clippy/tests/ui/items_after_statement.rs (renamed from src/tools/clippy/tests/ui/item_after_statement.rs)17
-rw-r--r--src/tools/clippy/tests/ui/items_after_statement.stderr (renamed from src/tools/clippy/tests/ui/item_after_statement.stderr)6
-rw-r--r--src/tools/clippy/tests/ui/large_futures.rs61
-rw-r--r--src/tools/clippy/tests/ui/large_futures.stderr82
-rw-r--r--src/tools/clippy/tests/ui/lines_filter_map_ok.fixed29
-rw-r--r--src/tools/clippy/tests/ui/lines_filter_map_ok.rs29
-rw-r--r--src/tools/clippy/tests/ui/lines_filter_map_ok.stderr51
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_size_calculation.rs36
-rw-r--r--src/tools/clippy/tests/ui/manual_slice_size_calculation.stderr51
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.fixed34
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.rs34
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.stderr26
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed9
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs9
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool.rs18
-rw-r--r--src/tools/clippy/tests/ui/print_literal.rs4
-rw-r--r--src/tools/clippy/tests/ui/redundant_async_block.fixed148
-rw-r--r--src/tools/clippy/tests/ui/redundant_async_block.rs148
-rw-r--r--src/tools/clippy/tests/ui/redundant_async_block.stderr46
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports.fixed6
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports.rs6
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports.stderr4
-rw-r--r--src/tools/clippy/tests/ui/suspicious_doc_comments.fixed81
-rw-r--r--src/tools/clippy/tests/ui/suspicious_doc_comments.rs81
-rw-r--r--src/tools/clippy/tests/ui/suspicious_doc_comments.stderr114
-rw-r--r--src/tools/clippy/tests/ui/suspicious_doc_comments_unfixable.rs16
-rw-r--r--src/tools/clippy/tests/ui/suspicious_doc_comments_unfixable.stderr37
-rw-r--r--src/tools/clippy/tests/ui/tests_outside_test_module.rs18
-rw-r--r--src/tools/clippy/tests/ui/tests_outside_test_module.stderr11
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed8
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs8
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr8
-rw-r--r--src/tools/clippy/tests/ui/uninit.rs18
-rw-r--r--src/tools/clippy/tests/ui/uninit.stderr10
-rw-r--r--src/tools/clippy/tests/ui/uninit_vec.rs8
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.fixed88
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.rs86
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.stderr14
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_box_returns.rs60
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_box_returns.stderr35
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.fixed18
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.rs18
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.stderr54
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs_unfixable.stderr12
-rw-r--r--src/tools/compiletest/src/common.rs3
-rw-r--r--src/tools/compiletest/src/main.rs9
-rw-r--r--src/tools/compiletest/src/runtest.rs11
-rw-r--r--src/tools/miri/.github/workflows/ci.yml7
-rw-r--r--src/tools/miri/Cargo.lock8
-rw-r--r--src/tools/miri/README.md9
-rwxr-xr-xsrc/tools/miri/ci.sh4
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/bin/miri.rs19
-rw-r--r--src/tools/miri/src/clock.rs5
-rw-r--r--src/tools/miri/src/lib.rs8
-rw-r--r--src/tools/miri/src/shims/panic.rs20
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs14
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.stderr4
-rw-r--r--src/tools/miri/tests/panic/alignment-assertion.rs9
-rw-r--r--src/tools/miri/tests/panic/alignment-assertion.stderr2
-rw-r--r--src/tools/miri/tests/pass-dep/shims/fcntl_f-fullfsync_apple.rs12
-rw-r--r--src/tools/miri/tests/pass-dep/shims/fcntl_f-fullfsync_apple.stderr2
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs5
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.stderr2
-rw-r--r--src/tools/miri/tests/pass-dep/tokio/sleep.rs6
-rw-r--r--src/tools/miri/tests/pass-dep/tokio/tokio_mvp.rs2
-rw-r--r--src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs4
-rw-r--r--src/tools/miri/tests/pass/shims/time-with-isolation.rs15
-rw-r--r--src/tools/miri/tests/pass/shims/time-with-isolation2.rs8
-rw-r--r--src/tools/miri/tests/pass/shims/time-with-isolation2.stdout1
-rw-r--r--tests/rustdoc-gui/anchor-navigable.goml2
-rw-r--r--tests/rustdoc-gui/anchors.goml8
-rw-r--r--tests/rustdoc-gui/basic-code.goml2
-rw-r--r--tests/rustdoc-gui/check-code-blocks-margin.goml2
-rw-r--r--tests/rustdoc-gui/check-stab-in-docblock.goml4
-rw-r--r--tests/rustdoc-gui/check_info_sign_position.goml4
-rw-r--r--tests/rustdoc-gui/code-blocks-overflow.goml4
-rw-r--r--tests/rustdoc-gui/code-color.goml4
-rw-r--r--tests/rustdoc-gui/code-sidebar-toggle.goml4
-rw-r--r--tests/rustdoc-gui/code-tags.goml12
-rw-r--r--tests/rustdoc-gui/codeblock-sub.goml2
-rw-r--r--tests/rustdoc-gui/codeblock-tooltip.goml4
-rw-r--r--tests/rustdoc-gui/cursor.goml6
-rw-r--r--tests/rustdoc-gui/default-settings.goml2
-rw-r--r--tests/rustdoc-gui/docblock-big-code-mobile.goml4
-rw-r--r--tests/rustdoc-gui/docblock-code-block-line-number.goml4
-rw-r--r--tests/rustdoc-gui/docblock-details.goml4
-rw-r--r--tests/rustdoc-gui/docblock-table-overflow.goml4
-rw-r--r--tests/rustdoc-gui/docblock-table.goml4
-rw-r--r--tests/rustdoc-gui/duplicate-macro-reexport.goml2
-rw-r--r--tests/rustdoc-gui/enum-variants.goml2
-rw-r--r--tests/rustdoc-gui/escape-key.goml2
-rw-r--r--tests/rustdoc-gui/font-weight.goml8
-rw-r--r--tests/rustdoc-gui/go-to-collapsed-elem.goml14
-rw-r--r--tests/rustdoc-gui/hash-item-expansion.goml2
-rw-r--r--tests/rustdoc-gui/headers-color.goml12
-rw-r--r--tests/rustdoc-gui/headings.goml16
-rw-r--r--tests/rustdoc-gui/help-page.goml16
-rw-r--r--tests/rustdoc-gui/highlight-colors.goml4
-rw-r--r--tests/rustdoc-gui/huge-collection-of-constants.goml2
-rw-r--r--tests/rustdoc-gui/huge-logo.goml12
-rw-r--r--tests/rustdoc-gui/impl-default-expansion.goml2
-rw-r--r--tests/rustdoc-gui/impl-doc.goml2
-rw-r--r--tests/rustdoc-gui/implementors.goml10
-rw-r--r--tests/rustdoc-gui/item-decl-colors.goml6
-rw-r--r--tests/rustdoc-gui/item-info-alignment.goml6
-rw-r--r--tests/rustdoc-gui/item-info-overflow.goml6
-rw-r--r--tests/rustdoc-gui/item-info.goml6
-rw-r--r--tests/rustdoc-gui/item-summary-table.goml2
-rw-r--r--tests/rustdoc-gui/javascript-disabled.goml2
-rw-r--r--tests/rustdoc-gui/jump-to-def-background.goml4
-rw-r--r--tests/rustdoc-gui/label-next-to-symbol.goml6
-rw-r--r--tests/rustdoc-gui/links-color.goml4
-rw-r--r--tests/rustdoc-gui/list_code_block.goml4
-rw-r--r--tests/rustdoc-gui/method-margins.goml2
-rw-r--r--tests/rustdoc-gui/mobile.goml12
-rw-r--r--tests/rustdoc-gui/module-items-font.goml2
-rw-r--r--tests/rustdoc-gui/no-docblock.goml4
-rw-r--r--tests/rustdoc-gui/notable-trait.goml18
-rw-r--r--tests/rustdoc-gui/overflow-tooltip-information.goml2
-rw-r--r--tests/rustdoc-gui/pocket-menu.goml10
-rw-r--r--tests/rustdoc-gui/run-on-hover.goml4
-rw-r--r--tests/rustdoc-gui/rust-logo.goml14
-rw-r--r--tests/rustdoc-gui/scrape-examples-button-focus.goml2
-rw-r--r--tests/rustdoc-gui/scrape-examples-color.goml8
-rw-r--r--tests/rustdoc-gui/scrape-examples-fonts.goml2
-rw-r--r--tests/rustdoc-gui/scrape-examples-layout.goml4
-rw-r--r--tests/rustdoc-gui/scrape-examples-toggle.goml4
-rw-r--r--tests/rustdoc-gui/search-error.goml4
-rw-r--r--tests/rustdoc-gui/search-filter.goml8
-rw-r--r--tests/rustdoc-gui/search-form-elements.goml8
-rw-r--r--tests/rustdoc-gui/search-input-mobile.goml6
-rw-r--r--tests/rustdoc-gui/search-keyboard.goml2
-rw-r--r--tests/rustdoc-gui/search-no-result.goml4
-rw-r--r--tests/rustdoc-gui/search-reexport.goml4
-rw-r--r--tests/rustdoc-gui/search-result-color.goml12
-rw-r--r--tests/rustdoc-gui/search-result-description.goml2
-rw-r--r--tests/rustdoc-gui/search-result-display.goml12
-rw-r--r--tests/rustdoc-gui/search-result-go-to-first.goml6
-rw-r--r--tests/rustdoc-gui/search-result-keyword.goml2
-rw-r--r--tests/rustdoc-gui/search-tab-change-title-fn-sig.goml10
-rw-r--r--tests/rustdoc-gui/search-tab.goml4
-rw-r--r--tests/rustdoc-gui/setting-auto-hide-content-large-items.goml2
-rw-r--r--tests/rustdoc-gui/setting-auto-hide-item-methods-docs.goml2
-rw-r--r--tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml2
-rw-r--r--tests/rustdoc-gui/setting-go-to-only-result.goml10
-rw-r--r--tests/rustdoc-gui/settings.goml10
-rw-r--r--tests/rustdoc-gui/shortcuts.goml2
-rw-r--r--tests/rustdoc-gui/sidebar-links-color.goml4
-rw-r--r--tests/rustdoc-gui/sidebar-macro-reexport.goml2
-rw-r--r--tests/rustdoc-gui/sidebar-mobile-scroll.goml6
-rw-r--r--tests/rustdoc-gui/sidebar-mobile.goml6
-rw-r--r--tests/rustdoc-gui/sidebar-source-code-display.goml18
-rw-r--r--tests/rustdoc-gui/sidebar-source-code.goml10
-rw-r--r--tests/rustdoc-gui/sidebar.goml22
-rw-r--r--tests/rustdoc-gui/source-anchor-scroll.goml4
-rw-r--r--tests/rustdoc-gui/source-code-page-code-scroll.goml4
-rw-r--r--tests/rustdoc-gui/source-code-page.goml12
-rw-r--r--tests/rustdoc-gui/src-font-size.goml2
-rw-r--r--tests/rustdoc-gui/stab-badge.goml8
-rw-r--r--tests/rustdoc-gui/struct-fields.goml2
-rw-r--r--tests/rustdoc-gui/target.goml4
-rw-r--r--tests/rustdoc-gui/theme-change.goml8
-rw-r--r--tests/rustdoc-gui/theme-defaults.goml6
-rw-r--r--tests/rustdoc-gui/theme-in-history.goml6
-rw-r--r--tests/rustdoc-gui/toggle-click-deadspace.goml2
-rw-r--r--tests/rustdoc-gui/toggle-docs-mobile.goml6
-rw-r--r--tests/rustdoc-gui/toggle-docs.goml6
-rw-r--r--tests/rustdoc-gui/toggle-implementors.goml2
-rw-r--r--tests/rustdoc-gui/toggled-open-implementations.goml2
-rw-r--r--tests/rustdoc-gui/trait-sidebar-item-order.goml2
-rw-r--r--tests/rustdoc-gui/type-declation-overflow.goml30
-rw-r--r--tests/rustdoc-gui/unsafe-fn.goml4
-rw-r--r--tests/rustdoc-gui/where-whitespace.goml6
-rw-r--r--tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs3
-rw-r--r--tests/rustdoc-ui/intra-doc/inline-external-enum.rs8
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs2
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr2
-rw-r--r--tests/ui/argument-suggestions/issue-109831.rs9
-rw-r--r--tests/ui/argument-suggestions/issue-109831.stderr51
-rw-r--r--tests/ui/associated-type-bounds/issue-104916.rs14
-rw-r--r--tests/ui/associated-type-bounds/issue-104916.stderr8
-rw-r--r--tests/ui/associated-types/associated-types-in-ambiguous-context.rs2
-rw-r--r--tests/ui/associated-types/associated-types-in-ambiguous-context.stderr21
-rw-r--r--tests/ui/box/unit/expr-block-generic-unique1.rs (renamed from tests/ui/unique/expr-block-generic-unique1.rs)0
-rw-r--r--tests/ui/box/unit/expr-block-generic-unique2.rs (renamed from tests/ui/unique/expr-block-generic-unique2.rs)0
-rw-r--r--tests/ui/box/unit/expr-if-unique.rs (renamed from tests/ui/unique/expr-if-unique.rs)0
-rw-r--r--tests/ui/box/unit/unique-assign-copy.rs (renamed from tests/ui/unique/unique-assign-copy.rs)0
-rw-r--r--tests/ui/box/unit/unique-assign-drop.rs (renamed from tests/ui/unique/unique-assign-drop.rs)0
-rw-r--r--tests/ui/box/unit/unique-assign-generic.rs (renamed from tests/ui/unique/unique-assign-generic.rs)0
-rw-r--r--tests/ui/box/unit/unique-assign.rs (renamed from tests/ui/unique/unique-assign.rs)0
-rw-r--r--tests/ui/box/unit/unique-autoderef-field.rs (renamed from tests/ui/unique/unique-autoderef-field.rs)0
-rw-r--r--tests/ui/box/unit/unique-autoderef-index.rs (renamed from tests/ui/unique/unique-autoderef-index.rs)0
-rw-r--r--tests/ui/box/unit/unique-cmp.rs (renamed from tests/ui/unique/unique-cmp.rs)0
-rw-r--r--tests/ui/box/unit/unique-containing-tag.rs (renamed from tests/ui/unique/unique-containing-tag.rs)0
-rw-r--r--tests/ui/box/unit/unique-create.rs (renamed from tests/ui/unique/unique-create.rs)0
-rw-r--r--tests/ui/box/unit/unique-decl-init-copy.rs (renamed from tests/ui/unique/unique-decl-init-copy.rs)0
-rw-r--r--tests/ui/box/unit/unique-decl-init.rs (renamed from tests/ui/unique/unique-decl-init.rs)0
-rw-r--r--tests/ui/box/unit/unique-decl-move.rs (renamed from tests/ui/unique/unique-decl-move.rs)0
-rw-r--r--tests/ui/box/unit/unique-decl.rs (renamed from tests/ui/unique/unique-decl.rs)0
-rw-r--r--tests/ui/box/unit/unique-deref.rs (renamed from tests/ui/unique/unique-deref.rs)0
-rw-r--r--tests/ui/box/unit/unique-destructure.rs (renamed from tests/ui/unique/unique-destructure.rs)0
-rw-r--r--tests/ui/box/unit/unique-drop-complex.rs (renamed from tests/ui/unique/unique-drop-complex.rs)0
-rw-r--r--tests/ui/box/unit/unique-ffi-symbols.rs (renamed from tests/ui/unique/unique-ffi-symbols.rs)0
-rw-r--r--tests/ui/box/unit/unique-fn-arg-move.rs (renamed from tests/ui/unique/unique-fn-arg-move.rs)0
-rw-r--r--tests/ui/box/unit/unique-fn-arg-mut.rs (renamed from tests/ui/unique/unique-fn-arg-mut.rs)0
-rw-r--r--tests/ui/box/unit/unique-fn-arg.rs (renamed from tests/ui/unique/unique-fn-arg.rs)0
-rw-r--r--tests/ui/box/unit/unique-fn-ret.rs (renamed from tests/ui/unique/unique-fn-ret.rs)0
-rw-r--r--tests/ui/box/unit/unique-generic-assign.rs (renamed from tests/ui/unique/unique-generic-assign.rs)0
-rw-r--r--tests/ui/box/unit/unique-in-tag.rs (renamed from tests/ui/unique/unique-in-tag.rs)0
-rw-r--r--tests/ui/box/unit/unique-in-vec-copy.rs (renamed from tests/ui/unique/unique-in-vec-copy.rs)0
-rw-r--r--tests/ui/box/unit/unique-in-vec.rs (renamed from tests/ui/unique/unique-in-vec.rs)0
-rw-r--r--tests/ui/box/unit/unique-init.rs (renamed from tests/ui/unique/unique-init.rs)0
-rw-r--r--tests/ui/box/unit/unique-kinds.rs (renamed from tests/ui/unique/unique-kinds.rs)0
-rw-r--r--tests/ui/box/unit/unique-log.rs (renamed from tests/ui/unique/unique-log.rs)0
-rw-r--r--tests/ui/box/unit/unique-match-discrim.rs (renamed from tests/ui/unique/unique-match-discrim.rs)0
-rw-r--r--tests/ui/box/unit/unique-move-drop.rs (renamed from tests/ui/unique/unique-move-drop.rs)0
-rw-r--r--tests/ui/box/unit/unique-move-temp.rs (renamed from tests/ui/unique/unique-move-temp.rs)0
-rw-r--r--tests/ui/box/unit/unique-move.rs (renamed from tests/ui/unique/unique-move.rs)0
-rw-r--r--tests/ui/box/unit/unique-mutable.rs (renamed from tests/ui/unique/unique-mutable.rs)0
-rw-r--r--tests/ui/box/unit/unique-object-move.rs (renamed from tests/ui/unique/unique-object-move.rs)0
-rw-r--r--tests/ui/box/unit/unique-object-noncopyable.rs (renamed from tests/ui/unique/unique-object-noncopyable.rs)0
-rw-r--r--tests/ui/box/unit/unique-object-noncopyable.stderr (renamed from tests/ui/unique/unique-object-noncopyable.stderr)0
-rw-r--r--tests/ui/box/unit/unique-pat-2.rs (renamed from tests/ui/unique/unique-pat-2.rs)0
-rw-r--r--tests/ui/box/unit/unique-pat-3.rs (renamed from tests/ui/unique/unique-pat-3.rs)0
-rw-r--r--tests/ui/box/unit/unique-pat.rs (renamed from tests/ui/unique/unique-pat.rs)0
-rw-r--r--tests/ui/box/unit/unique-pinned-nocopy.rs (renamed from tests/ui/unique/unique-pinned-nocopy.rs)0
-rw-r--r--tests/ui/box/unit/unique-pinned-nocopy.stderr (renamed from tests/ui/unique/unique-pinned-nocopy.stderr)0
-rw-r--r--tests/ui/box/unit/unique-rec.rs (renamed from tests/ui/unique/unique-rec.rs)0
-rw-r--r--tests/ui/box/unit/unique-send-2.rs (renamed from tests/ui/unique/unique-send-2.rs)0
-rw-r--r--tests/ui/box/unit/unique-send.rs (renamed from tests/ui/unique/unique-send.rs)0
-rw-r--r--tests/ui/box/unit/unique-swap.rs (renamed from tests/ui/unique/unique-swap.rs)0
-rw-r--r--tests/ui/box/unit/unwind-unique.rs (renamed from tests/ui/unique/unwind-unique.rs)0
-rw-r--r--tests/ui/check-cfg/compact-values.stderr2
-rw-r--r--tests/ui/error-codes/E0449.stderr16
-rw-r--r--tests/ui/extenv/extenv-no-args.rs2
-rw-r--r--tests/ui/extenv/extenv-no-args.stderr2
-rw-r--r--tests/ui/extenv/extenv-too-many-args.rs2
-rw-r--r--tests/ui/extenv/extenv-too-many-args.stderr2
-rw-r--r--tests/ui/extenv/issue-55897.stderr2
-rw-r--r--tests/ui/issues/issue-28433.rs4
-rw-r--r--tests/ui/issues/issue-28433.stderr10
-rw-r--r--tests/ui/issues/issue-50403.rs2
-rw-r--r--tests/ui/issues/issue-50403.stderr2
-rw-r--r--tests/ui/macros/concat-bytes-error.stderr8
-rw-r--r--tests/ui/macros/macro-path-prelude-fail-4.stderr8
-rw-r--r--tests/ui/macros/macro-path-prelude-fail-5.rs10
-rw-r--r--tests/ui/macros/macro-path-prelude-fail-5.stderr30
-rw-r--r--tests/ui/macros/macros-nonfatal-errors.stderr18
-rw-r--r--tests/ui/parser/assoc-static-semantic-fail.rs4
-rw-r--r--tests/ui/parser/assoc-static-semantic-fail.stderr10
-rw-r--r--tests/ui/parser/default.rs2
-rw-r--r--tests/ui/parser/default.stderr6
-rw-r--r--tests/ui/parser/trait-pub-assoc-const.rs2
-rw-r--r--tests/ui/parser/trait-pub-assoc-const.stderr6
-rw-r--r--tests/ui/parser/trait-pub-assoc-ty.rs2
-rw-r--r--tests/ui/parser/trait-pub-assoc-ty.stderr6
-rw-r--r--tests/ui/parser/trait-pub-method.rs2
-rw-r--r--tests/ui/parser/trait-pub-method.stderr6
-rw-r--r--tests/ui/privacy/issue-29161.rs2
-rw-r--r--tests/ui/privacy/issue-29161.stderr6
-rw-r--r--tests/ui/privacy/priv-in-bad-locations.rs8
-rw-r--r--tests/ui/privacy/priv-in-bad-locations.stderr20
-rw-r--r--tests/ui/privacy/privacy-sanity.rs36
-rw-r--r--tests/ui/privacy/privacy-sanity.stderr96
-rw-r--r--tests/ui/privacy/useless-pub.rs6
-rw-r--r--tests/ui/privacy/useless-pub.stderr18
-rw-r--r--tests/ui/proc-macro/macro-namespace-reserved-2.stderr16
-rw-r--r--tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr8
-rw-r--r--tests/ui/traits/new-solver/int-var-is-send.rs8
-rw-r--r--tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr17
-rw-r--r--tests/ui/traits/new-solver/stall-num-var-auto-trait.rs25
-rw-r--r--tests/ui/transmutability/primitives/bool.current.stderr (renamed from tests/ui/transmutability/primitives/bool.stderr)4
-rw-r--r--tests/ui/transmutability/primitives/bool.next.stderr19
-rw-r--r--tests/ui/transmutability/primitives/bool.rs4
-rw-r--r--tests/ui/transmutability/primitives/numbers.current.stderr (renamed from tests/ui/transmutability/primitives/numbers.stderr)228
-rw-r--r--tests/ui/transmutability/primitives/numbers.next.stderr915
-rw-r--r--tests/ui/transmutability/primitives/numbers.rs3
-rw-r--r--tests/ui/transmutability/primitives/unit.current.stderr (renamed from tests/ui/transmutability/primitives/unit.stderr)4
-rw-r--r--tests/ui/transmutability/primitives/unit.next.stderr25
-rw-r--r--tests/ui/transmutability/primitives/unit.rs3
-rw-r--r--tests/ui/transmutability/references.current.stderr (renamed from tests/ui/transmutability/references.stderr)4
-rw-r--r--tests/ui/transmutability/references.next.stderr26
-rw-r--r--tests/ui/transmutability/references.rs3
464 files changed, 9047 insertions, 3197 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 321e9cc35c5..b5932607128 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -830,6 +830,7 @@ dependencies = [
 name = "clippy_lints"
 version = "0.1.70"
 dependencies = [
+ "arrayvec 0.7.0",
  "cargo_metadata 0.15.3",
  "clippy_utils",
  "declare_clippy_lint",
@@ -1841,9 +1842,9 @@ dependencies = [
 
 [[package]]
 name = "git2"
-version = "0.16.0"
+version = "0.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be36bc9e0546df253c0cc41fd0af34f5e92845ad8509462ec76672fac6997f5b"
+checksum = "89511277159354bea13ae1e53e0c9ab85ba1b20d7e91618fa30e6bc5566857fb"
 dependencies = [
  "bitflags",
  "libc",
@@ -1856,9 +1857,9 @@ dependencies = [
 
 [[package]]
 name = "git2-curl"
-version = "0.17.0"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7577f4e6341ba7c90d883511130a45b956c274ba5f4d205d9f9da990f654cd33"
+checksum = "f8f8b7432b72928cff76f69e59ed5327f94a52763731e71274960dee72fe5f8c"
 dependencies = [
  "curl",
  "git2",
@@ -2962,9 +2963,9 @@ dependencies = [
 
 [[package]]
 name = "libgit2-sys"
-version = "0.14.1+1.5.0"
+version = "0.15.0+1.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a07fb2692bc3593bda59de45a502bb3071659f2c515e28c71e728306b038e17"
+checksum = "032e537ae4dd4e50c877f258dc55fcd0657b5021f454094a425bb6bcc9edea4c"
 dependencies = [
  "cc",
  "libc",
@@ -3002,9 +3003,9 @@ dependencies = [
 
 [[package]]
 name = "libssh2-sys"
-version = "0.2.23"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b094a36eb4b8b8c8a7b4b8ae43b2944502be3e59cd87687595cf6b0a71b3f4ca"
+checksum = "2dc8a030b787e2119a731f1951d6a773e2280c660f8ec4b0f5e1505a386e71ee"
 dependencies = [
  "cc",
  "libc",
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 747bd52b22c..a349fe6a3c4 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -17,9 +17,10 @@ ast_passes_keyword_lifetime =
 ast_passes_invalid_label =
     invalid label name `{$name}`
 
-ast_passes_invalid_visibility =
-    unnecessary visibility qualifier
-    .implied = `pub` not permitted here because it's implied
+ast_passes_visibility_not_permitted =
+    visibility qualifiers are not permitted here
+    .enum_variant = enum variants and their fields always share the visibility of the enum they are in
+    .trait_impl = trait items always share the visibility of their trait
     .individual_impl_items = place qualifiers on individual impl items instead
     .individual_foreign_items = place qualifiers on individual foreign items instead
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 1389acabfcb..e7cdfeca6f9 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -240,16 +240,12 @@ impl<'a> AstValidator<'a> {
         }
     }
 
-    fn invalid_visibility(&self, vis: &Visibility, note: Option<errors::InvalidVisibilityNote>) {
+    fn visibility_not_permitted(&self, vis: &Visibility, note: errors::VisibilityNotPermittedNote) {
         if let VisibilityKind::Inherited = vis.kind {
             return;
         }
 
-        self.session.emit_err(errors::InvalidVisibility {
-            span: vis.span,
-            implied: vis.kind.is_pub().then_some(vis.span),
-            note,
-        });
+        self.session.emit_err(errors::VisibilityNotPermitted { span: vis.span, note });
     }
 
     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
@@ -819,7 +815,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 items,
             }) => {
                 self.with_in_trait_impl(true, Some(*constness), |this| {
-                    this.invalid_visibility(&item.vis, None);
+                    this.visibility_not_permitted(
+                        &item.vis,
+                        errors::VisibilityNotPermittedNote::TraitImpl,
+                    );
                     if let TyKind::Err = self_ty.kind {
                         this.err_handler().emit_err(errors::ObsoleteAuto { span: item.span });
                     }
@@ -866,9 +865,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         only_trait: only_trait.then_some(()),
                     };
 
-                self.invalid_visibility(
+                self.visibility_not_permitted(
                     &item.vis,
-                    Some(errors::InvalidVisibilityNote::IndividualImplItems),
+                    errors::VisibilityNotPermittedNote::IndividualImplItems,
                 );
                 if let &Unsafe::Yes(span) = unsafety {
                     self.err_handler().emit_err(errors::InherentImplCannotUnsafe {
@@ -924,9 +923,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
             ItemKind::ForeignMod(ForeignMod { abi, unsafety, .. }) => {
                 let old_item = mem::replace(&mut self.extern_mod, Some(item));
-                self.invalid_visibility(
+                self.visibility_not_permitted(
                     &item.vis,
-                    Some(errors::InvalidVisibilityNote::IndividualForeignItems),
+                    errors::VisibilityNotPermittedNote::IndividualForeignItems,
                 );
                 if let &Unsafe::Yes(span) = unsafety {
                     self.err_handler().emit_err(errors::UnsafeItem { span, kind: "extern block" });
@@ -940,9 +939,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
             ItemKind::Enum(def, _) => {
                 for variant in &def.variants {
-                    self.invalid_visibility(&variant.vis, None);
+                    self.visibility_not_permitted(
+                        &variant.vis,
+                        errors::VisibilityNotPermittedNote::EnumVariant,
+                    );
                     for field in variant.data.fields() {
-                        self.invalid_visibility(&field.vis, None);
+                        self.visibility_not_permitted(
+                            &field.vis,
+                            errors::VisibilityNotPermittedNote::EnumVariant,
+                        );
                     }
                 }
             }
@@ -1301,7 +1306,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         }
 
         if ctxt == AssocCtxt::Trait || self.in_trait_impl {
-            self.invalid_visibility(&item.vis, None);
+            self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
             if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
                 self.check_trait_fn_not_const(sig.header.constness);
             }
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index d007097d918..27bbd237961 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -42,18 +42,20 @@ pub struct InvalidLabel {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_invalid_visibility, code = "E0449")]
-pub struct InvalidVisibility {
+#[diag(ast_passes_visibility_not_permitted, code = "E0449")]
+pub struct VisibilityNotPermitted {
     #[primary_span]
     pub span: Span,
-    #[label(ast_passes_implied)]
-    pub implied: Option<Span>,
     #[subdiagnostic]
-    pub note: Option<InvalidVisibilityNote>,
+    pub note: VisibilityNotPermittedNote,
 }
 
 #[derive(Subdiagnostic)]
-pub enum InvalidVisibilityNote {
+pub enum VisibilityNotPermittedNote {
+    #[note(ast_passes_enum_variant)]
+    EnumVariant,
+    #[note(ast_passes_trait_impl)]
+    TraitImpl,
     #[note(ast_passes_individual_impl_items)]
     IndividualImplItems,
     #[note(ast_passes_individual_foreign_items)]
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 4d088e27b36..83dc1ac50e5 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -3,3 +3,149 @@ builtin_macros_requires_cfg_pattern =
     .label = cfg-pattern required
 
 builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern
+
+builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function
+
+builtin_macros_assert_requires_boolean = macro requires a boolean expression as an argument
+    .label = boolean expression required
+
+builtin_macros_assert_requires_expression = macro requires an expression as an argument
+    .suggestion = try removing semicolon
+
+builtin_macros_assert_missing_comma = unexpected string literal
+    .suggestion = try adding a comma
+
+builtin_macros_cfg_accessible_unspecified_path = `cfg_accessible` path is not specified
+builtin_macros_cfg_accessible_multiple_paths = multiple `cfg_accessible` paths are specified
+builtin_macros_cfg_accessible_literal_path = `cfg_accessible` path cannot be a literal
+builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments
+
+builtin_macros_cfg_accessible_indeterminate = cannot determine whether the path is accessible or not
+
+builtin_macros_concat_bytestr = cannot concatenate a byte string literal
+
+builtin_macros_concat_missing_literal = expected a literal
+    .note = only literals (like `"foo"`, `-42` and `3.14`) can be passed to `concat!()`
+
+builtin_macros_concat_bytes_missing_literal = expected a byte literal
+    .note = only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
+
+builtin_macros_concat_bytes_invalid = cannot concatenate {$lit_kind} literals
+    .byte_char = try using a byte character
+    .byte_str = try using a byte string
+    .number_array = try wrapping the number in an array
+
+builtin_macros_concat_bytes_oob = numeric literal is out of bounds
+
+builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8`
+
+builtin_macros_concat_bytes_array = cannot concatenate doubly nested array
+    .note = byte strings are treated as arrays of bytes
+    .help = try flattening the array
+
+builtin_macros_concat_bytes_bad_repeat = repeat count is not a positive number
+
+builtin_macros_concat_idents_missing_args = `concat_idents!()` takes 1 or more arguments
+builtin_macros_concat_idents_missing_comma = `concat_idents!()` expecting comma
+builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args
+
+builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
+    .label = not applicable here
+    .label2 = not a `struct`, `enum` or `union`
+
+builtin_macros_unexpected_lit = expected path to a trait, found literal
+    .label = not a trait
+    .str_lit = try using `#[derive({$sym})]`
+    .other = for example, write `#[derive(Debug)]` for `Debug`
+
+builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept arguments
+    .suggestion = remove the arguments
+
+builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
+    .suggestion = remove the value
+
+builtin_macros_derive_macro_call = `derive` cannot be used on items with type macros
+
+builtin_macros_cannot_derive_union = this trait cannot be derived for unions
+
+builtin_macros_no_default_variant = no default declared
+    .help = make a unit variant default by placing `#[default]` above it
+    .suggestion = make `{$ident}` default
+
+builtin_macros_multiple_defaults = multiple declared defaults
+    .label = first default
+    .additional = additional default
+    .note = only one variant can be default
+    .suggestion = make `{$ident}` default
+
+builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants
+    .help = consider a manual implementation of `Default`
+
+builtin_macros_non_exhaustive_default = default variant must be exhaustive
+    .label = declared `#[non_exhaustive]` here
+    .help = consider a manual implementation of `Default`
+
+builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
+    .note = only one `#[default]` attribute is needed
+    .label = `#[default]` used here
+    .label_again = `#[default]` used again here
+    .help = try removing {$only_one ->
+    [true] this
+    *[false] these
+    }
+
+builtin_macros_default_arg = `#[default]` attribute does not accept a value
+    .suggestion = try using `#[default]`
+
+builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments
+
+builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
+    .cargo = Cargo sets build script variables at run time. Use `std::env::var("{$var}")` instead
+    .other = use `std::env::var("{$var}")` to read the variable at run time
+
+builtin_macros_format_requires_string = requires at least a format string argument
+
+builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}`
+    .label1 = previously here
+    .label2 = duplicate argument
+
+builtin_macros_format_positional_after_named = positional arguments cannot follow named arguments
+    .label = positional arguments must be before named arguments
+    .named_args = named argument
+
+builtin_macros_format_string_invalid = invalid format string: {$desc}
+    .label = {$label1} in format string
+    .note = {$note}
+    .second_label = {$label}
+
+builtin_macros_sugg = consider using a positional formatting argument instead
+
+builtin_macros_format_no_arg_named = there is no argument named `{$name}`
+    .note = did you intend to capture a variable `{$name}` from the surrounding scope?
+    .note2 = to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
+
+builtin_macros_format_unknown_trait = unknown format trait `{$ty}`
+    .note = the only appropriate formatting traits are:
+                                            - ``, which uses the `Display` trait
+                                            - `?`, which uses the `Debug` trait
+                                            - `e`, which uses the `LowerExp` trait
+                                            - `E`, which uses the `UpperExp` trait
+                                            - `o`, which uses the `Octal` trait
+                                            - `p`, which uses the `Pointer` trait
+                                            - `b`, which uses the `Binary` trait
+                                            - `x`, which uses the `LowerHex` trait
+                                            - `X`, which uses the `UpperHex` trait
+    .suggestion = use the `{$trait_name}` trait
+
+builtin_macros_format_unused_arg = {$named ->
+    [true] named argument
+    *[false] argument
+    } never used
+
+builtin_macros_format_unused_args = multiple unused formatting arguments
+    .label = multiple missing formatting specifiers
+
+builtin_macros_format_pos_mismatch = {$n} positional {$n ->
+    [one] argument
+    *[more] arguments
+    } in format string, but {$desc}
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index ac6697232cb..82bae9157e7 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -1,3 +1,4 @@
+use crate::errors;
 use crate::util::check_builtin_macro_attribute;
 
 use rustc_ast::ptr::P;
@@ -31,7 +32,7 @@ pub fn expand(
         {
             (item, true, ecx.with_def_site_ctxt(fn_kind.sig.span))
         } else {
-            ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "alloc_error_handler must be a function");
+            ecx.sess.parse_sess.span_diagnostic.emit_err(errors::AllocErrorMustBeFn {span: item.span() });
             return vec![orig_item];
         };
 
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index 75af5e2b1fa..0de424be2f1 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -1,12 +1,13 @@
 mod context;
 
 use crate::edition_panic::use_panic_2021;
+use crate::errors;
 use rustc_ast::ptr::P;
 use rustc_ast::token;
 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
 use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, MacDelimiter, Path, PathSegment, UnOp};
 use rustc_ast_pretty::pprust;
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::PResult;
 use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
 use rustc_parse::parser::Parser;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -114,9 +115,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
     let mut parser = cx.new_parser_from_tts(stream);
 
     if parser.token == token::Eof {
-        let mut err = cx.struct_span_err(sp, "macro requires a boolean expression as an argument");
-        err.span_label(sp, "boolean expression required");
-        return Err(err);
+        return Err(cx.create_err(errors::AssertRequiresBoolean { span: sp }));
     }
 
     let cond_expr = parser.parse_expr()?;
@@ -129,15 +128,7 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
     //
     // Emit an error about semicolon and suggest removing it.
     if parser.token == token::Semi {
-        let mut err = cx.struct_span_err(sp, "macro requires an expression as an argument");
-        err.span_suggestion(
-            parser.token.span,
-            "try removing semicolon",
-            "",
-            Applicability::MaybeIncorrect,
-        );
-        err.emit();
-
+        cx.emit_err(errors::AssertRequiresExpression { span: sp, token: parser.token.span });
         parser.bump();
     }
 
@@ -149,15 +140,8 @@ fn parse_assert<'a>(cx: &mut ExtCtxt<'a>, sp: Span, stream: TokenStream) -> PRes
     // Emit an error and suggest inserting a comma.
     let custom_message =
         if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind {
-            let mut err = cx.struct_span_err(parser.token.span, "unexpected string literal");
-            let comma_span = parser.prev_token.span.shrink_to_hi();
-            err.span_suggestion_short(
-                comma_span,
-                "try adding a comma",
-                ", ",
-                Applicability::MaybeIncorrect,
-            );
-            err.emit();
+            let comma = parser.prev_token.span.shrink_to_hi();
+            cx.emit_err(errors::AssertMissingComma { span: parser.token.span, comma });
 
             parse_custom_message(&mut parser)
         } else if parser.eat(&token::Comma) {
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index 5638c2f6180..1397cee7af8 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -2,13 +2,13 @@
 //! a literal `true` or `false` based on whether the given cfg matches the
 //! current compilation environment.
 
+use crate::errors;
 use rustc_ast as ast;
 use rustc_ast::token;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_attr as attr;
 use rustc_errors::PResult;
 use rustc_expand::base::{self, *};
-use rustc_macros::Diagnostic;
 use rustc_span::Span;
 
 pub fn expand_cfg(
@@ -35,26 +35,11 @@ pub fn expand_cfg(
     }
 }
 
-#[derive(Diagnostic)]
-#[diag(builtin_macros_requires_cfg_pattern)]
-struct RequiresCfgPattern {
-    #[primary_span]
-    #[label]
-    span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(builtin_macros_expected_one_cfg_pattern)]
-struct OneCfgPattern {
-    #[primary_span]
-    span: Span,
-}
-
 fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> {
     let mut p = cx.new_parser_from_tts(tts);
 
     if p.token == token::Eof {
-        return Err(cx.create_err(RequiresCfgPattern { span }));
+        return Err(cx.create_err(errors::RequiresCfgPattern { span }));
     }
 
     let cfg = p.parse_meta_item()?;
@@ -62,7 +47,7 @@ fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<
     let _ = p.eat(&token::Comma);
 
     if !p.eat(&token::Eof) {
-        return Err(cx.create_err(OneCfgPattern { span }));
+        return Err(cx.create_err(errors::OneCfgPattern { span }));
     }
 
     Ok(cfg)
diff --git a/compiler/rustc_builtin_macros/src/cfg_accessible.rs b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
index 4e4cafc7182..37ac09ccdff 100644
--- a/compiler/rustc_builtin_macros/src/cfg_accessible.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_accessible.rs
@@ -1,5 +1,6 @@
 //! Implementation of the `#[cfg_accessible(path)]` attribute macro.
 
+use crate::errors;
 use rustc_ast as ast;
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
 use rustc_feature::AttributeTemplate;
@@ -10,15 +11,22 @@ use rustc_span::Span;
 pub(crate) struct Expander;
 
 fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> {
+    use errors::CfgAccessibleInvalid::*;
     match mi.meta_item_list() {
         None => {}
-        Some([]) => ecx.span_err(mi.span, "`cfg_accessible` path is not specified"),
-        Some([_, .., l]) => ecx.span_err(l.span(), "multiple `cfg_accessible` paths are specified"),
+        Some([]) => {
+            ecx.emit_err(UnspecifiedPath(mi.span));
+        }
+        Some([_, .., l]) => {
+            ecx.emit_err(MultiplePaths(l.span()));
+        }
         Some([nmi]) => match nmi.meta_item() {
-            None => ecx.span_err(nmi.span(), "`cfg_accessible` path cannot be a literal"),
+            None => {
+                ecx.emit_err(LiteralPath(nmi.span()));
+            }
             Some(mi) => {
                 if !mi.is_word() {
-                    ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments");
+                    ecx.emit_err(HasArguments(mi.span));
                 }
                 return Some(&mi.path);
             }
@@ -53,7 +61,7 @@ impl MultiItemModifier for Expander {
             Ok(true) => ExpandResult::Ready(vec![item]),
             Ok(false) => ExpandResult::Ready(Vec::new()),
             Err(Indeterminate) if ecx.force_mode => {
-                ecx.span_err(span, "cannot determine whether the path is accessible or not");
+                ecx.emit_err(errors::CfgAccessibleIndeterminate { span });
                 ExpandResult::Ready(vec![item])
             }
             Err(Indeterminate) => ExpandResult::Retry(item),
diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs
index 72397aa2500..aeb3bb80045 100644
--- a/compiler/rustc_builtin_macros/src/compile_error.rs
+++ b/compiler/rustc_builtin_macros/src/compile_error.rs
@@ -13,6 +13,11 @@ pub fn expand_compile_error<'cx>(
         return DummyResult::any(sp);
     };
 
+    #[expect(
+        rustc::diagnostic_outside_of_impl,
+        reason = "diagnostic message is specified by user"
+    )]
+    #[expect(rustc::untranslatable_diagnostic, reason = "diagnostic message is specified by user")]
     cx.span_err(sp, var.as_str());
 
     DummyResult::any(sp)
diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs
index 36682bbe070..b92964d03e9 100644
--- a/compiler/rustc_builtin_macros/src/concat.rs
+++ b/compiler/rustc_builtin_macros/src/concat.rs
@@ -4,6 +4,8 @@ use rustc_expand::base::{self, DummyResult};
 use rustc_session::errors::report_lit_error;
 use rustc_span::symbol::Symbol;
 
+use crate::errors;
+
 pub fn expand_concat(
     cx: &mut base::ExtCtxt<'_>,
     sp: rustc_span::Span,
@@ -31,7 +33,7 @@ pub fn expand_concat(
                     accumulator.push_str(&b.to_string());
                 }
                 Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => {
-                    cx.span_err(e.span, "cannot concatenate a byte string literal");
+                    cx.emit_err(errors::ConcatBytestr { span: e.span });
                     has_errors = true;
                 }
                 Ok(ast::LitKind::Err) => {
@@ -55,7 +57,7 @@ pub fn expand_concat(
                 }
             }
             ast::ExprKind::IncludedBytes(..) => {
-                cx.span_err(e.span, "cannot concatenate a byte string literal")
+                cx.emit_err(errors::ConcatBytestr { span: e.span });
             }
             ast::ExprKind::Err => {
                 has_errors = true;
@@ -67,9 +69,7 @@ pub fn expand_concat(
     }
 
     if !missing_literal.is_empty() {
-        let mut err = cx.struct_span_err(missing_literal, "expected a literal");
-        err.note("only literals (like `\"foo\"`, `-42` and `3.14`) can be passed to `concat!()`");
-        err.emit();
+        cx.emit_err(errors::ConcatMissingLiteral { spans: missing_literal });
         return DummyResult::any(sp);
     } else if has_errors {
         return DummyResult::any(sp);
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 4f1a7d709ff..ba639c0a9fe 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -1,10 +1,11 @@
 use rustc_ast as ast;
 use rustc_ast::{ptr::P, tokenstream::TokenStream};
-use rustc_errors::Applicability;
 use rustc_expand::base::{self, DummyResult};
 use rustc_session::errors::report_lit_error;
 use rustc_span::Span;
 
+use crate::errors;
+
 /// Emits errors for literal expressions that are invalid inside and outside of an array.
 fn invalid_type_err(
     cx: &mut base::ExtCtxt<'_>,
@@ -12,62 +13,46 @@ fn invalid_type_err(
     span: Span,
     is_nested: bool,
 ) {
+    use errors::{
+        ConcatBytesInvalid, ConcatBytesInvalidSuggestion, ConcatBytesNonU8, ConcatBytesOob,
+    };
+    let snippet = cx.sess.source_map().span_to_snippet(span).ok();
     match ast::LitKind::from_token_lit(token_lit) {
         Ok(ast::LitKind::Char(_)) => {
-            let mut err = cx.struct_span_err(span, "cannot concatenate character literals");
-            if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
-                err.span_suggestion(
-                    span,
-                    "try using a byte character",
-                    format!("b{}", snippet),
-                    Applicability::MachineApplicable,
-                )
-                .emit();
-            }
+            let sugg =
+                snippet.map(|snippet| ConcatBytesInvalidSuggestion::CharLit { span, snippet });
+            cx.sess.emit_err(ConcatBytesInvalid { span, lit_kind: "character", sugg });
         }
         Ok(ast::LitKind::Str(_, _)) => {
-            let mut err = cx.struct_span_err(span, "cannot concatenate string literals");
             // suggestion would be invalid if we are nested
-            if !is_nested {
-                if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
-                    err.span_suggestion(
-                        span,
-                        "try using a byte string",
-                        format!("b{}", snippet),
-                        Applicability::MachineApplicable,
-                    );
-                }
-            }
-            err.emit();
+            let sugg = if !is_nested {
+                snippet.map(|snippet| ConcatBytesInvalidSuggestion::StrLit { span, snippet })
+            } else {
+                None
+            };
+            cx.emit_err(ConcatBytesInvalid { span, lit_kind: "string", sugg });
         }
         Ok(ast::LitKind::Float(_, _)) => {
-            cx.span_err(span, "cannot concatenate float literals");
+            cx.emit_err(ConcatBytesInvalid { span, lit_kind: "float", sugg: None });
         }
         Ok(ast::LitKind::Bool(_)) => {
-            cx.span_err(span, "cannot concatenate boolean literals");
+            cx.emit_err(ConcatBytesInvalid { span, lit_kind: "boolean", sugg: None });
         }
         Ok(ast::LitKind::Err) => {}
         Ok(ast::LitKind::Int(_, _)) if !is_nested => {
-            let mut err = cx.struct_span_err(span, "cannot concatenate numeric literals");
-            if let Ok(snippet) = cx.sess.source_map().span_to_snippet(span) {
-                err.span_suggestion(
-                    span,
-                    "try wrapping the number in an array",
-                    format!("[{}]", snippet),
-                    Applicability::MachineApplicable,
-                );
-            }
-            err.emit();
+            let sugg =
+                snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span: span, snippet });
+            cx.emit_err(ConcatBytesInvalid { span, lit_kind: "numeric", sugg });
         }
         Ok(ast::LitKind::Int(
             val,
             ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
         )) => {
             assert!(val > u8::MAX.into()); // must be an error
-            cx.span_err(span, "numeric literal is out of bounds");
+            cx.emit_err(ConcatBytesOob { span });
         }
         Ok(ast::LitKind::Int(_, _)) => {
-            cx.span_err(span, "numeric literal is not a `u8`");
+            cx.emit_err(ConcatBytesNonU8 { span });
         }
         Ok(ast::LitKind::ByteStr(..) | ast::LitKind::Byte(_)) => unreachable!(),
         Err(err) => {
@@ -85,7 +70,7 @@ fn handle_array_element(
     match expr.kind {
         ast::ExprKind::Array(_) | ast::ExprKind::Repeat(_, _) => {
             if !*has_errors {
-                cx.span_err(expr.span, "cannot concatenate doubly nested array");
+                cx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false });
             }
             *has_errors = true;
             None
@@ -99,10 +84,7 @@ fn handle_array_element(
             Ok(ast::LitKind::Byte(val)) => Some(val),
             Ok(ast::LitKind::ByteStr(..)) => {
                 if !*has_errors {
-                    cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
-                        .note("byte strings are treated as arrays of bytes")
-                        .help("try flattening the array")
-                        .emit();
+                    cx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: true });
                 }
                 *has_errors = true;
                 None
@@ -117,10 +99,7 @@ fn handle_array_element(
         },
         ast::ExprKind::IncludedBytes(..) => {
             if !*has_errors {
-                cx.struct_span_err(expr.span, "cannot concatenate doubly nested array")
-                    .note("byte strings are treated as arrays of bytes")
-                    .help("try flattening the array")
-                    .emit();
+                cx.emit_err(errors::ConcatBytesArray { span: expr.span, bytestr: false });
             }
             *has_errors = true;
             None
@@ -167,7 +146,7 @@ pub fn expand_concat_bytes(
                         }
                     }
                 } else {
-                    cx.span_err(count.value.span, "repeat count is not a positive number");
+                    cx.emit_err(errors::ConcatBytesBadRepeat {span: count.value.span });
                 }
             }
             &ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) {
@@ -196,9 +175,7 @@ pub fn expand_concat_bytes(
         }
     }
     if !missing_literals.is_empty() {
-        let mut err = cx.struct_span_err(missing_literals, "expected a byte literal");
-        err.note("only byte literals (like `b\"foo\"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`");
-        err.emit();
+        cx.emit_err(errors::ConcatBytesMissingLiteral { spans: missing_literals });
         return base::MacEager::expr(DummyResult::raw_expr(sp, true));
     } else if has_errors {
         return base::MacEager::expr(DummyResult::raw_expr(sp, true));
diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs
index 297c604e020..8c737f04323 100644
--- a/compiler/rustc_builtin_macros/src/concat_idents.rs
+++ b/compiler/rustc_builtin_macros/src/concat_idents.rs
@@ -6,13 +6,15 @@ use rustc_expand::base::{self, *};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
 
+use crate::errors;
+
 pub fn expand_concat_idents<'cx>(
     cx: &'cx mut ExtCtxt<'_>,
     sp: Span,
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'cx> {
     if tts.is_empty() {
-        cx.span_err(sp, "concat_idents! takes 1 or more arguments");
+        cx.emit_err(errors::ConcatIdentsMissingArgs { span: sp });
         return DummyResult::any(sp);
     }
 
@@ -22,7 +24,7 @@ pub fn expand_concat_idents<'cx>(
             match e {
                 TokenTree::Token(Token { kind: token::Comma, .. }, _) => {}
                 _ => {
-                    cx.span_err(sp, "concat_idents! expecting comma");
+                    cx.emit_err(errors::ConcatIdentsMissingComma { span: sp });
                     return DummyResult::any(sp);
                 }
             }
@@ -34,7 +36,7 @@ pub fn expand_concat_idents<'cx>(
                 }
             }
 
-            cx.span_err(sp, "concat_idents! requires ident args");
+            cx.emit_err(errors::ConcatIdentsIdentArgs { span: sp });
             return DummyResult::any(sp);
         }
     }
diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs
index 2a8dc02849e..fe4483104ee 100644
--- a/compiler/rustc_builtin_macros/src/derive.rs
+++ b/compiler/rustc_builtin_macros/src/derive.rs
@@ -1,8 +1,8 @@
 use crate::cfg_eval::cfg_eval;
+use crate::errors;
 
 use rustc_ast as ast;
 use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
-use rustc_errors::{struct_span_err, Applicability};
 use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
 use rustc_feature::AttributeTemplate;
 use rustc_parse::validate_attr;
@@ -116,49 +116,33 @@ fn report_bad_target(sess: &Session, item: &Annotatable, span: Span) -> bool {
     let bad_target =
         !matches!(item_kind, Some(ItemKind::Struct(..) | ItemKind::Enum(..) | ItemKind::Union(..)));
     if bad_target {
-        struct_span_err!(
-            sess,
-            span,
-            E0774,
-            "`derive` may only be applied to `struct`s, `enum`s and `union`s",
-        )
-        .span_label(span, "not applicable here")
-        .span_label(item.span(), "not a `struct`, `enum` or `union`")
-        .emit();
+        sess.emit_err(errors::BadDeriveTarget { span, item: item.span() });
     }
     bad_target
 }
 
 fn report_unexpected_meta_item_lit(sess: &Session, lit: &ast::MetaItemLit) {
-    let help_msg = match lit.kind {
+    let help = match lit.kind {
         ast::LitKind::Str(_, ast::StrStyle::Cooked)
             if rustc_lexer::is_ident(lit.symbol.as_str()) =>
         {
-            format!("try using `#[derive({})]`", lit.symbol)
+            errors::BadDeriveLitHelp::StrLit { sym: lit.symbol }
         }
-        _ => "for example, write `#[derive(Debug)]` for `Debug`".to_string(),
+        _ => errors::BadDeriveLitHelp::Other,
     };
-    struct_span_err!(sess, lit.span, E0777, "expected path to a trait, found literal",)
-        .span_label(lit.span, "not a trait")
-        .help(&help_msg)
-        .emit();
+    sess.emit_err(errors::BadDeriveLit { span: lit.span, help });
 }
 
 fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
-    let report_error = |title, action| {
-        let span = meta.span.with_lo(meta.path.span.hi());
-        sess.struct_span_err(span, title)
-            .span_suggestion(span, action, "", Applicability::MachineApplicable)
-            .emit();
-    };
+    let span = meta.span.with_lo(meta.path.span.hi());
+
     match meta.kind {
         MetaItemKind::Word => {}
-        MetaItemKind::List(..) => report_error(
-            "traits in `#[derive(...)]` don't accept arguments",
-            "remove the arguments",
-        ),
+        MetaItemKind::List(..) => {
+            sess.emit_err(errors::DerivePathArgsList { span });
+        }
         MetaItemKind::NameValue(..) => {
-            report_error("traits in `#[derive(...)]` don't accept values", "remove the value")
+            sess.emit_err(errors::DerivePathArgsValue { span });
         }
     }
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index cc32739d083..33fe98b40e1 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -1,8 +1,8 @@
 use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
+use crate::errors;
 use rustc_ast as ast;
 use rustc_ast::{attr, walk_list, EnumDef, VariantData};
-use rustc_errors::Applicability;
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::{kw, sym};
@@ -118,67 +118,50 @@ fn extract_default_variant<'a>(
                 .filter(|variant| matches!(variant.data, VariantData::Unit(..)))
                 .filter(|variant| !attr::contains_name(&variant.attrs, sym::non_exhaustive));
 
-            let mut diag = cx.struct_span_err(trait_span, "no default declared");
-            diag.help("make a unit variant default by placing `#[default]` above it");
-            for variant in possible_defaults {
-                // Suggest making each unit variant default.
-                diag.tool_only_span_suggestion(
-                    variant.span,
-                    &format!("make `{}` default", variant.ident),
-                    format!("#[default] {}", variant.ident),
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            diag.emit();
+            let suggs = possible_defaults
+                .map(|v| errors::NoDefaultVariantSugg { span: v.span, ident: v.ident })
+                .collect();
+            cx.emit_err(errors::NoDefaultVariant { span: trait_span, suggs });
 
             return Err(());
         }
         [first, rest @ ..] => {
-            let mut diag = cx.struct_span_err(trait_span, "multiple declared defaults");
-            diag.span_label(first.span, "first default");
-            diag.span_labels(rest.iter().map(|variant| variant.span), "additional default");
-            diag.note("only one variant can be default");
-            for variant in &default_variants {
-                // Suggest making each variant already tagged default.
-                let suggestion = default_variants
-                    .iter()
-                    .filter_map(|v| {
-                        if v.span == variant.span {
-                            None
-                        } else {
-                            Some((attr::find_by_name(&v.attrs, kw::Default)?.span, String::new()))
-                        }
-                    })
-                    .collect();
-
-                diag.tool_only_multipart_suggestion(
-                    &format!("make `{}` default", variant.ident),
-                    suggestion,
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            diag.emit();
-
+            let suggs = default_variants
+                .iter()
+                .map(|variant| {
+                    let spans = default_variants
+                        .iter()
+                        .filter_map(|v| {
+                            if v.span == variant.span {
+                                None
+                            } else {
+                                Some(attr::find_by_name(&v.attrs, kw::Default)?.span)
+                            }
+                        })
+                        .collect();
+                    errors::MultipleDefaultsSugg { spans, ident: variant.ident }
+                })
+                .collect();
+            cx.emit_err(errors::MultipleDefaults {
+                span: trait_span,
+                first: first.span,
+                additional: rest.iter().map(|v| v.span).collect(),
+                suggs,
+            });
             return Err(());
         }
     };
 
     if !matches!(variant.data, VariantData::Unit(..)) {
-        cx.struct_span_err(
-            variant.ident.span,
-            "the `#[default]` attribute may only be used on unit enum variants",
-        )
-        .help("consider a manual implementation of `Default`")
-        .emit();
-
+        cx.emit_err(errors::NonUnitDefault { span: variant.ident.span });
         return Err(());
     }
 
     if let Some(non_exhaustive_attr) = attr::find_by_name(&variant.attrs, sym::non_exhaustive) {
-        cx.struct_span_err(variant.ident.span, "default variant must be exhaustive")
-            .span_label(non_exhaustive_attr.span, "declared `#[non_exhaustive]` here")
-            .help("consider a manual implementation of `Default`")
-            .emit();
+        cx.emit_err(errors::NonExhaustiveDefault {
+            span: variant.ident.span,
+            non_exhaustive: non_exhaustive_attr.span,
+        });
 
         return Err(());
     }
@@ -199,35 +182,23 @@ fn validate_default_attribute(
             "this method must only be called with a variant that has a `#[default]` attribute",
         ),
         [first, rest @ ..] => {
-            let suggestion_text =
-                if rest.len() == 1 { "try removing this" } else { "try removing these" };
-
-            cx.struct_span_err(default_variant.ident.span, "multiple `#[default]` attributes")
-                .note("only one `#[default]` attribute is needed")
-                .span_label(first.span, "`#[default]` used here")
-                .span_label(rest[0].span, "`#[default]` used again here")
-                .span_help(rest.iter().map(|attr| attr.span).collect::<Vec<_>>(), suggestion_text)
-                // This would otherwise display the empty replacement, hence the otherwise
-                // repetitive `.span_help` call above.
-                .tool_only_multipart_suggestion(
-                    suggestion_text,
-                    rest.iter().map(|attr| (attr.span, String::new())).collect(),
-                    Applicability::MachineApplicable,
-                )
-                .emit();
+            let sugg = errors::MultipleDefaultAttrsSugg {
+                spans: rest.iter().map(|attr| attr.span).collect(),
+            };
+            cx.emit_err(errors::MultipleDefaultAttrs {
+                span: default_variant.ident.span,
+                first: first.span,
+                first_rest: rest[0].span,
+                rest: rest.iter().map(|attr| attr.span).collect::<Vec<_>>().into(),
+                only_one: rest.len() == 1,
+                sugg,
+            });
 
             return Err(());
         }
     };
     if !attr.is_word() {
-        cx.struct_span_err(attr.span, "`#[default]` attribute does not accept a value")
-            .span_suggestion_hidden(
-                attr.span,
-                "try using `#[default]`",
-                "#[default]",
-                Applicability::MaybeIncorrect,
-            )
-            .emit();
+        cx.emit_err(errors::DefaultHasArg { span: attr.span });
 
         return Err(());
     }
@@ -241,12 +212,7 @@ struct DetectNonVariantDefaultAttr<'a, 'b> {
 impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, 'b> {
     fn visit_attribute(&mut self, attr: &'a rustc_ast::Attribute) {
         if attr.has_name(kw::Default) {
-            self.cx
-                .struct_span_err(
-                    attr.span,
-                    "the `#[default]` attribute may only be used on unit enum variants",
-                )
-                .emit();
+            self.cx.emit_err(errors::NonUnitDefault { span: attr.span });
         }
 
         rustc_ast::visit::walk_attribute(self, attr);
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 6b3053fdfac..e5a00331588 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -162,7 +162,7 @@
 pub use StaticFields::*;
 pub use SubstructureFields::*;
 
-use crate::deriving;
+use crate::{deriving, errors};
 use rustc_ast::ptr::P;
 use rustc_ast::{
     self as ast, BindingAnnotation, ByRef, EnumDef, Expr, GenericArg, GenericParamKind, Generics,
@@ -415,7 +415,7 @@ fn find_type_parameters(
         }
 
         fn visit_mac_call(&mut self, mac: &ast::MacCall) {
-            self.cx.span_err(mac.span(), "`derive` cannot be used on items with type macros");
+            self.cx.emit_err(errors::DeriveMacroCall { span: mac.span() });
         }
     }
 
@@ -488,7 +488,7 @@ impl<'a> TraitDef<'a> {
                                 is_packed,
                             )
                         } else {
-                            cx.span_err(mitem.span, "this trait cannot be derived for unions");
+                            cx.emit_err(errors::DeriveUnion { span: mitem.span });
                             return;
                         }
                     }
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index f011cb754cb..58c972738c4 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -11,6 +11,8 @@ use rustc_span::Span;
 use std::env;
 use thin_vec::thin_vec;
 
+use crate::errors;
+
 pub fn expand_option_env<'cx>(
     cx: &'cx mut ExtCtxt<'_>,
     sp: Span,
@@ -54,7 +56,7 @@ pub fn expand_env<'cx>(
 ) -> Box<dyn base::MacResult + 'cx> {
     let mut exprs = match get_exprs_from_tts(cx, tts) {
         Some(exprs) if exprs.is_empty() || exprs.len() > 2 => {
-            cx.span_err(sp, "env! takes 1 or 2 arguments");
+            cx.emit_err(errors::EnvTakesArgs { span: sp });
             return DummyResult::any(sp);
         }
         None => return DummyResult::any(sp),
@@ -78,18 +80,12 @@ pub fn expand_env<'cx>(
     cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
     let e = match value {
         None => {
-            let (msg, help) = match custom_msg {
-                None => (
-                    format!("environment variable `{var}` not defined at compile time"),
-                    Some(help_for_missing_env_var(var.as_str())),
-                ),
-                Some(s) => (s.to_string(), None),
-            };
-            let mut diag = cx.struct_span_err(sp, &msg);
-            if let Some(help) = help {
-                diag.help(help);
-            }
-            diag.emit();
+            cx.emit_err(errors::EnvNotDefined {
+                span: sp,
+                msg: custom_msg,
+                var,
+                help: custom_msg.is_none().then(|| help_for_missing_env_var(var.as_str())),
+            });
             return DummyResult::any(sp);
         }
         Some(value) => cx.expr_str(sp, value),
@@ -97,15 +93,13 @@ pub fn expand_env<'cx>(
     MacEager::expr(e)
 }
 
-fn help_for_missing_env_var(var: &str) -> String {
+fn help_for_missing_env_var(var: &str) -> errors::EnvNotDefinedHelp {
     if var.starts_with("CARGO_")
         || var.starts_with("DEP_")
         || matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
     {
-        format!(
-            "Cargo sets build script variables at run time. Use `std::env::var(\"{var}\")` instead"
-        )
+        errors::EnvNotDefinedHelp::CargoVar
     } else {
-        format!("Use `std::env::var(\"{var}\")` to read the variable at run time")
+        errors::EnvNotDefinedHelp::Other
     }
 }
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
new file mode 100644
index 00000000000..630f9b87bc3
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -0,0 +1,553 @@
+use rustc_errors::{
+    AddToDiagnostic, EmissionGuarantee, IntoDiagnostic, MultiSpan, SingleLabelManySpans,
+};
+use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_span::{symbol::Ident, Span, Symbol};
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_requires_cfg_pattern)]
+pub(crate) struct RequiresCfgPattern {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_expected_one_cfg_pattern)]
+pub(crate) struct OneCfgPattern {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_alloc_error_must_be_fn)]
+pub(crate) struct AllocErrorMustBeFn {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_assert_requires_boolean)]
+pub(crate) struct AssertRequiresBoolean {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_assert_requires_expression)]
+pub(crate) struct AssertRequiresExpression {
+    #[primary_span]
+    pub(crate) span: Span,
+    #[suggestion(code = "", applicability = "maybe-incorrect")]
+    pub(crate) token: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_assert_missing_comma)]
+pub(crate) struct AssertMissingComma {
+    #[primary_span]
+    pub(crate) span: Span,
+    #[suggestion(code = ", ", applicability = "maybe-incorrect", style = "short")]
+    pub(crate) comma: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum CfgAccessibleInvalid {
+    #[diag(builtin_macros_cfg_accessible_unspecified_path)]
+    UnspecifiedPath(#[primary_span] Span),
+    #[diag(builtin_macros_cfg_accessible_multiple_paths)]
+    MultiplePaths(#[primary_span] Span),
+    #[diag(builtin_macros_cfg_accessible_literal_path)]
+    LiteralPath(#[primary_span] Span),
+    #[diag(builtin_macros_cfg_accessible_has_args)]
+    HasArguments(#[primary_span] Span),
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_cfg_accessible_indeterminate)]
+pub(crate) struct CfgAccessibleIndeterminate {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_missing_literal)]
+#[note]
+pub(crate) struct ConcatMissingLiteral {
+    #[primary_span]
+    pub(crate) spans: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_bytestr)]
+pub(crate) struct ConcatBytestr {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_bytes_invalid)]
+pub(crate) struct ConcatBytesInvalid {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) lit_kind: &'static str,
+    #[subdiagnostic]
+    pub(crate) sugg: Option<ConcatBytesInvalidSuggestion>,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ConcatBytesInvalidSuggestion {
+    #[suggestion(
+        builtin_macros_byte_char,
+        code = "b{snippet}",
+        applicability = "machine-applicable"
+    )]
+    CharLit {
+        #[primary_span]
+        span: Span,
+        snippet: String,
+    },
+    #[suggestion(
+        builtin_macros_byte_str,
+        code = "b{snippet}",
+        applicability = "machine-applicable"
+    )]
+    StrLit {
+        #[primary_span]
+        span: Span,
+        snippet: String,
+    },
+    #[suggestion(
+        builtin_macros_number_array,
+        code = "[{snippet}]",
+        applicability = "machine-applicable"
+    )]
+    IntLit {
+        #[primary_span]
+        span: Span,
+        snippet: String,
+    },
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_bytes_oob)]
+pub(crate) struct ConcatBytesOob {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_bytes_non_u8)]
+pub(crate) struct ConcatBytesNonU8 {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_bytes_missing_literal)]
+#[note]
+pub(crate) struct ConcatBytesMissingLiteral {
+    #[primary_span]
+    pub(crate) spans: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_bytes_array)]
+pub(crate) struct ConcatBytesArray {
+    #[primary_span]
+    pub(crate) span: Span,
+    #[note]
+    #[help]
+    pub(crate) bytestr: bool,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_bytes_bad_repeat)]
+pub(crate) struct ConcatBytesBadRepeat {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_idents_missing_args)]
+pub(crate) struct ConcatIdentsMissingArgs {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_idents_missing_comma)]
+pub(crate) struct ConcatIdentsMissingComma {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_concat_idents_ident_args)]
+pub(crate) struct ConcatIdentsIdentArgs {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_bad_derive_target, code = "E0774")]
+pub(crate) struct BadDeriveTarget {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    #[label(builtin_macros_label2)]
+    pub(crate) item: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_unexpected_lit, code = "E0777")]
+pub(crate) struct BadDeriveLit {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    #[subdiagnostic]
+    pub help: BadDeriveLitHelp,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum BadDeriveLitHelp {
+    #[help(builtin_macros_str_lit)]
+    StrLit { sym: Symbol },
+    #[help(builtin_macros_other)]
+    Other,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_derive_path_args_list)]
+pub(crate) struct DerivePathArgsList {
+    #[suggestion(code = "", applicability = "machine-applicable")]
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_derive_path_args_value)]
+pub(crate) struct DerivePathArgsValue {
+    #[suggestion(code = "", applicability = "machine-applicable")]
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_no_default_variant)]
+#[help]
+pub(crate) struct NoDefaultVariant {
+    #[primary_span]
+    pub(crate) span: Span,
+    #[subdiagnostic]
+    pub(crate) suggs: Vec<NoDefaultVariantSugg>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    builtin_macros_suggestion,
+    code = "#[default] {ident}",
+    applicability = "maybe-incorrect",
+    style = "tool-only"
+)]
+pub(crate) struct NoDefaultVariantSugg {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_multiple_defaults)]
+#[note]
+pub(crate) struct MultipleDefaults {
+    #[primary_span]
+    pub(crate) span: Span,
+    #[label]
+    pub(crate) first: Span,
+    #[label(builtin_macros_additional)]
+    pub additional: Vec<Span>,
+    #[subdiagnostic]
+    pub suggs: Vec<MultipleDefaultsSugg>,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    builtin_macros_suggestion,
+    applicability = "maybe-incorrect",
+    style = "tool-only"
+)]
+pub(crate) struct MultipleDefaultsSugg {
+    #[suggestion_part(code = "")]
+    pub(crate) spans: Vec<Span>,
+    pub(crate) ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_non_unit_default)]
+#[help]
+pub(crate) struct NonUnitDefault {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_non_exhaustive_default)]
+#[help]
+pub(crate) struct NonExhaustiveDefault {
+    #[primary_span]
+    pub(crate) span: Span,
+    #[label]
+    pub(crate) non_exhaustive: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_multiple_default_attrs)]
+#[note]
+pub(crate) struct MultipleDefaultAttrs {
+    #[primary_span]
+    pub(crate) span: Span,
+    #[label]
+    pub(crate) first: Span,
+    #[label(builtin_macros_label_again)]
+    pub(crate) first_rest: Span,
+    #[help]
+    pub(crate) rest: MultiSpan,
+    pub(crate) only_one: bool,
+    #[subdiagnostic]
+    pub(crate) sugg: MultipleDefaultAttrsSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    builtin_macros_help,
+    applicability = "machine-applicable",
+    style = "tool-only"
+)]
+pub(crate) struct MultipleDefaultAttrsSugg {
+    #[suggestion_part(code = "")]
+    pub(crate) spans: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_default_arg)]
+pub(crate) struct DefaultHasArg {
+    #[primary_span]
+    #[suggestion(code = "#[default]", style = "hidden", applicability = "maybe-incorrect")]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_derive_macro_call)]
+pub(crate) struct DeriveMacroCall {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_cannot_derive_union)]
+pub(crate) struct DeriveUnion {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_env_takes_args)]
+pub(crate) struct EnvTakesArgs {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+//#[derive(Diagnostic)]
+//#[diag(builtin_macros_env_not_defined)]
+pub(crate) struct EnvNotDefined {
+    pub(crate) span: Span,
+    pub(crate) msg: Option<Symbol>,
+    pub(crate) var: Symbol,
+    pub(crate) help: Option<EnvNotDefinedHelp>,
+}
+
+// Hand-written implementation to support custom user messages
+impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
+    #[track_caller]
+    fn into_diagnostic(
+        self,
+        handler: &'a rustc_errors::Handler,
+    ) -> rustc_errors::DiagnosticBuilder<'a, G> {
+        let mut diag = if let Some(msg) = self.msg {
+            handler.struct_diagnostic(msg.as_str())
+        } else {
+            handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
+        };
+        diag.set_arg("var", self.var);
+        diag.set_span(self.span);
+        if let Some(help) = self.help {
+            diag.subdiagnostic(help);
+        }
+        diag
+    }
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum EnvNotDefinedHelp {
+    #[help(builtin_macros_cargo)]
+    CargoVar,
+    #[help(builtin_macros_other)]
+    Other,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_format_requires_string)]
+pub(crate) struct FormatRequiresString {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_format_duplicate_arg)]
+pub(crate) struct FormatDuplicateArg {
+    #[primary_span]
+    pub(crate) span: Span,
+    #[label(builtin_macros_label1)]
+    pub(crate) prev: Span,
+    #[label(builtin_macros_label2)]
+    pub(crate) duplicate: Span,
+    pub(crate) ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_format_positional_after_named)]
+pub(crate) struct PositionalAfterNamed {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    #[label(builtin_macros_named_args)]
+    pub(crate) args: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_format_string_invalid)]
+pub(crate) struct InvalidFormatString {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    pub(crate) desc: String,
+    pub(crate) label1: String,
+    #[subdiagnostic]
+    pub(crate) note_: Option<InvalidFormatStringNote>,
+    #[subdiagnostic]
+    pub(crate) label_: Option<InvalidFormatStringLabel>,
+    #[subdiagnostic]
+    pub(crate) sugg_: Option<InvalidFormatStringSuggestion>,
+}
+
+#[derive(Subdiagnostic)]
+#[note(builtin_macros_note)]
+pub(crate) struct InvalidFormatStringNote {
+    pub(crate) note: String,
+}
+
+#[derive(Subdiagnostic)]
+#[label(builtin_macros_second_label)]
+pub(crate) struct InvalidFormatStringLabel {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) label: String,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    builtin_macros_sugg,
+    style = "verbose",
+    applicability = "machine-applicable"
+)]
+pub(crate) struct InvalidFormatStringSuggestion {
+    #[suggestion_part(code = "{len}")]
+    pub(crate) captured: Span,
+    pub(crate) len: String,
+    #[suggestion_part(code = ", {arg}")]
+    pub(crate) span: Span,
+    pub(crate) arg: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_format_no_arg_named)]
+#[note]
+#[note(builtin_macros_note2)]
+pub(crate) struct FormatNoArgNamed {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_format_unknown_trait)]
+#[note]
+pub(crate) struct FormatUnknownTrait<'a> {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) ty: &'a str,
+    #[subdiagnostic]
+    pub(crate) suggs: Vec<FormatUnknownTraitSugg>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    builtin_macros_suggestion,
+    code = "{fmt}",
+    style = "tool-only",
+    applicability = "maybe-incorrect"
+)]
+pub struct FormatUnknownTraitSugg {
+    #[primary_span]
+    pub span: Span,
+    pub fmt: &'static str,
+    pub trait_name: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_format_unused_arg)]
+pub(crate) struct FormatUnusedArg {
+    #[primary_span]
+    #[label(builtin_macros_format_unused_arg)]
+    pub(crate) span: Span,
+    pub(crate) named: bool,
+}
+
+// Allow the singular form to be a subdiagnostic of the multiple-unused
+// form of diagnostic.
+impl AddToDiagnostic for FormatUnusedArg {
+    fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F)
+    where
+        F: Fn(
+            &mut rustc_errors::Diagnostic,
+            rustc_errors::SubdiagnosticMessage,
+        ) -> rustc_errors::SubdiagnosticMessage,
+    {
+        diag.set_arg("named", self.named);
+        let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into());
+        diag.span_label(self.span, msg);
+    }
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_format_unused_args)]
+pub(crate) struct FormatUnusedArgs {
+    #[primary_span]
+    pub(crate) unused: Vec<Span>,
+    #[label]
+    pub(crate) fmt: Span,
+    #[subdiagnostic]
+    pub(crate) unused_labels: Vec<FormatUnusedArg>,
+}
+
+#[derive(Diagnostic)]
+#[diag(builtin_macros_format_pos_mismatch)]
+pub(crate) struct FormatPositionalMismatch {
+    #[primary_span]
+    pub(crate) span: MultiSpan,
+    pub(crate) n: usize,
+    pub(crate) desc: String,
+    #[subdiagnostic]
+    pub(crate) highlight: SingleLabelManySpans,
+}
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index db2ef7fba4b..435a07d8ce7 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -7,7 +7,7 @@ use rustc_ast::{
     FormatDebugHex, FormatOptions, FormatPlaceholder, FormatSign, FormatTrait,
 };
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{pluralize, Applicability, MultiSpan, PResult};
+use rustc_errors::{Applicability, MultiSpan, PResult, SingleLabelManySpans};
 use rustc_expand::base::{self, *};
 use rustc_parse_format as parse;
 use rustc_span::symbol::{Ident, Symbol};
@@ -36,6 +36,8 @@ enum PositionUsedAs {
 }
 use PositionUsedAs::*;
 
+use crate::errors;
+
 struct MacroInput {
     fmtstr: P<Expr>,
     args: FormatArguments,
@@ -66,7 +68,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
     let mut p = ecx.new_parser_from_tts(tts);
 
     if p.token == token::Eof {
-        return Err(ecx.struct_span_err(sp, "requires at least a format string argument"));
+        return Err(ecx.create_err(errors::FormatRequiresString { span: sp }));
     }
 
     let first_token = &p.token;
@@ -121,13 +123,12 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
                 p.expect(&token::Eq)?;
                 let expr = p.parse_expr()?;
                 if let Some((_, prev)) = args.by_name(ident.name) {
-                    ecx.struct_span_err(
-                        ident.span,
-                        &format!("duplicate argument named `{}`", ident),
-                    )
-                    .span_label(prev.kind.ident().unwrap().span, "previously here")
-                    .span_label(ident.span, "duplicate argument")
-                    .emit();
+                    ecx.emit_err(errors::FormatDuplicateArg {
+                        span: ident.span,
+                        prev: prev.kind.ident().unwrap().span,
+                        duplicate: ident.span,
+                        ident,
+                    });
                     continue;
                 }
                 args.add(FormatArgument { kind: FormatArgumentKind::Named(ident), expr });
@@ -135,20 +136,21 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<
             _ => {
                 let expr = p.parse_expr()?;
                 if !args.named_args().is_empty() {
-                    let mut err = ecx.struct_span_err(
-                        expr.span,
-                        "positional arguments cannot follow named arguments",
-                    );
-                    err.span_label(
-                        expr.span,
-                        "positional arguments must be before named arguments",
-                    );
-                    for arg in args.named_args() {
-                        if let Some(name) = arg.kind.ident() {
-                            err.span_label(name.span.to(arg.expr.span), "named argument");
-                        }
-                    }
-                    err.emit();
+                    ecx.emit_err(errors::PositionalAfterNamed {
+                        span: expr.span,
+                        args: args
+                            .named_args()
+                            .iter()
+                            .filter_map(|a| {
+                                if let Some(ident) = a.kind.ident() {
+                                    Some((a, ident))
+                                } else {
+                                    None
+                                }
+                            })
+                            .map(|(arg, n)| n.span.to(arg.expr.span))
+                            .collect(),
+                    });
                 }
                 args.add(FormatArgument { kind: FormatArgumentKind::Normal, expr });
             }
@@ -234,13 +236,19 @@ fn make_format_args(
             // argument span here.
             fmt_span
         };
-        let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}", err.description));
-        e.span_label(sp, err.label + " in format string");
+        let mut e = errors::InvalidFormatString {
+            span: sp,
+            note_: None,
+            label_: None,
+            sugg_: None,
+            desc: err.description,
+            label1: err.label,
+        };
         if let Some(note) = err.note {
-            e.note(&note);
+            e.note_ = Some(errors::InvalidFormatStringNote { note });
         }
         if let Some((label, span)) = err.secondary_label && is_source_literal {
-            e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
+            e.label_ = Some(errors::InvalidFormatStringLabel { span: fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label } );
         }
         if err.should_be_replaced_with_positional_argument {
             let captured_arg_span =
@@ -250,17 +258,15 @@ fn make_format_args(
                     Some(arg) => arg.expr.span,
                     None => fmt_span,
                 };
-                e.multipart_suggestion_verbose(
-                    "consider using a positional formatting argument instead",
-                    vec![
-                        (captured_arg_span, args.unnamed_args().len().to_string()),
-                        (span.shrink_to_hi(), format!(", {}", arg)),
-                    ],
-                    Applicability::MachineApplicable,
-                );
+                e.sugg_ = Some(errors::InvalidFormatStringSuggestion {
+                    captured: captured_arg_span,
+                    len: args.unnamed_args().len().to_string(),
+                    span: span.shrink_to_hi(),
+                    arg,
+                });
             }
         }
-        e.emit();
+        ecx.emit_err(e);
         return Err(());
     }
 
@@ -318,10 +324,7 @@ fn make_format_args(
                     } else {
                         // For the moment capturing variables from format strings expanded from macros is
                         // disabled (see RFC #2795)
-                        ecx.struct_span_err(span, &format!("there is no argument named `{name}`"))
-                            .note(format!("did you intend to capture a variable `{name}` from the surrounding scope?"))
-                            .note("to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro")
-                            .emit();
+                        ecx.emit_err(errors::FormatNoArgNamed { span, name });
                         DummyResult::raw_expr(span, true)
                     };
                     Ok(args.add(FormatArgument { kind: FormatArgumentKind::Captured(ident), expr }))
@@ -475,12 +478,8 @@ fn make_format_args(
         .enumerate()
         .filter(|&(_, used)| !used)
         .map(|(i, _)| {
-            let msg = if let FormatArgumentKind::Named(_) = args.explicit_args()[i].kind {
-                "named argument never used"
-            } else {
-                "argument never used"
-            };
-            (args.explicit_args()[i].expr.span, msg)
+            let named = matches!(args.explicit_args()[i].kind, FormatArgumentKind::Named(_));
+            (args.explicit_args()[i].expr.span, named)
         })
         .collect::<Vec<_>>();
 
@@ -531,22 +530,8 @@ fn invalid_placeholder_type_error(
     fmt_span: Span,
 ) {
     let sp = ty_span.map(|sp| fmt_span.from_inner(InnerSpan::new(sp.start, sp.end)));
-    let mut err =
-        ecx.struct_span_err(sp.unwrap_or(fmt_span), &format!("unknown format trait `{}`", ty));
-    err.note(
-        "the only appropriate formatting traits are:\n\
-                                - ``, which uses the `Display` trait\n\
-                                - `?`, which uses the `Debug` trait\n\
-                                - `e`, which uses the `LowerExp` trait\n\
-                                - `E`, which uses the `UpperExp` trait\n\
-                                - `o`, which uses the `Octal` trait\n\
-                                - `p`, which uses the `Pointer` trait\n\
-                                - `b`, which uses the `Binary` trait\n\
-                                - `x`, which uses the `LowerHex` trait\n\
-                                - `X`, which uses the `UpperHex` trait",
-    );
-    if let Some(sp) = sp {
-        for (fmt, name) in &[
+    let suggs = if let Some(sp) = sp {
+        [
             ("", "Display"),
             ("?", "Debug"),
             ("e", "LowerExp"),
@@ -556,40 +541,38 @@ fn invalid_placeholder_type_error(
             ("b", "Binary"),
             ("x", "LowerHex"),
             ("X", "UpperHex"),
-        ] {
-            err.tool_only_span_suggestion(
-                sp,
-                &format!("use the `{}` trait", name),
-                *fmt,
-                Applicability::MaybeIncorrect,
-            );
-        }
-    }
-    err.emit();
+        ]
+        .into_iter()
+        .map(|(fmt, trait_name)| errors::FormatUnknownTraitSugg { span: sp, fmt, trait_name })
+        .collect()
+    } else {
+        vec![]
+    };
+    ecx.emit_err(errors::FormatUnknownTrait { span: sp.unwrap_or(fmt_span), ty, suggs });
 }
 
 fn report_missing_placeholders(
     ecx: &mut ExtCtxt<'_>,
-    unused: Vec<(Span, &str)>,
+    unused: Vec<(Span, bool)>,
     detect_foreign_fmt: bool,
     str_style: Option<usize>,
     fmt_str: &str,
     fmt_span: Span,
 ) {
-    let mut diag = if let &[(span, msg)] = &unused[..] {
-        let mut diag = ecx.struct_span_err(span, msg);
-        diag.span_label(span, msg);
-        diag
+    let mut diag = if let &[(span, named)] = &unused[..] {
+        //let mut diag = ecx.struct_span_err(span, msg);
+        //diag.span_label(span, msg);
+        //diag
+        ecx.create_err(errors::FormatUnusedArg { span, named })
     } else {
-        let mut diag = ecx.struct_span_err(
-            unused.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
-            "multiple unused formatting arguments",
-        );
-        diag.span_label(fmt_span, "multiple missing formatting specifiers");
-        for &(span, msg) in &unused {
-            diag.span_label(span, msg);
-        }
-        diag
+        let unused_labels =
+            unused.iter().map(|&(span, named)| errors::FormatUnusedArg { span, named }).collect();
+        let unused_spans = unused.iter().map(|&(span, _)| span).collect();
+        ecx.create_err(errors::FormatUnusedArgs {
+            fmt: fmt_span,
+            unused: unused_spans,
+            unused_labels,
+        })
     };
 
     // Used to ensure we only report translations for *one* kind of foreign format.
@@ -768,18 +751,16 @@ fn report_invalid_references(
         } else {
             MultiSpan::from_spans(spans)
         };
-        e = ecx.struct_span_err(
+        e = ecx.create_err(errors::FormatPositionalMismatch {
             span,
-            &format!(
-                "{} positional argument{} in format string, but {}",
-                num_placeholders,
-                pluralize!(num_placeholders),
-                num_args_desc,
-            ),
-        );
-        for arg in args.explicit_args() {
-            e.span_label(arg.expr.span, "");
-        }
+            n: num_placeholders,
+            desc: num_args_desc,
+            highlight: SingleLabelManySpans {
+                spans: args.explicit_args().iter().map(|arg| arg.expr.span).collect(),
+                label: "",
+                kind: rustc_errors::LabelKind::Label,
+            },
+        });
         // Point out `{:.*}` placeholders: those take an extra argument.
         let mut has_precision_star = false;
         for piece in template {
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 7697b592e33..37fbd03a6a2 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -9,6 +9,7 @@
 #![feature(if_let_guard)]
 #![feature(is_sorted)]
 #![feature(let_chains)]
+#![feature(lint_reasons)]
 #![feature(proc_macro_internals)]
 #![feature(proc_macro_quote)]
 #![recursion_limit = "256"]
@@ -39,6 +40,7 @@ mod derive;
 mod deriving;
 mod edition_panic;
 mod env;
+mod errors;
 mod format;
 mod format_foreign;
 mod global_allocator;
diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs
index 9ec18da90d8..046903fe5ac 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_system.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs
@@ -15,6 +15,7 @@
 const MIN_ALIGN: usize = 8;
 #[cfg(any(target_arch = "x86_64",
               target_arch = "aarch64",
+              target_arch = "loongarch64",
               target_arch = "mips64",
               target_arch = "s390x",
               target_arch = "sparc64"))]
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 3e3fcc08bd6..d5d843702c0 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -127,6 +127,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         "msp430" => Architecture::Msp430,
         "hexagon" => Architecture::Hexagon,
         "bpf" => Architecture::Bpf,
+        "loongarch64" => Architecture::LoongArch64,
         // Unsupported architecture.
         _ => return None,
     };
@@ -190,6 +191,10 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
             }
             e_flags
         }
+        Architecture::LoongArch64 => {
+            // Source: https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_e_flags_identifies_abi_type_and_version
+            elf::EF_LARCH_OBJABI_V1 | elf::EF_LARCH_ABI_DOUBLE_FLOAT
+        }
         _ => 0,
     };
     // adapted from LLVM's `MCELFObjectTargetWriter::getOSABI`
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 754b085f1a8..611dd3d1cd1 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -251,6 +251,7 @@ const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("e", Some(sym::riscv_target_feature)),
     ("f", Some(sym::riscv_target_feature)),
     ("m", Some(sym::riscv_target_feature)),
+    ("relax", 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_error_codes/src/error_codes/E0449.md b/compiler/rustc_error_codes/src/error_codes/E0449.md
index 9afc67689bf..a5876e07528 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0449.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0449.md
@@ -1,4 +1,6 @@
-A visibility qualifier was used when it was unnecessary.
+A visibility qualifier was used where one is not permitted. Visibility
+qualifiers are not permitted on enum variants, trait items, impl blocks, and
+extern blocks, as they already share the visibility of the parent item.
 
 Erroneous code examples:
 
@@ -9,15 +11,18 @@ trait Foo {
     fn foo();
 }
 
-pub impl Bar {} // error: unnecessary visibility qualifier
+enum Baz {
+    pub Qux, // error: visibility qualifiers are not permitted here
+}
+
+pub impl Bar {} // error: visibility qualifiers are not permitted here
 
-pub impl Foo for Bar { // error: unnecessary visibility qualifier
-    pub fn foo() {} // error: unnecessary visibility qualifier
+pub impl Foo for Bar { // error: visibility qualifiers are not permitted here
+    pub fn foo() {} // error: visibility qualifiers are not permitted here
 }
 ```
 
-To fix this error, please remove the visibility qualifier when it is not
-required. Example:
+To fix this error, simply remove the visibility qualifier. Example:
 
 ```
 struct Bar;
@@ -26,12 +31,18 @@ trait Foo {
     fn foo();
 }
 
+enum Baz {
+    // Enum variants share the visibility of the enum they are in, so
+    // `pub` is not allowed here
+    Qux,
+}
+
 // Directly implemented methods share the visibility of the type itself,
-// so `pub` is unnecessary here
+// so `pub` is not allowed here
 impl Bar {}
 
-// Trait methods share the visibility of the trait, so `pub` is
-// unnecessary in either case
+// Trait methods share the visibility of the trait, so `pub` is not
+// allowed in either case
 impl Foo for Bar {
     fn foo() {}
 }
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index e09ef34b93d..29c692128bc 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -880,6 +880,7 @@ impl Diagnostic {
     ///
     /// This is intended to be used for suggestions that are *very* obvious in what the changes
     /// need to be from the message, but we still want other tools to be able to apply them.
+    #[rustc_lint_diagnostics]
     pub fn tool_only_span_suggestion(
         &mut self,
         sp: Span,
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index e82bad67b21..65f8a61a30a 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -1,4 +1,4 @@
-use crate::fluent_generated as fluent;
+use crate::{fluent_generated as fluent, AddToDiagnostic};
 use crate::{DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg};
 use rustc_ast as ast;
 use rustc_ast_pretty::pprust;
@@ -6,6 +6,7 @@ use rustc_hir as hir;
 use rustc_lint_defs::Level;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
+use rustc_span::Span;
 use rustc_target::abi::TargetDataLayoutErrors;
 use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
 use rustc_type_ir as type_ir;
@@ -276,3 +277,26 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
         }
     }
 }
+
+/// Utility struct used to apply a single label while highlighting multiple spans
+pub struct SingleLabelManySpans {
+    pub spans: Vec<Span>,
+    pub label: &'static str,
+    pub kind: LabelKind,
+}
+impl AddToDiagnostic for SingleLabelManySpans {
+    fn add_to_diagnostic_with<F>(self, diag: &mut crate::Diagnostic, _: F) {
+        match self.kind {
+            LabelKind::Note => diag.span_note(self.spans, self.label),
+            LabelKind::Label => diag.span_labels(self.spans, self.label),
+            LabelKind::Help => diag.span_help(self.spans, self.label),
+        };
+    }
+}
+
+/// The kind of label to attach when using [`SingleLabelManySpans`]
+pub enum LabelKind {
+    Note,
+    Label,
+    Help,
+}
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 9866a9bffe0..5b0d8096207 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -383,7 +383,9 @@ pub use diagnostic::{
     DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
 };
 pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted};
-pub use diagnostic_impls::{DiagnosticArgFromDisplay, DiagnosticSymbolList};
+pub use diagnostic_impls::{
+    DiagnosticArgFromDisplay, DiagnosticSymbolList, LabelKind, SingleLabelManySpans,
+};
 use std::backtrace::Backtrace;
 
 /// A handler deals with errors and other compiler output.
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index acca3fa2641..37c894348cd 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2580,7 +2580,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 tcx.all_impls(trait_def_id)
                     .filter(|impl_def_id| {
                         // Consider only accessible traits
-                        tcx.visibility(*impl_def_id).is_accessible_from(self.item_def_id(), tcx)
+                        tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
                             && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
                     })
                     .filter_map(|impl_def_id| tcx.impl_trait_ref(impl_def_id))
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index b02eae19fce..cf93d1d2182 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -768,7 +768,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let (provided_ty, provided_span) = provided_arg_tys[*provided_idx];
             let trace =
                 mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
-            if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
+            if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
                 self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
                 return true;
             }
@@ -1191,11 +1191,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // index position where it *should have been*, which is *after* the previous one.
             if let Some(provided_idx) = provided_idx {
                 prev = provided_idx.index() as i64;
+                continue;
             }
             let idx = ProvidedIdx::from_usize((prev + 1) as usize);
-            if let None = provided_idx
-                && let Some((_, arg_span)) = provided_arg_tys.get(idx)
-            {
+            if let Some((_, arg_span)) = provided_arg_tys.get(idx) {
+                prev += 1;
                 // There is a type that was *not* found anywhere, so it isn't a move, but a
                 // replacement and we look at what type it should have been. This will allow us
                 // To suggest a multipart suggestion when encountering `foo(1, "")` where the def
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 1e43644be89..4d4a7880b00 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -348,3 +348,47 @@ infer_prlf_known_limitation = this is a known limitation that will be removed in
 
 infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
     .label = opaque type defined here
+
+infer_fps_use_ref = consider using a reference
+infer_fps_remove_ref = consider removing the reference
+infer_fps_cast = consider casting to a fn pointer
+infer_fps_items_are_distinct = fn items are distinct from fn pointers
+infer_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}`
+
+infer_fn_uniq_types = different fn items have unique types, even if their signatures are the same
+infer_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}`
+
+infer_sarwa_option = you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`
+infer_sarwa_result = you can convert from `&Result<T, E>` to `Result<&T, &E>` using `.as_ref()`
+
+infer_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}`
+
+infer_sbfrit_change_return_type = you could change the return type to be a boxed trait object
+infer_sbfrit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions
+
+infer_stp_wrap_one = try wrapping the pattern in `{$variant}`
+infer_stp_wrap_many = try wrapping the pattern in a variant of `{$path}`
+
+infer_tuple_trailing_comma = use a trailing comma to create a tuple with one element
+
+infer_oc_method_compat = method not compatible with trait
+infer_oc_type_compat = type not compatible with trait
+infer_oc_const_compat = const not compatible with trait
+infer_oc_try_compat = `?` operator has incompatible types
+infer_oc_match_compat = `match` arms have incompatible types
+infer_oc_if_else_different = `if` and `else` have incompatible types
+infer_oc_no_else = `if` may be missing an `else` clause
+infer_oc_no_diverge = `else` clause of `let...else` does not diverge
+infer_oc_fn_main_correct_type = `main` function has wrong type
+infer_oc_fn_start_correct_type = `#[start]` function has wrong type
+infer_oc_intristic_correct_type = intrinsic has wrong type
+infer_oc_method_correct_type = mismatched `self` parameter type
+infer_oc_closure_selfref = closure/generator type that references itself
+infer_oc_cant_coerce = cannot coerce intrinsics to function pointers
+infer_oc_generic = mismatched types
+
+infer_meant_byte_literal = if you meant to write a byte literal, prefix with `b`
+infer_meant_char_literal = if you meant to write a `char` literal, use single quotes
+infer_meant_str_literal = if you meant to write a `str` literal, use double quotes
+infer_consider_specifying_length = consider specifying the actual array length
+infer_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}`
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 6bbd3fd3e6e..b129621130d 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -184,18 +184,6 @@ pub enum SourceKindMultiSuggestion<'a> {
     },
 }
 
-#[derive(Subdiagnostic)]
-#[suggestion(
-    infer_suggest_add_let_for_letchains,
-    style = "verbose",
-    applicability = "machine-applicable",
-    code = "let "
-)]
-pub(crate) struct SuggAddLetForLetChains {
-    #[primary_span]
-    pub span: Span,
-}
-
 impl<'a> SourceKindMultiSuggestion<'a> {
     pub fn new_fully_qualified(
         span: Span,
@@ -1157,3 +1145,380 @@ pub struct OpaqueCapturesLifetime<'tcx> {
     pub opaque_ty_span: Span,
     pub opaque_ty: Ty<'tcx>,
 }
+
+#[derive(Subdiagnostic)]
+pub enum FunctionPointerSuggestion<'a> {
+    #[suggestion(
+        infer_fps_use_ref,
+        code = "&{fn_name}",
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    UseRef {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+    },
+    #[suggestion(
+        infer_fps_remove_ref,
+        code = "{fn_name}",
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    RemoveRef {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+    },
+    #[suggestion(
+        infer_fps_cast,
+        code = "&({fn_name} as {sig})",
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    CastRef {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+        #[skip_arg]
+        sig: Binder<'a, FnSig<'a>>,
+    },
+    #[suggestion(
+        infer_fps_cast,
+        code = "{fn_name} as {sig}",
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    Cast {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+        #[skip_arg]
+        sig: Binder<'a, FnSig<'a>>,
+    },
+    #[suggestion(
+        infer_fps_cast_both,
+        code = "{fn_name} as {found_sig}",
+        style = "hidden",
+        applicability = "maybe-incorrect"
+    )]
+    CastBoth {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+        #[skip_arg]
+        found_sig: Binder<'a, FnSig<'a>>,
+        expected_sig: Binder<'a, FnSig<'a>>,
+    },
+    #[suggestion(
+        infer_fps_cast_both,
+        code = "&({fn_name} as {found_sig})",
+        style = "hidden",
+        applicability = "maybe-incorrect"
+    )]
+    CastBothRef {
+        #[primary_span]
+        span: Span,
+        #[skip_arg]
+        fn_name: String,
+        #[skip_arg]
+        found_sig: Binder<'a, FnSig<'a>>,
+        expected_sig: Binder<'a, FnSig<'a>>,
+    },
+}
+
+#[derive(Subdiagnostic)]
+#[note(infer_fps_items_are_distinct)]
+pub struct FnItemsAreDistinct;
+
+#[derive(Subdiagnostic)]
+#[note(infer_fn_uniq_types)]
+pub struct FnUniqTypes;
+
+#[derive(Subdiagnostic)]
+#[help(infer_fn_consider_casting)]
+pub struct FnConsiderCasting {
+    pub casting: String,
+}
+
+#[derive(Subdiagnostic)]
+pub enum SuggestAsRefWhereAppropriate<'a> {
+    #[suggestion(
+        infer_sarwa_option,
+        code = "{snippet}.as_ref()",
+        applicability = "machine-applicable"
+    )]
+    Option {
+        #[primary_span]
+        span: Span,
+        snippet: &'a str,
+    },
+    #[suggestion(
+        infer_sarwa_result,
+        code = "{snippet}.as_ref()",
+        applicability = "machine-applicable"
+    )]
+    Result {
+        #[primary_span]
+        span: Span,
+        snippet: &'a str,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub enum SuggestAccessingField<'a> {
+    #[suggestion(
+        infer_suggest_accessing_field,
+        code = "{snippet}.{name}",
+        applicability = "maybe-incorrect"
+    )]
+    Safe {
+        #[primary_span]
+        span: Span,
+        snippet: String,
+        name: Symbol,
+        ty: Ty<'a>,
+    },
+    #[suggestion(
+        infer_suggest_accessing_field,
+        code = "unsafe {{ {snippet}.{name} }}",
+        applicability = "maybe-incorrect"
+    )]
+    Unsafe {
+        #[primary_span]
+        span: Span,
+        snippet: String,
+        name: Symbol,
+        ty: Ty<'a>,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub enum SuggestBoxingForReturnImplTrait {
+    #[multipart_suggestion(infer_sbfrit_change_return_type, applicability = "maybe-incorrect")]
+    ChangeReturnType {
+        #[suggestion_part(code = "Box<dyn")]
+        start_sp: Span,
+        #[suggestion_part(code = ">")]
+        end_sp: Span,
+    },
+    #[multipart_suggestion(infer_sbfrit_box_return_expr, applicability = "maybe-incorrect")]
+    BoxReturnExpr {
+        #[suggestion_part(code = "Box::new(")]
+        starts: Vec<Span>,
+        #[suggestion_part(code = ")")]
+        ends: Vec<Span>,
+    },
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(infer_stp_wrap_one, applicability = "maybe-incorrect")]
+pub struct SuggestTuplePatternOne {
+    pub variant: String,
+    #[suggestion_part(code = "{variant}(")]
+    pub span_low: Span,
+    #[suggestion_part(code = ")")]
+    pub span_high: Span,
+}
+
+pub struct SuggestTuplePatternMany {
+    pub path: String,
+    pub cause_span: Span,
+    pub compatible_variants: Vec<String>,
+}
+
+impl AddToDiagnostic for SuggestTuplePatternMany {
+    fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, f: F)
+    where
+        F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+    {
+        diag.set_arg("path", self.path);
+        let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into());
+        diag.multipart_suggestions(
+            message,
+            self.compatible_variants.into_iter().map(|variant| {
+                vec![
+                    (self.cause_span.shrink_to_lo(), format!("{}(", variant)),
+                    (self.cause_span.shrink_to_hi(), ")".to_string()),
+                ]
+            }),
+            rustc_errors::Applicability::MaybeIncorrect,
+        );
+    }
+}
+
+#[derive(Subdiagnostic)]
+pub enum TypeErrorAdditionalDiags {
+    #[suggestion(
+        infer_meant_byte_literal,
+        code = "b'{code}'",
+        applicability = "machine-applicable"
+    )]
+    MeantByteLiteral {
+        #[primary_span]
+        span: Span,
+        code: String,
+    },
+    #[suggestion(
+        infer_meant_char_literal,
+        code = "'{code}'",
+        applicability = "machine-applicable"
+    )]
+    MeantCharLiteral {
+        #[primary_span]
+        span: Span,
+        code: String,
+    },
+    #[suggestion(
+        infer_meant_str_literal,
+        code = "\"{code}\"",
+        applicability = "machine-applicable"
+    )]
+    MeantStrLiteral {
+        #[primary_span]
+        span: Span,
+        code: String,
+    },
+    #[suggestion(
+        infer_consider_specifying_length,
+        code = "{length}",
+        applicability = "maybe-incorrect"
+    )]
+    ConsiderSpecifyingLength {
+        #[primary_span]
+        span: Span,
+        length: u64,
+    },
+    #[note(infer_try_cannot_convert)]
+    TryCannotConvert { found: String, expected: String },
+    #[suggestion(infer_tuple_trailing_comma, code = ",", applicability = "machine-applicable")]
+    TupleOnlyComma {
+        #[primary_span]
+        span: Span,
+    },
+    #[multipart_suggestion(infer_tuple_trailing_comma, applicability = "machine-applicable")]
+    TupleAlsoParentheses {
+        #[suggestion_part(code = "(")]
+        span_low: Span,
+        #[suggestion_part(code = ",)")]
+        span_high: Span,
+    },
+    #[suggestion(
+        infer_suggest_add_let_for_letchains,
+        style = "verbose",
+        applicability = "machine-applicable",
+        code = "let "
+    )]
+    AddLetForLetChains {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Diagnostic)]
+pub enum ObligationCauseFailureCode {
+    #[diag(infer_oc_method_compat, code = "E0308")]
+    MethodCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_type_compat, code = "E0308")]
+    TypeCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_const_compat, code = "E0308")]
+    ConstCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_try_compat, code = "E0308")]
+    TryCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_match_compat, code = "E0308")]
+    MatchCompat {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_if_else_different, code = "E0308")]
+    IfElseDifferent {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_no_else, code = "E0317")]
+    NoElse {
+        #[primary_span]
+        span: Span,
+    },
+    #[diag(infer_oc_no_diverge, code = "E0308")]
+    NoDiverge {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_fn_main_correct_type, code = "E0580")]
+    FnMainCorrectType {
+        #[primary_span]
+        span: Span,
+    },
+    #[diag(infer_oc_fn_start_correct_type, code = "E0308")]
+    FnStartCorrectType {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_intristic_correct_type, code = "E0308")]
+    IntristicCorrectType {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_method_correct_type, code = "E0308")]
+    MethodCorrectType {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_closure_selfref, code = "E0644")]
+    ClosureSelfref {
+        #[primary_span]
+        span: Span,
+    },
+    #[diag(infer_oc_cant_coerce, code = "E0308")]
+    CantCoerce {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+    #[diag(infer_oc_generic, code = "E0308")]
+    Generic {
+        #[primary_span]
+        span: Span,
+        #[subdiagnostic]
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    },
+}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 86fca9797d0..7901bc94021 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -49,11 +49,10 @@ use super::lexical_region_resolve::RegionResolutionError;
 use super::region_constraints::GenericKind;
 use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
 
-use crate::errors;
+use crate::errors::{self, ObligationCauseFailureCode, TypeErrorAdditionalDiags};
 use crate::infer;
 use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
 use crate::infer::ExpectedFound;
-use crate::traits::error_reporting::report_object_safety_error;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
     PredicateObligation,
@@ -90,6 +89,28 @@ pub use need_type_info::TypeAnnotationNeeded;
 
 pub mod nice_region_error;
 
+/// Makes a valid string literal from a string by escaping special characters (" and \),
+/// unless they are already escaped.
+fn escape_literal(s: &str) -> String {
+    let mut escaped = String::with_capacity(s.len());
+    let mut chrs = s.chars().peekable();
+    while let Some(first) = chrs.next() {
+        match (first, chrs.peek()) {
+            ('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => {
+                escaped.push('\\');
+                escaped.push(delim);
+                chrs.next();
+            }
+            ('"' | '\'', _) => {
+                escaped.push('\\');
+                escaped.push(first)
+            }
+            (c, _) => escaped.push(c),
+        };
+    }
+    escaped
+}
+
 /// A helper for building type related errors. The `typeck_results`
 /// field is only populated during an in-progress typeck.
 /// Get an instance by calling `InferCtxt::err` or `FnCtxt::infer_err`.
@@ -1899,233 +1920,182 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         debug!(?diag);
     }
 
-    pub fn report_and_explain_type_error(
+    pub fn type_error_additional_suggestions(
         &self,
-        trace: TypeTrace<'tcx>,
+        trace: &TypeTrace<'tcx>,
         terr: TypeError<'tcx>,
-    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+    ) -> Vec<TypeErrorAdditionalDiags> {
         use crate::traits::ObligationCauseCode::MatchExpressionArm;
-
-        debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
-
+        let mut suggestions = Vec::new();
         let span = trace.cause.span();
-        let failure_code = trace.cause.as_failure_code(terr);
-        let mut diag = match failure_code {
-            FailureCode::Error0038(did) => {
-                let violations = self.tcx.object_safety_violations(did);
-                report_object_safety_error(self.tcx, span, did, violations)
-            }
-            FailureCode::Error0317(failure_str) => {
-                struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
-            }
-            FailureCode::Error0580(failure_str) => {
-                struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
-            }
-            FailureCode::Error0308(failure_str) => {
-                fn escape_literal(s: &str) -> String {
-                    let mut escaped = String::with_capacity(s.len());
-                    let mut chrs = s.chars().peekable();
-                    while let Some(first) = chrs.next() {
-                        match (first, chrs.peek()) {
-                            ('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => {
-                                escaped.push('\\');
-                                escaped.push(delim);
-                                chrs.next();
-                            }
-                            ('"' | '\'', _) => {
-                                escaped.push('\\');
-                                escaped.push(first)
-                            }
-                            (c, _) => escaped.push(c),
-                        };
+        let values = self.resolve_vars_if_possible(trace.values);
+        if let Some((expected, found)) = values.ty() {
+            match (expected.kind(), found.kind()) {
+                (ty::Tuple(_), ty::Tuple(_)) => {}
+                // If a tuple of length one was expected and the found expression has
+                // parentheses around it, perhaps the user meant to write `(expr,)` to
+                // build a tuple (issue #86100)
+                (ty::Tuple(fields), _) => {
+                    suggestions.extend(self.suggest_wrap_to_build_a_tuple( span, found, fields))
+                }
+                // If a byte was expected and the found expression is a char literal
+                // containing a single ASCII character, perhaps the user meant to write `b'c'` to
+                // specify a byte literal
+                (ty::Uint(ty::UintTy::U8), ty::Char) => {
+                    if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
+                        && let Some(code) = code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
+                        && !code.starts_with("\\u") // forbid all Unicode escapes
+                        && code.chars().next().map_or(false, |c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII
+                    {
+                        suggestions.push(TypeErrorAdditionalDiags::MeantByteLiteral { span, code: escape_literal(code) })
                     }
-                    escaped
                 }
-                let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
-                let values = self.resolve_vars_if_possible(trace.values);
-                if let Some((expected, found)) = values.ty() {
-                    match (expected.kind(), found.kind()) {
-                        (ty::Tuple(_), ty::Tuple(_)) => {}
-                        // If a tuple of length one was expected and the found expression has
-                        // parentheses around it, perhaps the user meant to write `(expr,)` to
-                        // build a tuple (issue #86100)
-                        (ty::Tuple(fields), _) => {
-                            self.emit_tuple_wrap_err(&mut err, span, found, fields)
-                        }
-                        // If a byte was expected and the found expression is a char literal
-                        // containing a single ASCII character, perhaps the user meant to write `b'c'` to
-                        // specify a byte literal
-                        (ty::Uint(ty::UintTy::U8), ty::Char) => {
-                            if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
-                                && let Some(code) = code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
-                                && !code.starts_with("\\u") // forbid all Unicode escapes
-                                && code.chars().next().map_or(false, |c| c.is_ascii()) // forbids literal Unicode characters beyond ASCII
-                            {
-                                err.span_suggestion(
-                                    span,
-                                    "if you meant to write a byte literal, prefix with `b`",
-                                    format!("b'{}'", escape_literal(code)),
-                                    Applicability::MachineApplicable,
-                                );
-                            }
-                        }
-                        // If a character was expected and the found expression is a string literal
-                        // containing a single character, perhaps the user meant to write `'c'` to
-                        // specify a character literal (issue #92479)
-                        (ty::Char, ty::Ref(_, r, _)) if r.is_str() => {
-                            if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
-                                && let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
-                                && code.chars().count() == 1
-                            {
-                                err.span_suggestion(
-                                    span,
-                                    "if you meant to write a `char` literal, use single quotes",
-                                    format!("'{}'", escape_literal(code)),
-                                    Applicability::MachineApplicable,
-                                );
-                            }
-                        }
-                        // If a string was expected and the found expression is a character literal,
-                        // perhaps the user meant to write `"s"` to specify a string literal.
-                        (ty::Ref(_, r, _), ty::Char) if r.is_str() => {
-                            if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
-                                if let Some(code) =
-                                    code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
-                                {
-                                    err.span_suggestion(
-                                        span,
-                                        "if you meant to write a `str` literal, use double quotes",
-                                        format!("\"{}\"", escape_literal(code)),
-                                        Applicability::MachineApplicable,
-                                    );
-                                }
-                            }
-                        }
-                        // For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`,
-                        // we try to suggest to add the missing `let` for `if let Some(..) = expr`
-                        (ty::Bool, ty::Tuple(list)) => if list.len() == 0 {
-                            self.suggest_let_for_letchains(&mut err, &trace.cause, span);
-                        }
-                        (ty::Array(_, _), ty::Array(_, _)) => 'block: {
-                            let hir = self.tcx.hir();
-                            let TypeError::FixedArraySize(sz) = terr else {
-                                break 'block;
-                            };
-                            let tykind = match hir.find_by_def_id(trace.cause.body_id) {
-                                Some(hir::Node::Item(hir::Item {
-                                    kind: hir::ItemKind::Fn(_, _, body_id),
-                                    ..
-                                })) => {
-                                    let body = hir.body(*body_id);
-                                    struct LetVisitor<'v> {
-                                        span: Span,
-                                        result: Option<&'v hir::Ty<'v>>,
-                                    }
-                                    impl<'v> Visitor<'v> for LetVisitor<'v> {
-                                        fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
-                                            if self.result.is_some() {
-                                                return;
-                                            }
-                                            // Find a local statement where the initializer has
-                                            // the same span as the error and the type is specified.
-                                            if let hir::Stmt {
-                                                kind: hir::StmtKind::Local(hir::Local {
-                                                    init: Some(hir::Expr {
-                                                        span: init_span,
-                                                        ..
-                                                    }),
-                                                    ty: Some(array_ty),
-                                                    ..
-                                                }),
-                                                ..
-                                            } = s
-                                            && init_span == &self.span {
-                                                self.result = Some(*array_ty);
-                                            }
-                                        }
-                                    }
-                                    let mut visitor = LetVisitor {span, result: None};
-                                    visitor.visit_body(body);
-                                    visitor.result.map(|r| &r.peel_refs().kind)
-                                }
-                                Some(hir::Node::Item(hir::Item {
-                                    kind: hir::ItemKind::Const(ty, _),
-                                    ..
-                                })) => {
-                                    Some(&ty.peel_refs().kind)
-                                }
-                                _ => None
-                            };
-
-                            if let Some(tykind) = tykind
-                                && let hir::TyKind::Array(_, length) = tykind
-                                && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
-                                && let Some(span) = self.tcx.hir().opt_span(*hir_id)
-                            {
-                                err.span_suggestion(
-                                    span,
-                                    "consider specifying the actual array length",
-                                    sz.found,
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
+                // If a character was expected and the found expression is a string literal
+                // containing a single character, perhaps the user meant to write `'c'` to
+                // specify a character literal (issue #92479)
+                (ty::Char, ty::Ref(_, r, _)) if r.is_str() => {
+                    if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
+                        && let Some(code) = code.strip_prefix('"').and_then(|s| s.strip_suffix('"'))
+                        && code.chars().count() == 1
+                    {
+                        suggestions.push(TypeErrorAdditionalDiags::MeantCharLiteral { span, code: escape_literal(code) })
+                    }
+                }
+                // If a string was expected and the found expression is a character literal,
+                // perhaps the user meant to write `"s"` to specify a string literal.
+                (ty::Ref(_, r, _), ty::Char) if r.is_str() => {
+                    if let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span) {
+                        if let Some(code) =
+                            code.strip_prefix('\'').and_then(|s| s.strip_suffix('\''))
+                        {
+                            suggestions.push(TypeErrorAdditionalDiags::MeantStrLiteral { span, code: escape_literal(code) })
                         }
-                        _ => {}
                     }
                 }
-                let code = trace.cause.code();
-                if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
+                // For code `if Some(..) = expr `, the type mismatch may be expected `bool` but found `()`,
+                // we try to suggest to add the missing `let` for `if let Some(..) = expr`
+                (ty::Bool, ty::Tuple(list)) => if list.len() == 0 {
+                    suggestions.extend(self.suggest_let_for_letchains(&trace.cause, span));
+                }
+                (ty::Array(_, _), ty::Array(_, _)) => suggestions.extend(self.suggest_specify_actual_length(terr, trace, span)),
+                _ => {}
+            }
+        }
+        let code = trace.cause.code();
+        if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
                     && let hir::MatchSource::TryDesugar = source
                     && let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
                 {
-                    err.note(&format!(
-                        "`?` operator cannot convert from `{}` to `{}`",
-                        found_ty.content(),
-                        expected_ty.content(),
-                    ));
+                    suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert { found: found_ty.content(), expected: expected_ty.content() });
                 }
-                err
+        suggestions
+    }
+
+    fn suggest_specify_actual_length(
+        &self,
+        terr: TypeError<'_>,
+        trace: &TypeTrace<'_>,
+        span: Span,
+    ) -> Option<TypeErrorAdditionalDiags> {
+        let hir = self.tcx.hir();
+        let TypeError::FixedArraySize(sz) = terr else {
+            return None;
+        };
+        let tykind = match hir.find_by_def_id(trace.cause.body_id) {
+            Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => {
+                let body = hir.body(*body_id);
+                struct LetVisitor<'v> {
+                    span: Span,
+                    result: Option<&'v hir::Ty<'v>>,
+                }
+                impl<'v> Visitor<'v> for LetVisitor<'v> {
+                    fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) {
+                        if self.result.is_some() {
+                            return;
+                        }
+                        // Find a local statement where the initializer has
+                        // the same span as the error and the type is specified.
+                        if let hir::Stmt {
+                            kind: hir::StmtKind::Local(hir::Local {
+                                init: Some(hir::Expr {
+                                    span: init_span,
+                                    ..
+                                }),
+                                ty: Some(array_ty),
+                                ..
+                            }),
+                            ..
+                        } = s
+                        && init_span == &self.span {
+                            self.result = Some(*array_ty);
+                        }
+                    }
+                }
+                let mut visitor = LetVisitor { span, result: None };
+                visitor.visit_body(body);
+                visitor.result.map(|r| &r.peel_refs().kind)
             }
-            FailureCode::Error0644(failure_str) => {
-                struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
+            Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(ty, _), .. })) => {
+                Some(&ty.peel_refs().kind)
             }
+            _ => None,
         };
+        if let Some(tykind) = tykind
+            && let hir::TyKind::Array(_, length) = tykind
+            && let hir::ArrayLen::Body(hir::AnonConst { hir_id, .. }) = length
+            && let Some(span) = self.tcx.hir().opt_span(*hir_id)
+        {
+            Some(TypeErrorAdditionalDiags::ConsiderSpecifyingLength { span, length: sz.found })
+        } else {
+            None
+        }
+    }
+
+    pub fn report_and_explain_type_error(
+        &self,
+        trace: TypeTrace<'tcx>,
+        terr: TypeError<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
+
+        let span = trace.cause.span();
+        let failure_code = trace.cause.as_failure_code_diag(
+            terr,
+            span,
+            self.type_error_additional_suggestions(&trace, terr),
+        );
+        let mut diag = self.tcx.sess.create_err(failure_code);
         self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr, false, false);
         diag
     }
 
-    fn emit_tuple_wrap_err(
+    fn suggest_wrap_to_build_a_tuple(
         &self,
-        err: &mut Diagnostic,
         span: Span,
         found: Ty<'tcx>,
         expected_fields: &List<Ty<'tcx>>,
-    ) {
-        let [expected_tup_elem] = expected_fields[..] else { return };
+    ) -> Option<TypeErrorAdditionalDiags> {
+        let [expected_tup_elem] = expected_fields[..] else { return None};
 
         if !self.same_type_modulo_infer(expected_tup_elem, found) {
-            return;
+            return None;
         }
 
         let Ok(code) = self.tcx.sess().source_map().span_to_snippet(span)
-            else { return };
+            else { return None };
 
-        let msg = "use a trailing comma to create a tuple with one element";
-        if code.starts_with('(') && code.ends_with(')') {
+        let sugg = if code.starts_with('(') && code.ends_with(')') {
             let before_close = span.hi() - BytePos::from_u32(1);
-            err.span_suggestion(
-                span.with_hi(before_close).shrink_to_hi(),
-                msg,
-                ",",
-                Applicability::MachineApplicable,
-            );
+            TypeErrorAdditionalDiags::TupleOnlyComma {
+                span: span.with_hi(before_close).shrink_to_hi(),
+            }
         } else {
-            err.multipart_suggestion(
-                msg,
-                vec![(span.shrink_to_lo(), "(".into()), (span.shrink_to_hi(), ",)".into())],
-                Applicability::MachineApplicable,
-            );
-        }
+            TypeErrorAdditionalDiags::TupleAlsoParentheses {
+                span_low: span.shrink_to_lo(),
+                span_high: span.shrink_to_hi(),
+            }
+        };
+        Some(sugg)
     }
 
     fn values_str(
@@ -2828,15 +2798,21 @@ impl<'tcx> InferCtxt<'tcx> {
 }
 
 pub enum FailureCode {
-    Error0038(DefId),
-    Error0317(&'static str),
-    Error0580(&'static str),
-    Error0308(&'static str),
-    Error0644(&'static str),
+    Error0317,
+    Error0580,
+    Error0308,
+    Error0644,
 }
 
 pub trait ObligationCauseExt<'tcx> {
     fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode;
+
+    fn as_failure_code_diag(
+        &self,
+        terr: TypeError<'tcx>,
+        span: Span,
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    ) -> ObligationCauseFailureCode;
     fn as_requirement_str(&self) -> &'static str;
 }
 
@@ -2845,40 +2821,68 @@ impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
         use self::FailureCode::*;
         use crate::traits::ObligationCauseCode::*;
         match self.code() {
+            IfExpressionWithNoElse => Error0317,
+            MainFunctionType => Error0580,
+            CompareImplItemObligation { .. }
+            | MatchExpressionArm(_)
+            | IfExpression { .. }
+            | LetElse
+            | StartFunctionType
+            | IntrinsicType
+            | MethodReceiver => Error0308,
+
+            // In the case where we have no more specific thing to
+            // say, also take a look at the error code, maybe we can
+            // tailor to that.
+            _ => match terr {
+                TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => Error0644,
+                TypeError::IntrinsicCast => Error0308,
+                _ => Error0308,
+            },
+        }
+    }
+    fn as_failure_code_diag(
+        &self,
+        terr: TypeError<'tcx>,
+        span: Span,
+        subdiags: Vec<TypeErrorAdditionalDiags>,
+    ) -> ObligationCauseFailureCode {
+        use crate::traits::ObligationCauseCode::*;
+        match self.code() {
             CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => {
-                Error0308("method not compatible with trait")
+                ObligationCauseFailureCode::MethodCompat { span, subdiags }
             }
             CompareImplItemObligation { kind: ty::AssocKind::Type, .. } => {
-                Error0308("type not compatible with trait")
+                ObligationCauseFailureCode::TypeCompat { span, subdiags }
             }
             CompareImplItemObligation { kind: ty::AssocKind::Const, .. } => {
-                Error0308("const not compatible with trait")
-            }
-            MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
-                Error0308(match source {
-                    hir::MatchSource::TryDesugar => "`?` operator has incompatible types",
-                    _ => "`match` arms have incompatible types",
-                })
-            }
-            IfExpression { .. } => Error0308("`if` and `else` have incompatible types"),
-            IfExpressionWithNoElse => Error0317("`if` may be missing an `else` clause"),
-            LetElse => Error0308("`else` clause of `let...else` does not diverge"),
-            MainFunctionType => Error0580("`main` function has wrong type"),
-            StartFunctionType => Error0308("`#[start]` function has wrong type"),
-            IntrinsicType => Error0308("intrinsic has wrong type"),
-            MethodReceiver => Error0308("mismatched `self` parameter type"),
+                ObligationCauseFailureCode::ConstCompat { span, subdiags }
+            }
+            MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source {
+                hir::MatchSource::TryDesugar => {
+                    ObligationCauseFailureCode::TryCompat { span, subdiags }
+                }
+                _ => ObligationCauseFailureCode::MatchCompat { span, subdiags },
+            },
+            IfExpression { .. } => ObligationCauseFailureCode::IfElseDifferent { span, subdiags },
+            IfExpressionWithNoElse => ObligationCauseFailureCode::NoElse { span },
+            LetElse => ObligationCauseFailureCode::NoDiverge { span, subdiags },
+            MainFunctionType => ObligationCauseFailureCode::FnMainCorrectType { span },
+            StartFunctionType => ObligationCauseFailureCode::FnStartCorrectType { span, subdiags },
+            IntrinsicType => ObligationCauseFailureCode::IntristicCorrectType { span, subdiags },
+            MethodReceiver => ObligationCauseFailureCode::MethodCorrectType { span, subdiags },
 
             // In the case where we have no more specific thing to
             // say, also take a look at the error code, maybe we can
             // tailor to that.
             _ => match terr {
                 TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
-                    Error0644("closure/generator type that references itself")
+                    ObligationCauseFailureCode::ClosureSelfref { span }
                 }
                 TypeError::IntrinsicCast => {
-                    Error0308("cannot coerce intrinsics to function pointers")
+                    ObligationCauseFailureCode::CantCoerce { span, subdiags }
                 }
-                _ => Error0308("mismatched types"),
+                _ => ObligationCauseFailureCode::Generic { span, subdiags },
             },
         }
     }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index 8ad143247e8..b5aeca12a1f 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -1,7 +1,7 @@
 use hir::def::CtorKind;
 use hir::intravisit::{walk_expr, walk_stmt, Visitor};
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{Applicability, Diagnostic};
+use rustc_errors::Diagnostic;
 use rustc_hir as hir;
 use rustc_middle::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
@@ -13,11 +13,20 @@ use rustc_span::{sym, BytePos, Span};
 use rustc_target::abi::FieldIdx;
 
 use crate::errors::{
-    ConsiderAddingAwait, SuggAddLetForLetChains, SuggestRemoveSemiOrReturnBinding,
+    ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes,
+    FunctionPointerSuggestion, SuggestAccessingField, SuggestAsRefWhereAppropriate,
+    SuggestBoxingForReturnImplTrait, SuggestRemoveSemiOrReturnBinding, SuggestTuplePatternMany,
+    SuggestTuplePatternOne, TypeErrorAdditionalDiags,
 };
 
 use super::TypeErrCtxt;
 
+#[derive(Clone, Copy)]
+pub enum SuggestAsRefKind {
+    Option,
+    Result,
+}
+
 impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     pub(super) fn suggest_remove_semi_or_return_binding(
         &self,
@@ -72,25 +81,20 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         return_sp: Span,
         arm_spans: impl Iterator<Item = Span>,
     ) {
-        err.multipart_suggestion(
-            "you could change the return type to be a boxed trait object",
-            vec![
-                (return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
-                (return_sp.shrink_to_hi(), ">".to_string()),
-            ],
-            Applicability::MaybeIncorrect,
-        );
-        let sugg = arm_spans
-            .flat_map(|sp| {
-                [(sp.shrink_to_lo(), "Box::new(".to_string()), (sp.shrink_to_hi(), ")".to_string())]
-                    .into_iter()
-            })
-            .collect::<Vec<_>>();
-        err.multipart_suggestion(
-            "if you change the return type to expect trait objects, box the returned expressions",
-            sugg,
-            Applicability::MaybeIncorrect,
-        );
+        let sugg = SuggestBoxingForReturnImplTrait::ChangeReturnType {
+            start_sp: return_sp.with_hi(return_sp.lo() + BytePos(4)),
+            end_sp: return_sp.shrink_to_hi(),
+        };
+        err.subdiagnostic(sugg);
+
+        let mut starts = Vec::new();
+        let mut ends = Vec::new();
+        for span in arm_spans {
+            starts.push(span.shrink_to_lo());
+            ends.push(span.shrink_to_hi());
+        }
+        let sugg = SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends };
+        err.subdiagnostic(sugg);
     }
 
     pub(super) fn suggest_tuple_pattern(
@@ -130,30 +134,21 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 match &compatible_variants[..] {
                     [] => {}
                     [variant] => {
-                        diag.multipart_suggestion_verbose(
-                            &format!("try wrapping the pattern in `{}`", variant),
-                            vec![
-                                (cause.span.shrink_to_lo(), format!("{}(", variant)),
-                                (cause.span.shrink_to_hi(), ")".to_string()),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
+                        let sugg = SuggestTuplePatternOne {
+                            variant: variant.to_owned(),
+                            span_low: cause.span.shrink_to_lo(),
+                            span_high: cause.span.shrink_to_hi(),
+                        };
+                        diag.subdiagnostic(sugg);
                     }
                     _ => {
                         // More than one matching variant.
-                        diag.multipart_suggestions(
-                            &format!(
-                                "try wrapping the pattern in a variant of `{}`",
-                                self.tcx.def_path_str(expected_adt.did())
-                            ),
-                            compatible_variants.into_iter().map(|variant| {
-                                vec![
-                                    (cause.span.shrink_to_lo(), format!("{}(", variant)),
-                                    (cause.span.shrink_to_hi(), ")".to_string()),
-                                ]
-                            }),
-                            Applicability::MaybeIncorrect,
-                        );
+                        let sugg = SuggestTuplePatternMany {
+                            path: self.tcx.def_path_str(expected_adt.did()),
+                            cause_span: cause.span,
+                            compatible_variants,
+                        };
+                        diag.subdiagnostic(sugg);
                     }
                 }
             }
@@ -256,15 +251,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         }
     }
 
-    pub fn suggest_await_on_future(&self, diag: &mut Diagnostic, sp: Span) {
-        diag.span_suggestion_verbose(
-            sp.shrink_to_hi(),
-            "consider `await`ing on the `Future`",
-            ".await",
-            Applicability::MaybeIncorrect,
-        );
-    }
-
     pub(super) fn suggest_accessing_field_where_appropriate(
         &self,
         cause: &ObligationCause<'tcx>,
@@ -291,21 +277,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
                     if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
                         let suggestion = if expected_def.is_struct() {
-                            format!("{}.{}", snippet, name)
+                            SuggestAccessingField::Safe { span, snippet, name, ty }
                         } else if expected_def.is_union() {
-                            format!("unsafe {{ {}.{} }}", snippet, name)
+                            SuggestAccessingField::Unsafe { span, snippet, name, ty }
                         } else {
                             return;
                         };
-                        diag.span_suggestion(
-                            span,
-                            &format!(
-                                "you might have meant to use field `{}` whose type is `{}`",
-                                name, ty
-                            ),
-                            suggestion,
-                            Applicability::MaybeIncorrect,
-                        );
+                        diag.subdiagnostic(suggestion);
                     }
                 }
             }
@@ -321,15 +299,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         diag: &mut Diagnostic,
     ) {
         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
-            && let Some(msg) = self.should_suggest_as_ref(exp_found.expected, exp_found.found)
+            && let Some(msg) = self.should_suggest_as_ref_kind(exp_found.expected, exp_found.found)
         {
-            diag.span_suggestion(
-                span,
-                msg,
-                // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
-                format!("{}.as_ref()", snippet.trim_start_matches('&')),
-                Applicability::MachineApplicable,
-            );
+            // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
+            let snippet = snippet.trim_start_matches('&');
+            let subdiag = match msg {
+                SuggestAsRefKind::Option => SuggestAsRefWhereAppropriate::Option { span, snippet },
+                SuggestAsRefKind::Result => SuggestAsRefWhereAppropriate::Result { span, snippet },
+            };
+            diag.subdiagnostic(subdiag);
         }
     }
 
@@ -362,31 +340,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     return;
                 }
 
-                let (msg, sug) = match (expected.is_ref(), found.is_ref()) {
-                    (true, false) => {
-                        let msg = "consider using a reference";
-                        let sug = format!("&{fn_name}");
-                        (msg, sug)
-                    }
-                    (false, true) => {
-                        let msg = "consider removing the reference";
-                        let sug = format!("{fn_name}");
-                        (msg, sug)
-                    }
+                let sugg = match (expected.is_ref(), found.is_ref()) {
+                    (true, false) => FunctionPointerSuggestion::UseRef { span, fn_name },
+                    (false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name },
                     (true, true) => {
-                        diag.note("fn items are distinct from fn pointers");
-                        let msg = "consider casting to a fn pointer";
-                        let sug = format!("&({fn_name} as {sig})");
-                        (msg, sug)
+                        diag.subdiagnostic(FnItemsAreDistinct);
+                        FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig }
                     }
                     (false, false) => {
-                        diag.note("fn items are distinct from fn pointers");
-                        let msg = "consider casting to a fn pointer";
-                        let sug = format!("{fn_name} as {sig}");
-                        (msg, sug)
+                        diag.subdiagnostic(FnItemsAreDistinct);
+                        FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig }
                     }
                 };
-                diag.span_suggestion_verbose(span, msg, sug, Applicability::MaybeIncorrect);
+                diag.subdiagnostic(sugg);
             }
             (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
                 let expected_sig =
@@ -395,7 +361,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     &(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).subst(self.tcx, substs2));
 
                 if self.same_type_modulo_infer(*expected_sig, *found_sig) {
-                    diag.note("different fn items have unique types, even if their signatures are the same");
+                    diag.subdiagnostic(FnUniqTypes);
                 }
 
                 if !self.same_type_modulo_infer(*found_sig, *expected_sig)
@@ -409,16 +375,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
 
                 let fn_name = self.tcx.def_path_str_with_substs(*did2, substs2);
                 let sug = if found.is_ref() {
-                    format!("&({fn_name} as {found_sig})")
+                    FunctionPointerSuggestion::CastBothRef {
+                        span,
+                        fn_name,
+                        found_sig: *found_sig,
+                        expected_sig: *expected_sig,
+                    }
                 } else {
-                    format!("{fn_name} as {found_sig}")
+                    FunctionPointerSuggestion::CastBoth {
+                        span,
+                        fn_name,
+                        found_sig: *found_sig,
+                        expected_sig: *expected_sig,
+                    }
                 };
 
-                let msg = format!(
-                    "consider casting both fn items to fn pointers using `as {expected_sig}`"
-                );
-
-                diag.span_suggestion_hidden(span, msg, sug, Applicability::MaybeIncorrect);
+                diag.subdiagnostic(sug);
             }
             (ty::FnDef(did, substs), ty::FnPtr(sig)) => {
                 let expected_sig =
@@ -437,7 +409,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     format!("{fn_name} as {found_sig}")
                 };
 
-                diag.help(&format!("consider casting the fn item to a fn pointer: `{}`", casting));
+                diag.subdiagnostic(FnConsiderCasting { casting });
             }
             _ => {
                 return;
@@ -445,23 +417,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         };
     }
 
-    pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
+    pub fn should_suggest_as_ref_kind(
+        &self,
+        expected: Ty<'tcx>,
+        found: Ty<'tcx>,
+    ) -> Option<SuggestAsRefKind> {
         if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
             (expected.kind(), found.kind())
         {
             if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
                 if exp_def == &found_def {
                     let have_as_ref = &[
-                        (
-                            sym::Option,
-                            "you can convert from `&Option<T>` to `Option<&T>` using \
-                        `.as_ref()`",
-                        ),
-                        (
-                            sym::Result,
-                            "you can convert from `&Result<T, E>` to \
-                        `Result<&T, &E>` using `.as_ref()`",
-                        ),
+                        (sym::Option, SuggestAsRefKind::Option),
+                        (sym::Result, SuggestAsRefKind::Result),
                     ];
                     if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
                         self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
@@ -495,15 +463,28 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         None
     }
 
+    // FIXME: Remove once `rustc_hir_typeck` is migrated to diagnostic structs
+    pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
+        match self.should_suggest_as_ref_kind(expected, found) {
+            Some(SuggestAsRefKind::Option) => Some(
+                "you can convert from `&Option<T>` to `Option<&T>` using \
+            `.as_ref()`",
+            ),
+            Some(SuggestAsRefKind::Result) => Some(
+                "you can convert from `&Result<T, E>` to \
+            `Result<&T, &E>` using `.as_ref()`",
+            ),
+            None => None,
+        }
+    }
     /// Try to find code with pattern `if Some(..) = expr`
     /// use a `visitor` to mark the `if` which its span contains given error span,
     /// and then try to find a assignment in the `cond` part, which span is equal with error span
     pub(super) fn suggest_let_for_letchains(
         &self,
-        err: &mut Diagnostic,
         cause: &ObligationCause<'_>,
         span: Span,
-    ) {
+    ) -> Option<TypeErrorAdditionalDiags> {
         let hir = self.tcx.hir();
         if let Some(node) = self.tcx.hir().find_by_def_id(cause.body_id) &&
             let hir::Node::Item(hir::Item {
@@ -550,9 +531,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
         visitor.visit_body(&body);
         if visitor.result {
-                err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()});
+                return Some(TypeErrorAdditionalDiags::AddLetForLetChains{span: span.shrink_to_lo()});
             }
         }
+        None
     }
 }
 
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index f8e9ec535e4..b0783d75d47 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -10,6 +10,7 @@ const OPTIONAL_COMPONENTS: &[&str] = &[
     "aarch64",
     "amdgpu",
     "avr",
+    "loongarch",
     "m68k",
     "mips",
     "powerpc",
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 736766e35bc..08e38b0c9d5 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -146,6 +146,12 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
 #define SUBTARGET_HEXAGON
 #endif
 
+#ifdef LLVM_COMPONENT_LOONGARCH
+#define SUBTARGET_LOONGARCH SUBTARGET(LoongArch)
+#else
+#define SUBTARGET_LOONGARCH
+#endif
+
 #define GEN_SUBTARGETS                                                         \
   SUBTARGET_X86                                                                \
   SUBTARGET_ARM                                                                \
@@ -159,6 +165,7 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
   SUBTARGET_SPARC                                                              \
   SUBTARGET_HEXAGON                                                            \
   SUBTARGET_RISCV                                                              \
+  SUBTARGET_LOONGARCH                                                          \
 
 #define SUBTARGET(x)                                                           \
   namespace llvm {                                                             \
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index ec3cf34d710..a49ded4fd7b 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -103,6 +103,14 @@ pub fn initialize_available_targets() {
         LLVMInitializeM68kAsmParser
     );
     init_target!(
+        llvm_component = "loongarch",
+        LLVMInitializeLoongArchTargetInfo,
+        LLVMInitializeLoongArchTarget,
+        LLVMInitializeLoongArchTargetMC,
+        LLVMInitializeLoongArchAsmPrinter,
+        LLVMInitializeLoongArchAsmParser
+    );
+    init_target!(
         llvm_component = "mips",
         LLVMInitializeMipsTargetInfo,
         LLVMInitializeMipsTarget,
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 4540ded0f41..427c82c410b 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -392,14 +392,16 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
             }
             SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
                 let inner = info.ty.inner_type();
-                if type_matches_path(inner, &["rustc_span", "Span"]) {
+                if type_matches_path(inner, &["rustc_span", "Span"])
+                    || type_matches_path(inner, &["rustc_span", "MultiSpan"])
+                {
                     Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
                 } else if type_is_unit(inner)
                     || (matches!(info.ty, FieldInnerTy::Plain(_)) && type_is_bool(inner))
                 {
                     Ok(self.add_subdiagnostic(&fn_ident, slug))
                 } else {
-                    report_type_error(attr, "`Span`, `bool` or `()`")?
+                    report_type_error(attr, "`Span`, `MultiSpan`, `bool` or `()`")?
                 }
             }
             SubdiagnosticKind::Suggestion {
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index f9d32ffceef..77308212c32 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -749,6 +749,10 @@ impl CrateRoot {
 }
 
 impl<'a, 'tcx> CrateMetadataRef<'a> {
+    fn missing(self, descr: &str, id: DefIndex) -> ! {
+        bug!("missing `{descr}` for {:?}", self.local_def_id(id))
+    }
+
     fn raw_proc_macro(self, id: DefIndex) -> &'a ProcMacro {
         // DefIndex's in root.proc_macro_data have a one-to-one correspondence
         // with items in 'raw_proc_macros'.
@@ -782,8 +786,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
 
     fn opt_item_ident(self, item_index: DefIndex, sess: &Session) -> Option<Ident> {
         let name = self.opt_item_name(item_index)?;
-        let span =
-            self.root.tables.def_ident_span.get(self, item_index).unwrap().decode((self, sess));
+        let span = self
+            .root
+            .tables
+            .def_ident_span
+            .get(self, item_index)
+            .unwrap_or_else(|| self.missing("def_ident_span", item_index))
+            .decode((self, sess));
         Some(Ident::new(name, span))
     }
 
@@ -812,7 +821,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .tables
             .def_span
             .get(self, index)
-            .unwrap_or_else(|| panic!("Missing span for {index:?}"))
+            .unwrap_or_else(|| self.missing("def_span", index))
             .decode((self, sess))
     }
 
@@ -924,7 +933,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             .tables
             .visibility
             .get(self, id)
-            .unwrap()
+            .unwrap_or_else(|| self.missing("visibility", id))
             .decode(self)
             .map_id(|index| self.local_def_id(index))
     }
@@ -934,7 +943,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     fn get_expn_that_defined(self, id: DefIndex, sess: &Session) -> ExpnId {
-        self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess))
+        self.root
+            .tables
+            .expn_that_defined
+            .get(self, id)
+            .unwrap_or_else(|| self.missing("expn_that_defined", id))
+            .decode((self, sess))
     }
 
     fn get_debugger_visualizers(self) -> Vec<rustc_span::DebuggerVisualizerFile> {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 4291b9aa142..77ec03165fb 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -811,7 +811,7 @@ fn analyze_attr(attr: &Attribute, state: &mut AnalyzeAttrState) -> bool {
     should_encode
 }
 
-fn should_encode_visibility(def_kind: DefKind) -> bool {
+fn should_encode_span(def_kind: DefKind) -> bool {
     match def_kind {
         DefKind::Mod
         | DefKind::Struct
@@ -823,25 +823,136 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
         | DefKind::ForeignTy
         | DefKind::TraitAlias
         | DefKind::AssocTy
+        | DefKind::TyParam
         | DefKind::Fn
         | DefKind::Const
-        | DefKind::Static(..)
+        | DefKind::Static(_)
         | DefKind::Ctor(..)
         | DefKind::AssocFn
         | DefKind::AssocConst
-        | DefKind::Macro(..)
+        | DefKind::Macro(_)
+        | DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::OpaqueTy
+        | DefKind::Field
+        | DefKind::Impl { .. }
+        | DefKind::Closure
+        | DefKind::Generator => true,
+        DefKind::ConstParam
+        | DefKind::ExternCrate
+        | DefKind::Use
+        | DefKind::ForeignMod
+        | DefKind::ImplTraitPlaceholder
+        | DefKind::LifetimeParam
+        | DefKind::GlobalAsm => false,
+    }
+}
+
+fn should_encode_attrs(def_kind: DefKind) -> bool {
+    match def_kind {
+        DefKind::Mod
+        | DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Trait
+        | DefKind::TyAlias
+        | DefKind::ForeignTy
+        | DefKind::TraitAlias
+        | DefKind::AssocTy
+        | DefKind::Fn
+        | DefKind::Const
+        | DefKind::Static(_)
+        | DefKind::AssocFn
+        | DefKind::AssocConst
+        | DefKind::Macro(_)
+        | DefKind::Field
+        | DefKind::Impl { .. } => true,
+        DefKind::TyParam
+        | DefKind::ConstParam
+        | DefKind::Ctor(..)
+        | DefKind::ExternCrate
         | DefKind::Use
         | DefKind::ForeignMod
+        | DefKind::AnonConst
+        | DefKind::InlineConst
         | DefKind::OpaqueTy
         | DefKind::ImplTraitPlaceholder
-        | DefKind::Impl { .. }
+        | DefKind::LifetimeParam
+        | DefKind::GlobalAsm
+        | DefKind::Closure
+        | DefKind::Generator => false,
+    }
+}
+
+fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
+    match def_kind {
+        DefKind::Mod
+        | DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Trait
+        | DefKind::Impl { .. } => true,
+        DefKind::TyAlias
+        | DefKind::ForeignTy
+        | DefKind::TraitAlias
+        | DefKind::AssocTy
+        | DefKind::TyParam
+        | DefKind::Fn
+        | DefKind::Const
+        | DefKind::ConstParam
+        | DefKind::Static(_)
+        | DefKind::Ctor(..)
+        | DefKind::AssocFn
+        | DefKind::AssocConst
+        | DefKind::Macro(_)
+        | DefKind::ExternCrate
+        | DefKind::Use
+        | DefKind::ForeignMod
+        | DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
+        | DefKind::Field
+        | DefKind::LifetimeParam
+        | DefKind::GlobalAsm
+        | DefKind::Closure
+        | DefKind::Generator => false,
+    }
+}
+
+fn should_encode_visibility(def_kind: DefKind) -> bool {
+    match def_kind {
+        DefKind::Mod
+        | DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Trait
+        | DefKind::TyAlias
+        | DefKind::ForeignTy
+        | DefKind::TraitAlias
+        | DefKind::AssocTy
+        | DefKind::Fn
+        | DefKind::Const
+        | DefKind::Static(..)
+        | DefKind::Ctor(..)
+        | DefKind::AssocFn
+        | DefKind::AssocConst
+        | DefKind::Macro(..)
         | DefKind::Field => true,
-        DefKind::TyParam
+        DefKind::Use
+        | DefKind::ForeignMod
+        | DefKind::TyParam
         | DefKind::ConstParam
         | DefKind::LifetimeParam
         | DefKind::AnonConst
         | DefKind::InlineConst
+        | DefKind::OpaqueTy
+        | DefKind::ImplTraitPlaceholder
         | DefKind::GlobalAsm
+        | DefKind::Impl { .. }
         | DefKind::Closure
         | DefKind::Generator
         | DefKind::ExternCrate => false,
@@ -1160,11 +1271,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             let def_kind = tcx.opt_def_kind(local_id);
             let Some(def_kind) = def_kind else { continue };
             self.tables.opt_def_kind.set_some(def_id.index, def_kind);
-            let def_span = tcx.def_span(local_id);
-            record!(self.tables.def_span[def_id] <- def_span);
-            self.encode_attrs(local_id);
-            record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
-            if let Some(ident_span) = tcx.def_ident_span(def_id) {
+            if should_encode_span(def_kind) {
+                let def_span = tcx.def_span(local_id);
+                record!(self.tables.def_span[def_id] <- def_span);
+            }
+            if should_encode_attrs(def_kind) {
+                self.encode_attrs(local_id);
+            }
+            if should_encode_expn_that_defined(def_kind) {
+                record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
+            }
+            if should_encode_span(def_kind) && let Some(ident_span) = tcx.def_ident_span(def_id) {
                 record!(self.tables.def_ident_span[def_id] <- ident_span);
             }
             if def_kind.has_codegen_attrs() {
@@ -1523,23 +1640,32 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         })
     }
 
-    fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
+    fn encode_info_for_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         let tcx = self.tcx;
-
+        let def_id = item.owner_id.to_def_id();
         debug!("EncodeContext::encode_info_for_item({:?})", def_id);
 
+        let record_associated_item_def_ids = |this: &mut Self, def_ids: &[DefId]| {
+            record_array!(this.tables.children[def_id] <- def_ids.iter().map(|&def_id| {
+                assert!(def_id.is_local());
+                def_id.index
+            }))
+        };
+
         match item.kind {
             hir::ItemKind::Fn(ref sig, .., body) => {
                 self.tables.asyncness.set_some(def_id.index, sig.header.asyncness);
                 record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
                 self.tables.constness.set_some(def_id.index, sig.header.constness);
+                record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
+                self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id));
             }
             hir::ItemKind::Macro(ref macro_def, _) => {
                 self.tables.is_macro_rules.set(def_id.index, macro_def.macro_rules);
                 record!(self.tables.macro_definition[def_id] <- &*macro_def.body);
             }
             hir::ItemKind::Mod(ref m) => {
-                return self.encode_info_for_mod(item.owner_id.def_id, m);
+                self.encode_info_for_mod(item.owner_id.def_id, m);
             }
             hir::ItemKind::OpaqueTy(ref opaque) => {
                 self.encode_explicit_item_bounds(def_id);
@@ -1550,9 +1676,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
                 self.tables.impl_defaultness.set_some(def_id.index, *defaultness);
                 self.tables.constness.set_some(def_id.index, *constness);
+                self.tables.impl_polarity.set_some(def_id.index, self.tcx.impl_polarity(def_id));
+
+                if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
+                    record!(self.tables.impl_trait_ref[def_id] <- trait_ref);
 
-                let trait_ref = self.tcx.impl_trait_ref(def_id);
-                if let Some(trait_ref) = trait_ref {
                     let trait_ref = trait_ref.skip_binder();
                     let trait_def = self.tcx.trait_def(trait_ref.def_id);
                     if let Ok(mut an) = trait_def.ancestors(self.tcx, def_id) {
@@ -1570,21 +1698,27 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     }
                 }
 
-                let polarity = self.tcx.impl_polarity(def_id);
-                self.tables.impl_polarity.set_some(def_id.index, polarity);
+                let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
+                record_associated_item_def_ids(self, associated_item_def_ids);
+                for &trait_item_def_id in associated_item_def_ids {
+                    self.encode_info_for_impl_item(trait_item_def_id);
+                }
             }
             hir::ItemKind::Trait(..) => {
-                let trait_def = self.tcx.trait_def(def_id);
-                record!(self.tables.trait_def[def_id] <- trait_def);
+                record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id));
+
+                let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
+                record_associated_item_def_ids(self, associated_item_def_ids);
+                for &item_def_id in associated_item_def_ids {
+                    self.encode_info_for_trait_item(item_def_id);
+                }
             }
             hir::ItemKind::TraitAlias(..) => {
-                let trait_def = self.tcx.trait_def(def_id);
-                record!(self.tables.trait_def[def_id] <- trait_def);
-            }
-            hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {
-                bug!("cannot encode info for item {:?}", item)
+                record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id));
             }
-            hir::ItemKind::Static(..)
+            hir::ItemKind::ExternCrate(_)
+            | hir::ItemKind::Use(..)
+            | hir::ItemKind::Static(..)
             | hir::ItemKind::Const(..)
             | hir::ItemKind::Enum(..)
             | hir::ItemKind::Struct(..)
@@ -1592,49 +1726,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             | hir::ItemKind::ForeignMod { .. }
             | hir::ItemKind::GlobalAsm(..)
             | hir::ItemKind::TyAlias(..) => {}
-        };
-        // FIXME(eddyb) there should be a nicer way to do this.
-        match item.kind {
-            hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => {
-                let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
-                record_array!(self.tables.children[def_id] <-
-                    associated_item_def_ids.iter().map(|&def_id| {
-                        assert!(def_id.is_local());
-                        def_id.index
-                    })
-                );
-            }
-            _ => {}
-        }
-        if let hir::ItemKind::Fn(..) = item.kind {
-            record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
-            self.tables.is_intrinsic.set(def_id.index, tcx.is_intrinsic(def_id));
-        }
-        if let hir::ItemKind::Impl { .. } = item.kind {
-            if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
-                record!(self.tables.impl_trait_ref[def_id] <- trait_ref);
-            }
-        }
-        // In some cases, along with the item itself, we also
-        // encode some sub-items. Usually we want some info from the item
-        // so it's easier to do that here then to wait until we would encounter
-        // normally in the visitor walk.
-        match item.kind {
-            hir::ItemKind::Impl { .. } => {
-                for &trait_item_def_id in
-                    self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter()
-                {
-                    self.encode_info_for_impl_item(trait_item_def_id);
-                }
-            }
-            hir::ItemKind::Trait(..) => {
-                for &item_def_id in
-                    self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter()
-                {
-                    self.encode_info_for_trait_item(item_def_id);
-                }
-            }
-            _ => {}
         }
     }
 
@@ -2020,10 +2111,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> {
     }
     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
         intravisit::walk_item(self, item);
-        match item.kind {
-            hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these
-            _ => self.encode_info_for_item(item.owner_id.to_def_id(), item),
-        }
+        self.encode_info_for_item(item);
     }
     fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) {
         intravisit::walk_foreign_item(self, ni);
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 9d97a75a2fa..e551c76f8db 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -8,7 +8,7 @@ use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::*;
 use rustc_index::vec::Idx;
@@ -179,7 +179,19 @@ impl<'hir> Map<'hir> {
     /// Do not call this function directly. The query should be called.
     pub(super) fn opt_def_kind(self, local_def_id: LocalDefId) -> Option<DefKind> {
         let hir_id = self.local_def_id_to_hir_id(local_def_id);
-        let def_kind = match self.find(hir_id)? {
+        let node = match self.find(hir_id) {
+            Some(node) => node,
+            None => match self.def_key(local_def_id).disambiguated_data.data {
+                // FIXME: Some anonymous constants do not have corresponding HIR nodes,
+                // so many local queries will panic on their def ids. `None` is currently
+                // returned here instead of `DefKind::{Anon,Inline}Const` to avoid such panics.
+                // Ideally all def ids should have `DefKind`s, we need to create the missing
+                // HIR nodes or feed relevant query results to achieve that.
+                DefPathData::AnonConst => return None,
+                _ => bug!("no HIR node for def id {local_def_id:?}"),
+            },
+        };
+        let def_kind = match node {
             Node::Item(item) => match item.kind {
                 ItemKind::Static(_, mt, _) => DefKind::Static(mt),
                 ItemKind::Const(..) => DefKind::Const,
@@ -266,7 +278,10 @@ impl<'hir> Map<'hir> {
             | Node::Param(_)
             | Node::Arm(_)
             | Node::Lifetime(_)
-            | Node::Block(_) => return None,
+            | Node::Block(_) => span_bug!(
+                self.span(hir_id),
+                "unexpected node with def id {local_def_id:?}: {node:?}"
+            ),
         };
         Some(def_kind)
     }
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 5bbd396d6f3..24cbe8e8281 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -15,6 +15,7 @@ use hir::def::DefKind;
 use polonius_engine::Atom;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::Interned;
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
@@ -864,8 +865,8 @@ impl<'tcx> PolyTraitRef<'tcx> {
     }
 }
 
-impl rustc_errors::IntoDiagnosticArg for PolyTraitRef<'_> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
         self.to_string().into_diagnostic_arg()
     }
 }
@@ -910,6 +911,12 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
     }
 }
 
+impl<'tcx> IntoDiagnosticArg for ExistentialTraitRef<'tcx> {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        self.to_string().into_diagnostic_arg()
+    }
+}
+
 pub type PolyExistentialTraitRef<'tcx> = Binder<'tcx, ExistentialTraitRef<'tcx>>;
 
 impl<'tcx> PolyExistentialTraitRef<'tcx> {
@@ -926,12 +933,6 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
     }
 }
 
-impl rustc_errors::IntoDiagnosticArg for PolyExistentialTraitRef<'_> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
-        self.to_string().into_diagnostic_arg()
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum BoundVariableKind {
@@ -1146,6 +1147,15 @@ impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
     }
 }
 
+impl<'tcx, T> IntoDiagnosticArg for Binder<'tcx, T>
+where
+    T: IntoDiagnosticArg,
+{
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        self.0.into_diagnostic_arg()
+    }
+}
+
 struct SkipBindersAt<'tcx> {
     tcx: TyCtxt<'tcx>,
     index: ty::DebruijnIndex,
@@ -1362,6 +1372,12 @@ impl<'tcx> FnSig<'tcx> {
     }
 }
 
+impl<'tcx> IntoDiagnosticArg for FnSig<'tcx> {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        self.to_string().into_diagnostic_arg()
+    }
+}
+
 pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
 
 impl<'tcx> PolyFnSig<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 6814cadb9a8..08a62c900f9 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -83,6 +83,9 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable<TyCtxt<'tcx>> {
                 | TypeFlags::HAS_CT_PLACEHOLDER,
         )
     }
+    fn has_non_region_placeholders(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_TY_PLACEHOLDER | TypeFlags::HAS_CT_PLACEHOLDER)
+    }
     fn needs_subst(&self) -> bool {
         self.has_type_flags(TypeFlags::NEEDS_SUBST)
     }
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 2199ceee532..2628f247c54 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -213,3 +213,13 @@ resolve_tool_module_imported =
 
 resolve_module_only =
     visibility must resolve to a module
+
+resolve_macro_expected_found =
+    expected {$expected}, found {$found} `{$macro_path}`
+
+resolve_remove_surrounding_derive =
+    remove from the surrounding `derive()`
+
+resolve_add_as_non_derive =
+    add as non-Derive macro
+    `#[{$macro_path}]`
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 07aaaa1eb7f..afa796cb645 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -481,3 +481,30 @@ pub(crate) struct ToolModuleImported {
 #[derive(Diagnostic)]
 #[diag(resolve_module_only)]
 pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span);
+
+#[derive(Diagnostic, Default)]
+#[diag(resolve_macro_expected_found)]
+pub(crate) struct MacroExpectedFound<'a> {
+    #[primary_span]
+    pub(crate) span: Span,
+    pub(crate) found: &'a str,
+    pub(crate) expected: &'a str,
+    pub(crate) macro_path: &'a str,
+    #[subdiagnostic]
+    pub(crate) remove_surrounding_derive: Option<RemoveSurroundingDerive>,
+    #[subdiagnostic]
+    pub(crate) add_as_non_derive: Option<AddAsNonDerive<'a>>,
+}
+
+#[derive(Subdiagnostic)]
+#[help(resolve_remove_surrounding_derive)]
+pub(crate) struct RemoveSurroundingDerive {
+    #[primary_span]
+    pub(crate) span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[help(resolve_add_as_non_derive)]
+pub(crate) struct AddAsNonDerive<'a> {
+    pub(crate) macro_path: &'a str,
+}
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 48707d37a10..22b014c0651 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -1,6 +1,7 @@
 //! A bunch of methods and structures more or less related to resolving macros and
 //! interface provided by `Resolver` to macro expander.
 
+use crate::errors::{AddAsNonDerive, MacroExpectedFound, RemoveSurroundingDerive};
 use crate::Namespace::*;
 use crate::{BuiltinMacroState, Determinacy};
 use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet};
@@ -543,12 +544,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         };
         if let Some((article, expected)) = unexpected_res {
             let path_str = pprust::path_to_string(path);
-            let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str);
-            self.tcx
-                .sess
-                .struct_span_err(path.span, &msg)
-                .span_label(path.span, format!("not {} {}", article, expected))
-                .emit();
+
+            let mut err = MacroExpectedFound {
+                span: path.span,
+                expected,
+                found: res.descr(),
+                macro_path: &path_str,
+                ..Default::default() // Subdiagnostics default to None
+            };
+
+            // Suggest moving the macro out of the derive() if the macro isn't Derive
+            if !path.span.from_expansion()
+                && kind == MacroKind::Derive
+                && ext.macro_kind() != MacroKind::Derive
+            {
+                err.remove_surrounding_derive = Some(RemoveSurroundingDerive { span: path.span });
+                err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str });
+            }
+
+            let mut err = self.tcx.sess.create_err(err);
+            err.span_label(path.span, format!("not {} {}", article, expected));
+
+            err.emit();
+
             return Ok((self.dummy_ext(kind), Res::Err));
         }
 
diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..db8b9c70e67
--- /dev/null
+++ b/compiler/rustc_target/src/spec/loongarch64_unknown_linux_gnu.rs
@@ -0,0 +1,17 @@
+use crate::spec::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    Target {
+        llvm_target: "loongarch64-unknown-linux-gnu".into(),
+        pointer_width: 64,
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
+        arch: "loongarch64".into(),
+        options: TargetOptions {
+            cpu: "generic".into(),
+            features: "+f,+d".into(),
+            llvm_abiname: "lp64d".into(),
+            max_atomic_width: Some(64),
+            ..super::linux_gnu_base::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 62c58c204e0..192b2ab0ca2 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1021,6 +1021,7 @@ supported_targets! {
     ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
     ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
     ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
+    ("loongarch64-unknown-linux-gnu", loongarch64_unknown_linux_gnu),
     ("m68k-unknown-linux-gnu", m68k_unknown_linux_gnu),
     ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
     ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 12ee80b6722..a33e8ef4b4a 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -225,6 +225,11 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<TyCtxt<'tcx>> + Copy + Eq {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx>;
+
+    fn consider_builtin_transmute_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx>;
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
@@ -373,6 +378,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             G::consider_builtin_discriminant_kind_candidate(self, goal)
         } else if lang_items.destruct_trait() == Some(trait_def_id) {
             G::consider_builtin_destruct_candidate(self, goal)
+        } else if lang_items.transmute_trait() == Some(trait_def_id) {
+            G::consider_builtin_transmute_candidate(self, goal)
         } else {
             Err(NoSolution)
         };
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
index cbec39d8285..1a566e87dc8 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs
@@ -24,21 +24,19 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
         | ty::FnDef(..)
         | ty::FnPtr(_)
         | ty::Error(_)
-        | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
         | ty::Never
         | ty::Char => Ok(vec![]),
 
-        // Treat this like `struct str([u8]);`
+        // Treat `str` like it's defined as `struct str([u8]);`
         ty::Str => Ok(vec![tcx.mk_slice(tcx.types.u8)]),
 
         ty::Dynamic(..)
         | ty::Param(..)
         | ty::Foreign(..)
         | ty::Alias(ty::Projection, ..)
-        | ty::Placeholder(..) => Err(NoSolution),
-
-        ty::Bound(..)
-        | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+        | ty::Placeholder(..)
+        | ty::Bound(..)
+        | ty::Infer(_) => {
             bug!("unexpected type `{ty}`")
         }
 
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index 28aca76cceb..c29b5b04e00 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -639,4 +639,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         crate::traits::wf::unnormalized_obligations(self.infcx, param_env, arg)
             .map(|obligations| obligations.into_iter().map(|obligation| obligation.into()))
     }
+
+    pub(super) fn is_transmutable(
+        &self,
+        src_and_dst: rustc_transmute::Types<'tcx>,
+        scope: Ty<'tcx>,
+        assume: rustc_transmute::Assume,
+    ) -> Result<Certainty, NoSolution> {
+        // FIXME(transmutability): This really should be returning nested goals for `Answer::If*`
+        match rustc_transmute::TransmuteTypeEnv::new(self.infcx).is_transmutable(
+            ObligationCause::dummy(),
+            ty::Binder::dummy(src_and_dst),
+            scope,
+            assume,
+        ) {
+            rustc_transmute::Answer::Yes => Ok(Certainty::Yes),
+            rustc_transmute::Answer::No(_)
+            | rustc_transmute::Answer::IfTransmutable { .. }
+            | rustc_transmute::Answer::IfAll(_)
+            | rustc_transmute::Answer::IfAny(_) => Err(NoSolution),
+        }
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 2a47da81ec7..14cb43b89c3 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -524,6 +524,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
     ) -> QueryResult<'tcx> {
         bug!("`Destruct` does not have an associated type: {:?}", goal);
     }
+
+    fn consider_builtin_transmute_candidate(
+        _ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        bug!("`BikeshedIntrinsicFrom` does not have an associated type: {:?}", goal)
+    }
 }
 
 /// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index 81f89fd950c..716d5acb324 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -147,24 +147,66 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
         ecx: &mut EvalCtxt<'_, 'tcx>,
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
-        // This differs from the current stable behavior and
-        // fixes #84857. Due to breakage found via crater, we
-        // currently instead lint patterns which can be used to
-        // exploit this unsoundness on stable, see #93367 for
-        // more details.
-        //
-        // Using `TreatProjections::NextSolverLookup` is fine here because
-        // `instantiate_constituent_tys_for_auto_trait` returns nothing for
-        // projection types anyways. So it doesn't really matter what we do
-        // here, and this is faster.
-        if let Some(def_id) = ecx.tcx().find_map_relevant_impl(
-            goal.predicate.def_id(),
-            goal.predicate.self_ty(),
-            TreatProjections::NextSolverLookup,
-            Some,
-        ) {
-            debug!(?def_id, ?goal, "disqualified auto-trait implementation");
-            return Err(NoSolution);
+        let self_ty = goal.predicate.self_ty();
+        match *self_ty.kind() {
+            // Stall int and float vars until they are resolved to a concrete
+            // numerical type. That's because the check for impls below treats
+            // int vars as matching any impl. Even if we filtered such impls,
+            // we probably don't want to treat an `impl !AutoTrait for i32` as
+            // disqualifying the built-in auto impl for `i64: AutoTrait` either.
+            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
+                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
+            }
+
+            // These types cannot be structurally decomposed into constitutent
+            // types, and therefore have no builtin impl.
+            ty::Dynamic(..)
+            | ty::Param(..)
+            | ty::Foreign(..)
+            | ty::Alias(ty::Projection, ..)
+            | ty::Placeholder(..) => return Err(NoSolution),
+
+            ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"),
+
+            // For rigid types, we only register a builtin auto implementation
+            // if there is no implementation that could ever apply to the self
+            // type.
+            //
+            // This differs from the current stable behavior and fixes #84857.
+            // Due to breakage found via crater, we currently instead lint
+            // patterns which can be used to exploit this unsoundness on stable,
+            // see #93367 for more details.
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Str
+            | ty::Array(_, _)
+            | ty::Slice(_)
+            | ty::RawPtr(_)
+            | ty::Ref(_, _, _)
+            | ty::FnDef(_, _)
+            | ty::FnPtr(_)
+            | ty::Closure(_, _)
+            | ty::Generator(_, _, _)
+            | ty::GeneratorWitness(_)
+            | ty::GeneratorWitnessMIR(_, _)
+            | ty::Never
+            | ty::Tuple(_)
+            | ty::Error(_)
+            | ty::Adt(_, _)
+            | ty::Alias(ty::Opaque, _) => {
+                if let Some(def_id) = ecx.tcx().find_map_relevant_impl(
+                    goal.predicate.def_id(),
+                    goal.predicate.self_ty(),
+                    TreatProjections::NextSolverLookup,
+                    Some,
+                ) {
+                    debug!(?def_id, ?goal, "disqualified auto-trait implementation");
+                    return Err(NoSolution);
+                }
+            }
         }
 
         ecx.probe_and_evaluate_goal_for_constituent_tys(
@@ -556,6 +598,35 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             Err(NoSolution)
         }
     }
+
+    fn consider_builtin_transmute_candidate(
+        ecx: &mut EvalCtxt<'_, 'tcx>,
+        goal: Goal<'tcx, Self>,
+    ) -> QueryResult<'tcx> {
+        // `rustc_transmute` does not have support for type or const params
+        if goal.has_non_region_placeholders() {
+            return Err(NoSolution);
+        }
+
+        // Erase regions because we compute layouts in `rustc_transmute`,
+        // which will ICE for region vars.
+        let substs = ecx.tcx().erase_regions(goal.predicate.trait_ref.substs);
+
+        let Some(assume) = rustc_transmute::Assume::from_const(
+            ecx.tcx(),
+            goal.param_env,
+            substs.const_at(3),
+        ) else {
+            return Err(NoSolution);
+        };
+
+        let certainty = ecx.is_transmutable(
+            rustc_transmute::Types { dst: substs.type_at(0), src: substs.type_at(1) },
+            substs.type_at(2),
+            assume,
+        )?;
+        ecx.evaluate_added_goals_and_make_canonical_response(certainty)
+    }
 }
 
 impl<'tcx> EvalCtxt<'_, 'tcx> {
diff --git a/config.example.toml b/config.example.toml
index 081b3638383..6d9c762ceca 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -88,7 +88,7 @@ changelog-seen = 2
 # the resulting rustc being unable to compile for the disabled architectures.
 #
 # To add support for new targets, see https://rustc-dev-guide.rust-lang.org/building/new-target.html.
-#targets = "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
+#targets = "AArch64;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
 
 # LLVM experimental targets to build support for. These targets are specified in
 # the same format as above, but since these targets are experimental, they are
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 529f62f4d6c..7c93c93b4a0 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -712,8 +712,8 @@ macro_rules! unimplemented {
 
 /// Indicates unfinished code.
 ///
-/// This can be useful if you are prototyping and are just looking to have your
-/// code typecheck.
+/// This can be useful if you are prototyping and just
+/// want a placeholder to let your code pass type analysis.
 ///
 /// The difference between [`unimplemented!`] and `todo!` is that while `todo!` conveys
 /// an intent of implementing the functionality later and the message is "not yet
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 932038a0b01..114deeea387 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1363,12 +1363,11 @@ macro_rules! uint_impl {
         ///
         /// Basic usage:
         ///
-        /// Please note that this example is shared between integer types.
-        /// Which explains why `i8` is used here.
-        ///
         /// ```
-        /// assert_eq!(100i8.wrapping_neg(), -100);
-        /// assert_eq!((-128i8).wrapping_neg(), -128);
+        #[doc = concat!("assert_eq!(0_", stringify!($SelfT), ".wrapping_neg(), 0);")]
+        #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_neg(), 1);")]
+        #[doc = concat!("assert_eq!(13_", stringify!($SelfT), ".wrapping_neg(), (!13) + 1);")]
+        #[doc = concat!("assert_eq!(42_", stringify!($SelfT), ".wrapping_neg(), !(42 - 1));")]
         /// ```
         #[stable(feature = "num_wrapping", since = "1.2.0")]
         #[rustc_const_stable(feature = "const_wrapping_math", since = "1.32.0")]
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 183f9ab3b08..d372fa64065 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -236,21 +236,14 @@ fn _var(key: &OsStr) -> Result<String, VarError> {
 }
 
 /// Fetches the environment variable `key` from the current process, returning
-/// [`None`] if the variable isn't set or there's another error.
+/// [`None`] if the variable isn't set or if there is another error.
 ///
-/// Note that the method will not check if the environment variable
-/// is valid Unicode. If you want to have an error on invalid UTF-8,
-/// use the [`var`] function instead.
-///
-/// # Errors
-///
-/// This function returns an error if the environment variable isn't set.
-///
-/// This function may return an error if the environment variable's name contains
+/// It may return `None` if the environment variable's name contains
 /// the equal sign character (`=`) or the NUL character.
 ///
-/// This function may return an error if the environment variable's value contains
-/// the NUL character.
+/// Note that this function will not check if the environment variable
+/// is valid Unicode. If you want to have an error on invalid UTF-8,
+/// use the [`var`] function instead.
 ///
 /// # Examples
 ///
@@ -895,6 +888,7 @@ pub mod consts {
     /// - x86_64
     /// - arm
     /// - aarch64
+    /// - loongarch64
     /// - m68k
     /// - mips
     /// - mips64
diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs
index f46028c3a96..c55ca8ba26e 100644
--- a/library/std/src/os/linux/raw.rs
+++ b/library/std/src/os/linux/raw.rs
@@ -231,6 +231,7 @@ mod arch {
 }
 
 #[cfg(any(
+    target_arch = "loongarch64",
     target_arch = "mips64",
     target_arch = "s390x",
     target_arch = "sparc64",
diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs
index 41c0fe725a5..0421b47be02 100644
--- a/library/std/src/personality/gcc.rs
+++ b/library/std/src/personality/gcc.rs
@@ -77,6 +77,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
 #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
 const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11
 
+#[cfg(target_arch = "loongarch64")]
+const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1
+
 // The following code is based on GCC's C and C++ personality routines.  For reference, see:
 // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
diff --git a/library/std/src/sys/common/alloc.rs b/library/std/src/sys/common/alloc.rs
index 403a5e627f1..a5fcbdf39c6 100644
--- a/library/std/src/sys/common/alloc.rs
+++ b/library/std/src/sys/common/alloc.rs
@@ -22,6 +22,7 @@ pub const MIN_ALIGN: usize = 8;
 #[cfg(any(
     target_arch = "x86_64",
     target_arch = "aarch64",
+    target_arch = "loongarch64",
     target_arch = "mips64",
     target_arch = "s390x",
     target_arch = "sparc64",
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index eeeed3afcd3..f6a68073b2f 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -75,6 +75,9 @@ pub const unwinder_private_data_size: usize = 20;
 #[cfg(all(target_arch = "hexagon", target_os = "linux"))]
 pub const unwinder_private_data_size: usize = 35;
 
+#[cfg(target_arch = "loongarch64")]
+pub const unwinder_private_data_size: usize = 2;
+
 #[repr(C)]
 pub struct _Unwind_Exception {
     pub exception_class: _Unwind_Exception_Class,
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index d12781cc33a..025145244c4 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -304,6 +304,7 @@ def default_build_triple(verbose):
         'i486': 'i686',
         'i686': 'i686',
         'i786': 'i686',
+        'loongarch64': 'loongarch64',
         'm68k': 'm68k',
         'powerpc': 'powerpc',
         'powerpc64': 'powerpc64',
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index e3581943f2c..85d1c12cc6a 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -83,11 +83,11 @@ impl Step for Std {
         let target = self.target;
         let compiler = self.compiler;
 
-        // These artifacts were already copied (in `impl Step for Sysroot`).
-        // Don't recompile them.
+        // When using `download-rustc`, we already have artifacts for the host available
+        // (they were copied in `impl Step for Sysroot`). Don't recompile them.
         // NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
         // so its artifacts can't be reused.
-        if builder.download_rustc() && compiler.stage != 0 {
+        if builder.download_rustc() && compiler.stage != 0 && target == builder.build.build {
             return;
         }
 
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 5ee18cf6411..eaa3afa4b7b 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -129,7 +129,8 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
     /* Extra values not defined in the built-in targets yet, but used in std */
     (Some(Mode::Std), "target_env", Some(&["libnx"])),
     // (Some(Mode::Std), "target_os", Some(&[])),
-    (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa"])),
+    // #[cfg(bootstrap)] loongarch64
+    (Some(Mode::Std), "target_arch", Some(&["asmjs", "spirv", "nvptx", "xtensa", "loongarch64"])),
     /* Extra names used by dependencies */
     // FIXME: Used by serde_json, but we should not be triggering on external dependencies.
     (Some(Mode::Rustc), "no_btreemap_remove_entry", None),
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs
index cc2b45a9bdb..d123deec354 100644
--- a/src/bootstrap/llvm.rs
+++ b/src/bootstrap/llvm.rs
@@ -291,7 +291,7 @@ impl Step for Llvm {
         let llvm_targets = match &builder.config.llvm_targets {
             Some(s) => s,
             None => {
-                "AArch64;ARM;BPF;Hexagon;MSP430;Mips;NVPTX;PowerPC;RISCV;\
+                "AArch64;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;\
                      Sparc;SystemZ;WebAssembly;X86"
             }
         };
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 058ff429e80..f9c5837b7d6 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1535,7 +1535,10 @@ note: if you're sure you want to do this, please open an issue as to why. In the
         flags.extend(builder.config.cmd.rustc_args().iter().map(|s| s.to_string()));
 
         if let Some(linker) = builder.linker(target) {
-            cmd.arg("--linker").arg(linker);
+            cmd.arg("--target-linker").arg(linker);
+        }
+        if let Some(linker) = builder.linker(compiler.host) {
+            cmd.arg("--host-linker").arg(linker);
         }
 
         let mut hostflags = flags.clone();
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 66fb941ea37..7092c7c46f8 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.14.6
\ No newline at end of file
+0.15.0
\ No newline at end of file
diff --git a/src/doc/book b/src/doc/book
-Subproject 0510ca84c2ce6bf93c4ccf9248756e9e4fd00b1
+Subproject c06006157b14b3d47b5c716fc392b77f3b2e21c
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 3c47807a3131b3c7cacb508f52632078d253cd0
+Subproject 1f8dc727e94ae4ef92adf70df979521a1ea1143
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject ba84bf35d0f17d404003349309201654d25f61a
+Subproject 31961fe22521a779070a44a8f30a2b00a20b621
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject fca8af6c154c6cde2512f1331cf2704f214a818
+Subproject 6337ed17fb8dcd918d78b7d97d213e923530337
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 0452126cc37..8ded2ee59dd 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -29,6 +29,7 @@
     - [\*-linux-ohos](platform-support/openharmony.md)
     - [\*-unknown-fuchsia](platform-support/fuchsia.md)
     - [\*-kmc-solid_\*](platform-support/kmc-solid.md)
+    - [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md)
     - [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
     - [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
     - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 67fe2a610c2..c378532dbf6 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -266,6 +266,7 @@ 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
new file mode 100644
index 00000000000..e046ec244ec
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/loongarch-linux.md
@@ -0,0 +1,92 @@
+# loongarch\*-unknown-linux-\*
+
+**Tier: 3**
+
+[LoongArch] is a new RISC ISA developed by Loongson Technology Corporation Limited.
+
+[LoongArch]: https://loongson.github.io/LoongArch-Documentation/README-EN.html
+
+The target name follow this format: `<machine>-<vendor>-<os><fabi_suffix>, where `<machine>` specifies the CPU family/model, `<vendor>` specifies the vendor and `<os>` the operating system name.
+While the integer base ABI is implied by the machine field, the floating point base ABI type is encoded into the os field of the specifier using the string suffix `<fabi-suffix>`.
+
+|    `<fabi-suffix>`     |                           `Description`                            |
+|------------------------|--------------------------------------------------------------------|
+|          f64           | The base ABI use 64-bits FPRs for parameter passing.(lp64d)|
+|          f32           | The base ABI uses 32-bit FPRs for parameter passing. (lp64f)|
+|          sf            | The base ABI uses no FPR for parameter passing. (lp64s)     |
+
+|`ABI type(Base ABI/ABI extension)`| `C library` | `kernel` |          `target tuple`          |
+|----------------------------------|-------------|----------|----------------------------------|
+|           lp64d/base             |   glibc     |  linux   | loongarch64-unknown-linux-gnu |
+|           lp64f/base             |   glibc     |  linux   | loongarch64-unknown-linux-gnuf32 |
+|           lp64s/base             |   glibc     |  linux   | loongarch64-unknown-linux-gnusf  |
+|           lp64d/base             |  musl libc  |  linux   | loongarch64-unknown-linux-musl|
+|           lp64f/base             |  musl libc  |  linux   | loongarch64-unknown-linux-muslf32|
+|           lp64s/base             |  musl libc  |  linux   | loongarch64-unknown-linux-muslsf |
+
+## Target maintainers
+
+- [ZHAI xiaojuan](https://github.com/zhaixiaojuan) `zhaixiaojuan@loongson.cn`
+- [WANG rui](https://github.com/heiher) `wangrui@loongson.cn`
+- [ZHAI xiang](https://github.com/xiangzhai) `zhaixiang@loongson.cn`
+- [WANG Xuerui](https://github.com/xen0n) `git@xen0n.name`
+
+## Requirements
+
+This target is cross-compiled.
+A GNU toolchain for LoongArch target is required.  It can be downloaded from https://github.com/loongson/build-tools/releases, or built from the source code of GCC (12.1.0 or later) and Binutils (2.40 or later).
+
+## Building the target
+
+The target can be built by enabling it for a `rustc` build.
+
+```toml
+[build]
+target = ["loongarch64-unknown-linux-gnu"]
+```
+
+Make sure `loongarch64-unknown-linux-gnu-gcc` can be searched from the directories specified in`$PATH`. Alternatively, you can use GNU LoongArch Toolchain by adding the following to `config.toml`:
+
+```toml
+[target.loongarch64-unknown-linux-gnu]
+# ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN
+cc = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc"
+cxx = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-g++"
+ar = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-ar"
+ranlib = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-ranlib"
+linker = "/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc"
+```
+
+## Cross-compilation
+
+This target can be cross-compiled on a `x86_64-unknown-linux-gnu` host. Cross-compilation on other hosts may work but is not tested.
+
+## Testing
+To test a cross-compiled binary on your build system, install the qemu binary that supports the LoongArch architecture and execute the following commands.
+```text
+CC_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \
+CXX_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-g++ \
+AR_loongarch64_unknown_linux_gnu=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc-ar \
+CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_LINKER=/TOOLCHAIN_PATH/bin/loongarch64-unknown-linux-gnu-gcc \
+# SET TARGET SYSTEM LIBRARY PATH
+CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNUN_RUNNER="qemu-loongarch64 -L /TOOLCHAIN_PATH/TARGET_LIBRAY_PATH" \
+cargo run --target loongarch64-unknown-linux-gnu --release
+```
+Tested on x86 architecture, other architectures not tested.
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you will either need to build Rust with the target enabled (see "Building the target" above), or build your own copy of `std` by using `build-std` or similar.
+
+If `rustc` has support for that target and the library artifacts are available, then Rust static libraries can be built for that target:
+
+```shell
+$ rustc --target loongarch64-unknown-linux-gnu your-code.rs --crate-type staticlib
+$ ls libyour_code.a
+```
+
+On Rust Nightly it's possible to build without the target artifacts available:
+
+```text
+cargo build -Z build-std --target loongarch64-unknown-linux-gnu
+```
diff --git a/src/etc/rust-gdb b/src/etc/rust-gdb
index b950cea79ed..d812f7a802b 100755
--- a/src/etc/rust-gdb
+++ b/src/etc/rust-gdb
@@ -13,6 +13,8 @@ fi
 # Find out where the pretty printer Python module is
 RUSTC_SYSROOT="$("$RUSTC" --print=sysroot)"
 GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
+# Get the commit hash for path remapping
+RUSTC_COMMIT_HASH="$("$RUSTC" -vV | sed -n 's/commit-hash: \(\w*\)/\1/p')"
 
 # Run GDB with the additional arguments that load the pretty printers
 # Set the environment variable `RUST_GDB` to overwrite the call to a
@@ -21,4 +23,6 @@ RUST_GDB="${RUST_GDB:-gdb}"
 PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" exec ${RUST_GDB} \
   --directory="$GDB_PYTHON_MODULE_DIRECTORY" \
   -iex "add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY" \
+  -iex "set substitute-path /rustc/$RUSTC_COMMIT_HASH $RUSTC_SYSROOT/lib/rustlib/src/rust" \
   "$@"
+ 
\ No newline at end of file
diff --git a/src/etc/rust-gdbgui b/src/etc/rust-gdbgui
index 590e488e643..e7bafcc99b8 100755
--- a/src/etc/rust-gdbgui
+++ b/src/etc/rust-gdbgui
@@ -42,6 +42,8 @@ fi
 # Find out where the pretty printer Python module is
 RUSTC_SYSROOT="$("$RUSTC" --print=sysroot)"
 GDB_PYTHON_MODULE_DIRECTORY="$RUSTC_SYSROOT/lib/rustlib/etc"
+# Get the commit hash for path remapping
+RUSTC_COMMIT_HASH="$("$RUSTC" -vV | sed -n 's/commit-hash: \(\w*\)/\1/p')"
 
 # Set the environment variable `RUST_GDB` to overwrite the call to a
 # different/specific command (defaults to `gdb`).
@@ -53,7 +55,9 @@ RUST_GDBGUI="${RUST_GDBGUI:-gdbgui}"
 
 # These arguments get passed through to GDB and make it load the
 # Rust pretty printers.
-GDB_ARGS="--directory=\"$GDB_PYTHON_MODULE_DIRECTORY\" -iex \"add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY\""
+GDB_ARGS="--directory=\"$GDB_PYTHON_MODULE_DIRECTORY\"" \
+   "-iex \"add-auto-load-safe-path $GDB_PYTHON_MODULE_DIRECTORY\"" \
+   "-iex \"set substitute-path /rustc/$RUSTC_COMMIT_HASH $RUSTC_SYSROOT/lib/rustlib/src/rust\""
 
 # Finally we execute gdbgui.
 PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" \
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index dd58a5b51fc..5177cffe6ba 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -517,6 +517,7 @@ impl<'a> fmt::Display for Display<'a> {
                         "aarch64" => "AArch64",
                         "arm" => "ARM",
                         "asmjs" => "JavaScript",
+                        "loongarch64" => "LoongArch LA64",
                         "m68k" => "M68k",
                         "mips" => "MIPS",
                         "mips64" => "MIPS-64",
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 7f150f38025..b3df12a9df1 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2381,7 +2381,8 @@ fn clean_extern_crate<'tcx>(
                     Some(l) => attr::list_contains_name(&l, sym::inline),
                     None => false,
                 }
-        });
+        })
+        && !cx.output_format.is_json();
 
     let krate_owner_def_id = krate.owner_id.to_def_id();
     if please_inline {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index cd97766752d..e34ece9264c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -687,7 +687,7 @@ impl Item {
                 return None;
             }
             // Variants always inherit visibility
-            VariantItem(..) => return None,
+            VariantItem(..) | ImplItem(..) => return None,
             // Trait items inherit the trait's visibility
             AssocConstItem(..) | TyAssocConstItem(..) | AssocTypeItem(..) | TyAssocTypeItem(..)
             | TyMethodItem(..) | MethodItem(..) => {
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 0e474cfd7b16b018cf46e95da3f6a5b2f1f6a9e
+Subproject 7bf43f028ba5eb1f4d70d271c2546c38512c987
diff --git a/src/tools/clippy/.cargo/config.toml b/src/tools/clippy/.cargo/config.toml
index f3dd9275a42..4d80d3ce63d 100644
--- a/src/tools/clippy/.cargo/config.toml
+++ b/src/tools/clippy/.cargo/config.toml
@@ -11,3 +11,6 @@ target-dir = "target"
 
 [unstable]
 binary-dep-depinfo = true
+
+[profile.dev]
+split-debuginfo = "unpacked"
diff --git a/src/tools/clippy/.editorconfig b/src/tools/clippy/.editorconfig
index ec6e107d547..bc7642bf8c7 100644
--- a/src/tools/clippy/.editorconfig
+++ b/src/tools/clippy/.editorconfig
@@ -11,6 +11,7 @@ trim_trailing_whitespace = true
 insert_final_newline = true
 indent_style = space
 indent_size = 4
+max_line_length = 120
 
 [*.md]
 # double whitespace at end of line
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 24e677ce8e1..93198aabdb5 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -180,6 +180,8 @@ jobs:
 
     # Run
     - name: Build Integration Test
+      env:
+        CARGO_PROFILE_DEV_SPLIT_DEBUGINFO: off
       run: cargo test --test integration --features integration --no-run
 
     # Upload
diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml
index 81ef072bbb0..116058b7c75 100644
--- a/src/tools/clippy/.github/workflows/remark.yml
+++ b/src/tools/clippy/.github/workflows/remark.yml
@@ -29,7 +29,7 @@ jobs:
     - name: Install mdbook
       run: |
         mkdir mdbook
-        curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.18/mdbook-v0.4.18-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook
+        curl -Lf https://github.com/rust-lang/mdBook/releases/download/v0.4.28/mdbook-v0.4.28-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook
         echo `pwd`/mdbook >> $GITHUB_PATH
 
     # Run
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 1323f973ccf..559b560dde4 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -4441,6 +4441,7 @@ Released 2018-09-13
 [`chars_last_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_last_cmp
 [`chars_next_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#chars_next_cmp
 [`checked_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#checked_conversions
+[`clear_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#clear_with_drain
 [`clone_double_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_double_ref
 [`clone_on_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy
 [`clone_on_ref_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_ref_ptr
@@ -4632,6 +4633,7 @@ Released 2018-09-13
 [`large_const_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays
 [`large_digit_groups`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_digit_groups
 [`large_enum_variant`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_enum_variant
+[`large_futures`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_futures
 [`large_include_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_include_file
 [`large_stack_arrays`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays
 [`large_types_passed_by_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#large_types_passed_by_value
@@ -4645,6 +4647,7 @@ Released 2018-09-13
 [`let_underscore_untyped`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_untyped
 [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
 [`let_with_type_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_with_type_underscore
+[`lines_filter_map_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok
 [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
 [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
 [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
@@ -4671,6 +4674,7 @@ Released 2018-09-13
 [`manual_rem_euclid`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_rem_euclid
 [`manual_retain`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_retain
 [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
+[`manual_slice_size_calculation`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_slice_size_calculation
 [`manual_split_once`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_split_once
 [`manual_str_repeat`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_str_repeat
 [`manual_string_new`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_string_new
@@ -4921,6 +4925,7 @@ Released 2018-09-13
 [`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl
 [`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting
 [`suspicious_command_arg_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_command_arg_space
+[`suspicious_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_doc_comments
 [`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting
 [`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map
 [`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl
@@ -4933,6 +4938,7 @@ Released 2018-09-13
 [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments
 [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment
 [`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr
+[`tests_outside_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#tests_outside_test_module
 [`to_digit_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_digit_is_some
 [`to_string_in_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_display
 [`to_string_in_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#to_string_in_format_args
@@ -4974,6 +4980,7 @@ Released 2018-09-13
 [`unit_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash
 [`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord
 [`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#unknown_clippy_lints
+[`unnecessary_box_returns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns
 [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
 [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
 [`unnecessary_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_find_map
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index b69ed8900a4..85798e0e80c 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -11,7 +11,7 @@ Lints are divided into categories, each with a default [lint level](https://doc.
 You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
 
 | Category              | Description                                                                         | Default level |
-| --------------------- | ----------------------------------------------------------------------------------- | ------------- |
+|-----------------------|-------------------------------------------------------------------------------------|---------------|
 | `clippy::all`         | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** |
 | `clippy::correctness` | code that is outright wrong or useless                                              | **deny**      |
 | `clippy::suspicious`  | code that is most likely wrong or useless                                           | **warn**      |
@@ -130,7 +130,7 @@ for example.
 
 You can add Clippy to Travis CI in the same way you use it locally:
 
-```yml
+```yaml
 language: rust
 rust:
   - stable
@@ -253,7 +253,7 @@ rust-version = "1.30"
 
 The MSRV can also be specified as an attribute, like below.
 
-```rust
+```rust,ignore
 #![feature(custom_inner_attributes)]
 #![clippy::msrv = "1.30.0"]
 
diff --git a/src/tools/clippy/book/src/README.md b/src/tools/clippy/book/src/README.md
index df4a1f2702e..3b627096268 100644
--- a/src/tools/clippy/book/src/README.md
+++ b/src/tools/clippy/book/src/README.md
@@ -14,7 +14,7 @@ much Clippy is supposed to ~~annoy~~ help you by changing the lint level by
 category.
 
 | Category              | Description                                                                         | Default level |
-| --------------------- | ----------------------------------------------------------------------------------- | ------------- |
+|-----------------------|-------------------------------------------------------------------------------------|---------------|
 | `clippy::all`         | all lints that are on by default (correctness, suspicious, style, complexity, perf) | **warn/deny** |
 | `clippy::correctness` | code that is outright wrong or useless                                              | **deny**      |
 | `clippy::suspicious`  | code that is most likely wrong or useless                                           | **warn**      |
diff --git a/src/tools/clippy/book/src/SUMMARY.md b/src/tools/clippy/book/src/SUMMARY.md
index 0649f7a631d..cbd73376dfa 100644
--- a/src/tools/clippy/book/src/SUMMARY.md
+++ b/src/tools/clippy/book/src/SUMMARY.md
@@ -13,6 +13,7 @@
 - [Development](development/README.md)
     - [Basics](development/basics.md)
     - [Adding Lints](development/adding_lints.md)
+    - [Type Checking](development/type_checking.md)
     - [Common Tools](development/common_tools_writing_lints.md)
     - [Infrastructure](development/infrastructure/README.md)
         - [Syncing changes between Clippy and rust-lang/rust](development/infrastructure/sync.md)
diff --git a/src/tools/clippy/book/src/configuration.md b/src/tools/clippy/book/src/configuration.md
index 87f4a697af9..1304f6a8c2f 100644
--- a/src/tools/clippy/book/src/configuration.md
+++ b/src/tools/clippy/book/src/configuration.md
@@ -3,7 +3,7 @@
 > **Note:** The configuration file is unstable and may be deprecated in the future.
 
 Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`. It contains a
-basic `variable = value` mapping eg.
+basic `variable = value` mapping e.g.
 
 ```toml
 avoid-breaking-exported-api = false
@@ -60,7 +60,7 @@ And to warn on `lint_name`, run
 cargo clippy -- -W clippy::lint_name
 ```
 
-This also works with lint groups. For example you can run Clippy with warnings for all lints enabled:
+This also works with lint groups. For example, you can run Clippy with warnings for all lints enabled:
 
 ```terminal
 cargo clippy -- -W clippy::pedantic
@@ -84,7 +84,7 @@ msrv = "1.30.0"
 
 The MSRV can also be specified as an attribute, like below.
 
-```rust
+```rust,ignore
 #![feature(custom_inner_attributes)]
 #![clippy::msrv = "1.30.0"]
 
@@ -96,7 +96,28 @@ fn main() {
 You can also omit the patch version when specifying the MSRV, so `msrv = 1.30`
 is equivalent to `msrv = 1.30.0`.
 
-Note: `custom_inner_attributes` is an unstable feature so it has to be enabled explicitly.
+Note: `custom_inner_attributes` is an unstable feature, so it has to be enabled explicitly.
 
 Lints that recognize this configuration option can be
 found [here](https://rust-lang.github.io/rust-clippy/master/index.html#msrv)
+
+### Disabling evaluation of certain code
+
+> **Note:** This should only be used in cases where other solutions, like `#[allow(clippy::all)]`, are not sufficient.
+
+Very rarely, you may wish to prevent Clippy from evaluating certain sections of code entirely. You can do this with
+[conditional compilation](https://doc.rust-lang.org/reference/conditional-compilation.html) by checking that the
+`cargo-clippy` feature is not set. You may need to provide a stub so that the code compiles:
+
+```rust
+#[cfg(not(feature = "cargo-clippy"))]
+include!(concat!(env!("OUT_DIR"), "/my_big_function-generated.rs"));
+
+#[cfg(feature = "cargo-clippy")]
+fn my_big_function(_input: &str) -> Option<MyStruct> {
+    None
+}
+```
+
+This feature is not actually part of your crate, so specifying `--all-features` to other tools, e.g. `cargo test
+--all-features`, will not disable it.
diff --git a/src/tools/clippy/book/src/development/README.md b/src/tools/clippy/book/src/development/README.md
index 5cf7201cffa..616e6d182b7 100644
--- a/src/tools/clippy/book/src/development/README.md
+++ b/src/tools/clippy/book/src/development/README.md
@@ -5,7 +5,7 @@ making Clippy better by contributing to it. In that case, welcome to the
 project!
 
 > _Note:_ If you're just interested in using Clippy, there's nothing to see from
-> this point onward and you should return to one of the earlier chapters.
+> this point onward, and you should return to one of the earlier chapters.
 
 ## Getting started
 
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index f57dc627dce..9dacaaaae5c 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -18,6 +18,7 @@ because that's clearly a non-descriptive name.
     - [Cargo lints](#cargo-lints)
   - [Rustfix tests](#rustfix-tests)
   - [Testing manually](#testing-manually)
+  - [Running directly](#running-directly)
   - [Lint declaration](#lint-declaration)
   - [Lint registration](#lint-registration)
   - [Lint passes](#lint-passes)
@@ -186,6 +187,15 @@ cargo dev lint input.rs
 from the working copy root. With tests in place, let's have a look at
 implementing our lint now.
 
+## Running directly
+
+While it's easier to just use `cargo dev lint`, it might be desirable to get
+`target/release/cargo-clippy` and `target/release/clippy-driver` to work as well in some cases.
+By default, they don't work because clippy dynamically links rustc. To help them find rustc,
+add the path printed by`rustc --print target-libdir` (ran inside this workspace so that the rustc version matches)
+to your library search path.
+On linux, this can be done by setting the `LD_LIBRARY_PATH` environment variable to that path.
+
 ## Lint declaration
 
 Let's start by opening the new file created in the `clippy_lints` crate at
@@ -265,7 +275,7 @@ When declaring a new lint by hand and `cargo dev update_lints` is used, the lint
 pass may have to be registered manually in the `register_plugins` function in
 `clippy_lints/src/lib.rs`:
 
-```rust
+```rust,ignore
 store.register_early_pass(|| Box::new(foo_functions::FooFunctions));
 ```
 
@@ -291,7 +301,7 @@ either [`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass].
 
 In short, the `LateLintPass` has access to type information while the
 `EarlyLintPass` doesn't. If you don't need access to type information, use the
-`EarlyLintPass`. The `EarlyLintPass` is also faster. However linting speed
+`EarlyLintPass`. The `EarlyLintPass` is also faster. However, linting speed
 hasn't really been a concern with Clippy so far.
 
 Since we don't need type information for checking the function name, we used
@@ -308,7 +318,7 @@ implementation of the lint logic.
 
 Let's start by implementing the `EarlyLintPass` for our `FooFunctions`:
 
-```rust
+```rust,ignore
 impl EarlyLintPass for FooFunctions {
     fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) {
         // TODO: Emit lint here
@@ -327,10 +337,10 @@ variety of lint emission functions. They can all be found in
 [`clippy_utils/src/diagnostics.rs`][diagnostics].
 
 `span_lint_and_help` seems most appropriate in this case. It allows us to
-provide an extra help message and we can't really suggest a better name
+provide an extra help message, and we can't really suggest a better name
 automatically. This is how it looks:
 
-```rust
+```rust,ignore
 impl EarlyLintPass for FooFunctions {
     fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) {
         span_lint_and_help(
@@ -469,7 +479,7 @@ the value from `clippy.toml`. This can be accounted for using the
 `extract_msrv_attr!(LintContext)` macro and passing
 `LateContext`/`EarlyContext`.
 
-```rust
+```rust,ignore
 impl<'tcx> LateLintPass<'tcx> for ManualStrip {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         ...
@@ -483,7 +493,7 @@ the lint's test file, `tests/ui/manual_strip.rs` in this example. It should
 have a case for the version below the MSRV and one with the same contents but
 for the MSRV version itself.
 
-```rust
+```rust,ignore
 ...
 
 #[clippy::msrv = "1.44"]
@@ -514,7 +524,7 @@ define_Conf! {
 
 If you have trouble implementing your lint, there is also the internal `author`
 lint to generate Clippy code that detects the offending pattern. It does not
-work for all of the Rust syntax, but can give a good starting point.
+work for all the Rust syntax, but can give a good starting point.
 
 The quickest way to use it, is the [Rust playground:
 play.rust-lang.org][author_example]. Put the code you want to lint into the
@@ -607,7 +617,7 @@ output in the `stdout` part.
 
 ## PR Checklist
 
-Before submitting your PR make sure you followed all of the basic requirements:
+Before submitting your PR make sure you followed all the basic requirements:
 
 <!-- Sync this with `.github/PULL_REQUEST_TEMPLATE` -->
 
@@ -627,7 +637,7 @@ for some users. Adding a configuration is done in the following steps:
 
 1. Adding a new configuration entry to [`clippy_lints::utils::conf`] like this:
 
-   ```rust
+   ```rust,ignore
    /// Lint: LINT_NAME.
    ///
    /// <The configuration field doc comment>
@@ -680,7 +690,7 @@ for some users. Adding a configuration is done in the following steps:
    configuration value is now cloned or copied into a local value that is then
    passed to the impl struct like this:
 
-   ```rust
+   ```rust,ignore
    // Default generated registration:
    store.register_*_pass(|| box module::StructName);
 
diff --git a/src/tools/clippy/book/src/development/basics.md b/src/tools/clippy/book/src/development/basics.md
index 6fb53236e6f..7615dc12f9e 100644
--- a/src/tools/clippy/book/src/development/basics.md
+++ b/src/tools/clippy/book/src/development/basics.md
@@ -4,8 +4,8 @@ This document explains the basics for hacking on Clippy. Besides others, this
 includes how to build and test Clippy. For a more in depth description on the
 codebase take a look at [Adding Lints] or [Common Tools].
 
-[Adding Lints]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/adding_lints.md
-[Common Tools]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/common_tools_writing_lints.md
+[Adding Lints]: adding_lints.md
+[Common Tools]: common_tools_writing_lints.md
 
 - [Basics for hacking on Clippy](#basics-for-hacking-on-clippy)
   - [Get the Code](#get-the-code)
@@ -125,7 +125,7 @@ We follow a rustc no merge-commit policy. See
 ## Common Abbreviations
 
 | Abbreviation | Meaning                                |
-| ------------ | -------------------------------------- |
+|--------------|----------------------------------------|
 | UB           | Undefined Behavior                     |
 | FP           | False Positive                         |
 | FN           | False Negative                         |
diff --git a/src/tools/clippy/book/src/development/common_tools_writing_lints.md b/src/tools/clippy/book/src/development/common_tools_writing_lints.md
index f5aa06e4bf6..09171d86a20 100644
--- a/src/tools/clippy/book/src/development/common_tools_writing_lints.md
+++ b/src/tools/clippy/book/src/development/common_tools_writing_lints.md
@@ -3,7 +3,7 @@
 You may need following tooltips to catch up with common operations.
 
 - [Common tools for writing lints](#common-tools-for-writing-lints)
-  - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression)
+  - [Retrieving the type of expression](#retrieving-the-type-of-expression)
   - [Checking if an expr is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method)
   - [Checking for a specific type](#checking-for-a-specific-type)
   - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait)
@@ -16,7 +16,7 @@ Useful Rustc dev guide links:
 - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
 - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
 
-## Retrieving the type of an expression
+## Retrieving the type of expression
 
 Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for
 example to answer following questions:
@@ -45,7 +45,7 @@ impl LateLintPass<'_> for MyStructLint {
 }
 ```
 
-Similarly in [`TypeckResults`][TypeckResults] methods, you have the
+Similarly, in [`TypeckResults`][TypeckResults] methods, you have the
 [`pat_ty()`][pat_ty] method to retrieve a type from a pattern.
 
 Two noticeable items here:
@@ -192,7 +192,7 @@ functions to deal with macros:
 - `span.from_expansion()`: detects if a span is from macro expansion or
   desugaring. Checking this is a common first step in a lint.
 
-   ```rust
+   ```rust,ignore
    if expr.span.from_expansion() {
        // just forget it
        return;
@@ -203,11 +203,11 @@ functions to deal with macros:
   if so, which macro call expanded it. It is sometimes useful to check if the
   context of two spans are equal.
 
-  ```rust
+  ```rust,ignore
   // expands to `1 + 0`, but don't lint
   1 + mac!()
   ```
-  ```rust
+  ```rust,ignore
   if left.span.ctxt() != right.span.ctxt() {
       // the coder most likely cannot modify this expression
       return;
@@ -246,7 +246,7 @@ functions to deal with macros:
   `macro_rules!` with `a == $b`, `$b` is expanded to some expression with a
   different context from `a`.
 
-   ```rust
+   ```rust,ignore
    macro_rules! m {
        ($a:expr, $b:expr) => {
            if $a.is_some() {
diff --git a/src/tools/clippy/book/src/development/infrastructure/book.md b/src/tools/clippy/book/src/development/infrastructure/book.md
index dbd624ecd73..de5de4bebaa 100644
--- a/src/tools/clippy/book/src/development/infrastructure/book.md
+++ b/src/tools/clippy/book/src/development/infrastructure/book.md
@@ -13,7 +13,7 @@ guide to Clippy that you're reading right now. The Clippy book is formatted with
 While not strictly necessary since the book source is simply Markdown text
 files, having mdBook locally will allow you to build, test and serve the book
 locally to view changes before you commit them to the repository. You likely
-already have `cargo` installed, so the easiest option is to simply:
+already have `cargo` installed, so the easiest option is to:
 
 ```shell
 cargo install mdbook
@@ -26,7 +26,7 @@ instructions for other options.
 
 The book's
 [src](https://github.com/rust-lang/rust-clippy/tree/master/book/src)
-directory contains all of the markdown files used to generate the book. If you
+directory contains all the markdown files used to generate the book. If you
 want to see your changes in real time, you can use the mdBook `serve` command to
 run a web server locally that will automatically update changes as they are
 made. From the top level of your `rust-clippy` directory:
diff --git a/src/tools/clippy/book/src/development/infrastructure/changelog_update.md b/src/tools/clippy/book/src/development/infrastructure/changelog_update.md
index d1ac7237b5e..df9b1bbe18f 100644
--- a/src/tools/clippy/book/src/development/infrastructure/changelog_update.md
+++ b/src/tools/clippy/book/src/development/infrastructure/changelog_update.md
@@ -101,7 +101,7 @@ Look for the [`beta-accepted`] label and make sure to also include the PRs with
 that label in the changelog. If you can, remove the `beta-accepted` labels
 **after** the changelog PR was merged.
 
-> _Note:_ Some of those PRs might even got backported to the previous `beta`.
+> _Note:_ Some of those PRs might even get backported to the previous `beta`.
 > Those have to be included in the changelog of the _previous_ release.
 
 ### 4. Update `clippy::version` attributes
diff --git a/src/tools/clippy/book/src/development/infrastructure/release.md b/src/tools/clippy/book/src/development/infrastructure/release.md
index 0572281803e..98fabf8e89a 100644
--- a/src/tools/clippy/book/src/development/infrastructure/release.md
+++ b/src/tools/clippy/book/src/development/infrastructure/release.md
@@ -44,7 +44,7 @@ $ git push origin backport_remerge  # This can be pushed to your fork
 ```
 
 After this, open a PR to the master branch. In this PR, the commit hash of the
-`HEAD` of the `beta` branch must exists. In addition to that, no files should be
+`HEAD` of the `beta` branch must exist. In addition to that, no files should be
 changed by this PR.
 
 ## Update the `beta` branch
diff --git a/src/tools/clippy/book/src/development/infrastructure/sync.md b/src/tools/clippy/book/src/development/infrastructure/sync.md
index 02cfc11b55a..e1fe92f9525 100644
--- a/src/tools/clippy/book/src/development/infrastructure/sync.md
+++ b/src/tools/clippy/book/src/development/infrastructure/sync.md
@@ -19,8 +19,7 @@ to beta. For reference, the first sync following this cadence was performed the
 2020-08-27.
 
 This process is described in detail in the following sections. For general
-information about `subtree`s in the Rust repository see [Rust's
-`CONTRIBUTING.md`][subtree].
+information about `subtree`s in the Rust repository see [the rustc-dev-guide][subtree].
 
 ## Patching git-subtree to work with big repos
 
@@ -47,7 +46,7 @@ sudo chown --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subt
 
 > _Note:_ If you are a Debian user, `dash` is the shell used by default for
 > scripts instead of `sh`. This shell has a hardcoded recursion limit set to
-> 1000. In order to make this process work, you need to force the script to run
+> 1,000. In order to make this process work, you need to force the script to run
 > `bash` instead. You can do this by editing the first line of the `git-subtree`
 > script and changing `sh` to `bash`.
 
@@ -71,10 +70,10 @@ $ git remote add clippy-local /path/to/rust-clippy
 
 ## Performing the sync from [`rust-lang/rust`] to Clippy
 
-Here is a TL;DR version of the sync process (all of the following commands have
+Here is a TL;DR version of the sync process (all the following commands have
 to be run inside the `rust` directory):
 
-1. Clone the [`rust-lang/rust`] repository or make sure it is up to date.
+1. Clone the [`rust-lang/rust`] repository or make sure it is up-to-date.
 2. Checkout the commit from the latest available nightly. You can get it using
    `rustup check`.
 3. Sync the changes to the rust-copy of Clippy to your Clippy fork:
@@ -107,7 +106,7 @@ to be run inside the `rust` directory):
 
 ## Performing the sync from Clippy to [`rust-lang/rust`]
 
-All of the following commands have to be run inside the `rust` directory.
+All the following commands have to be run inside the `rust` directory.
 
 1. Make sure you have checked out the latest `master` of `rust-lang/rust`.
 2. Sync the `rust-lang/rust-clippy` master to the rust-copy of Clippy:
@@ -118,5 +117,5 @@ All of the following commands have to be run inside the `rust` directory.
 3. Open a PR to [`rust-lang/rust`]
 
 [gitgitgadget-pr]: https://github.com/gitgitgadget/git/pull/493
-[subtree]: https://rustc-dev-guide.rust-lang.org/contributing.html#external-dependencies-subtree
+[subtree]: https://rustc-dev-guide.rust-lang.org/external-repos.html#external-dependencies-subtree
 [`rust-lang/rust`]: https://github.com/rust-lang/rust
diff --git a/src/tools/clippy/book/src/development/proposals/README.md b/src/tools/clippy/book/src/development/proposals/README.md
index 78fe34ebf8f..059c22ce1ce 100644
--- a/src/tools/clippy/book/src/development/proposals/README.md
+++ b/src/tools/clippy/book/src/development/proposals/README.md
@@ -6,6 +6,6 @@ or around Clippy in the long run.
 Besides adding more and more lints and improve the lints that Clippy already
 has, Clippy is also interested in making the experience of its users, developers
 and maintainers better over time. Projects that address bigger picture things
-like this usually take more time and it is useful to have a proposal for those
+like this usually take more time, and it is useful to have a proposal for those
 first. This is the place where such proposals are collected, so that we can
 refer to them when working on them.
diff --git a/src/tools/clippy/book/src/development/proposals/roadmap-2021.md b/src/tools/clippy/book/src/development/proposals/roadmap-2021.md
index fe8b080f56f..4406616bbb6 100644
--- a/src/tools/clippy/book/src/development/proposals/roadmap-2021.md
+++ b/src/tools/clippy/book/src/development/proposals/roadmap-2021.md
@@ -52,8 +52,8 @@ In the following, plans to improve the usability are covered.
 
 #### No Output After `cargo check`
 
-Currently when `cargo clippy` is run after `cargo check`, it does not produce
-any output. This is especially problematic since `rust-analyzer` is on the rise
+Currently, when `cargo clippy` is run after `cargo check`, it does not produce
+any output. This is especially problematic since `rust-analyzer` is on the rise,
 and it uses `cargo check` for checking code. A fix is already implemented, but
 it still has to be pushed over the finish line. This also includes the
 stabilization of the `cargo clippy --fix` command or the support of multi-span
@@ -221,7 +221,7 @@ regarding the user facing issues.
 
 Rust's roadmap process was established by [RFC 1728] in 2016. Since then every
 year a roadmap was published, that defined the bigger plans for the coming
-years. This years roadmap can be found [here][Rust Roadmap 2021].
+years. This year roadmap can be found [here][Rust Roadmap 2021].
 
 [RFC 1728]: https://rust-lang.github.io/rfcs/1728-north-star.html
 
diff --git a/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md b/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md
index ea4978011b1..36d722609f4 100644
--- a/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md
+++ b/src/tools/clippy/book/src/development/proposals/syntax-tree-patterns.md
@@ -16,7 +16,7 @@ lints. For non-trivial lints, it often requires nested pattern matching of AST /
 HIR nodes. For example, testing that an expression is a boolean literal requires
 the following checks:
 
-```rust
+```rust,ignore
 if let ast::ExprKind::Lit(lit) = &expr.node {
     if let ast::LitKind::Bool(_) = &lit.node {
         ...
@@ -28,7 +28,7 @@ Writing this kind of matching code quickly becomes a complex task and the
 resulting code is often hard to comprehend. The code below shows a simplified
 version of the pattern matching required by the `collapsible_if` lint:
 
-```rust
+```rust,ignore
 // simplified version of the collapsible_if lint
 if let ast::ExprKind::If(check, then, None) = &expr.node {
     if then.stmts.len() == 1 {
@@ -111,7 +111,7 @@ expressions that are boolean literals with value `false`.
 
 The pattern can then be used to implement lints in the following way:
 
-```rust
+```rust,ignore
 ...
 
 impl EarlyLintPass for MyAwesomeLint {
@@ -346,7 +346,7 @@ pattern!{
 one could get references to the nodes that matched the subpatterns in the
 following way:
 
-```rust
+```rust,ignore
 ...
 fn check_expr(expr: &syntax::ast::Expr) {
     if let Some(result) = my_pattern(expr) {
@@ -372,7 +372,7 @@ matches arrays that consist of any number of literal expressions. Because those
 expressions are named `foo`, the result struct contains a `foo` attribute which
 is a vector of expressions:
 
-```rust
+```rust,ignore
 ...
 if let Some(result) = my_pattern_seq(expr) {
     result.foo        // type: Vec<&syntax::ast::Expr>
@@ -394,7 +394,7 @@ In the pattern above, the `bar` name is only defined if the pattern matches a
 boolean literal. If it matches an integer literal, the name isn't set. To
 account for this, the result struct's `bar` attribute is an option type:
 
-```rust
+```rust,ignore
 ...
 if let Some(result) = my_pattern_alt(expr) {
     result.bar        // type: Option<&bool>
@@ -404,7 +404,7 @@ if let Some(result) = my_pattern_alt(expr) {
 It's also possible to use a name in multiple alternation branches if they have
 compatible types:
 
-```rust
+```rust,ignore
 pattern!{
     // matches if expression is a boolean or integer literal
     my_pattern_mult: Expr =
@@ -519,7 +519,7 @@ The `Alt`, `Seq` and `Opt` structs look like these:
 > Note: The current implementation can be found
 > [here](https://github.com/fkohlgrueber/pattern-matching/blob/dfb3bc9fbab69cec7c91e72564a63ebaa2ede638/pattern-match/src/matchers.rs#L35-L60).
 
-```rust
+```rust,ignore
 pub enum Alt<T> {
     Any,
     Elmt(Box<T>),
@@ -580,7 +580,7 @@ implementations is the `IsMatch` trait. It defines how to match *PatternTree*
 nodes against specific syntax tree nodes. A simplified implementation of the
 `IsMatch` trait is shown below:
 
-```rust
+```rust,ignore
 pub trait IsMatch<O> {
     fn is_match(&self, other: &'o O) -> bool;
 }
@@ -619,7 +619,7 @@ approach (matching against the coarse pattern first and checking for additional
 properties later) might be slower than the current practice of checking for
 structure and additional properties in one pass. For example, the following lint
 
-```rust
+```rust,ignore
 pattern!{
     pat_if_without_else: Expr =
         If(
@@ -644,7 +644,7 @@ first matches against the pattern and then checks that the `then` block doesn't
 start with a comment. Using clippy's current approach, it's possible to check
 for these conditions earlier:
 
-```rust
+```rust,ignore
 fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
     if_chain! {
         if let ast::ExprKind::If(ref check, ref then, None) = expr.node;
@@ -708,7 +708,7 @@ is similar to actual Rust syntax (probably like the `quote!` macro). For
 example, a pattern that matches `if` expressions that have `false` in their
 condition could look like this:
 
-```rust
+```rust,ignore
 if false {
     #[*]
 }
@@ -742,7 +742,7 @@ affects the structure of the resulting AST. `1 + 0 + 0` is parsed as `(1 + 0) +
 Another example of a problem would be named submatches. Take a look at this
 pattern:
 
-```rust
+```rust,ignore
 fn test() {
     1 #foo
 }
@@ -862,7 +862,7 @@ op b` and recommends changing it to `a op= b` requires that both occurrences of
 `a` are the same. Using `=#...` as syntax for backreferences, the lint could be
 implemented like this:
 
-```rust
+```rust,ignore
 pattern!{
     assign_op_pattern: Expr =
         Assign(_#target, Binary(_, =#target, _)
diff --git a/src/tools/clippy/book/src/development/type_checking.md b/src/tools/clippy/book/src/development/type_checking.md
new file mode 100644
index 00000000000..5ce434b99a1
--- /dev/null
+++ b/src/tools/clippy/book/src/development/type_checking.md
@@ -0,0 +1,144 @@
+# Type Checking
+
+When we work on a new lint or improve an existing lint, we might want
+to retrieve the type `Ty` of an expression `Expr` for a variety of
+reasons. This can be achieved by utilizing the [`LateContext`][LateContext]
+that is available for [`LateLintPass`][LateLintPass].
+
+## `LateContext` and `TypeckResults`
+
+The lint context [`LateContext`][LateContext] and [`TypeckResults`][TypeckResults]
+(returned by `LateContext::typeck_results`) are the two most useful data structures
+in `LateLintPass`. They allow us to jump to type definitions and other compilation
+stages such as HIR.
+
+> Note: `LateContext.typeck_results`'s return value is [`TypeckResults`][TypeckResults]
+> and is created in the type checking step, it includes useful information such as types of
+> expressions, ways to resolve methods and so on.
+
+`TypeckResults` contains useful methods such as [`expr_ty`][expr_ty],
+which gives us access to the underlying structure [`Ty`][Ty] of a given expression.
+
+```rust
+pub fn expr_ty(&self, expr: &Expr<'_>) -> Ty<'tcx>
+```
+
+As a side note, besides `expr_ty`, [`TypeckResults`][TypeckResults] contains a
+[`pat_ty()`][pat_ty] method that is useful for retrieving a type from a pattern.
+
+## `Ty`
+
+`Ty` struct contains the type information of an expression.
+Let's take a look at `rustc_middle`'s [`Ty`][Ty] struct to examine this struct:
+
+```rust
+pub struct Ty<'tcx>(Interned<'tcx, WithStableHash<TyS<'tcx>>>);
+```
+
+At a first glance, this struct looks quite esoteric. But at a closer look,
+we will see that this struct contains many useful methods for type checking.
+
+For instance, [`is_char`][is_char] checks if the given `Ty` struct corresponds
+to the primitive character type.
+
+### `is_*` Usage
+
+In some scenarios, all we need to do is check if the `Ty` of an expression
+is a specific type, such as `char` type, so we could write the following:
+
+```rust
+impl LateLintPass<'_> for MyStructLint {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        // Get type of `expr`
+        let ty = cx.typeck_results().expr_ty(expr);
+        
+        // Check if the `Ty` of this expression is of character type
+        if ty.is_char() {
+            println!("Our expression is a char!");
+        }
+    }
+}
+```
+
+Furthermore, if we examine the [source code][is_char_source] for `is_char`,
+we find something very interesting:
+
+```rust
+#[inline]
+pub fn is_char(self) -> bool {
+    matches!(self.kind(), Char)
+}
+```
+
+Indeed, we just discovered `Ty`'s [`kind` method][kind], which provides us
+with [`TyKind`][TyKind] of a `Ty`.
+
+## `TyKind`
+
+`TyKind` defines the kinds of types in Rust's type system.
+Peeking into [`TyKind` documentation][TyKind], we will see that it is an
+enum of 27 variants, including items such as `Bool`, `Int`, `Ref`, etc.
+
+### `kind` Usage
+
+The `TyKind` of `Ty` can be returned by calling [`Ty.kind` method][kind].
+We often use this method to perform pattern matching in Clippy.
+
+For instance, if we want to check for a `struct`, we could examine if the
+`ty.kind` corresponds to an [`Adt`][Adt] (algebraic data type) and if its
+[`AdtDef`][AdtDef] is a struct:
+
+```rust
+impl LateLintPass<'_> for MyStructLint {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        // Get type of `expr`
+        let ty = cx.typeck_results().expr_ty(expr);
+        // Match its kind to enter the type
+        match ty.kind {
+            ty::Adt(adt_def, _) if adt_def.is_struct() => println!("Our `expr` is a struct!"),
+            _ => ()
+        }
+    }
+}
+```
+
+## `hir::Ty` and `ty::Ty`
+
+We've been talking about [`ty::Ty`][middle_ty] this whole time without addressing [`hir::Ty`][hir_ty], but the latter
+is also important to understand.
+
+`hir::Ty` would represent *what* an user wrote, while `ty::Ty` would understand the meaning of it (because it has more
+information).
+
+**Example: `fn foo(x: u32) -> u32 { x }`**
+
+Here the HIR sees the types without "thinking" about them, it knows that the function takes an `u32` and returns
+an `u32`. But at the `ty::Ty` level the compiler understands that they're the same type, in-depth lifetimes, etc...
+
+you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function to convert from a `hir::Ty` to a `ty::Ty`
+
+## Useful Links
+
+Below are some useful links to further explore the concepts covered
+in this chapter:
+
+- [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation)
+- [Diagnostic items](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html)
+- [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
+[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
+[is_char]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.is_char
+[is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1831-1834
+[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
+[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
+[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
+[hir_ty_to_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir_analysis/fn.hir_ty_to_ty.html
diff --git a/src/tools/clippy/book/src/installation.md b/src/tools/clippy/book/src/installation.md
index cce888b17d4..d54fff9deba 100644
--- a/src/tools/clippy/book/src/installation.md
+++ b/src/tools/clippy/book/src/installation.md
@@ -17,8 +17,8 @@ $ rustup component add clippy [--toolchain=<name>]
 
 ## From Source
 
-Take a look at the [Basics] chapter in the Clippy developer guide to find step
-by step instructions on how to build and install Clippy from source.
+Take a look at the [Basics] chapter in the Clippy developer guide to find step-by-step
+instructions on how to build and install Clippy from source.
 
 [Basics]: development/basics.md#install-from-source
 [Usage]: usage.md
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 9ed6627b741..78e1a55cff3 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -54,6 +54,7 @@ Please use that command to update the file and do not edit it by hand.
 | [allow-mixed-uninlined-format-args](#allow-mixed-uninlined-format-args) | `true` |
 | [suppress-restriction-lint-in-const](#suppress-restriction-lint-in-const) | `false` |
 | [missing-docs-in-crate-items](#missing-docs-in-crate-items) | `false` |
+| [future-size-threshold](#future-size-threshold) | `16384` |
 
 ### arithmetic-side-effects-allowed
 Suppress checking of the passed type names in all types of operations.
@@ -130,6 +131,7 @@ Suppress lints whenever the suggested change would cause breakage for other crat
 * [option_option](https://rust-lang.github.io/rust-clippy/master/index.html#option_option)
 * [linkedlist](https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist)
 * [rc_mutex](https://rust-lang.github.io/rust-clippy/master/index.html#rc_mutex)
+* [unnecessary_box_returns](https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_box_returns)
 
 
 ### msrv
@@ -193,7 +195,7 @@ The maximum cognitive complexity a function can have
 ### disallowed-names
 The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
 `".."` can be used as part of the list to indicate, that the configured values should be appended to the
-default configuration of Clippy. By default any configuration will replace the default value.
+default configuration of Clippy. By default, any configuration will replace the default value.
 
 **Default Value:** `["foo", "baz", "quux"]` (`Vec<String>`)
 
@@ -203,7 +205,7 @@ default configuration of Clippy. By default any configuration will replace the d
 ### doc-valid-idents
 The list of words this lint should not consider as identifiers needing ticks. The value
 `".."` can be used as part of the list to indicate, that the configured values should be appended to the
-default configuration of Clippy. By default any configuraction will replace the default value. For example:
+default configuration of Clippy. By default, any configuration will replace the default value. For example:
 * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
 * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
 
@@ -413,7 +415,7 @@ For internal testing only, ignores the current `publish` settings in the Cargo m
 Enforce the named macros always use the braces specified.
 
 A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
-is could be used with a full path two `MacroMatcher`s have to be added one with the full path
+could be used with a full path two `MacroMatcher`s have to be added one with the full path
 `crate_name::macro_name` and one with just the macro name.
 
 **Default Value:** `[]` (`Vec<crate::nonstandard_macro_braces::MacroMatcher>`)
@@ -447,7 +449,7 @@ Whether to apply the raw pointer heuristic to determine if a type is `Send`.
 
 ### max-suggested-slice-pattern-length
 When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in
-the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed.
+the slice pattern that is suggested. If more elements are necessary, the lint is suppressed.
 For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
 
 **Default Value:** `3` (`u64`)
@@ -551,4 +553,12 @@ crate. For example, `pub(crate)` items.
 * [missing_docs_in_private_items](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items)
 
 
+### future-size-threshold
+The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
+
+**Default Value:** `16384` (`u64`)
+
+* [large_futures](https://rust-lang.github.io/rust-clippy/master/index.html#large_futures)
+
+
 
diff --git a/src/tools/clippy/book/src/lints.md b/src/tools/clippy/book/src/lints.md
index 35e30960b56..442dc63914e 100644
--- a/src/tools/clippy/book/src/lints.md
+++ b/src/tools/clippy/book/src/lints.md
@@ -17,7 +17,7 @@ The different lint groups were defined in the [Clippy 1.0 RFC].
 The `clippy::correctness` group is the only lint group in Clippy which lints are
 deny-by-default and abort the compilation when triggered. This is for good
 reason: If you see a `correctness` lint, it means that your code is outright
-wrong or useless and you should try to fix it.
+wrong or useless, and you should try to fix it.
 
 Lints in this category are carefully picked and should be free of false
 positives. So just `#[allow]`ing those lints is not recommended.
@@ -41,7 +41,7 @@ simplify your code. It mostly focuses on code that can be written in a shorter
 and more readable way, while preserving the semantics.
 
 If you should see a complexity lint, it usually means that you can remove or
-replace some code and it is recommended to do so. However, if you need the more
+replace some code, and it is recommended to do so. However, if you need the more
 complex code for some expressiveness reason, it is recommended to allow
 complexity lints on a case-by-case basis.
 
@@ -50,9 +50,9 @@ complexity lints on a case-by-case basis.
 The `clippy::perf` group gives you suggestions on how you can increase the
 performance of your code. Those lints are mostly about code that the compiler
 can't trivially optimize, but has to be written in a slightly different way to
-make the optimizer's job easier.
+make the optimizer job easier.
 
-Perf lints are usually easy to apply and it is recommended to do so.
+Perf lints are usually easy to apply, and it is recommended to do so.
 
 ## Style
 
@@ -91,7 +91,7 @@ and your use case.
 
 Lints from this group will restrict you in some way. If you enable a restriction
 lint for your crate it is recommended to also fix code that this lint triggers
-on. However, those lints are really strict by design and you might want to
+on. However, those lints are really strict by design, and you might want to
 `#[allow]` them in some special cases, with a comment justifying that.
 
 ## Cargo
diff --git a/src/tools/clippy/book/src/usage.md b/src/tools/clippy/book/src/usage.md
index 61a90445d75..32084a9199b 100644
--- a/src/tools/clippy/book/src/usage.md
+++ b/src/tools/clippy/book/src/usage.md
@@ -19,7 +19,7 @@ cargo clippy
 ### Lint configuration
 
 The above command will run the default set of lints, which are included in the
-lint group `clippy::all`. You might want to use even more lints or you might not
+lint group `clippy::all`. You might want to use even more lints, or you may not
 agree with every Clippy lint, and for that there are ways to configure lint
 levels.
 
@@ -98,7 +98,7 @@ other of Clippy's lint groups.
 You can configure lint levels in source code the same way you can configure
 `rustc` lints:
 
-```rust
+```rust,ignore
 #![allow(clippy::style)]
 
 #[warn(clippy::double_neg)]
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 8871873c661..3a8b070d735 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -1,3 +1,4 @@
+#![feature(lazy_cell)]
 #![feature(let_chains)]
 #![feature(rustc_private)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index 420214d9256..13a27703427 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -369,9 +369,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
                     }}
                     todo!();
                 }}
-           "#,
-            context_import = context_import,
-            name_upper = name_upper,
+           "#
         );
     } else {
         let _: fmt::Result = writedoc!(
@@ -385,9 +383,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
                 pub(super) fn check(cx: &{context_import}) {{
                     todo!();
                 }}
-           "#,
-            context_import = context_import,
-            name_upper = name_upper,
+           "#
         );
     }
 
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 779e4d0e1e3..95222a9acdf 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -537,17 +537,13 @@ fn declare_deprecated(name: &str, path: &Path, reason: &str) -> io::Result<()> {
             /// Nothing. This lint has been deprecated.
             ///
             /// ### Deprecation reason
-            /// {}
-            #[clippy::version = \"{}\"]
-            pub {},
-            \"{}\"
+            /// {deprecation_reason}
+            #[clippy::version = \"{version}\"]
+            pub {name},
+            \"{reason}\"
         }}
 
-        ",
-        deprecation_reason,
-        version,
-        name,
-        reason,
+        "
     )
 }
 
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 0b3846c1316..18e8bf77225 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -9,6 +9,7 @@ keywords = ["clippy", "lint", "plugin"]
 edition = "2021"
 
 [dependencies]
+arrayvec = { version = "0.7", default-features = false }
 cargo_metadata = "0.15.3"
 clippy_utils = { path = "../clippy_utils" }
 declare_clippy_lint = { path = "../declare_clippy_lint" }
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 29fde9336c0..455f0df7cd0 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -7,7 +7,7 @@ use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
 use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, Level};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map::Span;
@@ -430,23 +430,25 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
                 }
             }
             let nonminimal_bool_lint = |suggestions: Vec<_>| {
-                span_lint_hir_and_then(
-                    self.cx,
-                    NONMINIMAL_BOOL,
-                    e.hir_id,
-                    e.span,
-                    "this boolean expression can be simplified",
-                    |diag| {
-                        diag.span_suggestions(
-                            e.span,
-                            "try",
-                            suggestions.into_iter(),
-                            // nonminimal_bool can produce minimal but
-                            // not human readable expressions (#3141)
-                            Applicability::Unspecified,
-                        );
-                    },
-                );
+                if self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, e.hir_id).0 != Level::Allow {
+                    span_lint_hir_and_then(
+                        self.cx,
+                        NONMINIMAL_BOOL,
+                        e.hir_id,
+                        e.span,
+                        "this boolean expression can be simplified",
+                        |diag| {
+                            diag.span_suggestions(
+                                e.span,
+                                "try",
+                                suggestions.into_iter(),
+                                // nonminimal_bool can produce minimal but
+                                // not human readable expressions (#3141)
+                                Applicability::Unspecified,
+                            );
+                        },
+                    );
+                }
             };
             if improvements.is_empty() {
                 let mut visitor = NotSimplificationVisitor { cx: self.cx };
@@ -498,6 +500,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NotSimplificationVisitor<'a, 'tcx> {
         if let ExprKind::Unary(UnOp::Not, inner) = &expr.kind &&
             !inner.span.from_expansion() &&
             let Some(suggestion) = simplify_not(self.cx, inner)
+			&& self.cx.tcx.lint_level_at_node(NONMINIMAL_BOOL, expr.hir_id).0 != Level::Allow
         {
             span_lint_and_sugg(
                 self.cx,
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 823970e35ab..95c2ecbf791 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
@@ -2,8 +2,9 @@ use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
 use clippy_utils::expr_or_init;
 use clippy_utils::source::snippet;
+use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
-use rustc_errors::{Applicability, SuggestionStyle};
+use rustc_errors::{Applicability, Diagnostic, SuggestionStyle};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -163,19 +164,34 @@ pub(super) fn check(
         _ => return,
     };
 
-    let name_of_cast_from = snippet(cx, cast_expr.span, "..");
-    let cast_to_snip = snippet(cx, cast_to_span, "..");
-    let suggestion = format!("{cast_to_snip}::try_from({name_of_cast_from})");
-
     span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
         diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...");
-        diag.span_suggestion_with_style(
-            expr.span,
-            "... or use `try_from` and handle the error accordingly",
-            suggestion,
-            Applicability::Unspecified,
-            // always show the suggestion in a separate line
-            SuggestionStyle::ShowAlways,
-        );
+        if !cast_from.is_floating_point() {
+            offer_suggestion(cx, expr, cast_expr, cast_to_span, diag);
+        }
     });
 }
+
+fn offer_suggestion(
+    cx: &LateContext<'_>,
+    expr: &Expr<'_>,
+    cast_expr: &Expr<'_>,
+    cast_to_span: Span,
+    diag: &mut Diagnostic,
+) {
+    let cast_to_snip = snippet(cx, cast_to_span, "..");
+    let suggestion = if cast_to_snip == "_" {
+        format!("{}.try_into()", Sugg::hir(cx, cast_expr, "..").maybe_par())
+    } else {
+        format!("{cast_to_snip}::try_from({})", Sugg::hir(cx, cast_expr, ".."))
+    };
+
+    diag.span_suggestion_with_style(
+        expr.span,
+        "... or use `try_from` and handle the error accordingly",
+        suggestion,
+        Applicability::Unspecified,
+        // always show the suggestion in a separate line
+        SuggestionStyle::ShowAlways,
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
index 10f2bef268a..5e2eb5789f6 100644
--- a/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
+++ b/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs
@@ -1,9 +1,9 @@
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use clippy_utils::visitors::for_each_expr_with_closures;
 use clippy_utils::{get_enclosing_block, get_parent_node, path_to_local_id};
 use core::ops::ControlFlow;
-use rustc_hir::{Block, ExprKind, HirId, Local, Node, PatKind};
+use rustc_hir::{Block, ExprKind, HirId, LangItem, Local, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::sym;
@@ -44,7 +44,8 @@ declare_clippy_lint! {
 }
 declare_lint_pass!(CollectionIsNeverRead => [COLLECTION_IS_NEVER_READ]);
 
-static COLLECTIONS: [Symbol; 10] = [
+// Add `String` here when it is added to diagnostic items
+static COLLECTIONS: [Symbol; 9] = [
     sym::BTreeMap,
     sym::BTreeSet,
     sym::BinaryHeap,
@@ -52,7 +53,6 @@ static COLLECTIONS: [Symbol; 10] = [
     sym::HashSet,
     sym::LinkedList,
     sym::Option,
-    sym::String,
     sym::Vec,
     sym::VecDeque,
 ];
@@ -60,8 +60,7 @@ static COLLECTIONS: [Symbol; 10] = [
 impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
     fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx Local<'tcx>) {
         // Look for local variables whose type is a container. Search surrounding bock for read access.
-        let ty = cx.typeck_results().pat_ty(local.pat);
-        if COLLECTIONS.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym))
+        if match_acceptable_type(cx, local, &COLLECTIONS)
             && let PatKind::Binding(_, local_id, _, _) = local.pat.kind
             && let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id)
             && has_no_read_access(cx, local_id, enclosing_block)
@@ -71,6 +70,13 @@ impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
     }
 }
 
+fn match_acceptable_type(cx: &LateContext<'_>, local: &Local<'_>, collections: &[rustc_span::Symbol]) -> bool {
+    let ty = cx.typeck_results().pat_ty(local.pat);
+    collections.iter().any(|&sym| is_type_diagnostic_item(cx, ty, sym))
+    // String type is a lang item but not a diagnostic item for now so we need a separate check
+        || is_type_lang_item(cx, ty, LangItem::String)
+}
+
 fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Block<'tcx>) -> bool {
     let mut has_access = false;
     let mut has_read_access = false;
@@ -95,9 +101,9 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc
             return ControlFlow::Continue(());
         }
 
-        // Method call on `id` in a statement ignores any return value, so it's not a read access:
+        // Look for method call with receiver `id`. It might be a non-read access:
         //
-        // id.foo(...); // Not reading `id`.
+        // id.foo(args)
         //
         // Only assuming this for "official" methods defined on the type. For methods defined in extension
         // traits (identified as local, based on the orphan rule), pessimistically assume that they might
@@ -105,11 +111,24 @@ fn has_no_read_access<'tcx>(cx: &LateContext<'tcx>, id: HirId, block: &'tcx Bloc
         if let Some(Node::Expr(parent)) = get_parent_node(cx.tcx, expr.hir_id)
             && let ExprKind::MethodCall(_, receiver, _, _) = parent.kind
             && path_to_local_id(receiver, id)
-            && let Some(Node::Stmt(..)) = get_parent_node(cx.tcx, parent.hir_id)
             && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(parent.hir_id)
             && !method_def_id.is_local()
         {
-            return ControlFlow::Continue(());
+            // The method call is a statement, so the return value is not used. That's not a read access:
+            //
+            // id.foo(args);
+            if let Some(Node::Stmt(..)) = get_parent_node(cx.tcx, parent.hir_id) {
+                return ControlFlow::Continue(());
+            }
+
+            // The method call is not a statement, so its return value is used somehow but its type is the
+            // unit type, so this is not a real read access. Examples:
+            //
+            // let y = x.clear();
+            // println!("{:?}", x.clear());
+            if cx.typeck_results().expr_ty(parent).is_unit() {
+                return ControlFlow::Continue(());
+            }
         }
 
         // Any other access to `id` is a read access. Stop searching.
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 8ca91301472..f24dab62780 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -218,6 +218,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR_INFO,
     crate::large_const_arrays::LARGE_CONST_ARRAYS_INFO,
     crate::large_enum_variant::LARGE_ENUM_VARIANT_INFO,
+    crate::large_futures::LARGE_FUTURES_INFO,
     crate::large_include_file::LARGE_INCLUDE_FILE_INFO,
     crate::large_stack_arrays::LARGE_STACK_ARRAYS_INFO,
     crate::len_zero::COMPARISON_TO_EMPTY_INFO,
@@ -231,6 +232,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::let_with_type_underscore::LET_WITH_TYPE_UNDERSCORE_INFO,
     crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO,
     crate::lifetimes::NEEDLESS_LIFETIMES_INFO,
+    crate::lines_filter_map_ok::LINES_FILTER_MAP_OK_INFO,
     crate::literal_representation::DECIMAL_LITERAL_REPRESENTATION_INFO,
     crate::literal_representation::INCONSISTENT_DIGIT_GROUPING_INFO,
     crate::literal_representation::LARGE_DIGIT_GROUPS_INFO,
@@ -267,6 +269,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE_INFO,
     crate::manual_rem_euclid::MANUAL_REM_EUCLID_INFO,
     crate::manual_retain::MANUAL_RETAIN_INFO,
+    crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO,
     crate::manual_string_new::MANUAL_STRING_NEW_INFO,
     crate::manual_strip::MANUAL_STRIP_INFO,
     crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO,
@@ -307,6 +310,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS_INFO,
     crate::methods::CHARS_LAST_CMP_INFO,
     crate::methods::CHARS_NEXT_CMP_INFO,
+    crate::methods::CLEAR_WITH_DRAIN_INFO,
     crate::methods::CLONED_INSTEAD_OF_COPIED_INFO,
     crate::methods::CLONE_DOUBLE_REF_INFO,
     crate::methods::CLONE_ON_COPY_INFO,
@@ -565,6 +569,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::strings::STR_TO_STRING_INFO,
     crate::strings::TRIM_SPLIT_WHITESPACE_INFO,
     crate::strlen_on_c_strings::STRLEN_ON_C_STRINGS_INFO,
+    crate::suspicious_doc_comments::SUSPICIOUS_DOC_COMMENTS_INFO,
     crate::suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS_INFO,
     crate::suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL_INFO,
     crate::suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL_INFO,
@@ -574,6 +579,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::swap_ptr_to_ref::SWAP_PTR_TO_REF_INFO,
     crate::tabs_in_doc_comments::TABS_IN_DOC_COMMENTS_INFO,
     crate::temporary_assignment::TEMPORARY_ASSIGNMENT_INFO,
+    crate::tests_outside_test_module::TESTS_OUTSIDE_TEST_MODULE_INFO,
     crate::to_digit_is_some::TO_DIGIT_IS_SOME_INFO,
     crate::trailing_empty_array::TRAILING_EMPTY_ARRAY_INFO,
     crate::trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS_INFO,
@@ -616,6 +622,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::unit_types::UNIT_CMP_INFO,
     crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
     crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO,
+    crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO,
     crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
     crate::unnecessary_self_imports::UNNECESSARY_SELF_IMPORTS_INFO,
     crate::unnecessary_struct_initialization::UNNECESSARY_STRUCT_INITIALIZATION_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
index 084190f0013..c9fad98e437 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
@@ -32,7 +32,7 @@ declare_clippy_lint! {
     /// ### Example
     /// ```rust
     /// // Assuming that `clippy.toml` contains the following line:
-    /// // allowed-locales = ["Latin", "Cyrillic"]
+    /// // allowed-scripts = ["Latin", "Cyrillic"]
     /// let counter = 10; // OK, latin is allowed.
     /// let счётчик = 10; // OK, cyrillic is allowed.
     /// let zähler = 10; // OK, it's still latin.
diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs
index c0ea6f338a2..315df6c714f 100644
--- a/src/tools/clippy/clippy_lints/src/explicit_write.rs
+++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::FormatArgsExpn;
+use clippy_utils::macros::{find_format_args, format_args_inputs_span};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_expn_of, match_function_call, paths};
 use if_chain::if_chain;
@@ -8,7 +8,7 @@ use rustc_hir::def::Res;
 use rustc_hir::{BindingAnnotation, Block, BlockCheckMode, Expr, ExprKind, Node, PatKind, QPath, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
+use rustc_span::{sym, ExpnId};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -43,23 +43,22 @@ declare_lint_pass!(ExplicitWrite => [EXPLICIT_WRITE]);
 
 impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        if_chain! {
-            // match call to unwrap
-            if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind;
-            if unwrap_fun.ident.name == sym::unwrap;
+        // match call to unwrap
+        if let ExprKind::MethodCall(unwrap_fun, write_call, [], _) = expr.kind
+            && unwrap_fun.ident.name == sym::unwrap
             // match call to write_fmt
-            if let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind);
-            if write_fun.ident.name == sym!(write_fmt);
+            && let ExprKind::MethodCall(write_fun, write_recv, [write_arg], _) = look_in_block(cx, &write_call.kind)
+            && write_fun.ident.name == sym!(write_fmt)
             // match calls to std::io::stdout() / std::io::stderr ()
-            if let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
+            && let Some(dest_name) = if match_function_call(cx, write_recv, &paths::STDOUT).is_some() {
                 Some("stdout")
             } else if match_function_call(cx, write_recv, &paths::STDERR).is_some() {
                 Some("stderr")
             } else {
                 None
-            };
-            if let Some(format_args) = FormatArgsExpn::parse(cx, write_arg);
-            then {
+            }
+        {
+            find_format_args(cx, write_arg, ExpnId::root(), |format_args| {
                 let calling_macro =
                     // ordering is important here, since `writeln!` uses `write!` internally
                     if is_expn_of(write_call.span, "writeln").is_some() {
@@ -92,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                 let mut applicability = Applicability::MachineApplicable;
                 let inputs_snippet = snippet_with_applicability(
                     cx,
-                    format_args.inputs_span(),
+                    format_args_inputs_span(format_args),
                     "..",
                     &mut applicability,
                 );
@@ -104,8 +103,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
                     "try this",
                     format!("{prefix}{sugg_mac}!({inputs_snippet})"),
                     applicability,
-                )
-            }
+                );
+            });
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
index 20565e1d232..eeb4de8b58f 100644
--- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -1,10 +1,10 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
 use clippy_utils::trait_ref_of_method;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::MultiSpan;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_impl_item, walk_item, walk_param_bound, walk_ty, Visitor};
 use rustc_hir::{
-    BodyId, ExprKind, GenericBound, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind,
+    BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind,
     PredicateOrigin, Ty, TyKind, WherePredicate,
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -53,13 +53,19 @@ impl ExtraUnusedTypeParameters {
         }
     }
 
-    /// Don't lint external macros or functions with empty bodies. Also, don't lint public items if
-    /// the `avoid_breaking_exported_api` config option is set.
-    fn check_false_positive(&self, cx: &LateContext<'_>, span: Span, def_id: LocalDefId, body_id: BodyId) -> bool {
+    /// Don't lint external macros or functions with empty bodies. Also, don't lint exported items
+    /// if the `avoid_breaking_exported_api` config option is set.
+    fn is_empty_exported_or_macro(
+        &self,
+        cx: &LateContext<'_>,
+        span: Span,
+        def_id: LocalDefId,
+        body_id: BodyId,
+    ) -> bool {
         let body = cx.tcx.hir().body(body_id).value;
         let fn_empty = matches!(&body.kind, ExprKind::Block(blk, None) if blk.stmts.is_empty() && blk.expr.is_none());
         let is_exported = cx.effective_visibilities.is_exported(def_id);
-        in_external_macro(cx.sess(), span) || (self.avoid_breaking_exported_api && is_exported) || fn_empty
+        in_external_macro(cx.sess(), span) || fn_empty || (is_exported && self.avoid_breaking_exported_api)
     }
 }
 
@@ -69,85 +75,129 @@ impl_lint_pass!(ExtraUnusedTypeParameters => [EXTRA_UNUSED_TYPE_PARAMETERS]);
 /// trait bounds those parameters have.
 struct TypeWalker<'cx, 'tcx> {
     cx: &'cx LateContext<'tcx>,
-    /// Collection of all the function's type parameters.
+    /// Collection of the function's type parameters. Once the function has been walked, this will
+    /// contain only unused type parameters.
     ty_params: FxHashMap<DefId, Span>,
-    /// Collection of any (inline) trait bounds corresponding to each type parameter.
-    bounds: FxHashMap<DefId, Span>,
+    /// Collection of any inline trait bounds corresponding to each type parameter.
+    inline_bounds: FxHashMap<DefId, Span>,
+    /// Collection of any type parameters with trait bounds that appear in a where clause.
+    where_bounds: FxHashSet<DefId>,
     /// The entire `Generics` object of the function, useful for querying purposes.
     generics: &'tcx Generics<'tcx>,
-    /// The value of this will remain `true` if *every* parameter:
-    ///   1. Is a type parameter, and
-    ///   2. Goes unused in the function.
-    /// Otherwise, if any type parameters end up being used, or if any lifetime or const-generic
-    /// parameters are present, this will be set to `false`.
-    all_params_unused: bool,
 }
 
 impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
     fn new(cx: &'cx LateContext<'tcx>, generics: &'tcx Generics<'tcx>) -> Self {
-        let mut all_params_unused = true;
         let ty_params = generics
             .params
             .iter()
-            .filter_map(|param| {
-                if let GenericParamKind::Type { synthetic, .. } = param.kind {
-                    (!synthetic).then_some((param.def_id.into(), param.span))
-                } else {
-                    if !param.is_elided_lifetime() {
-                        all_params_unused = false;
-                    }
-                    None
-                }
+            .filter_map(|param| match param.kind {
+                GenericParamKind::Type { synthetic, .. } if !synthetic => Some((param.def_id.into(), param.span)),
+                _ => None,
             })
             .collect();
 
         Self {
             cx,
             ty_params,
-            bounds: FxHashMap::default(),
+            inline_bounds: FxHashMap::default(),
+            where_bounds: FxHashSet::default(),
             generics,
-            all_params_unused,
         }
     }
 
-    fn mark_param_used(&mut self, def_id: DefId) {
-        if self.ty_params.remove(&def_id).is_some() {
-            self.all_params_unused = false;
-        }
+    fn get_bound_span(&self, param: &'tcx GenericParam<'tcx>) -> Span {
+        self.inline_bounds
+            .get(&param.def_id.to_def_id())
+            .map_or(param.span, |bound_span| param.span.with_hi(bound_span.hi()))
+    }
+
+    fn emit_help(&self, spans: Vec<Span>, msg: &str, help: &'static str) {
+        span_lint_and_help(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, None, help);
+    }
+
+    fn emit_sugg(&self, spans: Vec<Span>, msg: &str, help: &'static str) {
+        let suggestions: Vec<(Span, String)> = spans.iter().copied().zip(std::iter::repeat(String::new())).collect();
+        span_lint_and_then(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, spans, msg, |diag| {
+            diag.multipart_suggestion(help, suggestions, Applicability::MachineApplicable);
+        });
     }
 
     fn emit_lint(&self) {
-        let (msg, help) = match self.ty_params.len() {
+        let explicit_params = self
+            .generics
+            .params
+            .iter()
+            .filter(|param| !param.is_elided_lifetime() && !param.is_impl_trait())
+            .collect::<Vec<_>>();
+
+        let extra_params = explicit_params
+            .iter()
+            .enumerate()
+            .filter(|(_, param)| self.ty_params.contains_key(&param.def_id.to_def_id()))
+            .collect::<Vec<_>>();
+
+        let (msg, help) = match extra_params.len() {
             0 => return,
             1 => (
-                "type parameter goes unused in function definition",
+                format!(
+                    "type parameter `{}` goes unused in function definition",
+                    extra_params[0].1.name.ident()
+                ),
                 "consider removing the parameter",
             ),
             _ => (
-                "type parameters go unused in function definition",
+                format!(
+                    "type parameters go unused in function definition: {}",
+                    extra_params
+                        .iter()
+                        .map(|(_, param)| param.name.ident().to_string())
+                        .collect::<Vec<_>>()
+                        .join(", ")
+                ),
                 "consider removing the parameters",
             ),
         };
 
-        let source_map = self.cx.sess().source_map();
-        let span = if self.all_params_unused {
-            self.generics.span.into() // Remove the entire list of generics
+        // If any parameters are bounded in where clauses, don't try to form a suggestion.
+        // Otherwise, the leftover where bound would produce code that wouldn't compile.
+        if extra_params
+            .iter()
+            .any(|(_, param)| self.where_bounds.contains(&param.def_id.to_def_id()))
+        {
+            let spans = extra_params
+                .iter()
+                .map(|(_, param)| self.get_bound_span(param))
+                .collect::<Vec<_>>();
+            self.emit_help(spans, &msg, help);
         } else {
-            MultiSpan::from_spans(
-                self.ty_params
+            let spans = if explicit_params.len() == extra_params.len() {
+                vec![self.generics.span] // Remove the entire list of generics
+            } else {
+                let mut end: Option<LocalDefId> = None;
+                extra_params
                     .iter()
-                    .map(|(def_id, &span)| {
-                        // Extend the span past any trait bounds, and include the comma at the end.
-                        let span_to_extend = self.bounds.get(def_id).copied().map_or(span, Span::shrink_to_hi);
-                        let comma_range = source_map.span_extend_to_next_char(span_to_extend, '>', false);
-                        let comma_span = source_map.span_through_char(comma_range, ',');
-                        span.with_hi(comma_span.hi())
+                    .rev()
+                    .map(|(idx, param)| {
+                        if let Some(next) = explicit_params.get(idx + 1) && end != Some(next.def_id) {
+                        // Extend the current span forward, up until the next param in the list.
+                        param.span.until(next.span)
+                    } else {
+                        // Extend the current span back to include the comma following the previous
+                        // param. If the span of the next param in the list has already been
+                        // extended, we continue the chain. This is why we're iterating in reverse.
+                        end = Some(param.def_id);
+
+                        // idx will never be 0, else we'd be removing the entire list of generics
+                        let prev = explicit_params[idx - 1];
+                        let prev_span = self.get_bound_span(prev);
+                        self.get_bound_span(param).with_lo(prev_span.hi())
+                    }
                     })
-                    .collect(),
-            )
+                    .collect()
+            };
+            self.emit_sugg(spans, &msg, help);
         };
-
-        span_lint_and_help(self.cx, EXTRA_UNUSED_TYPE_PARAMETERS, span, msg, None, help);
     }
 }
 
@@ -162,7 +212,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
 
     fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) {
         if let Some((def_id, _)) = t.peel_refs().as_generic_param() {
-            self.mark_param_used(def_id);
+            self.ty_params.remove(&def_id);
         } else if let TyKind::OpaqueDef(id, _, _) = t.kind {
             // Explicitly walk OpaqueDef. Normally `walk_ty` would do the job, but it calls
             // `visit_nested_item`, which checks that `Self::NestedFilter::INTER` is set. We're
@@ -176,9 +226,18 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
 
     fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) {
         if let WherePredicate::BoundPredicate(predicate) = predicate {
-            // Collect spans for any bounds on type parameters. We only keep bounds that appear in
-            // the list of generics (not in a where-clause).
+            // Collect spans for any bounds on type parameters.
             if let Some((def_id, _)) = predicate.bounded_ty.peel_refs().as_generic_param() {
+                match predicate.origin {
+                    PredicateOrigin::GenericParam => {
+                        self.inline_bounds.insert(def_id, predicate.span);
+                    },
+                    PredicateOrigin::WhereClause => {
+                        self.where_bounds.insert(def_id);
+                    },
+                    PredicateOrigin::ImplTrait => (),
+                }
+
                 // If the bound contains non-public traits, err on the safe side and don't lint the
                 // corresponding parameter.
                 if !predicate
@@ -187,12 +246,10 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
                     .filter_map(bound_to_trait_def_id)
                     .all(|id| self.cx.effective_visibilities.is_exported(id))
                 {
-                    self.mark_param_used(def_id);
-                } else if let PredicateOrigin::GenericParam = predicate.origin {
-                    self.bounds.insert(def_id, predicate.span);
+                    self.ty_params.remove(&def_id);
                 }
             }
-            // Only walk the right-hand side of where-bounds
+            // Only walk the right-hand side of where bounds
             for bound in predicate.bounds {
                 walk_param_bound(self, bound);
             }
@@ -207,7 +264,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
 impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
         if let ItemKind::Fn(_, generics, body_id) = item.kind
-            && !self.check_false_positive(cx, item.span, item.owner_id.def_id, body_id)
+            && !self.is_empty_exported_or_macro(cx, item.span, item.owner_id.def_id, body_id)
         {
             let mut walker = TypeWalker::new(cx, generics);
             walk_item(&mut walker, item);
@@ -219,7 +276,7 @@ impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
         // Only lint on inherent methods, not trait methods.
         if let ImplItemKind::Fn(.., body_id) = item.kind
             && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
-            && !self.check_false_positive(cx, item.span, item.owner_id.def_id, body_id)
+            && !self.is_empty_exported_or_macro(cx, item.span, item.owner_id.def_id, body_id)
         {
             let mut walker = TypeWalker::new(cx, item.generics);
             walk_impl_item(&mut walker, item);
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index 8040938c626..d34d6e9279e 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -1,14 +1,13 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn};
-use clippy_utils::source::snippet_with_context;
+use clippy_utils::macros::{find_format_arg_expr, find_format_args, root_macro_call_first_node};
+use clippy_utils::source::{snippet_opt, snippet_with_context};
 use clippy_utils::sugg::Sugg;
-use if_chain::if_chain;
+use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::symbol::kw;
 use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
@@ -44,55 +43,53 @@ declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);
 
 impl<'tcx> LateLintPass<'tcx> for UselessFormat {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        let (format_args, call_site) = if_chain! {
-            if let Some(macro_call) = root_macro_call_first_node(cx, expr);
-            if cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id);
-            if let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, macro_call.expn);
-            then {
-                (format_args, macro_call.span)
-            } else {
-                return
-            }
-        };
+        let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return };
+        if !cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) {
+            return;
+        }
+
+        find_format_args(cx, expr, macro_call.expn, |format_args| {
+            let mut applicability = Applicability::MachineApplicable;
+            let call_site = macro_call.span;
 
-        let mut applicability = Applicability::MachineApplicable;
-        if format_args.args.is_empty() {
-            match *format_args.format_string.parts {
-                [] => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability),
-                [_] => {
+            match (format_args.arguments.all_args(), &format_args.template[..]) {
+                ([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability),
+                ([], [_]) => {
                     // Simulate macro expansion, converting {{ and }} to { and }.
-                    let s_expand = format_args.format_string.snippet.replace("{{", "{").replace("}}", "}");
+                    let Some(snippet) = snippet_opt(cx, format_args.span) else { return };
+                    let s_expand = snippet.replace("{{", "{").replace("}}", "}");
                     let sugg = format!("{s_expand}.to_string()");
                     span_useless_format(cx, call_site, sugg, applicability);
                 },
-                [..] => {},
-            }
-        } else if let [arg] = &*format_args.args {
-            let value = arg.param.value;
-            if_chain! {
-                if format_args.format_string.parts == [kw::Empty];
-                if arg.format.is_default();
-                if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
-                    ty::Adt(adt, _) => Some(adt.did()) == cx.tcx.lang_items().string(),
-                    ty::Str => true,
-                    _ => false,
-                };
-                then {
-                    let is_new_string = match value.kind {
-                        ExprKind::Binary(..) => true,
-                        ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string,
-                        _ => false,
-                    };
-                    let sugg = if is_new_string {
-                        snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability).0.into_owned()
-                    } else {
-                        let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "<arg>", &mut applicability);
-                        format!("{}.to_string()", sugg.maybe_par())
-                    };
-                    span_useless_format(cx, call_site, sugg, applicability);
-                }
+                ([arg], [piece]) => {
+                    if let Ok(value) = find_format_arg_expr(expr, arg)
+                        && let FormatArgsPiece::Placeholder(placeholder) = piece
+                        && placeholder.format_trait == FormatTrait::Display
+                        && placeholder.format_options == FormatOptions::default()
+                        && match cx.typeck_results().expr_ty(value).peel_refs().kind() {
+                            ty::Adt(adt, _) => Some(adt.did()) == cx.tcx.lang_items().string(),
+                            ty::Str => true,
+                            _ => false,
+                        }
+                    {
+                        let is_new_string = match value.kind {
+                            ExprKind::Binary(..) => true,
+                            ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string,
+                            _ => false,
+                        };
+                        let sugg = if is_new_string {
+                            snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability).0.into_owned()
+                        } else {
+                            let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "<arg>", &mut applicability);
+                            format!("{}.to_string()", sugg.maybe_par())
+                        };
+                        span_useless_format(cx, call_site, sugg, applicability);
+
+                    }
+                },
+                _ => {},
             }
-        };
+        });
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index c511d85e9cf..08e45ed7d0e 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -1,27 +1,31 @@
+use arrayvec::ArrayVec;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::is_diag_trait_item;
-use clippy_utils::macros::FormatParamKind::{Implicit, Named, NamedInline, Numbered, Starred};
 use clippy_utils::macros::{
-    is_assert_macro, is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam,
-    FormatParamUsage,
+    find_format_arg_expr, find_format_args, format_arg_removal_span, format_placeholder_format_span, is_assert_macro,
+    is_format_macro, is_panic, root_macro_call, root_macro_call_first_node, FormatParamUsage,
 };
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{implements_trait, is_type_lang_item};
 use if_chain::if_chain;
 use itertools::Itertools;
+use rustc_ast::{
+    FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions,
+    FormatPlaceholder, FormatTrait,
+};
 use rustc_errors::{
     Applicability,
     SuggestionStyle::{CompletelyHidden, ShowCode},
 };
-use rustc_hir::{Expr, ExprKind, HirId, LangItem, QPath};
+use rustc_hir::{Expr, ExprKind, LangItem};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment};
 use rustc_middle::ty::Ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::DefId;
 use rustc_span::edition::Edition::Edition2021;
-use rustc_span::{sym, ExpnData, ExpnKind, Span, Symbol};
+use rustc_span::{sym, Span, Symbol};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -184,72 +188,79 @@ impl FormatArgs {
 
 impl<'tcx> LateLintPass<'tcx> for FormatArgs {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        if let Some(format_args) = FormatArgsExpn::parse(cx, expr)
-            && let expr_expn_data = expr.span.ctxt().outer_expn_data()
-            && let outermost_expn_data = outermost_expn_data(expr_expn_data)
-            && let Some(macro_def_id) = outermost_expn_data.macro_def_id
-            && is_format_macro(cx, macro_def_id)
-            && let ExpnKind::Macro(_, name) = outermost_expn_data.kind
-        {
-            for arg in &format_args.args {
-                check_unused_format_specifier(cx, arg);
-                if !arg.format.is_default() {
-                    continue;
-                }
-                if is_aliased(&format_args, arg.param.value.hir_id) {
-                    continue;
+        let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return };
+        if !is_format_macro(cx, macro_call.def_id) {
+            return;
+        }
+        let name = cx.tcx.item_name(macro_call.def_id);
+
+        find_format_args(cx, expr, macro_call.expn, |format_args| {
+            for piece in &format_args.template {
+                if let FormatArgsPiece::Placeholder(placeholder) = piece
+                    && let Ok(index) = placeholder.argument.index
+                    && let Some(arg) = format_args.arguments.all_args().get(index)
+                {
+                    let arg_expr = find_format_arg_expr(expr, arg);
+
+                    check_unused_format_specifier(cx, placeholder, arg_expr);
+
+                    if placeholder.format_trait != FormatTrait::Display
+                        || placeholder.format_options != FormatOptions::default()
+                        || is_aliased(format_args, index)
+                    {
+                        continue;
+                    }
+
+                    if let Ok(arg_hir_expr) = arg_expr {
+                        check_format_in_format_args(cx, macro_call.span, name, arg_hir_expr);
+                        check_to_string_in_format_args(cx, name, arg_hir_expr);
+                    }
                 }
-                check_format_in_format_args(cx, outermost_expn_data.call_site, name, arg.param.value);
-                check_to_string_in_format_args(cx, name, arg.param.value);
             }
+
             if self.msrv.meets(msrvs::FORMAT_ARGS_CAPTURE) {
-                check_uninlined_args(cx, &format_args, outermost_expn_data.call_site, macro_def_id, self.ignore_mixed);
+                check_uninlined_args(cx, format_args, macro_call.span, macro_call.def_id, self.ignore_mixed);
             }
-        }
+        });
     }
 
     extract_msrv_attr!(LateContext);
 }
 
-fn check_unused_format_specifier(cx: &LateContext<'_>, arg: &FormatArg<'_>) {
-    let param_ty = cx.typeck_results().expr_ty(arg.param.value).peel_refs();
+fn check_unused_format_specifier(
+    cx: &LateContext<'_>,
+    placeholder: &FormatPlaceholder,
+    arg_expr: Result<&Expr<'_>, &rustc_ast::Expr>,
+) {
+    let ty_or_ast_expr = arg_expr.map(|expr| cx.typeck_results().expr_ty(expr).peel_refs());
 
-    if let Count::Implied(Some(mut span)) = arg.format.precision
-        && !span.is_empty()
-    {
-        span_lint_and_then(
-            cx,
-            UNUSED_FORMAT_SPECS,
-            span,
-            "empty precision specifier has no effect",
-            |diag| {
-                if param_ty.is_floating_point() {
-                    diag.note("a precision specifier is not required to format floats");
-                }
+    let is_format_args = match ty_or_ast_expr {
+        Ok(ty) => is_type_lang_item(cx, ty, LangItem::FormatArguments),
+        Err(expr) => matches!(expr.peel_parens_and_refs().kind, rustc_ast::ExprKind::FormatArgs(_)),
+    };
 
-                if arg.format.is_default() {
-                    // If there's no other specifiers remove the `:` too
-                    span = arg.format_span();
-                }
+    let options = &placeholder.format_options;
 
-                diag.span_suggestion_verbose(span, "remove the `.`", "", Applicability::MachineApplicable);
-            },
-        );
-    }
+    let arg_span = match arg_expr {
+        Ok(expr) => expr.span,
+        Err(expr) => expr.span,
+    };
 
-    if is_type_lang_item(cx, param_ty, LangItem::FormatArguments) && !arg.format.is_default_for_trait() {
+    if let Some(placeholder_span) = placeholder.span
+        && is_format_args
+        && *options != FormatOptions::default()
+    {
         span_lint_and_then(
             cx,
             UNUSED_FORMAT_SPECS,
-            arg.span,
+            placeholder_span,
             "format specifiers have no effect on `format_args!()`",
             |diag| {
-                let mut suggest_format = |spec, span| {
+                let mut suggest_format = |spec| {
                     let message = format!("for the {spec} to apply consider using `format!()`");
 
-                    if let Some(mac_call) = root_macro_call(arg.param.value.span)
+                    if let Some(mac_call) = root_macro_call(arg_span)
                         && cx.tcx.is_diagnostic_item(sym::format_args_macro, mac_call.def_id)
-                        && arg.span.eq_ctxt(mac_call.span)
                     {
                         diag.span_suggestion(
                             cx.sess().source_map().span_until_char(mac_call.span, '!'),
@@ -257,25 +268,27 @@ fn check_unused_format_specifier(cx: &LateContext<'_>, arg: &FormatArg<'_>) {
                             "format",
                             Applicability::MaybeIncorrect,
                         );
-                    } else if let Some(span) = span {
-                        diag.span_help(span, message);
+                    } else {
+                        diag.help(message);
                     }
                 };
 
-                if !arg.format.width.is_implied() {
-                    suggest_format("width", arg.format.width.span());
+                if options.width.is_some() {
+                    suggest_format("width");
                 }
 
-                if !arg.format.precision.is_implied() {
-                    suggest_format("precision", arg.format.precision.span());
+                if options.precision.is_some() {
+                    suggest_format("precision");
                 }
 
-                diag.span_suggestion_verbose(
-                    arg.format_span(),
-                    "if the current behavior is intentional, remove the format specifiers",
-                    "",
-                    Applicability::MaybeIncorrect,
-                );
+                if let Some(format_span) = format_placeholder_format_span(placeholder) {
+                    diag.span_suggestion_verbose(
+                        format_span,
+                        "if the current behavior is intentional, remove the format specifiers",
+                        "",
+                        Applicability::MaybeIncorrect,
+                    );
+                }
             },
         );
     }
@@ -283,12 +296,12 @@ fn check_unused_format_specifier(cx: &LateContext<'_>, arg: &FormatArg<'_>) {
 
 fn check_uninlined_args(
     cx: &LateContext<'_>,
-    args: &FormatArgsExpn<'_>,
+    args: &rustc_ast::FormatArgs,
     call_site: Span,
     def_id: DefId,
     ignore_mixed: bool,
 ) {
-    if args.format_string.span.from_expansion() {
+    if args.span.from_expansion() {
         return;
     }
     if call_site.edition() < Edition2021 && (is_panic(cx, def_id) || is_assert_macro(cx, def_id)) {
@@ -303,7 +316,13 @@ fn check_uninlined_args(
     // we cannot remove any other arguments in the format string,
     // because the index numbers might be wrong after inlining.
     // Example of an un-inlinable format:  print!("{}{1}", foo, 2)
-    if !args.params().all(|p| check_one_arg(args, &p, &mut fixes, ignore_mixed)) || fixes.is_empty() {
+    for (pos, usage) in format_arg_positions(args) {
+        if !check_one_arg(args, pos, usage, &mut fixes, ignore_mixed) {
+            return;
+        }
+    }
+
+    if fixes.is_empty() {
         return;
     }
 
@@ -332,47 +351,40 @@ fn check_uninlined_args(
 }
 
 fn check_one_arg(
-    args: &FormatArgsExpn<'_>,
-    param: &FormatParam<'_>,
+    args: &rustc_ast::FormatArgs,
+    pos: &FormatArgPosition,
+    usage: FormatParamUsage,
     fixes: &mut Vec<(Span, String)>,
     ignore_mixed: bool,
 ) -> bool {
-    if matches!(param.kind, Implicit | Starred | Named(_) | Numbered)
-        && let ExprKind::Path(QPath::Resolved(None, path)) = param.value.kind
-        && let [segment] = path.segments
+    let index = pos.index.unwrap();
+    let arg = &args.arguments.all_args()[index];
+
+    if !matches!(arg.kind, FormatArgumentKind::Captured(_))
+        && let rustc_ast::ExprKind::Path(None, path) = &arg.expr.kind
+        && let [segment] = path.segments.as_slice()
         && segment.args.is_none()
-        && let Some(arg_span) = args.value_with_prev_comma_span(param.value.hir_id)
+        && let Some(arg_span) = format_arg_removal_span(args, index)
+        && let Some(pos_span) = pos.span
     {
-        let replacement = match param.usage {
+        let replacement = match usage {
             FormatParamUsage::Argument => segment.ident.name.to_string(),
             FormatParamUsage::Width => format!("{}$", segment.ident.name),
             FormatParamUsage::Precision => format!(".{}$", segment.ident.name),
         };
-        fixes.push((param.span, replacement));
+        fixes.push((pos_span, replacement));
         fixes.push((arg_span, String::new()));
         true  // successful inlining, continue checking
     } else {
         // Do not continue inlining (return false) in case
         // * if we can't inline a numbered argument, e.g. `print!("{0} ...", foo.bar, ...)`
         // * if allow_mixed_uninlined_format_args is false and this arg hasn't been inlined already
-        param.kind != Numbered && (!ignore_mixed || matches!(param.kind, NamedInline(_)))
-    }
-}
-
-fn outermost_expn_data(expn_data: ExpnData) -> ExpnData {
-    if expn_data.call_site.from_expansion() {
-        outermost_expn_data(expn_data.call_site.ctxt().outer_expn_data())
-    } else {
-        expn_data
+        pos.kind != FormatArgPositionKind::Number
+            && (!ignore_mixed || matches!(arg.kind, FormatArgumentKind::Captured(_)))
     }
 }
 
-fn check_format_in_format_args(
-    cx: &LateContext<'_>,
-    call_site: Span,
-    name: Symbol,
-    arg: &Expr<'_>,
-) {
+fn check_format_in_format_args(cx: &LateContext<'_>, call_site: Span, name: Symbol, arg: &Expr<'_>) {
     let expn_data = arg.span.ctxt().outer_expn_data();
     if expn_data.call_site.from_expansion() {
         return;
@@ -443,9 +455,33 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
     }
 }
 
-/// Returns true if `hir_id` is referred to by multiple format params
-fn is_aliased(args: &FormatArgsExpn<'_>, hir_id: HirId) -> bool {
-    args.params().filter(|param| param.value.hir_id == hir_id).at_most_one().is_err()
+fn format_arg_positions(
+    format_args: &rustc_ast::FormatArgs,
+) -> impl Iterator<Item = (&FormatArgPosition, FormatParamUsage)> {
+    format_args.template.iter().flat_map(|piece| match piece {
+        FormatArgsPiece::Placeholder(placeholder) => {
+            let mut positions = ArrayVec::<_, 3>::new();
+
+            positions.push((&placeholder.argument, FormatParamUsage::Argument));
+            if let Some(FormatCount::Argument(position)) = &placeholder.format_options.width {
+                positions.push((position, FormatParamUsage::Width));
+            }
+            if let Some(FormatCount::Argument(position)) = &placeholder.format_options.precision {
+                positions.push((position, FormatParamUsage::Precision));
+            }
+
+            positions
+        },
+        FormatArgsPiece::Literal(_) => ArrayVec::new(),
+    })
+}
+
+/// Returns true if the format argument at `index` is referred to by multiple format params
+fn is_aliased(format_args: &rustc_ast::FormatArgs, index: usize) -> bool {
+    format_arg_positions(format_args)
+        .filter(|(position, _)| position.index == Ok(index))
+        .at_most_one()
+        .is_err()
 }
 
 fn count_needed_derefs<'tcx, I>(mut ty: Ty<'tcx>, mut iter: I) -> (usize, Ty<'tcx>)
@@ -455,7 +491,11 @@ where
     let mut n_total = 0;
     let mut n_needed = 0;
     loop {
-        if let Some(Adjustment { kind: Adjust::Deref(overloaded_deref), target }) = iter.next() {
+        if let Some(Adjustment {
+            kind: Adjust::Deref(overloaded_deref),
+            target,
+        }) = iter.next()
+        {
             n_total += 1;
             if overloaded_deref.is_some() {
                 n_needed = n_total;
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index ed1342a5465..e3ddbfb5981 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -1,11 +1,13 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
-use clippy_utils::macros::{is_format_macro, root_macro_call_first_node, FormatArg, FormatArgsExpn};
+use clippy_utils::macros::{find_format_arg_expr, find_format_args, is_format_macro, root_macro_call_first_node};
 use clippy_utils::{get_parent_as_impl, is_diag_trait_item, path_to_local, peel_ref_operators};
 use if_chain::if_chain;
+use rustc_ast::{FormatArgsPiece, FormatTrait};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Impl, ImplItem, ImplItemKind, QPath};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Span;
 use rustc_span::{sym, symbol::kw, Symbol};
 
 declare_clippy_lint! {
@@ -89,7 +91,7 @@ declare_clippy_lint! {
 }
 
 #[derive(Clone, Copy)]
-struct FormatTrait {
+struct FormatTraitNames {
     /// e.g. `sym::Display`
     name: Symbol,
     /// `f` in `fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {}`
@@ -99,7 +101,7 @@ struct FormatTrait {
 #[derive(Default)]
 pub struct FormatImpl {
     // Whether we are inside Display or Debug trait impl - None for neither
-    format_trait_impl: Option<FormatTrait>,
+    format_trait_impl: Option<FormatTraitNames>,
 }
 
 impl FormatImpl {
@@ -161,43 +163,57 @@ fn check_to_string_in_display(cx: &LateContext<'_>, expr: &Expr<'_>) {
     }
 }
 
-fn check_self_in_format_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, impl_trait: FormatTrait) {
+fn check_self_in_format_args<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, impl_trait: FormatTraitNames) {
     // Check each arg in format calls - do we ever use Display on self (directly or via deref)?
-    if_chain! {
-        if let Some(outer_macro) = root_macro_call_first_node(cx, expr);
-        if let macro_def_id = outer_macro.def_id;
-        if let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, outer_macro.expn);
-        if is_format_macro(cx, macro_def_id);
-        then {
-            for arg in format_args.args {
-                if arg.format.r#trait != impl_trait.name {
-                    continue;
+    if let Some(outer_macro) = root_macro_call_first_node(cx, expr)
+        && let macro_def_id = outer_macro.def_id
+        && is_format_macro(cx, macro_def_id)
+    {
+        find_format_args(cx, expr, outer_macro.expn, |format_args| {
+            for piece in &format_args.template {
+                if let FormatArgsPiece::Placeholder(placeholder) = piece
+                    && let trait_name = match placeholder.format_trait {
+                        FormatTrait::Display => sym::Display,
+                        FormatTrait::Debug => sym::Debug,
+                        FormatTrait::LowerExp => sym!(LowerExp),
+                        FormatTrait::UpperExp => sym!(UpperExp),
+                        FormatTrait::Octal => sym!(Octal),
+                        FormatTrait::Pointer => sym::Pointer,
+                        FormatTrait::Binary => sym!(Binary),
+                        FormatTrait::LowerHex => sym!(LowerHex),
+                        FormatTrait::UpperHex => sym!(UpperHex),
+                    }
+                    && trait_name == impl_trait.name
+                    && let Ok(index) = placeholder.argument.index
+                    && let Some(arg) = format_args.arguments.all_args().get(index)
+                    && let Ok(arg_expr) = find_format_arg_expr(expr, arg)
+                {
+                    check_format_arg_self(cx, expr.span, arg_expr, impl_trait);
                 }
-                check_format_arg_self(cx, expr, &arg, impl_trait);
             }
-        }
+        });
     }
 }
 
-fn check_format_arg_self(cx: &LateContext<'_>, expr: &Expr<'_>, arg: &FormatArg<'_>, impl_trait: FormatTrait) {
+fn check_format_arg_self(cx: &LateContext<'_>, span: Span, arg: &Expr<'_>, impl_trait: FormatTraitNames) {
     // Handle multiple dereferencing of references e.g. &&self
     // Handle dereference of &self -> self that is equivalent (i.e. via *self in fmt() impl)
     // Since the argument to fmt is itself a reference: &self
-    let reference = peel_ref_operators(cx, arg.param.value);
+    let reference = peel_ref_operators(cx, arg);
     let map = cx.tcx.hir();
     // Is the reference self?
     if path_to_local(reference).map(|x| map.name(x)) == Some(kw::SelfLower) {
-        let FormatTrait { name, .. } = impl_trait;
+        let FormatTraitNames { name, .. } = impl_trait;
         span_lint(
             cx,
             RECURSIVE_FORMAT_IMPL,
-            expr.span,
+            span,
             &format!("using `self` as `{name}` in `impl {name}` will cause infinite recursion"),
         );
     }
 }
 
-fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: FormatTrait) {
+fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait: FormatTraitNames) {
     if_chain! {
         if let Some(macro_call) = root_macro_call_first_node(cx, expr);
         if let Some(name) = cx.tcx.get_diagnostic_name(macro_call.def_id);
@@ -227,7 +243,7 @@ fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait:
     }
 }
 
-fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option<FormatTrait> {
+fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Option<FormatTraitNames> {
     if_chain! {
         if impl_item.ident.name == sym::fmt;
         if let ImplItemKind::Fn(_, body_id) = impl_item.kind;
@@ -241,7 +257,7 @@ fn is_format_trait_impl(cx: &LateContext<'_>, impl_item: &ImplItem<'_>) -> Optio
                 .and_then(|param| param.pat.simple_ident())
                 .map(|ident| ident.name);
 
-            Some(FormatTrait {
+            Some(FormatTraitNames {
                 name,
                 formatter_name,
             })
diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
index 1e9e826631c..d0ad2628264 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -1,7 +1,9 @@
+use hir::FnSig;
 use rustc_ast::ast::Attribute;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefIdSet;
 use rustc_hir::{self as hir, def::Res, QPath};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::{
     lint::in_external_macro,
@@ -27,7 +29,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
         let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id);
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
         if let Some(attr) = attr {
-            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
+            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, sig);
         } else if is_public && !is_proc_macro(attrs) && !attrs.iter().any(|a| a.has_name(sym::no_mangle)) {
             check_must_use_candidate(
                 cx,
@@ -49,7 +51,7 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
         let attrs = cx.tcx.hir().attrs(item.hir_id());
         let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
         if let Some(attr) = attr {
-            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
+            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, sig);
         } else if is_public && !is_proc_macro(attrs) && trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
             check_must_use_candidate(
                 cx,
@@ -72,7 +74,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
         let attrs = cx.tcx.hir().attrs(item.hir_id());
         let attr = cx.tcx.get_attr(item.owner_id, sym::must_use);
         if let Some(attr) = attr {
-            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr);
+            check_needless_must_use(cx, sig.decl, item.owner_id, item.span, fn_header_span, attr, sig);
         } else if let hir::TraitFn::Provided(eid) = *eid {
             let body = cx.tcx.hir().body(eid);
             if attr.is_none() && is_public && !is_proc_macro(attrs) {
@@ -97,6 +99,7 @@ fn check_needless_must_use(
     item_span: Span,
     fn_header_span: Span,
     attr: &Attribute,
+    sig: &FnSig<'_>,
 ) {
     if in_external_macro(cx.sess(), item_span) {
         return;
@@ -112,6 +115,15 @@ fn check_needless_must_use(
             },
         );
     } else if attr.value_str().is_none() && is_must_use_ty(cx, return_ty(cx, item_id)) {
+        // Ignore async functions unless Future::Output type is a must_use type
+        if sig.header.is_async() {
+            let infcx = cx.tcx.infer_ctxt().build();
+            if let Some(future_ty) = infcx.get_impl_future_output_ty(return_ty(cx, item_id))
+			&& !is_must_use_ty(cx, future_ty) {
+				return;
+			}
+        }
+
         span_lint_and_help(
             cx,
             DOUBLE_MUST_USE,
diff --git a/src/tools/clippy/clippy_lints/src/items_after_statements.rs b/src/tools/clippy/clippy_lints/src/items_after_statements.rs
index 46d439b4497..a7ec57e2850 100644
--- a/src/tools/clippy/clippy_lints/src/items_after_statements.rs
+++ b/src/tools/clippy/clippy_lints/src/items_after_statements.rs
@@ -1,8 +1,8 @@
 //! lint when items are used after statements
 
-use clippy_utils::diagnostics::span_lint;
-use rustc_ast::ast::{Block, ItemKind, StmtKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use clippy_utils::diagnostics::span_lint_hir;
+use rustc_hir::{Block, ItemKind, StmtKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -52,33 +52,34 @@ declare_clippy_lint! {
 
 declare_lint_pass!(ItemsAfterStatements => [ITEMS_AFTER_STATEMENTS]);
 
-impl EarlyLintPass for ItemsAfterStatements {
-    fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
-        if in_external_macro(cx.sess(), item.span) {
+impl LateLintPass<'_> for ItemsAfterStatements {
+    fn check_block(&mut self, cx: &LateContext<'_>, block: &Block<'_>) {
+        if in_external_macro(cx.sess(), block.span) {
             return;
         }
 
-        // skip initial items and trailing semicolons
-        let stmts = item
+        // skip initial items
+        let stmts = block
             .stmts
             .iter()
-            .map(|stmt| &stmt.kind)
-            .skip_while(|s| matches!(**s, StmtKind::Item(..) | StmtKind::Empty));
+            .skip_while(|stmt| matches!(stmt.kind, StmtKind::Item(..)));
 
         // lint on all further items
         for stmt in stmts {
-            if let StmtKind::Item(ref it) = *stmt {
-                if in_external_macro(cx.sess(), it.span) {
+            if let StmtKind::Item(item_id) = stmt.kind {
+                let item = cx.tcx.hir().item(item_id);
+                if in_external_macro(cx.sess(), item.span) || !item.span.eq_ctxt(block.span) {
                     return;
                 }
-                if let ItemKind::MacroDef(..) = it.kind {
+                if let ItemKind::Macro(..) = item.kind {
                     // do not lint `macro_rules`, but continue processing further statements
                     continue;
                 }
-                span_lint(
+                span_lint_hir(
                     cx,
                     ITEMS_AFTER_STATEMENTS,
-                    it.span,
+                    item.hir_id(),
+                    item.span,
                     "adding items after statements is confusing, since items exist from the \
                      start of the scope",
                 );
diff --git a/src/tools/clippy/clippy_lints/src/large_futures.rs b/src/tools/clippy/clippy_lints/src/large_futures.rs
new file mode 100644
index 00000000000..1b054481371
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/large_futures.rs
@@ -0,0 +1,87 @@
+use clippy_utils::source::snippet;
+use clippy_utils::{diagnostics::span_lint_and_sugg, ty::implements_trait};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, LangItem, MatchSource, QPath};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_target::abi::Size;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// It checks for the size of a `Future` created by `async fn` or `async {}`.
+    ///
+    /// ### Why is this bad?
+    /// Due to the current [unideal implemention](https://github.com/rust-lang/rust/issues/69826) of `Generator`,
+    /// large size of a `Future` may cause stack overflows.
+    ///
+    /// ### Example
+    /// ```rust
+    /// async fn wait(f: impl std::future::Future<Output = ()>) {}
+    ///
+    /// async fn big_fut(arg: [u8; 1024]) {}
+    ///
+    /// pub async fn test() {
+    ///     let fut = big_fut([0u8; 1024]);
+    ///     wait(fut).await;
+    /// }
+    /// ```
+    ///
+    /// `Box::pin` the big future instead.
+    ///
+    /// ```rust
+    /// async fn wait(f: impl std::future::Future<Output = ()>) {}
+    ///
+    /// async fn big_fut(arg: [u8; 1024]) {}
+    ///
+    /// pub async fn test() {
+    ///     let fut = Box::pin(big_fut([0u8; 1024]));
+    ///     wait(fut).await;
+    /// }
+    /// ```
+    #[clippy::version = "1.68.0"]
+    pub LARGE_FUTURES,
+    pedantic,
+    "large future may lead to unexpected stack overflows"
+}
+
+#[derive(Copy, Clone)]
+pub struct LargeFuture {
+    future_size_threshold: u64,
+}
+
+impl LargeFuture {
+    pub fn new(future_size_threshold: u64) -> Self {
+        Self { future_size_threshold }
+    }
+}
+
+impl_lint_pass!(LargeFuture => [LARGE_FUTURES]);
+
+impl<'tcx> LateLintPass<'tcx> for LargeFuture {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        if matches!(expr.span.ctxt().outer_expn_data().kind, rustc_span::ExpnKind::Macro(..)) {
+            return;
+        }
+        if let ExprKind::Match(expr, _, MatchSource::AwaitDesugar) = expr.kind {
+            if let ExprKind::Call(func, [expr, ..]) = expr.kind
+                && let ExprKind::Path(QPath::LangItem(LangItem::IntoFutureIntoFuture, ..)) = func.kind
+                && let ty = cx.typeck_results().expr_ty(expr)
+                && let Some(future_trait_def_id) = cx.tcx.lang_items().future_trait()
+                && implements_trait(cx, ty, future_trait_def_id, &[])
+                && let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty))
+                && let size = layout.layout.size()
+                && size >= Size::from_bytes(self.future_size_threshold)
+            {
+                span_lint_and_sugg(
+                    cx,
+                    LARGE_FUTURES,
+                    expr.span,
+                    &format!("large future with a size of {} bytes", size.bytes()),
+                    "consider `Box::pin` on it",
+                    format!("Box::pin({})", snippet(cx, expr.span, "..")),
+                    Applicability::Unspecified,
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 3da7f95c1b9..b0ec14855e7 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -1,7 +1,6 @@
 #![feature(array_windows)]
 #![feature(binary_heap_into_iter_sorted)]
 #![feature(box_patterns)]
-#![feature(drain_filter)]
 #![feature(if_let_guard)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
@@ -162,6 +161,7 @@ mod items_after_statements;
 mod iter_not_returning_iterator;
 mod large_const_arrays;
 mod large_enum_variant;
+mod large_futures;
 mod large_include_file;
 mod large_stack_arrays;
 mod len_zero;
@@ -169,6 +169,7 @@ mod let_if_seq;
 mod let_underscore;
 mod let_with_type_underscore;
 mod lifetimes;
+mod lines_filter_map_ok;
 mod literal_representation;
 mod loops;
 mod macro_use;
@@ -183,6 +184,7 @@ mod manual_main_separator_str;
 mod manual_non_exhaustive;
 mod manual_rem_euclid;
 mod manual_retain;
+mod manual_slice_size_calculation;
 mod manual_string_new;
 mod manual_strip;
 mod map_unit_fn;
@@ -281,6 +283,7 @@ mod slow_vector_initialization;
 mod std_instead_of_core;
 mod strings;
 mod strlen_on_c_strings;
+mod suspicious_doc_comments;
 mod suspicious_operation_groupings;
 mod suspicious_trait_impl;
 mod suspicious_xor_used_as_pow;
@@ -288,6 +291,7 @@ mod swap;
 mod swap_ptr_to_ref;
 mod tabs_in_doc_comments;
 mod temporary_assignment;
+mod tests_outside_test_module;
 mod to_digit_is_some;
 mod trailing_empty_array;
 mod trait_bounds;
@@ -299,6 +303,7 @@ mod uninit_vec;
 mod unit_return_expecting_ord;
 mod unit_types;
 mod unnamed_address;
+mod unnecessary_box_returns;
 mod unnecessary_owned_empty_strings;
 mod unnecessary_self_imports;
 mod unnecessary_struct_initialization;
@@ -344,13 +349,17 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se
 }
 
 #[doc(hidden)]
-pub fn read_conf(sess: &Session, path: &io::Result<Option<PathBuf>>) -> Conf {
+pub fn read_conf(sess: &Session, path: &io::Result<(Option<PathBuf>, Vec<String>)>) -> Conf {
+    if let Ok((_, warnings)) = path {
+        for warning in warnings {
+            sess.warn(warning);
+        }
+    }
     let file_name = match path {
-        Ok(Some(path)) => path,
-        Ok(None) => return Conf::default(),
+        Ok((Some(path), _)) => path,
+        Ok((None, _)) => return Conf::default(),
         Err(error) => {
-            sess.struct_err(format!("error finding Clippy's configuration file: {error}"))
-                .emit();
+            sess.err(format!("error finding Clippy's configuration file: {error}"));
             return Conf::default();
         },
     };
@@ -746,7 +755,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_early_pass(|| Box::new(unused_unit::UnusedUnit));
     store.register_late_pass(|_| Box::new(returns::Return));
     store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf));
-    store.register_early_pass(|| Box::new(items_after_statements::ItemsAfterStatements));
+    store.register_late_pass(|_| Box::new(items_after_statements::ItemsAfterStatements));
     store.register_early_pass(|| Box::new(precedence::Precedence));
     store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals));
     store.register_early_pass(|| Box::new(needless_continue::NeedlessContinue));
@@ -808,6 +817,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv())));
     store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
     store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));
+    let future_size_threshold = conf.future_size_threshold;
+    store.register_late_pass(move |_| Box::new(large_futures::LargeFuture::new(future_size_threshold)));
     store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex));
     store.register_late_pass(|_| Box::new(if_not_else::IfNotElse));
     store.register_late_pass(|_| Box::new(equatable_if_let::PatternEquality));
@@ -934,11 +945,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(no_mangle_with_rust_abi::NoMangleWithRustAbi));
     store.register_late_pass(|_| Box::new(collection_is_never_read::CollectionIsNeverRead));
     store.register_late_pass(|_| Box::new(missing_assert_message::MissingAssertMessage));
-    store.register_early_pass(|| Box::new(redundant_async_block::RedundantAsyncBlock));
+    store.register_late_pass(|_| Box::new(redundant_async_block::RedundantAsyncBlock));
     store.register_late_pass(|_| Box::new(let_with_type_underscore::UnderscoreTyped));
     store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
     store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
     store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct));
+    store.register_late_pass(move |_| {
+        Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new(
+            avoid_breaking_exported_api,
+        ))
+    });
+    store.register_late_pass(|_| Box::new(lines_filter_map_ok::LinesFilterMapOk));
+    store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule));
+    store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
+    store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments));
     // 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
new file mode 100644
index 00000000000..b0f9276475d
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
@@ -0,0 +1,100 @@
+use clippy_utils::{
+    diagnostics::span_lint_and_then, is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths,
+    ty::match_type,
+};
+use rustc_errors::Applicability;
+use rustc_hir::{Body, Closure, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detect uses of `lines.filter_map(Result::ok)` or `lines.flat_map(Result::ok)`
+    /// when `lines` has type `std::io::Lines`.
+    ///
+    /// ### Why is this bad?
+    /// `Lines` instances might produce a never-ending stream of `Err`, in which case
+    /// `filter_map(Result::ok)` will enter an infinite loop while waiting for an
+    /// `Ok` variant. Calling `next()` once is sufficient to enter the infinite loop,
+    /// even in the absence of explicit loops in the user code.
+    ///
+    /// This situation can arise when working with user-provided paths. On some platforms,
+    /// `std::fs::File::open(path)` might return `Ok(fs)` even when `path` is a directory,
+    /// but any later attempt to read from `fs` will return an error.
+    ///
+    /// ### 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
+    /// appropriate or necessary:
+    ///
+    /// - If the `Lines` instance can never produce any error, or if an error is produced
+    ///   only once just before terminating the iterator, using `map_while()` is not
+    ///   necessary but will not do any harm.
+    /// - If the `Lines` instance can produce intermittent errors then recover and produce
+    ///   successful results, using `map_while()` would stop at the first error.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use std::{fs::File, io::{self, BufRead, BufReader}};
+    /// # let _ = || -> io::Result<()> {
+    /// let mut lines = BufReader::new(File::open("some-path")?).lines().filter_map(Result::ok);
+    /// // If "some-path" points to a directory, the next statement never terminates:
+    /// let first_line: Option<String> = lines.next();
+    /// # Ok(()) };
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # use std::{fs::File, io::{self, BufRead, BufReader}};
+    /// # let _ = || -> io::Result<()> {
+    /// let mut lines = BufReader::new(File::open("some-path")?).lines().map_while(Result::ok);
+    /// let first_line: Option<String> = lines.next();
+    /// # Ok(()) };
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub LINES_FILTER_MAP_OK,
+    suspicious,
+    "filtering `std::io::Lines` with `filter_map()` or `flat_map()` might cause an infinite loop"
+}
+declare_lint_pass!(LinesFilterMapOk => [LINES_FILTER_MAP_OK]);
+
+impl LateLintPass<'_> for LinesFilterMapOk {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if let ExprKind::MethodCall(fm_method, fm_receiver, [fm_arg], fm_span) = expr.kind &&
+            is_trait_method(cx, expr, sym::Iterator) &&
+            (fm_method.ident.as_str() == "filter_map" || fm_method.ident.as_str() == "flat_map") &&
+            match_type(cx, cx.typeck_results().expr_ty_adjusted(fm_receiver), &paths::STD_IO_LINES)
+        {
+            let lint = match &fm_arg.kind {
+                // Detect `Result::ok`
+                ExprKind::Path(qpath) =>
+                    cx.qpath_res(qpath, fm_arg.hir_id).opt_def_id().map(|did|
+                        match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)).unwrap_or_default(),
+                // Detect `|x| x.ok()`
+                ExprKind::Closure(Closure { body, .. }) =>
+                    if let Body { params: [param], value, .. } = cx.tcx.hir().body(*body) &&
+                        let ExprKind::MethodCall(method, receiver, [], _) = value.kind &&
+                        path_to_local_id(receiver, param.pat.hir_id) &&
+                        let Some(method_did) = cx.typeck_results().type_dependent_def_id(value.hir_id)
+                    {
+                        is_diag_item_method(cx, method_did, sym::Result) && method.ident.as_str() == "ok"
+                    } else {
+                        false
+                    }
+                _ => false,
+            };
+            if lint {
+                span_lint_and_then(cx,
+                    LINES_FILTER_MAP_OK,
+                    fm_span,
+                    &format!("`{}()` will run forever if the iterator repeatedly produces an `Err`", fm_method.ident),
+                    |diag| {
+                        diag.span_note(
+                            fm_receiver.span,
+                            "this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error");
+                        diag.span_suggestion(fm_span, "replace with", "map_while(Result::ok)", Applicability::MaybeIncorrect);
+                    });
+                }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs b/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs
new file mode 100644
index 00000000000..92ee79453a3
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_slice_size_calculation.rs
@@ -0,0 +1,93 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::{expr_or_init, in_constant};
+use rustc_hir::{BinOpKind, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::sym;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// When `a` is `&[T]`, detect `a.len() * size_of::<T>()` and suggest `size_of_val(a)`
+    /// instead.
+    ///
+    /// ### Why is this better?
+    /// * Shorter to write
+    /// * Removes the need for the human and the compiler to worry about overflow in the
+    ///   multiplication
+    /// * Potentially faster at runtime as rust emits special no-wrapping flags when it
+    ///   calculates the byte length
+    /// * Less turbofishing
+    ///
+    /// ### Example
+    /// ```rust
+    /// # let data : &[i32] = &[1, 2, 3];
+    /// let newlen = data.len() * std::mem::size_of::<i32>();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # let data : &[i32] = &[1, 2, 3];
+    /// let newlen = std::mem::size_of_val(data);
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub MANUAL_SLICE_SIZE_CALCULATION,
+    complexity,
+    "manual slice size calculation"
+}
+declare_lint_pass!(ManualSliceSizeCalculation => [MANUAL_SLICE_SIZE_CALCULATION]);
+
+impl<'tcx> LateLintPass<'tcx> for ManualSliceSizeCalculation {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        // Does not apply inside const because size_of_value is not cost in stable.
+        if !in_constant(cx, expr.hir_id)
+            && let ExprKind::Binary(ref op, left, right) = expr.kind
+            && BinOpKind::Mul == op.node
+            && let Some(_receiver) = simplify(cx, left, right)
+        {
+            span_lint_and_help(
+                cx,
+                MANUAL_SLICE_SIZE_CALCULATION,
+                expr.span,
+                "manual slice size calculation",
+                None,
+                "consider using std::mem::size_of_value instead");
+        }
+    }
+}
+
+fn simplify<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr1: &'tcx Expr<'tcx>,
+    expr2: &'tcx Expr<'tcx>,
+) -> Option<&'tcx Expr<'tcx>> {
+    let expr1 = expr_or_init(cx, expr1);
+    let expr2 = expr_or_init(cx, expr2);
+
+    simplify_half(cx, expr1, expr2).or_else(|| simplify_half(cx, expr2, expr1))
+}
+
+fn simplify_half<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr1: &'tcx Expr<'tcx>,
+    expr2: &'tcx Expr<'tcx>,
+) -> Option<&'tcx Expr<'tcx>> {
+    if
+        // expr1 is `[T1].len()`?
+        let ExprKind::MethodCall(method_path, receiver, _, _) = expr1.kind
+        && method_path.ident.name == sym::len
+        && let receiver_ty = cx.typeck_results().expr_ty(receiver)
+        && let ty::Slice(ty1) = receiver_ty.peel_refs().kind()
+        // expr2 is `size_of::<T2>()`?
+        && let ExprKind::Call(func, _) = expr2.kind
+        && let ExprKind::Path(ref func_qpath) = func.kind
+        && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
+        && cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id)
+        && let Some(ty2) = cx.typeck_results().node_substs(func.hir_id).types().next()
+        // T1 == T2?
+        && *ty1 == ty2
+    {
+        Some(receiver)
+    } else {
+        None
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index 35024ec1224..8a921d4af16 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -1,12 +1,13 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_non_aggregate_primitive_type;
-use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res};
+use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
-use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath};
+use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -101,40 +102,26 @@ declare_clippy_lint! {
 impl_lint_pass!(MemReplace =>
     [MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]);
 
-fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
-    // Check that second argument is `Option::None`
-    if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
-        // Since this is a late pass (already type-checked),
-        // and we already know that the second argument is an
-        // `Option`, we do not need to check the first
-        // argument's type. All that's left is to get
-        // replacee's path.
-        let replaced_path = match dest.kind {
-            ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => {
-                if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind {
-                    replaced_path
-                } else {
-                    return;
-                }
-            },
-            ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path,
-            _ => return,
-        };
-
-        let mut applicability = Applicability::MachineApplicable;
-        span_lint_and_sugg(
-            cx,
-            MEM_REPLACE_OPTION_WITH_NONE,
-            expr_span,
-            "replacing an `Option` with `None`",
-            "consider `Option::take()` instead",
-            format!(
-                "{}.take()",
-                snippet_with_applicability(cx, replaced_path.span, "", &mut applicability)
-            ),
-            applicability,
-        );
-    }
+fn check_replace_option_with_none(cx: &LateContext<'_>, dest: &Expr<'_>, expr_span: Span) {
+    // Since this is a late pass (already type-checked),
+    // and we already know that the second argument is an
+    // `Option`, we do not need to check the first
+    // argument's type. All that's left is to get
+    // the replacee's expr after peeling off the `&mut`
+    let sugg_expr = peel_ref_operators(cx, dest);
+    let mut applicability = Applicability::MachineApplicable;
+    span_lint_and_sugg(
+        cx,
+        MEM_REPLACE_OPTION_WITH_NONE,
+        expr_span,
+        "replacing an `Option` with `None`",
+        "consider `Option::take()` instead",
+        format!(
+            "{}.take()",
+            Sugg::hir_with_context(cx, sugg_expr, expr_span.ctxt(), "", &mut applicability).maybe_par()
+        ),
+        applicability,
+    );
 }
 
 fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
@@ -200,10 +187,6 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
     if is_non_aggregate_primitive_type(expr_type) {
         return;
     }
-    // disable lint for Option since it is covered in another lint
-    if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
-        return;
-    }
     if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) {
         span_lint_and_then(
             cx,
@@ -246,11 +229,13 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace {
             if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
             if cx.tcx.is_diagnostic_item(sym::mem_replace, def_id);
             then {
-                check_replace_option_with_none(cx, src, dest, expr.span);
-                check_replace_with_uninit(cx, src, dest, expr.span);
-                if self.msrv.meets(msrvs::MEM_TAKE) {
+                // Check that second argument is `Option::None`
+                if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
+                    check_replace_option_with_none(cx, dest, expr.span);
+                } else if self.msrv.meets(msrvs::MEM_TAKE) {
                     check_replace_with_default(cx, src, dest, expr.span);
                 }
+                check_replace_with_uninit(cx, src, dest, expr.span);
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/clear_with_drain.rs b/src/tools/clippy/clippy_lints/src/methods/clear_with_drain.rs
new file mode 100644
index 00000000000..67ad58d5a8c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/clear_with_drain.rs
@@ -0,0 +1,53 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_range_full;
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::{Expr, ExprKind, LangItem, QPath};
+use rustc_lint::LateContext;
+use rustc_span::symbol::sym;
+use rustc_span::Span;
+
+use super::CLEAR_WITH_DRAIN;
+
+// Add `String` here when it is added to diagnostic items
+const ACCEPTABLE_TYPES_WITH_ARG: [rustc_span::Symbol; 2] = [sym::Vec, sym::VecDeque];
+
+const ACCEPTABLE_TYPES_WITHOUT_ARG: [rustc_span::Symbol; 3] = [sym::BinaryHeap, sym::HashMap, sym::HashSet];
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, arg: Option<&Expr<'_>>) {
+    if let Some(arg) = arg {
+        if match_acceptable_type(cx, recv, &ACCEPTABLE_TYPES_WITH_ARG)
+            && let ExprKind::Path(QPath::Resolved(None, container_path)) = recv.kind
+            && is_range_full(cx, arg, Some(container_path))
+        {
+            suggest(cx, expr, recv, span);
+        }
+    } else if match_acceptable_type(cx, recv, &ACCEPTABLE_TYPES_WITHOUT_ARG) {
+        suggest(cx, expr, recv, span);
+    }
+}
+
+fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, types: &[rustc_span::Symbol]) -> bool {
+    let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
+    types.iter().any(|&ty| is_type_diagnostic_item(cx, expr_ty, ty))
+    // String type is a lang item but not a diagnostic item for now so we need a separate check
+        || is_type_lang_item(cx, expr_ty, LangItem::String)
+}
+
+fn suggest(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span) {
+    if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def()
+    // Use `opt_item_name` while `String` is not a diagnostic item
+        && let Some(ty_name) = cx.tcx.opt_item_name(adt.did())
+    {
+        span_lint_and_sugg(
+            cx,
+            CLEAR_WITH_DRAIN,
+            span.with_hi(expr.span.hi()),
+            &format!("`drain` used to clear a `{ty_name}`"),
+            "try",
+            "clear()".to_string(),
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
index a22285058d4..92d21bb8932 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn};
+use clippy_utils::macros::{find_format_args, format_args_inputs_span, root_macro_call_first_node};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
 use rustc_errors::Applicability;
@@ -136,18 +136,19 @@ pub(super) fn check<'tcx>(
         if !cx.tcx.is_diagnostic_item(sym::format_macro, macro_call.def_id) {
             return;
         }
-        let Some(format_args) = FormatArgsExpn::find_nested(cx, arg_root, macro_call.expn) else { return };
-        let span = format_args.inputs_span();
-        let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
-        span_lint_and_sugg(
-            cx,
-            EXPECT_FUN_CALL,
-            span_replace_word,
-            &format!("use of `{name}` followed by a function call"),
-            "try this",
-            format!("unwrap_or_else({closure_args} panic!({sugg}))"),
-            applicability,
-        );
+        find_format_args(cx, arg_root, macro_call.expn, |format_args| {
+            let span = format_args_inputs_span(format_args);
+            let sugg = snippet_with_applicability(cx, span, "..", &mut applicability);
+            span_lint_and_sugg(
+                cx,
+                EXPECT_FUN_CALL,
+                span_replace_word,
+                &format!("use of `{name}` followed by a function call"),
+                "try this",
+                format!("unwrap_or_else({closure_args} panic!({sugg}))"),
+                applicability,
+            );
+        });
         return;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs b/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
index 3da230e12d7..f6772c5c6b3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
@@ -1,7 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::higher::Range;
-use clippy_utils::is_integer_const;
-use rustc_ast::ast::RangeLimits;
+use clippy_utils::is_range_full;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, QPath};
 use rustc_lint::LateContext;
@@ -15,8 +13,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span
         && let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def()
         && let Some(ty_name) = cx.tcx.get_diagnostic_name(adt.did())
         && matches!(ty_name, sym::Vec | sym::VecDeque)
-        && let Some(range) = Range::hir(arg)
-        && is_full_range(cx, recv, range)
+        && let ExprKind::Path(QPath::Resolved(None, container_path)) = recv.kind
+        && is_range_full(cx, arg, Some(container_path))
     {
         span_lint_and_sugg(
             cx,
@@ -29,19 +27,3 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span
         );
     };
 }
-
-fn is_full_range(cx: &LateContext<'_>, container: &Expr<'_>, range: Range<'_>) -> bool {
-    range.start.map_or(true, |e| is_integer_const(cx, e, 0))
-        && range.end.map_or(true, |e| {
-            if range.limits == RangeLimits::HalfOpen
-                && let ExprKind::Path(QPath::Resolved(None, container_path)) = container.kind
-                && let ExprKind::MethodCall(name, self_arg, [], _) = e.kind
-                && name.ident.name == sym::len
-                && let ExprKind::Path(QPath::Resolved(None, path)) = self_arg.kind
-            {
-                container_path.res == path.res
-            } else {
-                false
-            }
-        })
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 56e3988bf09..64bf55ba24c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -9,6 +9,7 @@ mod chars_last_cmp;
 mod chars_last_cmp_with_unwrap;
 mod chars_next_cmp;
 mod chars_next_cmp_with_unwrap;
+mod clear_with_drain;
 mod clone_on_copy;
 mod clone_on_ref_ptr;
 mod cloned_instead_of_copied;
@@ -110,7 +111,7 @@ use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_
 use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, return_ty};
 use if_chain::if_chain;
 use rustc_hir as hir;
-use rustc_hir::{Expr, ExprKind, TraitItem, TraitItemKind};
+use rustc_hir::{Expr, ExprKind, Node, Stmt, StmtKind, TraitItem, TraitItemKind};
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -3190,6 +3191,31 @@ declare_clippy_lint! {
     "single command line argument that looks like it should be multiple arguments"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `.drain(..)` for the sole purpose of clearing a container.
+    ///
+    /// ### Why is this bad?
+    /// This creates an unnecessary iterator that is dropped immediately.
+    ///
+    /// Calling `.clear()` also makes the intent clearer.
+    ///
+    /// ### Example
+    /// ```rust
+    /// let mut v = vec![1, 2, 3];
+    /// v.drain(..);
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// let mut v = vec![1, 2, 3];
+    /// v.clear();
+    /// ```
+    #[clippy::version = "1.69.0"]
+    pub CLEAR_WITH_DRAIN,
+    nursery,
+    "calling `drain` in order to `clear` a container"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -3318,6 +3344,7 @@ impl_lint_pass!(Methods => [
     SEEK_TO_START_INSTEAD_OF_REWIND,
     NEEDLESS_COLLECT,
     SUSPICIOUS_COMMAND_ARG_SPACE,
+    CLEAR_WITH_DRAIN,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -3562,8 +3589,15 @@ impl Methods {
                     Some(("bytes", recv2, [], _, _)) => bytes_count_to_len::check(cx, expr, recv, recv2),
                     _ => {},
                 },
-                ("drain", [arg]) => {
-                    iter_with_drain::check(cx, expr, recv, span, arg);
+                ("drain", ..) => {
+                    if let Node::Stmt(Stmt { hir_id: _, kind, .. }) = cx.tcx.hir().get_parent(expr.hir_id)
+                        && matches!(kind, StmtKind::Semi(_))
+                        && args.len() <= 1
+                    {
+                        clear_with_drain::check(cx, expr, recv, span, args.first());
+                    } else if let [arg] = args {
+                        iter_with_drain::check(cx, expr, recv, span, arg);
+                    }
                 },
                 ("ends_with", [arg]) => {
                     if let ExprKind::MethodCall(.., span) = expr.kind {
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 87bd007a26a..f1831a30461 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -41,6 +41,7 @@ declare_clippy_lint! {
     /// can't be const as it calls a non-const function. Making `a` const and running Clippy again,
     /// will suggest to make `b` const, too.
     ///
+    /// If you are marking a public function with `const`, removing it again will break API compatibility.
     /// ### Example
     /// ```rust
     /// # struct Foo {
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 25e8de94863..e5713735672 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
@@ -154,10 +154,18 @@ impl ArithmeticSideEffects {
                 Self::literal_integer(cx, actual_rhs),
             ) {
                 (None, None) => false,
-                (None, Some(n)) | (Some(n), None) => match (&op.node, n) {
+                (None, Some(n)) => match (&op.node, n) {
                     // Division and module are always valid if applied to non-zero integers
                     (hir::BinOpKind::Div | hir::BinOpKind::Rem, local_n) if local_n != 0 => true,
-                    // Addition or subtracting zeros is always a no-op
+                    // Adding or subtracting zeros is always a no-op
+                    (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
+                    // Multiplication by 1 or 0 will never overflow
+                    | (hir::BinOpKind::Mul, 0 | 1)
+                    => true,
+                    _ => false,
+                },
+                (Some(n), None) => match (&op.node, n) {
+                    // Adding or subtracting zeros is always a no-op
                     (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
                     // Multiplication by 1 or 0 will never overflow
                     | (hir::BinOpKind::Mul, 0 | 1)
diff --git a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
index 5ac203665d0..a0f831764d0 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_async_block.rs
@@ -1,8 +1,15 @@
-use clippy_utils::{diagnostics::span_lint_and_sugg, source::snippet};
-use rustc_ast::ast::{Expr, ExprKind, Stmt, StmtKind};
-use rustc_ast::visit::Visitor as AstVisitor;
+use std::ops::ControlFlow;
+
+use clippy_utils::{
+    diagnostics::span_lint_and_sugg,
+    peel_blocks,
+    source::{snippet, walk_span_to_context},
+    visitors::for_each_expr,
+};
 use rustc_errors::Applicability;
-use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_hir::{AsyncGeneratorKind, Closure, Expr, ExprKind, GeneratorKind, MatchSource};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::{lint::in_external_macro, ty::UpvarCapture};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
@@ -14,106 +21,88 @@ declare_clippy_lint! {
     ///
     /// ### Example
     /// ```rust
-    /// async fn f() -> i32 {
-    ///     1 + 2
-    /// }
-    ///
+    /// let f = async {
+    ///    1 + 2
+    /// };
     /// let fut = async {
-    ///     f().await
+    ///     f.await
     /// };
     /// ```
     /// Use instead:
     /// ```rust
-    /// async fn f() -> i32 {
-    ///     1 + 2
-    /// }
-    ///
-    /// let fut = f();
+    /// let f = async {
+    ///    1 + 2
+    /// };
+    /// let fut = f;
     /// ```
     #[clippy::version = "1.69.0"]
     pub REDUNDANT_ASYNC_BLOCK,
-    nursery,
+    complexity,
     "`async { future.await }` can be replaced by `future`"
 }
 declare_lint_pass!(RedundantAsyncBlock => [REDUNDANT_ASYNC_BLOCK]);
 
-impl EarlyLintPass for RedundantAsyncBlock {
-    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
-        if expr.span.from_expansion() {
-            return;
-        }
-        if let ExprKind::Async(_, block) = &expr.kind && block.stmts.len() == 1 &&
-            let Some(Stmt { kind: StmtKind::Expr(last), .. }) = block.stmts.last() &&
-            let ExprKind::Await(future) = &last.kind &&
-            !future.span.from_expansion() &&
-            !await_in_expr(future)
+impl<'tcx> LateLintPass<'tcx> for RedundantAsyncBlock {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        let span = expr.span;
+        if !in_external_macro(cx.tcx.sess, span) &&
+            let Some(body_expr) = desugar_async_block(cx, expr) &&
+            let Some(expr) = desugar_await(peel_blocks(body_expr)) &&
+            // The await prefix must not come from a macro as its content could change in the future.
+            expr.span.ctxt() == body_expr.span.ctxt() &&
+            // An async block does not have immediate side-effects from a `.await` point-of-view.
+            (!expr.can_have_side_effects() || desugar_async_block(cx, expr).is_some()) &&
+            let Some(shortened_span) = walk_span_to_context(expr.span, span.ctxt())
         {
-            if captures_value(last) {
-                // If the async block captures variables then there is no equivalence.
-                return;
-            }
-
             span_lint_and_sugg(
                 cx,
                 REDUNDANT_ASYNC_BLOCK,
-                expr.span,
+                span,
                 "this async expression only awaits a single future",
                 "you can reduce it to",
-                snippet(cx, future.span, "..").into_owned(),
+                snippet(cx, shortened_span, "..").into_owned(),
                 Applicability::MachineApplicable,
             );
         }
     }
 }
 
-/// Check whether an expression contains `.await`
-fn await_in_expr(expr: &Expr) -> bool {
-    let mut detector = AwaitDetector::default();
-    detector.visit_expr(expr);
-    detector.await_found
-}
-
-#[derive(Default)]
-struct AwaitDetector {
-    await_found: bool,
-}
-
-impl<'ast> AstVisitor<'ast> for AwaitDetector {
-    fn visit_expr(&mut self, ex: &'ast Expr) {
-        match (&ex.kind, self.await_found) {
-            (ExprKind::Await(_), _) => self.await_found = true,
-            (_, false) => rustc_ast::visit::walk_expr(self, ex),
-            _ => (),
-        }
+/// If `expr` is a desugared `async` block, return the original expression if it does not capture
+/// any variable by ref.
+fn desugar_async_block<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
+    if let ExprKind::Closure(Closure { body, def_id, .. }) = expr.kind &&
+        let body = cx.tcx.hir().body(*body) &&
+        matches!(body.generator_kind, Some(GeneratorKind::Async(AsyncGeneratorKind::Block)))
+    {
+        cx
+            .typeck_results()
+            .closure_min_captures
+            .get(def_id)
+            .map_or(true, |m| {
+                m.values().all(|places| {
+                    places
+                        .iter()
+                        .all(|place| matches!(place.info.capture_kind, UpvarCapture::ByValue))
+                })
+            })
+            .then_some(body.value)
+    } else {
+        None
     }
 }
 
-/// Check whether an expression may have captured a local variable.
-/// This is done by looking for paths with only one segment, except as
-/// a prefix of `.await` since this would be captured by value.
-///
-/// This function will sometimes return `true` even tough there are no
-/// captures happening: at the AST level, it is impossible to
-/// dinstinguish a function call from a call to a closure which comes
-/// from the local environment.
-fn captures_value(expr: &Expr) -> bool {
-    let mut detector = CaptureDetector::default();
-    detector.visit_expr(expr);
-    detector.capture_found
-}
-
-#[derive(Default)]
-struct CaptureDetector {
-    capture_found: bool,
-}
-
-impl<'ast> AstVisitor<'ast> for CaptureDetector {
-    fn visit_expr(&mut self, ex: &'ast Expr) {
-        match (&ex.kind, self.capture_found) {
-            (ExprKind::Await(fut), _) if matches!(fut.kind, ExprKind::Path(..)) => (),
-            (ExprKind::Path(_, path), _) if path.segments.len() == 1 => self.capture_found = true,
-            (_, false) => rustc_ast::visit::walk_expr(self, ex),
-            _ => (),
-        }
+/// If `expr` is a desugared `.await`, return the original expression if it does not come from a
+/// macro expansion.
+fn desugar_await<'tcx>(expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
+    if let ExprKind::Match(match_value, _, MatchSource::AwaitDesugar) = expr.kind &&
+        let ExprKind::Call(_, [into_future_arg]) = match_value.kind &&
+        let ctxt = expr.span.ctxt() &&
+        for_each_expr(into_future_arg, |e|
+            walk_span_to_context(e.span, ctxt)
+                .map_or(ControlFlow::Break(()), |_| ControlFlow::Continue(()))).is_none()
+    {
+        Some(into_future_arg)
+    } else {
+        None
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
index 11b908e7e53..038dfe8e480 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet;
-use rustc_ast::ast::{Item, ItemKind, Ty, TyKind, StaticItem, ConstItem};
+use rustc_ast::ast::{ConstItem, Item, ItemKind, StaticItem, Ty, TyKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -106,7 +106,7 @@ impl EarlyLintPass for RedundantStaticLifetimes {
                 // #2438)
             }
 
-            if let ItemKind::Static(box StaticItem { ty: ref var_type,.. }) = item.kind {
+            if let ItemKind::Static(box StaticItem { ty: ref var_type, .. }) = item.kind {
                 Self::visit_type(var_type, cx, "statics have by default a `'static` lifetime");
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index f0d7dd23a67..df126d7617e 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -9,7 +9,7 @@ use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, LangItem, MatchSource, PatKind, QPath, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map::Span;
@@ -175,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for Return {
                 } else {
                     RetReplacement::Empty
                 };
-                check_final_expr(cx, body.value, vec![], replacement);
+                check_final_expr(cx, body.value, vec![], replacement, None);
             },
             FnKind::ItemFn(..) | FnKind::Method(..) => {
                 check_block_return(cx, &body.value.kind, sp, vec![]);
@@ -188,11 +188,11 @@ impl<'tcx> LateLintPass<'tcx> for Return {
 fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>, sp: Span, mut semi_spans: Vec<Span>) {
     if let ExprKind::Block(block, _) = expr_kind {
         if let Some(block_expr) = block.expr {
-            check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty);
+            check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty, None);
         } else if let Some(stmt) = block.stmts.iter().last() {
             match stmt.kind {
                 StmtKind::Expr(expr) => {
-                    check_final_expr(cx, expr, semi_spans, RetReplacement::Empty);
+                    check_final_expr(cx, expr, semi_spans, RetReplacement::Empty, None);
                 },
                 StmtKind::Semi(semi_expr) => {
                     // Remove ending semicolons and any whitespace ' ' in between.
@@ -202,7 +202,7 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, expr_kind: &ExprKind<'tcx>,
                             span_find_starting_semi(cx.sess().source_map(), semi_span.with_hi(sp.hi()));
                         semi_spans.push(semi_span_to_remove);
                     }
-                    check_final_expr(cx, semi_expr, semi_spans, RetReplacement::Empty);
+                    check_final_expr(cx, semi_expr, semi_spans, RetReplacement::Empty, None);
                 },
                 _ => (),
             }
@@ -216,6 +216,7 @@ fn check_final_expr<'tcx>(
     semi_spans: Vec<Span>, /* containing all the places where we would need to remove semicolons if finding an
                             * needless return */
     replacement: RetReplacement<'tcx>,
+    match_ty_opt: Option<Ty<'_>>,
 ) {
     let peeled_drop_expr = expr.peel_drop_temps();
     match &peeled_drop_expr.kind {
@@ -244,7 +245,22 @@ fn check_final_expr<'tcx>(
                     RetReplacement::Expr(snippet, applicability)
                 }
             } else {
-                replacement
+                match match_ty_opt {
+                    Some(match_ty) => {
+                        match match_ty.kind() {
+                            // If the code got till here with
+                            // tuple not getting detected before it,
+                            // then we are sure it's going to be Unit
+                            // type
+                            ty::Tuple(_) => RetReplacement::Unit,
+                            // We don't want to anything in this case
+                            // cause we can't predict what the user would
+                            // want here
+                            _ => return,
+                        }
+                    },
+                    None => replacement,
+                }
             };
 
             if !cx.tcx.hir().attrs(expr.hir_id).is_empty() {
@@ -268,8 +284,9 @@ fn check_final_expr<'tcx>(
         // note, if without else is going to be a type checking error anyways
         // (except for unit type functions) so we don't match it
         ExprKind::Match(_, arms, MatchSource::Normal) => {
+            let match_ty = cx.typeck_results().expr_ty(peeled_drop_expr);
             for arm in arms.iter() {
-                check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit);
+                check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit, Some(match_ty));
             }
         },
         // if it's a whole block, check it
@@ -293,6 +310,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec<Span>,
     if ret_span.from_expansion() {
         return;
     }
+
     let applicability = replacement.applicability().unwrap_or(Applicability::MachineApplicable);
     let return_replacement = replacement.to_string();
     let sugg_help = replacement.sugg_help();
diff --git a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
index d46f6a6352c..5743dd21c28 100644
--- a/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/single_component_path_imports.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
 use rustc_ast::node_id::{NodeId, NodeMap};
-use rustc_ast::{ptr::P, Crate, Item, ItemKind, MacroDef, ModKind, UseTreeKind};
+use rustc_ast::visit::{walk_expr, Visitor};
+use rustc_ast::{ptr::P, Crate, Expr, ExprKind, Item, ItemKind, MacroDef, ModKind, Ty, TyKind, UseTreeKind};
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -55,7 +56,7 @@ impl EarlyLintPass for SingleComponentPathImports {
             return;
         }
 
-        self.check_mod(cx, &krate.items);
+        self.check_mod(&krate.items);
     }
 
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
@@ -84,8 +85,43 @@ impl EarlyLintPass for SingleComponentPathImports {
     }
 }
 
+#[derive(Default)]
+struct ImportUsageVisitor {
+    // keep track of imports reused with `self` keyword, such as `self::std` in the example below.
+    // Removing the `use std;` would make this a compile error (#10549)
+    // ```
+    // use std;
+    //
+    // fn main() {
+    //     let _ = self::std::io::stdout();
+    // }
+    // ```
+    imports_referenced_with_self: Vec<Symbol>,
+}
+
+impl<'tcx> Visitor<'tcx> for ImportUsageVisitor {
+    fn visit_expr(&mut self, expr: &Expr) {
+        if let ExprKind::Path(_, path) = &expr.kind
+            && path.segments.len() > 1
+            && path.segments[0].ident.name == kw::SelfLower
+        {
+            self.imports_referenced_with_self.push(path.segments[1].ident.name);
+        }
+        walk_expr(self, expr);
+    }
+
+    fn visit_ty(&mut self, ty: &Ty) {
+        if let TyKind::Path(_, path) = &ty.kind
+            && path.segments.len() > 1
+            && path.segments[0].ident.name == kw::SelfLower
+        {
+            self.imports_referenced_with_self.push(path.segments[1].ident.name);
+        }
+    }
+}
+
 impl SingleComponentPathImports {
-    fn check_mod(&mut self, cx: &EarlyContext<'_>, items: &[P<Item>]) {
+    fn check_mod(&mut self, items: &[P<Item>]) {
         // keep track of imports reused with `self` keyword, such as `self::crypto_hash` in the example
         // below. Removing the `use crypto_hash;` would make this a compile error
         // ```
@@ -108,18 +144,16 @@ impl SingleComponentPathImports {
         // ```
         let mut macros = Vec::new();
 
+        let mut import_usage_visitor = ImportUsageVisitor::default();
         for item in items {
-            self.track_uses(
-                cx,
-                item,
-                &mut imports_reused_with_self,
-                &mut single_use_usages,
-                &mut macros,
-            );
+            self.track_uses(item, &mut imports_reused_with_self, &mut single_use_usages, &mut macros);
+            import_usage_visitor.visit_item(item);
         }
 
         for usage in single_use_usages {
-            if !imports_reused_with_self.contains(&usage.name) {
+            if !imports_reused_with_self.contains(&usage.name)
+                && !import_usage_visitor.imports_referenced_with_self.contains(&usage.name)
+            {
                 self.found.entry(usage.item_id).or_default().push(usage);
             }
         }
@@ -127,7 +161,6 @@ impl SingleComponentPathImports {
 
     fn track_uses(
         &mut self,
-        cx: &EarlyContext<'_>,
         item: &Item,
         imports_reused_with_self: &mut Vec<Symbol>,
         single_use_usages: &mut Vec<SingleUse>,
@@ -139,7 +172,7 @@ impl SingleComponentPathImports {
 
         match &item.kind {
             ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) => {
-                self.check_mod(cx, items);
+                self.check_mod(items);
             },
             ItemKind::MacroDef(MacroDef { macro_rules: true, .. }) => {
                 macros.push(item.ident.name);
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_doc_comments.rs b/src/tools/clippy/clippy_lints/src/suspicious_doc_comments.rs
new file mode 100644
index 00000000000..e5746ca99ca
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/suspicious_doc_comments.rs
@@ -0,0 +1,94 @@
+use clippy_utils::diagnostics::{multispan_sugg_with_applicability, span_lint_and_then};
+use if_chain::if_chain;
+use rustc_ast::{token::CommentKind, AttrKind, AttrStyle, Attribute, Item};
+use rustc_errors::Applicability;
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Detects the use of outer doc comments (`///`, `/**`) followed by a bang (`!`): `///!`
+    ///
+    /// ### Why is this bad?
+    /// Triple-slash comments (known as "outer doc comments") apply to items that follow it.
+    /// An outer doc comment followed by a bang (i.e. `///!`) has no specific meaning.
+    ///
+    /// The user most likely meant to write an inner doc comment (`//!`, `/*!`), which
+    /// applies to the parent item (i.e. the item that the comment is contained in,
+    /// usually a module or crate).
+    ///
+    /// ### Known problems
+    /// Inner doc comments can only appear before items, so there are certain cases where the suggestion
+    /// made by this lint is not valid code. For example:
+    /// ```rs
+    /// fn foo() {}
+    /// ///!
+    /// fn bar() {}
+    /// ```
+    /// This lint detects the doc comment and suggests changing it to `//!`, but an inner doc comment
+    /// is not valid at that position.
+    ///
+    /// ### Example
+    /// In this example, the doc comment is attached to the *function*, rather than the *module*.
+    /// ```rust
+    /// pub mod util {
+    ///     ///! This module contains utility functions.
+    ///
+    ///     pub fn dummy() {}
+    /// }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    /// pub mod util {
+    ///     //! This module contains utility functions.
+    ///
+    ///     pub fn dummy() {}
+    /// }
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub SUSPICIOUS_DOC_COMMENTS,
+    suspicious,
+    "suspicious usage of (outer) doc comments"
+}
+declare_lint_pass!(SuspiciousDocComments => [SUSPICIOUS_DOC_COMMENTS]);
+
+const WARNING: &str = "this is an outer doc comment and does not apply to the parent module or crate";
+const HELP: &str = "use an inner doc comment to document the parent module or crate";
+
+impl EarlyLintPass for SuspiciousDocComments {
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+        let replacements = collect_doc_comment_replacements(&item.attrs);
+
+        if let Some(((lo_span, _), (hi_span, _))) = replacements.first().zip(replacements.last()) {
+            let span = lo_span.to(*hi_span);
+
+            span_lint_and_then(cx, SUSPICIOUS_DOC_COMMENTS, span, WARNING, |diag| {
+                multispan_sugg_with_applicability(diag, HELP, Applicability::MaybeIncorrect, replacements);
+            });
+        }
+    }
+}
+
+fn collect_doc_comment_replacements(attrs: &[Attribute]) -> Vec<(Span, String)> {
+    attrs
+        .iter()
+        .filter_map(|attr| {
+            if_chain! {
+                if let AttrKind::DocComment(com_kind, sym) = attr.kind;
+                if let AttrStyle::Outer = attr.style;
+                if let Some(com) = sym.as_str().strip_prefix('!');
+                then {
+                    let sugg = match com_kind {
+                        CommentKind::Line => format!("//!{com}"),
+                        CommentKind::Block => format!("/*!{com}*/")
+                    };
+                    Some((attr.span, sugg))
+                } else {
+                    None
+                }
+            }
+        })
+        .collect()
+}
diff --git a/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs b/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs
new file mode 100644
index 00000000000..0a0a77082e0
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/tests_outside_test_module.rs
@@ -0,0 +1,71 @@
+use clippy_utils::{diagnostics::span_lint_and_note, is_in_cfg_test, is_in_test_function};
+use rustc_hir::{intravisit::FnKind, Body, FnDecl};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{def_id::LocalDefId, Span};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Triggers when a testing function (marked with the `#[test]` attribute) isn't inside a testing module
+    /// (marked with `#[cfg(test)]`).
+    /// ### Why is this bad?
+    /// The idiomatic (and more performant) way of writing tests is inside a testing module (flagged with `#[cfg(test)]`),
+    /// having test functions outside of this module is confusing and may lead to them being "hidden".
+    /// ### Example
+    /// ```rust
+    /// #[test]
+    /// fn my_cool_test() {
+    ///     // [...]
+    /// }
+    ///
+    /// #[cfg(test)]
+    /// mod tests {
+    ///     // [...]
+    /// }
+    ///
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// #[cfg(test)]
+    /// mod tests {
+    ///     #[test]
+    ///     fn my_cool_test() {
+    ///         // [...]
+    ///     }
+    /// }
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub TESTS_OUTSIDE_TEST_MODULE,
+    restriction,
+    "A test function is outside the testing module."
+}
+
+declare_lint_pass!(TestsOutsideTestModule => [TESTS_OUTSIDE_TEST_MODULE]);
+
+impl LateLintPass<'_> for TestsOutsideTestModule {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'_>,
+        kind: FnKind<'_>,
+        _: &FnDecl<'_>,
+        body: &Body<'_>,
+        sp: Span,
+        _: LocalDefId,
+    ) {
+        if_chain! {
+            if !matches!(kind, FnKind::Closure);
+            if is_in_test_function(cx.tcx, body.id().hir_id);
+            if !is_in_cfg_test(cx.tcx, body.id().hir_id);
+            then {
+                span_lint_and_note(
+                    cx,
+                    TESTS_OUTSIDE_TEST_MODULE,
+                    sp,
+                    "this function marked with #[test] is outside a #[cfg(test)] module",
+                    None,
+                    "move it to a testing module marked with #[cfg(test)]",
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
index 8530b43243f..85cd74f23ef 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs
@@ -2,8 +2,9 @@ use super::utils::check_cast;
 use super::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::sugg::Sugg;
+use rustc_ast::ExprPrecedence;
 use rustc_errors::Applicability;
-use rustc_hir::Expr;
+use rustc_hir::{Expr, Node};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{cast::CastKind, Ty};
 
@@ -19,7 +20,7 @@ pub(super) fn check<'tcx>(
 ) -> bool {
     use CastKind::{AddrPtrCast, ArrayPtrCast, FnPtrAddrCast, FnPtrPtrCast, PtrAddrCast, PtrPtrCast};
     let mut app = Applicability::MachineApplicable;
-    let sugg = match check_cast(cx, e, from_ty, to_ty) {
+    let mut sugg = match check_cast(cx, e, from_ty, to_ty) {
         Some(PtrPtrCast | AddrPtrCast | ArrayPtrCast | FnPtrPtrCast | FnPtrAddrCast) => {
             Sugg::hir_with_context(cx, arg, e.span.ctxt(), "..", &mut app)
                 .as_ty(to_ty.to_string())
@@ -39,6 +40,12 @@ pub(super) fn check<'tcx>(
         _ => return false,
     };
 
+    if let Node::Expr(parent) = cx.tcx.hir().get_parent(e.hir_id)
+        && parent.precedence().order() > ExprPrecedence::Cast.order()
+    {
+        sugg = format!("({sugg})");
+    }
+
     span_lint_and_sugg(
         cx,
         TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
new file mode 100644
index 00000000000..912bcda630b
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_box_returns.rs
@@ -0,0 +1,120 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use rustc_errors::Applicability;
+use rustc_hir::{def_id::LocalDefId, FnDecl, FnRetTy, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Symbol;
+
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Checks for a return type containing a `Box<T>` where `T` implements `Sized`
+    ///
+    /// ### Why is this bad?
+    ///
+    /// It's better to just return `T` in these cases. The caller may not need
+    /// the value to be boxed, and it's expensive to free the memory once the
+    /// `Box<T>` been dropped.
+    ///
+    /// ### Example
+    /// ```rust
+    /// fn foo() -> Box<String> {
+    ///     Box::new(String::from("Hello, world!"))
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// fn foo() -> String {
+    ///     String::from("Hello, world!")
+    /// }
+    /// ```
+    #[clippy::version = "1.70.0"]
+    pub UNNECESSARY_BOX_RETURNS,
+    pedantic,
+    "Needlessly returning a Box"
+}
+
+pub struct UnnecessaryBoxReturns {
+    avoid_breaking_exported_api: bool,
+}
+
+impl_lint_pass!(UnnecessaryBoxReturns => [UNNECESSARY_BOX_RETURNS]);
+
+impl UnnecessaryBoxReturns {
+    pub fn new(avoid_breaking_exported_api: bool) -> Self {
+        Self {
+            avoid_breaking_exported_api,
+        }
+    }
+
+    fn check_fn_item(&mut self, cx: &LateContext<'_>, decl: &FnDecl<'_>, def_id: LocalDefId, name: Symbol) {
+        // we don't want to tell someone to break an exported function if they ask us not to
+        if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) {
+            return;
+        }
+
+        // functions which contain the word "box" are exempt from this lint
+        if name.as_str().contains("box") {
+            return;
+        }
+
+        let FnRetTy::Return(return_ty_hir) = &decl.output else { return };
+
+        let return_ty = cx
+            .tcx
+            .erase_late_bound_regions(cx.tcx.fn_sig(def_id).skip_binder())
+            .output();
+
+        if !return_ty.is_box() {
+            return;
+        }
+
+        let boxed_ty = return_ty.boxed_ty();
+
+        // it's sometimes useful to return Box<T> if T is unsized, so don't lint those
+        if boxed_ty.is_sized(cx.tcx, cx.param_env) {
+            span_lint_and_then(
+                cx,
+                UNNECESSARY_BOX_RETURNS,
+                return_ty_hir.span,
+                format!("boxed return of the sized type `{boxed_ty}`").as_str(),
+                |diagnostic| {
+                    diagnostic.span_suggestion(
+                        return_ty_hir.span,
+                        "try",
+                        boxed_ty.to_string(),
+                        // the return value and function callers also needs to
+                        // be changed, so this can't be MachineApplicable
+                        Applicability::Unspecified,
+                    );
+                    diagnostic.help("changing this also requires a change to the return expressions in this function");
+                },
+            );
+        }
+    }
+}
+
+impl LateLintPass<'_> for UnnecessaryBoxReturns {
+    fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
+        let TraitItemKind::Fn(signature, _) = &item.kind else { return };
+        self.check_fn_item(cx, signature.decl, item.owner_id.def_id, item.ident.name);
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ImplItem<'_>) {
+        // Ignore implementations of traits, because the lint should be on the
+        // trait, not on the implmentation of it.
+        let Node::Item(parent) = cx.tcx.hir().get_parent(item.hir_id()) else { return };
+        let ItemKind::Impl(parent) = parent.kind else { return };
+        if parent.of_trait.is_some() {
+            return;
+        }
+
+        let ImplItemKind::Fn(signature, ..) = &item.kind else { return };
+        self.check_fn_item(cx, signature.decl, item.owner_id.def_id, item.ident.name);
+    }
+
+    fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+        let ItemKind::Fn(signature, ..) = &item.kind else { return };
+        self.check_fn_item(cx, signature.decl, item.owner_id.def_id, item.ident.name);
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs b/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs
index af0b4b1592f..084b031982d 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_struct_initialization.rs
@@ -9,7 +9,7 @@ declare_clippy_lint! {
     /// any field.
     ///
     /// ### Why is this bad?
-    /// Readibility suffers from unnecessary struct building.
+    /// Readability suffers from unnecessary struct building.
     ///
     /// ### Example
     /// ```rust
@@ -25,9 +25,13 @@ declare_clippy_lint! {
     /// let a = S { s: String::from("Hello, world!") };
     /// let b = a;
     /// ```
+    ///
+    /// ### Known Problems
+    /// Has false positives when the base is a place expression that cannot be
+    /// moved out of, see [#10547](https://github.com/rust-lang/rust-clippy/issues/10547).
     #[clippy::version = "1.70.0"]
     pub UNNECESSARY_STRUCT_INITIALIZATION,
-    complexity,
+    nursery,
     "struct built from a base that can be written mode concisely"
 }
 declare_lint_pass!(UnnecessaryStruct => [UNNECESSARY_STRUCT_INITIALIZATION]);
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 7dfb0956077..5a02987453c 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -10,8 +10,8 @@ use rustc_hir::{
     def::{CtorOf, DefKind, Res},
     def_id::LocalDefId,
     intravisit::{walk_inf, walk_ty, Visitor},
-    Expr, ExprKind, FnRetTy, FnSig, GenericArg, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl, ImplItemKind, Item,
-    ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
+    Expr, ExprKind, FnRetTy, FnSig, GenericArg, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl,
+    ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
 };
 use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 8ba252425a3..896a01af37d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -249,7 +249,7 @@ define_Conf! {
     /// arithmetic-side-effects-allowed-unary = ["SomeType", "AnotherType"]
     /// ```
     (arithmetic_side_effects_allowed_unary: rustc_data_structures::fx::FxHashSet<String> = <_>::default()),
-    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX.
+    /// Lint: ENUM_VARIANT_NAMES, LARGE_TYPES_PASSED_BY_VALUE, TRIVIALLY_COPY_PASS_BY_REF, UNNECESSARY_WRAPS, UNUSED_SELF, UPPER_CASE_ACRONYMS, WRONG_SELF_CONVENTION, BOX_COLLECTION, REDUNDANT_ALLOCATION, RC_BUFFER, VEC_BOX, OPTION_OPTION, LINKEDLIST, RC_MUTEX, UNNECESSARY_BOX_RETURNS.
     ///
     /// Suppress lints whenever the suggested change would cause breakage for other crates.
     (avoid_breaking_exported_api: bool = true),
@@ -275,13 +275,13 @@ define_Conf! {
     ///
     /// The list of disallowed names to lint about. NB: `bar` is not here since it has legitimate uses. The value
     /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the
-    /// default configuration of Clippy. By default any configuration will replace the default value.
+    /// default configuration of Clippy. By default, any configuration will replace the default value.
     (disallowed_names: Vec<String> = super::DEFAULT_DISALLOWED_NAMES.iter().map(ToString::to_string).collect()),
     /// Lint: DOC_MARKDOWN.
     ///
     /// The list of words this lint should not consider as identifiers needing ticks. The value
     /// `".."` can be used as part of the list to indicate, that the configured values should be appended to the
-    /// default configuration of Clippy. By default any configuraction will replace the default value. For example:
+    /// default configuration of Clippy. By default, any configuration will replace the default value. For example:
     /// * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
     /// * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
     ///
@@ -390,7 +390,7 @@ define_Conf! {
     /// Enforce the named macros always use the braces specified.
     ///
     /// A `MacroMatcher` can be added like so `{ name = "macro_name", brace = "(" }`. If the macro
-    /// is could be used with a full path two `MacroMatcher`s have to be added one with the full path
+    /// could be used with a full path two `MacroMatcher`s have to be added one with the full path
     /// `crate_name::macro_name` and one with just the macro name.
     (standard_macro_braces: Vec<crate::nonstandard_macro_braces::MacroMatcher> = Vec::new()),
     /// Lint: MISSING_ENFORCED_IMPORT_RENAMES.
@@ -408,7 +408,7 @@ define_Conf! {
     /// Lint: INDEX_REFUTABLE_SLICE.
     ///
     /// When Clippy suggests using a slice pattern, this is the maximum number of elements allowed in
-    /// the slice pattern that is suggested. If more elements would be necessary, the lint is suppressed.
+    /// the slice pattern that is suggested. If more elements are necessary, the lint is suppressed.
     /// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
     (max_suggested_slice_pattern_length: u64 = 3),
     /// Lint: AWAIT_HOLDING_INVALID_TYPE.
@@ -459,6 +459,10 @@ define_Conf! {
     /// Whether to **only** check for missing documentation in items visible within the current
     /// crate. For example, `pub(crate)` items.
     (missing_docs_in_crate_items: bool = false),
+    /// Lint: LARGE_FUTURES.
+    ///
+    /// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
+    (future_size_threshold: u64 = 16 * 1024),
 }
 
 /// Search for the configuration file.
@@ -466,7 +470,7 @@ define_Conf! {
 /// # Errors
 ///
 /// Returns any unexpected filesystem error encountered when searching for the config file
-pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> {
+pub fn lookup_conf_file() -> io::Result<(Option<PathBuf>, Vec<String>)> {
     /// Possible filename to search for.
     const CONFIG_FILE_NAMES: [&str; 2] = [".clippy.toml", "clippy.toml"];
 
@@ -474,9 +478,11 @@ pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> {
     // If neither of those exist, use ".".
     let mut current = env::var_os("CLIPPY_CONF_DIR")
         .or_else(|| env::var_os("CARGO_MANIFEST_DIR"))
-        .map_or_else(|| PathBuf::from("."), PathBuf::from);
+        .map_or_else(|| PathBuf::from("."), PathBuf::from)
+        .canonicalize()?;
 
     let mut found_config: Option<PathBuf> = None;
+    let mut warnings = vec![];
 
     loop {
         for config_file_name in &CONFIG_FILE_NAMES {
@@ -487,12 +493,12 @@ pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> {
                     Ok(md) if md.is_dir() => {},
                     Ok(_) => {
                         // warn if we happen to find two config files #8323
-                        if let Some(ref found_config_) = found_config {
-                            eprintln!(
-                                "Using config file `{}`\nWarning: `{}` will be ignored.",
-                                found_config_.display(),
-                                config_file.display(),
-                            );
+                        if let Some(ref found_config) = found_config {
+                            warnings.push(format!(
+                                "using config file `{}`, `{}` will be ignored",
+                                found_config.display(),
+                                config_file.display()
+                            ));
                         } else {
                             found_config = Some(config_file);
                         }
@@ -502,12 +508,12 @@ pub fn lookup_conf_file() -> io::Result<Option<PathBuf>> {
         }
 
         if found_config.is_some() {
-            return Ok(found_config);
+            return Ok((found_config, warnings));
         }
 
         // If the current directory has no parent, we're done searching.
         if !current.pop() {
-            return Ok(None);
+            return Ok((None, warnings));
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs
index be56b842b98..09fcb82c37c 100644
--- a/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/format_args_collector.rs
@@ -1,7 +1,12 @@
 use clippy_utils::macros::collect_ast_format_args;
-use rustc_ast::{Expr, ExprKind};
+use clippy_utils::source::snippet_opt;
+use itertools::Itertools;
+use rustc_ast::{Expr, ExprKind, FormatArgs};
+use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::hygiene;
+use std::iter::once;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -15,9 +20,79 @@ declare_clippy_lint! {
 declare_lint_pass!(FormatArgsCollector => [FORMAT_ARGS_COLLECTOR]);
 
 impl EarlyLintPass for FormatArgsCollector {
-    fn check_expr(&mut self, _: &EarlyContext<'_>, expr: &Expr) {
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
         if let ExprKind::FormatArgs(args) = &expr.kind {
+            if has_span_from_proc_macro(cx, args) {
+                return;
+            }
+
             collect_ast_format_args(expr.span, args);
         }
     }
 }
+
+/// Detects if the format string or an argument has its span set by a proc macro to something inside
+/// a macro callsite, e.g.
+///
+/// ```ignore
+/// println!(some_proc_macro!("input {}"), a);
+/// ```
+///
+/// Where `some_proc_macro` expands to
+///
+/// ```ignore
+/// println!("output {}", a);
+/// ```
+///
+/// But with the span of `"output {}"` set to the macro input
+///
+/// ```ignore
+/// println!(some_proc_macro!("input {}"), a);
+/// //                        ^^^^^^^^^^
+/// ```
+fn has_span_from_proc_macro(cx: &EarlyContext<'_>, args: &FormatArgs) -> bool {
+    let ctxt = args.span.ctxt();
+
+    // `format!("{} {} {c}", "one", "two", c = "three")`
+    //                       ^^^^^  ^^^^^      ^^^^^^^
+    let argument_span = args
+        .arguments
+        .explicit_args()
+        .iter()
+        .map(|argument| hygiene::walk_chain(argument.expr.span, ctxt));
+
+    // `format!("{} {} {c}", "one", "two", c = "three")`
+    //                     ^^     ^^     ^^^^^^
+    let between_spans = once(args.span)
+        .chain(argument_span)
+        .tuple_windows()
+        .map(|(start, end)| start.between(end));
+
+    for between_span in between_spans {
+        let mut seen_comma = false;
+
+        let Some(snippet) = snippet_opt(cx, between_span) else { return true };
+        for token in tokenize(&snippet) {
+            match token.kind {
+                TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace => {},
+                TokenKind::Comma if !seen_comma => seen_comma = true,
+                // named arguments, `start_val, name = end_val`
+                //                            ^^^^^^^^^ between_span
+                TokenKind::Ident | TokenKind::Eq if seen_comma => {},
+                // An unexpected token usually indicates that we crossed a macro boundary
+                //
+                // `println!(some_proc_macro!("input {}"), a)`
+                //                                      ^^^ between_span
+                // `println!("{}", val!(x))`
+                //               ^^^^^^^ between_span
+                _ => return true,
+            }
+        }
+
+        if !seen_comma {
+            return true;
+        }
+    }
+
+    false
+}
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 8114a8463fa..d7c94b909bd 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -463,12 +463,18 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
             && let Some(value_string) = snippet_opt(cx, arg.expr.span)
     {
             let (replacement, replace_raw) = match lit.kind {
-                LitKind::Str | LitKind::StrRaw(_)  => extract_str_literal(&value_string),
+                LitKind::Str | LitKind::StrRaw(_)  => match extract_str_literal(&value_string) {
+                    Some(extracted) => extracted,
+                    None => return,
+                },
                 LitKind::Char => (
                     match lit.symbol.as_str() {
                         "\"" => "\\\"",
                         "\\'" => "'",
-                        _ => &value_string[1..value_string.len() - 1],
+                        _ => match value_string.strip_prefix('\'').and_then(|s| s.strip_suffix('\'')) {
+                            Some(stripped) => stripped,
+                            None => return,
+                        },
                     }
                     .to_string(),
                     false,
@@ -533,13 +539,13 @@ fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgs, name: &str) {
 /// `r#"a"#` -> (`a`, true)
 ///
 /// `"b"` -> (`b`, false)
-fn extract_str_literal(literal: &str) -> (String, bool) {
+fn extract_str_literal(literal: &str) -> Option<(String, bool)> {
     let (literal, raw) = match literal.strip_prefix('r') {
         Some(stripped) => (stripped.trim_matches('#'), true),
         None => (literal, false),
     };
 
-    (literal[1..literal.len() - 1].to_string(), raw)
+    Some((literal.strip_prefix('"')?.strip_suffix('"')?.to_string(), raw))
 }
 
 enum UnescapeErr {
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs
index c5b58b0c060..1f15598db36 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -286,8 +286,30 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
     match (l, r) {
         (ExternCrate(l), ExternCrate(r)) => l == r,
         (Use(l), Use(r)) => eq_use_tree(l, r),
-        (Static(box ast::StaticItem { ty: lt, mutability: lm, expr: le}), Static(box ast::StaticItem { ty: rt, mutability: rm, expr: re})) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
-        (Const(box ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(box ast::ConstItem { defaultness: rd, ty: rt, expr: re} )) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
+        (
+            Static(box ast::StaticItem {
+                ty: lt,
+                mutability: lm,
+                expr: le,
+            }),
+            Static(box ast::StaticItem {
+                ty: rt,
+                mutability: rm,
+                expr: re,
+            }),
+        ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re),
+        (
+            Const(box ast::ConstItem {
+                defaultness: ld,
+                ty: lt,
+                expr: le,
+            }),
+            Const(box ast::ConstItem {
+                defaultness: rd,
+                ty: rt,
+                expr: re,
+            }),
+        ) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
         (
             Fn(box ast::Fn {
                 defaultness: ld,
@@ -451,7 +473,18 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
 pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
     use AssocItemKind::*;
     match (l, r) {
-        (Const(box ast::ConstItem { defaultness: ld, ty: lt, expr: le}), Const(box ast::ConstItem { defaultness: rd, ty: rt, expr: re})) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
+        (
+            Const(box ast::ConstItem {
+                defaultness: ld,
+                ty: lt,
+                expr: le,
+            }),
+            Const(box ast::ConstItem {
+                defaultness: rd,
+                ty: rt,
+                expr: re,
+            }),
+        ) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
         (
             Fn(box ast::Fn {
                 defaultness: ld,
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 9051cf51658..6b677df4641 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -32,7 +32,6 @@ extern crate rustc_lexer;
 extern crate rustc_lint;
 extern crate rustc_middle;
 extern crate rustc_mir_dataflow;
-extern crate rustc_parse_format;
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
@@ -77,7 +76,7 @@ use std::sync::OnceLock;
 use std::sync::{Mutex, MutexGuard};
 
 use if_chain::if_chain;
-use rustc_ast::ast::{self, LitKind};
+use rustc_ast::ast::{self, LitKind, RangeLimits};
 use rustc_ast::Attribute;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::unhash::UnhashMap;
@@ -95,6 +94,7 @@ use rustc_hir::{
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
 use rustc_middle::hir::place::PlaceBase;
+use rustc_middle::mir::ConstantKind;
 use rustc_middle::ty as rustc_ty;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::binding::BindingMode;
@@ -113,7 +113,8 @@ use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::Integer;
 
-use crate::consts::{constant, Constant};
+use crate::consts::{constant, miri_to_const, Constant};
+use crate::higher::Range;
 use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param};
 use crate::visitors::for_each_expr;
 
@@ -1490,6 +1491,68 @@ pub fn is_else_clause(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
     }
 }
 
+/// Checks whether the given `Expr` is a range equivalent to a `RangeFull`.
+/// For the lower bound, this means that:
+/// - either there is none
+/// - or it is the smallest value that can be represented by the range's integer type
+/// For the upper bound, this means that:
+/// - either there is none
+/// - or it is the largest value that can be represented by the range's integer type and is
+///   inclusive
+/// - or it is a call to some container's `len` method and is exclusive, and the range is passed to
+///   a method call on that same container (e.g. `v.drain(..v.len())`)
+/// If the given `Expr` is not some kind of range, the function returns `false`.
+pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Option<&Path<'_>>) -> bool {
+    let ty = cx.typeck_results().expr_ty(expr);
+    if let Some(Range { start, end, limits }) = Range::hir(expr) {
+        let start_is_none_or_min = start.map_or(true, |start| {
+            if let rustc_ty::Adt(_, subst) = ty.kind()
+                && let bnd_ty = subst.type_at(0)
+                && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx)
+                && 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)
+            {
+                start_const == min_const
+            } else {
+                false
+            }
+        });
+        let end_is_none_or_max = end.map_or(true, |end| {
+            match limits {
+                RangeLimits::Closed => {
+                    if let rustc_ty::Adt(_, subst) = ty.kind()
+                        && let bnd_ty = subst.type_at(0)
+                        && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx)
+                        && 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)
+                    {
+                        end_const == max_const
+                    } else {
+                        false
+                    }
+                },
+                RangeLimits::HalfOpen => {
+                    if let Some(container_path) = container_path
+                        && let ExprKind::MethodCall(name, self_arg, [], _) = end.kind
+                        && name.ident.name == sym::len
+                        && let ExprKind::Path(QPath::Resolved(None, path)) = self_arg.kind
+                    {
+                        container_path.res == path.res
+                    } else {
+                        false
+                    }
+                },
+            }
+        });
+        return start_is_none_or_min && end_is_none_or_max;
+    }
+    false
+}
+
 /// Checks whether the given expression is a constant integer of the given value.
 /// unlike `is_integer_literal`, this version does const folding
 pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool {
@@ -2104,8 +2167,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
         .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
     traits::impossible_predicates(
         cx.tcx,
-        traits::elaborate(cx.tcx, predicates)
-            .collect::<Vec<_>>(),
+        traits::elaborate(cx.tcx, predicates).collect::<Vec<_>>(),
     )
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index c0e32068eca..62d388a5ece 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -1,24 +1,16 @@
 #![allow(clippy::similar_names)] // `expr` and `expn`
 
-use crate::source::snippet_opt;
 use crate::visitors::{for_each_expr, Descend};
 
 use arrayvec::ArrayVec;
-use itertools::{izip, Either, Itertools};
-use rustc_ast::ast::LitKind;
-use rustc_ast::FormatArgs;
+use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, LangItem, Node, QPath, TyKind};
-use rustc_lexer::unescape::unescape_literal;
-use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
+use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
 use rustc_lint::LateContext;
-use rustc_parse_format::{self as rpf, Alignment};
 use rustc_span::def_id::DefId;
 use rustc_span::hygiene::{self, MacroKind, SyntaxContext};
-use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Pos, Span, SpanData, Symbol};
+use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Span, Symbol};
 use std::cell::RefCell;
-use std::iter::{once, zip};
 use std::ops::ControlFlow;
 use std::sync::atomic::{AtomicBool, Ordering};
 
@@ -226,11 +218,11 @@ pub enum PanicExpn<'a> {
     /// A single argument that implements `Display` - `panic!("{}", object)`
     Display(&'a Expr<'a>),
     /// Anything else - `panic!("error {}: {}", a, b)`
-    Format(FormatArgsExpn<'a>),
+    Format(&'a Expr<'a>),
 }
 
 impl<'a> PanicExpn<'a> {
-    pub fn parse(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<Self> {
+    pub fn parse(expr: &'a Expr<'a>) -> Option<Self> {
         let ExprKind::Call(callee, [arg, rest @ ..]) = &expr.kind else { return None };
         let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else { return None };
         let result = match path.segments.last().unwrap().ident.as_str() {
@@ -240,7 +232,7 @@ impl<'a> PanicExpn<'a> {
                 let ExprKind::AddrOf(_, _, e) = &arg.kind else { return None };
                 Self::Display(e)
             },
-            "panic_fmt" => Self::Format(FormatArgsExpn::parse(cx, arg)?),
+            "panic_fmt" => Self::Format(arg),
             // Since Rust 1.52, `assert_{eq,ne}` macros expand to use:
             // `core::panicking::assert_failed(.., left_val, right_val, None | Some(format_args!(..)));`
             "assert_failed" => {
@@ -252,7 +244,7 @@ impl<'a> PanicExpn<'a> {
                 // `msg_arg` is either `None` (no custom message) or `Some(format_args!(..))` (custom message)
                 let msg_arg = &rest[2];
                 match msg_arg.kind {
-                    ExprKind::Call(_, [fmt_arg]) => Self::Format(FormatArgsExpn::parse(cx, fmt_arg)?),
+                    ExprKind::Call(_, [fmt_arg]) => Self::Format(fmt_arg),
                     _ => Self::Empty,
                 }
             },
@@ -304,7 +296,7 @@ fn find_assert_args_inner<'a, const N: usize>(
     let mut args = ArrayVec::new();
     let panic_expn = for_each_expr(expr, |e| {
         if args.is_full() {
-            match PanicExpn::parse(cx, e) {
+            match PanicExpn::parse(e) {
                 Some(expn) => ControlFlow::Break(expn),
                 None => ControlFlow::Continue(Descend::Yes),
             }
@@ -391,30 +383,82 @@ pub fn collect_ast_format_args(span: Span, format_args: &FormatArgs) {
     });
 }
 
-/// Calls `callback` with an AST [`FormatArgs`] node if one is found
+/// Calls `callback` with an AST [`FormatArgs`] node if a `format_args` expansion is found as a
+/// descendant of `expn_id`
 pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId, callback: impl FnOnce(&FormatArgs)) {
     let format_args_expr = for_each_expr(start, |expr| {
         let ctxt = expr.span.ctxt();
-        if ctxt == start.span.ctxt() {
-            ControlFlow::Continue(Descend::Yes)
-        } else if ctxt.outer_expn().is_descendant_of(expn_id)
-            && macro_backtrace(expr.span)
+        if ctxt.outer_expn().is_descendant_of(expn_id) {
+            if macro_backtrace(expr.span)
                 .map(|macro_call| cx.tcx.item_name(macro_call.def_id))
                 .any(|name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl))
-        {
-            ControlFlow::Break(expr)
+            {
+                ControlFlow::Break(expr)
+            } else {
+                ControlFlow::Continue(Descend::Yes)
+            }
         } else {
             ControlFlow::Continue(Descend::No)
         }
     });
 
-    if let Some(format_args_expr) = format_args_expr {
+    if let Some(expr) = format_args_expr {
         AST_FORMAT_ARGS.with(|ast_format_args| {
-            ast_format_args.borrow().get(&format_args_expr.span).map(callback);
+            ast_format_args.borrow().get(&expr.span).map(callback);
         });
     }
 }
 
+/// Attempt to find the [`rustc_hir::Expr`] that corresponds to the [`FormatArgument`]'s value, if
+/// it cannot be found it will return the [`rustc_ast::Expr`].
+pub fn find_format_arg_expr<'hir, 'ast>(
+    start: &'hir Expr<'hir>,
+    target: &'ast FormatArgument,
+) -> Result<&'hir rustc_hir::Expr<'hir>, &'ast rustc_ast::Expr> {
+    for_each_expr(start, |expr| {
+        if expr.span == target.expr.span {
+            ControlFlow::Break(expr)
+        } else {
+            ControlFlow::Continue(())
+        }
+    })
+    .ok_or(&target.expr)
+}
+
+/// Span of the `:` and format specifiers
+///
+/// ```ignore
+/// format!("{:.}"), format!("{foo:.}")
+///           ^^                  ^^
+/// ```
+pub fn format_placeholder_format_span(placeholder: &FormatPlaceholder) -> Option<Span> {
+    let base = placeholder.span?.data();
+
+    // `base.hi` is `{...}|`, subtract 1 byte (the length of '}') so that it points before the closing
+    // brace `{...|}`
+    Some(Span::new(
+        placeholder.argument.span?.hi(),
+        base.hi - BytePos(1),
+        base.ctxt,
+        base.parent,
+    ))
+}
+
+/// Span covering the format string and values
+///
+/// ```ignore
+/// format("{}.{}", 10, 11)
+/// //     ^^^^^^^^^^^^^^^
+/// ```
+pub fn format_args_inputs_span(format_args: &FormatArgs) -> Span {
+    match format_args.arguments.explicit_args() {
+        [] => format_args.span,
+        [.., last] => format_args
+            .span
+            .to(hygiene::walk_chain(last.expr.span, format_args.span.ctxt())),
+    }
+}
+
 /// Returns the [`Span`] of the value at `index` extended to the previous comma, e.g. for the value
 /// `10`
 ///
@@ -436,251 +480,6 @@ pub fn format_arg_removal_span(format_args: &FormatArgs, index: usize) -> Option
     Some(current.with_lo(prev.hi()))
 }
 
-/// The format string doesn't exist in the HIR, so we reassemble it from source code
-#[derive(Debug)]
-pub struct FormatString {
-    /// Span of the whole format string literal, including `[r#]"`.
-    pub span: Span,
-    /// Snippet of the whole format string literal, including `[r#]"`.
-    pub snippet: String,
-    /// If the string is raw `r"..."`/`r#""#`, how many `#`s does it have on each side.
-    pub style: Option<usize>,
-    /// The unescaped value of the format string, e.g. `"val – {}"` for the literal
-    /// `"val \u{2013} {}"`.
-    pub unescaped: String,
-    /// The format string split by format args like `{..}`.
-    pub parts: Vec<Symbol>,
-}
-
-impl FormatString {
-    fn new(cx: &LateContext<'_>, pieces: &Expr<'_>) -> Option<Self> {
-        // format_args!(r"a {} b \", 1);
-        //
-        // expands to
-        //
-        // ::core::fmt::Arguments::new_v1(&["a ", " b \\"],
-        //      &[::core::fmt::ArgumentV1::new_display(&1)]);
-        //
-        // where `pieces` is the expression `&["a ", " b \\"]`. It has the span of `r"a {} b \"`
-        let span = pieces.span;
-        let snippet = snippet_opt(cx, span)?;
-
-        let (inner, style) = match tokenize(&snippet).next()?.kind {
-            TokenKind::Literal { kind, .. } => {
-                let style = match kind {
-                    LiteralKind::Str { .. } => None,
-                    LiteralKind::RawStr { n_hashes: Some(n), .. } => Some(n.into()),
-                    _ => return None,
-                };
-
-                let start = style.map_or(1, |n| 2 + n);
-                let end = snippet.len() - style.map_or(1, |n| 1 + n);
-
-                (&snippet[start..end], style)
-            },
-            _ => return None,
-        };
-
-        let mode = if style.is_some() {
-            unescape::Mode::RawStr
-        } else {
-            unescape::Mode::Str
-        };
-
-        let mut unescaped = String::with_capacity(inner.len());
-        // Sometimes the original string comes from a macro which accepts a malformed string, such as in a
-        // #[display(""somestring)] attribute (accepted by the `displaythis` crate). Reconstructing the
-        // string from the span will not be possible, so we will just return None here.
-        let mut unparsable = false;
-        unescape_literal(inner, mode, &mut |_, ch| match ch {
-            Ok(ch) => unescaped.push(ch),
-            Err(e) if !e.is_fatal() => (),
-            Err(_) => unparsable = true,
-        });
-        if unparsable {
-            return None;
-        }
-
-        let mut parts = Vec::new();
-        let _: Option<!> = for_each_expr(pieces, |expr| {
-            if let ExprKind::Lit(lit) = &expr.kind
-                && let LitKind::Str(symbol, _) = lit.node
-            {
-                parts.push(symbol);
-            }
-            ControlFlow::Continue(())
-        });
-
-        Some(Self {
-            span,
-            snippet,
-            style,
-            unescaped,
-            parts,
-        })
-    }
-}
-
-struct FormatArgsValues<'tcx> {
-    /// Values passed after the format string and implicit captures. `[1, z + 2, x]` for
-    /// `format!("{x} {} {}", 1, z + 2)`.
-    value_args: Vec<&'tcx Expr<'tcx>>,
-    /// Maps an `rt::v1::Argument::position` or an `rt::v1::Count::Param` to its index in
-    /// `value_args`
-    pos_to_value_index: Vec<usize>,
-    /// Used to check if a value is declared inline & to resolve `InnerSpan`s.
-    format_string_span: SpanData,
-}
-
-impl<'tcx> FormatArgsValues<'tcx> {
-    fn new_empty(format_string_span: SpanData) -> Self {
-        Self {
-            value_args: Vec::new(),
-            pos_to_value_index: Vec::new(),
-            format_string_span,
-        }
-    }
-
-    fn new(args: &'tcx Expr<'tcx>, format_string_span: SpanData) -> Self {
-        let mut pos_to_value_index = Vec::new();
-        let mut value_args = Vec::new();
-        let _: Option<!> = for_each_expr(args, |expr| {
-            if expr.span.ctxt() == args.span.ctxt() {
-                // ArgumentV1::new_<format_trait>(<val>)
-                // ArgumentV1::from_usize(<val>)
-                if let ExprKind::Call(callee, [val]) = expr.kind
-                    && let ExprKind::Path(QPath::TypeRelative(ty, _)) = callee.kind
-                    && let TyKind::Path(QPath::LangItem(LangItem::FormatArgument, _, _)) = ty.kind
-                {
-                    let val_idx = if val.span.ctxt() == expr.span.ctxt()
-                        && let ExprKind::Field(_, field) = val.kind
-                        && let Ok(idx) = field.name.as_str().parse()
-                    {
-                        // tuple index
-                        idx
-                    } else {
-                        // assume the value expression is passed directly
-                        pos_to_value_index.len()
-                    };
-
-                    pos_to_value_index.push(val_idx);
-                }
-                ControlFlow::Continue(Descend::Yes)
-            } else {
-                // assume that any expr with a differing span is a value
-                value_args.push(expr);
-                ControlFlow::Continue(Descend::No)
-            }
-        });
-
-        Self {
-            value_args,
-            pos_to_value_index,
-            format_string_span,
-        }
-    }
-}
-
-/// The positions of a format argument's value, precision and width
-///
-/// A position is an index into the second argument of `Arguments::new_v1[_formatted]`
-#[derive(Debug, Default, Copy, Clone)]
-struct ParamPosition {
-    /// The position stored in `rt::v1::Argument::position`.
-    value: usize,
-    /// The position stored in `rt::v1::FormatSpec::width` if it is a `Count::Param`.
-    width: Option<usize>,
-    /// The position stored in `rt::v1::FormatSpec::precision` if it is a `Count::Param`.
-    precision: Option<usize>,
-}
-
-impl<'tcx> Visitor<'tcx> for ParamPosition {
-    fn visit_expr_field(&mut self, field: &'tcx ExprField<'tcx>) {
-        match field.ident.name {
-            sym::position => {
-                if let ExprKind::Lit(lit) = &field.expr.kind
-                    && let LitKind::Int(pos, _) = lit.node
-                {
-                    self.value = pos as usize;
-                }
-            },
-            sym::precision => {
-                self.precision = parse_count(field.expr);
-            },
-            sym::width => {
-                self.width = parse_count(field.expr);
-            },
-            _ => walk_expr(self, field.expr),
-        }
-    }
-}
-
-fn parse_count(expr: &Expr<'_>) -> Option<usize> {
-    // <::core::fmt::rt::v1::Count>::Param(1usize),
-    if let ExprKind::Call(ctor, [val]) = expr.kind
-        && let ExprKind::Path(QPath::TypeRelative(_, path)) = ctor.kind
-            && path.ident.name == sym::Param
-            && let ExprKind::Lit(lit) = &val.kind
-            && let LitKind::Int(pos, _) = lit.node
-    {
-        Some(pos as usize)
-    } else {
-        None
-    }
-}
-
-/// Parses the `fmt` arg of `Arguments::new_v1_formatted(pieces, args, fmt, _)`
-fn parse_rt_fmt<'tcx>(fmt_arg: &'tcx Expr<'tcx>) -> Option<impl Iterator<Item = ParamPosition> + 'tcx> {
-    if let ExprKind::AddrOf(.., array) = fmt_arg.kind
-        && let ExprKind::Array(specs) = array.kind
-    {
-        Some(specs.iter().map(|spec| {
-            if let ExprKind::Call(f, args) = spec.kind
-                && let ExprKind::Path(QPath::TypeRelative(ty, f)) = f.kind
-                && let TyKind::Path(QPath::LangItem(LangItem::FormatPlaceholder, _, _)) = ty.kind
-                && f.ident.name == sym::new
-                && let [position, _fill, _align, _flags, precision, width] = args
-                && let ExprKind::Lit(position) = &position.kind
-                && let LitKind::Int(position, _) = position.node {
-                    ParamPosition {
-                        value: position as usize,
-                        width: parse_count(width),
-                        precision: parse_count(precision),
-                    }
-            } else {
-                ParamPosition::default()
-            }
-        }))
-    } else {
-        None
-    }
-}
-
-/// `Span::from_inner`, but for `rustc_parse_format`'s `InnerSpan`
-fn span_from_inner(base: SpanData, inner: rpf::InnerSpan) -> Span {
-    Span::new(
-        base.lo + BytePos::from_usize(inner.start),
-        base.lo + BytePos::from_usize(inner.end),
-        base.ctxt,
-        base.parent,
-    )
-}
-
-/// How a format parameter is used in the format string
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-pub enum FormatParamKind {
-    /// An implicit parameter , such as `{}` or `{:?}`.
-    Implicit,
-    /// A parameter with an explicit number, e.g. `{1}`, `{0:?}`, or `{:.0$}`
-    Numbered,
-    /// A parameter with an asterisk precision. e.g. `{:.*}`.
-    Starred,
-    /// A named parameter with a named `value_arg`, such as the `x` in `format!("{x}", x = 1)`.
-    Named(Symbol),
-    /// An implicit named parameter, such as the `y` in `format!("{y}")`.
-    NamedInline(Symbol),
-}
-
 /// Where a format parameter is being used in the format string
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub enum FormatParamUsage {
@@ -692,467 +491,6 @@ pub enum FormatParamUsage {
     Precision,
 }
 
-/// A `FormatParam` is any place in a `FormatArgument` that refers to a supplied value, e.g.
-///
-/// ```
-/// let precision = 2;
-/// format!("{:.precision$}", 0.1234);
-/// ```
-///
-/// has two `FormatParam`s, a [`FormatParamKind::Implicit`] `.kind` with a `.value` of `0.1234`
-/// and a [`FormatParamKind::NamedInline("precision")`] `.kind` with a `.value` of `2`
-#[derive(Debug, Copy, Clone)]
-pub struct FormatParam<'tcx> {
-    /// The expression this parameter refers to.
-    pub value: &'tcx Expr<'tcx>,
-    /// How this parameter refers to its `value`.
-    pub kind: FormatParamKind,
-    /// Where this format param is being used - argument/width/precision
-    pub usage: FormatParamUsage,
-    /// Span of the parameter, may be zero width. Includes the whitespace of implicit parameters.
-    ///
-    /// ```text
-    /// format!("{}, {  }, {0}, {name}", ...);
-    ///          ^    ~~    ~    ~~~~
-    /// ```
-    pub span: Span,
-}
-
-impl<'tcx> FormatParam<'tcx> {
-    fn new(
-        mut kind: FormatParamKind,
-        usage: FormatParamUsage,
-        position: usize,
-        inner: rpf::InnerSpan,
-        values: &FormatArgsValues<'tcx>,
-    ) -> Option<Self> {
-        let value_index = *values.pos_to_value_index.get(position)?;
-        let value = *values.value_args.get(value_index)?;
-        let span = span_from_inner(values.format_string_span, inner);
-
-        // if a param is declared inline, e.g. `format!("{x}")`, the generated expr's span points
-        // into the format string
-        if let FormatParamKind::Named(name) = kind && values.format_string_span.contains(value.span.data()) {
-            kind = FormatParamKind::NamedInline(name);
-        }
-
-        Some(Self {
-            value,
-            kind,
-            usage,
-            span,
-        })
-    }
-}
-
-/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and
-/// [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
-#[derive(Debug, Copy, Clone)]
-pub enum Count<'tcx> {
-    /// Specified with a literal number, stores the value.
-    Is(usize, Span),
-    /// Specified using `$` and `*` syntaxes. The `*` format is still considered to be
-    /// `FormatParamKind::Numbered`.
-    Param(FormatParam<'tcx>),
-    /// Not specified.
-    Implied(Option<Span>),
-}
-
-impl<'tcx> Count<'tcx> {
-    fn new(
-        usage: FormatParamUsage,
-        count: rpf::Count<'_>,
-        position: Option<usize>,
-        inner: Option<rpf::InnerSpan>,
-        values: &FormatArgsValues<'tcx>,
-    ) -> Option<Self> {
-        let span = inner.map(|inner| span_from_inner(values.format_string_span, inner));
-
-        Some(match count {
-            rpf::Count::CountIs(val) => Self::Is(val, span?),
-            rpf::Count::CountIsName(name, _) => Self::Param(FormatParam::new(
-                FormatParamKind::Named(Symbol::intern(name)),
-                usage,
-                position?,
-                inner?,
-                values,
-            )?),
-            rpf::Count::CountIsParam(_) => Self::Param(FormatParam::new(
-                FormatParamKind::Numbered,
-                usage,
-                position?,
-                inner?,
-                values,
-            )?),
-            rpf::Count::CountIsStar(_) => Self::Param(FormatParam::new(
-                FormatParamKind::Starred,
-                usage,
-                position?,
-                inner?,
-                values,
-            )?),
-            rpf::Count::CountImplied => Self::Implied(span),
-        })
-    }
-
-    pub fn is_implied(self) -> bool {
-        matches!(self, Count::Implied(_))
-    }
-
-    pub fn param(self) -> Option<FormatParam<'tcx>> {
-        match self {
-            Count::Param(param) => Some(param),
-            _ => None,
-        }
-    }
-
-    pub fn span(self) -> Option<Span> {
-        match self {
-            Count::Is(_, span) => Some(span),
-            Count::Param(param) => Some(param.span),
-            Count::Implied(span) => span,
-        }
-    }
-}
-
-/// Specification for the formatting of an argument in the format string. See
-/// <https://doc.rust-lang.org/std/fmt/index.html#formatting-parameters> for the precise meanings.
-#[derive(Debug)]
-pub struct FormatSpec<'tcx> {
-    /// Optionally specified character to fill alignment with.
-    pub fill: Option<char>,
-    /// Optionally specified alignment.
-    pub align: Alignment,
-    /// Whether all flag options are set to default (no flags specified).
-    pub no_flags: bool,
-    /// Represents either the maximum width or the integer precision.
-    pub precision: Count<'tcx>,
-    /// The minimum width, will be padded according to `width`/`align`
-    pub width: Count<'tcx>,
-    /// The formatting trait used by the argument, e.g. `sym::Display` for `{}`, `sym::Debug` for
-    /// `{:?}`.
-    pub r#trait: Symbol,
-    pub trait_span: Option<Span>,
-}
-
-impl<'tcx> FormatSpec<'tcx> {
-    fn new(spec: rpf::FormatSpec<'_>, positions: ParamPosition, values: &FormatArgsValues<'tcx>) -> Option<Self> {
-        Some(Self {
-            fill: spec.fill,
-            align: spec.align,
-            no_flags: spec.sign.is_none() && !spec.alternate && !spec.zero_pad && spec.debug_hex.is_none(),
-            precision: Count::new(
-                FormatParamUsage::Precision,
-                spec.precision,
-                positions.precision,
-                spec.precision_span,
-                values,
-            )?,
-            width: Count::new(
-                FormatParamUsage::Width,
-                spec.width,
-                positions.width,
-                spec.width_span,
-                values,
-            )?,
-            r#trait: match spec.ty {
-                "" => sym::Display,
-                "?" => sym::Debug,
-                "o" => sym!(Octal),
-                "x" => sym!(LowerHex),
-                "X" => sym!(UpperHex),
-                "p" => sym::Pointer,
-                "b" => sym!(Binary),
-                "e" => sym!(LowerExp),
-                "E" => sym!(UpperExp),
-                _ => return None,
-            },
-            trait_span: spec
-                .ty_span
-                .map(|span| span_from_inner(values.format_string_span, span)),
-        })
-    }
-
-    /// Returns true if this format spec is unchanged from the default. e.g. returns true for `{}`,
-    /// `{foo}` and `{2}`, but false for `{:?}`, `{foo:5}` and `{3:.5}`
-    pub fn is_default(&self) -> bool {
-        self.r#trait == sym::Display && self.is_default_for_trait()
-    }
-
-    /// Has no other formatting specifiers than setting the format trait. returns true for `{}`,
-    /// `{foo}`, `{:?}`, but false for `{foo:5}`, `{3:.5?}`
-    pub fn is_default_for_trait(&self) -> bool {
-        self.width.is_implied() && self.precision.is_implied() && self.align == Alignment::AlignUnknown && self.no_flags
-    }
-}
-
-/// A format argument, such as `{}`, `{foo:?}`.
-#[derive(Debug)]
-pub struct FormatArg<'tcx> {
-    /// The parameter the argument refers to.
-    pub param: FormatParam<'tcx>,
-    /// How to format `param`.
-    pub format: FormatSpec<'tcx>,
-    /// span of the whole argument, `{..}`.
-    pub span: Span,
-}
-
-impl<'tcx> FormatArg<'tcx> {
-    /// Span of the `:` and format specifiers
-    ///
-    /// ```ignore
-    /// format!("{:.}"), format!("{foo:.}")
-    ///           ^^                  ^^
-    /// ```
-    pub fn format_span(&self) -> Span {
-        let base = self.span.data();
-
-        // `base.hi` is `{...}|`, subtract 1 byte (the length of '}') so that it points before the closing
-        // brace `{...|}`
-        Span::new(self.param.span.hi(), base.hi - BytePos(1), base.ctxt, base.parent)
-    }
-}
-
-/// A parsed `format_args!` expansion.
-#[derive(Debug)]
-pub struct FormatArgsExpn<'tcx> {
-    /// The format string literal.
-    pub format_string: FormatString,
-    /// The format arguments, such as `{:?}`.
-    pub args: Vec<FormatArg<'tcx>>,
-    /// Has an added newline due to `println!()`/`writeln!()`/etc. The last format string part will
-    /// include this added newline.
-    pub newline: bool,
-    /// Spans of the commas between the format string and explicit values, excluding any trailing
-    /// comma
-    ///
-    /// ```ignore
-    /// format!("..", 1, 2, 3,)
-    /// //          ^  ^  ^
-    /// ```
-    comma_spans: Vec<Span>,
-    /// Explicit values passed after the format string, ignoring implicit captures. `[1, z + 2]` for
-    /// `format!("{x} {} {y}", 1, z + 2)`.
-    explicit_values: Vec<&'tcx Expr<'tcx>>,
-}
-
-impl<'tcx> FormatArgsExpn<'tcx> {
-    /// Gets the spans of the commas inbetween the format string and explicit args, not including
-    /// any trailing comma
-    ///
-    /// ```ignore
-    /// format!("{} {}", a, b)
-    /// //             ^  ^
-    /// ```
-    ///
-    /// Ensures that the format string and values aren't coming from a proc macro that sets the
-    /// output span to that of its input
-    fn comma_spans(cx: &LateContext<'_>, explicit_values: &[&Expr<'_>], fmt_span: Span) -> Option<Vec<Span>> {
-        // `format!("{} {} {c}", "one", "two", c = "three")`
-        //                       ^^^^^  ^^^^^      ^^^^^^^
-        let value_spans = explicit_values
-            .iter()
-            .map(|val| hygiene::walk_chain(val.span, fmt_span.ctxt()));
-
-        // `format!("{} {} {c}", "one", "two", c = "three")`
-        //                     ^^     ^^     ^^^^^^
-        let between_spans = once(fmt_span)
-            .chain(value_spans)
-            .tuple_windows()
-            .map(|(start, end)| start.between(end));
-
-        let mut comma_spans = Vec::new();
-        for between_span in between_spans {
-            let mut offset = 0;
-            let mut seen_comma = false;
-
-            for token in tokenize(&snippet_opt(cx, between_span)?) {
-                match token.kind {
-                    TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace => {},
-                    TokenKind::Comma if !seen_comma => {
-                        seen_comma = true;
-
-                        let base = between_span.data();
-                        comma_spans.push(Span::new(
-                            base.lo + BytePos(offset),
-                            base.lo + BytePos(offset + 1),
-                            base.ctxt,
-                            base.parent,
-                        ));
-                    },
-                    // named arguments, `start_val, name = end_val`
-                    //                            ^^^^^^^^^ between_span
-                    TokenKind::Ident | TokenKind::Eq if seen_comma => {},
-                    // An unexpected token usually indicates the format string or a value came from a proc macro output
-                    // that sets the span of its output to an input, e.g. `println!(some_proc_macro!("input"), ..)` that
-                    // emits a string literal with the span set to that of `"input"`
-                    _ => return None,
-                }
-                offset += token.len;
-            }
-
-            if !seen_comma {
-                return None;
-            }
-        }
-
-        Some(comma_spans)
-    }
-
-    pub fn parse(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<Self> {
-        let macro_name = macro_backtrace(expr.span)
-            .map(|macro_call| cx.tcx.item_name(macro_call.def_id))
-            .find(|&name| matches!(name, sym::const_format_args | sym::format_args | sym::format_args_nl))?;
-        let newline = macro_name == sym::format_args_nl;
-
-        // ::core::fmt::Arguments::new_const(pieces)
-        // ::core::fmt::Arguments::new_v1(pieces, args)
-        // ::core::fmt::Arguments::new_v1_formatted(pieces, args, fmt, _unsafe_arg)
-        if let ExprKind::Call(callee, [pieces, rest @ ..]) = expr.kind
-            && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = callee.kind
-            && let TyKind::Path(QPath::LangItem(LangItem::FormatArguments, _, _)) = ty.kind
-            && matches!(seg.ident.as_str(), "new_const" | "new_v1" | "new_v1_formatted")
-        {
-            let format_string = FormatString::new(cx, pieces)?;
-
-            let mut parser = rpf::Parser::new(
-                &format_string.unescaped,
-                format_string.style,
-                Some(format_string.snippet.clone()),
-                // `format_string.unescaped` does not contain the appended newline
-                false,
-                rpf::ParseMode::Format,
-            );
-
-            let parsed_args = parser
-                .by_ref()
-                .filter_map(|piece| match piece {
-                    rpf::Piece::NextArgument(a) => Some(a),
-                    rpf::Piece::String(_) => None,
-                })
-                .collect_vec();
-            if !parser.errors.is_empty() {
-                return None;
-            }
-
-            let positions = if let Some(fmt_arg) = rest.get(1) {
-                // If the argument contains format specs, `new_v1_formatted(_, _, fmt, _)`, parse
-                // them.
-
-                Either::Left(parse_rt_fmt(fmt_arg)?)
-            } else {
-                // If no format specs are given, the positions are in the given order and there are
-                // no `precision`/`width`s to consider.
-
-                Either::Right((0..).map(|n| ParamPosition {
-                    value: n,
-                    width: None,
-                    precision: None,
-                }))
-            };
-
-            let values = if let Some(args) = rest.first() {
-                FormatArgsValues::new(args, format_string.span.data())
-            } else {
-                FormatArgsValues::new_empty(format_string.span.data())
-            };
-
-            let args = izip!(positions, parsed_args, parser.arg_places)
-                .map(|(position, parsed_arg, arg_span)| {
-                    Some(FormatArg {
-                        param: FormatParam::new(
-                            match parsed_arg.position {
-                                rpf::Position::ArgumentImplicitlyIs(_) => FormatParamKind::Implicit,
-                                rpf::Position::ArgumentIs(_) => FormatParamKind::Numbered,
-                                // NamedInline is handled by `FormatParam::new()`
-                                rpf::Position::ArgumentNamed(name) => FormatParamKind::Named(Symbol::intern(name)),
-                            },
-                            FormatParamUsage::Argument,
-                            position.value,
-                            parsed_arg.position_span,
-                            &values,
-                        )?,
-                        format: FormatSpec::new(parsed_arg.format, position, &values)?,
-                        span: span_from_inner(values.format_string_span, arg_span),
-                    })
-                })
-                .collect::<Option<Vec<_>>>()?;
-
-            let mut explicit_values = values.value_args;
-            // remove values generated for implicitly captured vars
-            let len = explicit_values
-                .iter()
-                .take_while(|val| !format_string.span.contains(val.span))
-                .count();
-            explicit_values.truncate(len);
-
-            let comma_spans = Self::comma_spans(cx, &explicit_values, format_string.span)?;
-
-            Some(Self {
-                format_string,
-                args,
-                newline,
-                comma_spans,
-                explicit_values,
-            })
-        } else {
-            None
-        }
-    }
-
-    pub fn find_nested(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expn_id: ExpnId) -> Option<Self> {
-        for_each_expr(expr, |e| {
-            let e_ctxt = e.span.ctxt();
-            if e_ctxt == expr.span.ctxt() {
-                ControlFlow::Continue(Descend::Yes)
-            } else if e_ctxt.outer_expn().is_descendant_of(expn_id) {
-                if let Some(args) = FormatArgsExpn::parse(cx, e) {
-                    ControlFlow::Break(args)
-                } else {
-                    ControlFlow::Continue(Descend::No)
-                }
-            } else {
-                ControlFlow::Continue(Descend::No)
-            }
-        })
-    }
-
-    /// Source callsite span of all inputs
-    pub fn inputs_span(&self) -> Span {
-        match *self.explicit_values {
-            [] => self.format_string.span,
-            [.., last] => self
-                .format_string
-                .span
-                .to(hygiene::walk_chain(last.span, self.format_string.span.ctxt())),
-        }
-    }
-
-    /// Get the span of a value expanded to the previous comma, e.g. for the value `10`
-    ///
-    /// ```ignore
-    /// format("{}.{}", 10, 11)
-    /// //            ^^^^
-    /// ```
-    pub fn value_with_prev_comma_span(&self, value_id: HirId) -> Option<Span> {
-        for (comma_span, value) in zip(&self.comma_spans, &self.explicit_values) {
-            if value.hir_id == value_id {
-                return Some(comma_span.to(hygiene::walk_chain(value.span, comma_span.ctxt())));
-            }
-        }
-
-        None
-    }
-
-    /// Iterator of all format params, both values and those referenced by `width`/`precision`s.
-    pub fn params(&'tcx self) -> impl Iterator<Item = FormatParam<'tcx>> {
-        self.args
-            .iter()
-            .flat_map(|arg| [Some(arg.param), arg.format.precision.param(), arg.format.width.param()])
-            .flatten()
-    }
-}
-
 /// A node with a `HirId` and a `Span`
 pub trait HirNode {
     fn hir_id(&self) -> HirId;
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index c919575bfe9..9be2d0eae80 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -23,6 +23,7 @@ pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
 pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
 pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
 pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
+pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
 pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
 pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
 pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
@@ -113,6 +114,7 @@ pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
 pub const STDOUT: [&str; 4] = ["std", "io", "stdio", "stdout"];
 pub const CONVERT_IDENTITY: [&str; 3] = ["core", "convert", "identity"];
 pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
+pub const STD_IO_LINES: [&str; 3] = ["std", "io", "Lines"];
 pub const STD_IO_SEEK: [&str; 3] = ["std", "io", "Seek"];
 pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
 pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 0b47234647f..9449f0b5567 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -541,9 +541,25 @@ pub fn same_type_and_consts<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
 pub fn is_uninit_value_valid_for_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
     cx.tcx
         .check_validity_requirement((ValidityRequirement::Uninit, cx.param_env.and(ty)))
-        // For types containing generic parameters we cannot get a layout to check.
-        // Therefore, we are conservative and assume that they don't allow uninit.
-        .unwrap_or(false)
+        .unwrap_or_else(|_| is_uninit_value_valid_for_ty_fallback(cx, ty))
+}
+
+/// A fallback for polymorphic types, which are not supported by `check_validity_requirement`.
+fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+    match *ty.kind() {
+        // The array length may be polymorphic, let's try the inner type.
+        ty::Array(component, _) => is_uninit_value_valid_for_ty(cx, component),
+        // Peek through tuples and try their fallbacks.
+        ty::Tuple(types) => types.iter().all(|ty| is_uninit_value_valid_for_ty(cx, ty)),
+        // Unions are always fine right now.
+        // This includes MaybeUninit, the main way people use uninitialized memory.
+        // For ADTs, we could look at all fields just like for tuples, but that's potentially
+        // exponential, so let's avoid doing that for now. Code doing that is sketchy enough to
+        // just use an `#[allow()]`.
+        ty::Adt(adt, _) => adt.is_union(),
+        // For the rest, conservatively assume that they cannot be uninit.
+        _ => false,
+    }
 }
 
 /// Gets an iterator over all predicates which apply to the given item.
diff --git a/src/tools/clippy/etc/relicense/RELICENSE_DOCUMENTATION.md b/src/tools/clippy/etc/relicense/RELICENSE_DOCUMENTATION.md
index fcd7abbf3f1..ffb99cde4f8 100644
--- a/src/tools/clippy/etc/relicense/RELICENSE_DOCUMENTATION.md
+++ b/src/tools/clippy/etc/relicense/RELICENSE_DOCUMENTATION.md
@@ -35,7 +35,7 @@ relicensing are archived on GitHub. We also have saved Wayback Machine copies of
 
 The usernames of commenters on these issues can be found in relicense_comments.txt
 
-There are a couple people in relicense_comments.txt who are not found in contributors.txt:
+There are a few people in relicense_comments.txt who are not found in contributors.txt:
 
 - @EpocSquadron has [made minor text contributions to the
   README](https://github.com/rust-lang/rust-clippy/commits?author=EpocSquadron) which have since been overwritten, and
@@ -55,7 +55,7 @@ There are a couple people in relicense_comments.txt who are not found in contrib
   we rewrote (see below)
 
 
-Two of these contributors had nonminor contributions (#2184, #427) requiring a rewrite, carried out in #3251
+Two of these contributors had non-minor contributions (#2184, #427) requiring a rewrite, carried out in #3251
 ([archive](http://web.archive.org/web/20181005192411/https://github.com/rust-lang-nursery/rust-clippy/pull/3251),
 [screenshot](https://user-images.githubusercontent.com/1617736/46573515-5cb69580-c94b-11e8-86e5-b456452121b2.png))
 
diff --git a/src/tools/clippy/lintcheck/README.md b/src/tools/clippy/lintcheck/README.md
index e997eb47e32..faf3ce9093a 100644
--- a/src/tools/clippy/lintcheck/README.md
+++ b/src/tools/clippy/lintcheck/README.md
@@ -16,7 +16,7 @@ or
 cargo lintcheck
 ```
 
-By default the logs will be saved into
+By default, the logs will be saved into
 `lintcheck-logs/lintcheck_crates_logs.txt`.
 
 You can set a custom sources.toml by adding `--crates-toml custom.toml` or using
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 0b2458ea007..91e8ccea1f4 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-03-24"
+channel = "nightly-2023-04-06"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 9e0822404b6..718bc41fb99 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -130,7 +130,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks {
     #[allow(rustc::bad_opt_access)]
     fn config(&mut self, config: &mut interface::Config) {
         let conf_path = clippy_lints::lookup_conf_file();
-        let conf_path_string = if let Ok(Some(path)) = &conf_path {
+        let conf_path_string = if let Ok((Some(path), _)) = &conf_path {
             path.to_str().map(String::from)
         } else {
             None
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr b/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr
index 98697e001f9..aa1b3c638a0 100644
--- a/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/multiple_config_files/warn/src/main.stderr
@@ -1,2 +1,4 @@
-Using config file `$SRC_DIR/.clippy.toml`
-Warning: `$SRC_DIR/clippy.toml` will be ignored.
+warning: using config file `$SRC_DIR/.clippy.toml`, `$SRC_DIR/clippy.toml` will be ignored
+
+warning: 1 warning emitted
+
diff --git a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr
index ee941762196..1be0cda12fc 100644
--- a/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr
+++ b/src/tools/clippy/tests/ui-toml/allow_mixed_uninlined_format_args/uninlined_format_args.stderr
@@ -11,29 +11,29 @@ LL -     println!("val='{}'", local_i32);
 LL +     println!("val='{local_i32}'");
    |
 
-error: literal with an empty format string
-  --> $DIR/uninlined_format_args.rs:10:35
+error: variables can be used directly in the `format!` string
+  --> $DIR/uninlined_format_args.rs:10:5
    |
 LL |     println!("Hello {} is {:.*}", "x", local_i32, local_f64);
-   |                                   ^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `-D clippy::print-literal` implied by `-D warnings`
-help: try this
+help: change this to
    |
 LL -     println!("Hello {} is {:.*}", "x", local_i32, local_f64);
-LL +     println!("Hello x is {:.*}", local_i32, local_f64);
+LL +     println!("Hello {} is {local_f64:.local_i32$}", "x");
    |
 
-error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:10:5
+error: literal with an empty format string
+  --> $DIR/uninlined_format_args.rs:10:35
    |
 LL |     println!("Hello {} is {:.*}", "x", local_i32, local_f64);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                   ^^^
    |
-help: change this to
+   = note: `-D clippy::print-literal` implied by `-D warnings`
+help: try this
    |
 LL -     println!("Hello {} is {:.*}", "x", local_i32, local_f64);
-LL +     println!("Hello {} is {local_f64:.local_i32$}", "x");
+LL +     println!("Hello x is {:.*}", local_i32, local_f64);
    |
 
 error: variables can be used directly in the `format!` string
diff --git a/src/tools/clippy/tests/ui-toml/extra_unused_type_parameters/clippy.toml b/src/tools/clippy/tests/ui-toml/extra_unused_type_parameters/clippy.toml
new file mode 100644
index 00000000000..5f304987aa9
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/extra_unused_type_parameters/clippy.toml
@@ -0,0 +1 @@
+avoid-breaking-exported-api = true
diff --git a/src/tools/clippy/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs b/src/tools/clippy/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs
new file mode 100644
index 00000000000..5655232455c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/extra_unused_type_parameters/extra_unused_type_parameters.rs
@@ -0,0 +1,9 @@
+pub struct S;
+
+impl S {
+    pub fn exported_fn<T>() {
+        unimplemented!();
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/large_futures/clippy.toml b/src/tools/clippy/tests/ui-toml/large_futures/clippy.toml
new file mode 100644
index 00000000000..61bb17fdf6b
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/large_futures/clippy.toml
@@ -0,0 +1 @@
+future-size-threshold = 1024
diff --git a/src/tools/clippy/tests/ui-toml/large_futures/large_futures.rs b/src/tools/clippy/tests/ui-toml/large_futures/large_futures.rs
new file mode 100644
index 00000000000..4158df8b5ff
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/large_futures/large_futures.rs
@@ -0,0 +1,27 @@
+#![warn(clippy::large_futures)]
+
+fn main() {}
+
+pub async fn should_warn() {
+    let x = [0u8; 1024];
+    async {}.await;
+    dbg!(x);
+}
+
+pub async fn should_not_warn() {
+    let x = [0u8; 1020];
+    async {}.await;
+    dbg!(x);
+}
+
+pub async fn bar() {
+    should_warn().await;
+
+    async {
+        let x = [0u8; 1024];
+        dbg!(x);
+    }
+    .await;
+
+    should_not_warn().await;
+}
diff --git a/src/tools/clippy/tests/ui-toml/large_futures/large_futures.stderr b/src/tools/clippy/tests/ui-toml/large_futures/large_futures.stderr
new file mode 100644
index 00000000000..b92734de2f0
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/large_futures/large_futures.stderr
@@ -0,0 +1,10 @@
+error: large future with a size of 1026 bytes
+  --> $DIR/large_futures.rs:18:5
+   |
+LL |     should_warn().await;
+   |     ^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(should_warn())`
+   |
+   = note: `-D clippy::large-futures` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 6a246afac76..8447c31722d 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -24,6 +24,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
            enforced-import-renames
            enum-variant-name-threshold
            enum-variant-size-threshold
+           future-size-threshold
            ignore-interior-mutability
            large-error-threshold
            literal-representation-threshold
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index ee7d2ba444b..3c06676d722 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -425,4 +425,8 @@ pub fn integer_arithmetic() {
     i ^= i;
 }
 
+pub fn issue_10583(a: u16) -> u16 {
+    10 / a
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 3895f08964c..2c8ee2884e7 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -577,6 +577,12 @@ LL |     i * 2;
    |     ^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:394:5
+   |
+LL |     1 % i / 2;
+   |     ^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
   --> $DIR/arithmetic_side_effects.rs:395:5
    |
 LL |     i - 2 + 2 - i;
@@ -642,5 +648,11 @@ error: arithmetic operation that can potentially result in unexpected side-effec
 LL |     i %= var2;
    |     ^^^^^^^^^
 
-error: aborting due to 107 previous errors
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:429:5
+   |
+LL |     10 / a
+   |     ^^^^^^
+
+error: aborting due to 109 previous errors
 
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
index 325be83a0d7..3d5beab1eff 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macros.rs
@@ -63,7 +63,7 @@ fn group_with_span(delimiter: Delimiter, stream: TokenStream, span: Span) -> Gro
 /// Token used to escape the following token from the macro's span rules.
 const ESCAPE_CHAR: char = '$';
 
-/// Takes a single token followed by a sequence tokens. Returns the sequence of tokens with their
+/// Takes a single token followed by a sequence of tokens. Returns the sequence of tokens with their
 /// span set to that of the first token. Tokens may be escaped with either `#ident` or `#(tokens)`.
 #[proc_macro]
 pub fn with_span(input: TokenStream) -> TokenStream {
diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs
index 8b2673c2a7f..a86b85706a3 100644
--- a/src/tools/clippy/tests/ui/cast.rs
+++ b/src/tools/clippy/tests/ui/cast.rs
@@ -29,6 +29,12 @@ fn main() {
     1f64 as isize;
     1f64 as usize;
     1f32 as u32 as u16;
+    {
+        let _x: i8 = 1i32 as _;
+        1f32 as i32;
+        1f64 as i32;
+        1f32 as u8;
+    }
     // Test clippy::cast_possible_wrap
     1u8 as i8;
     1u16 as i16;
diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr
index 451078de23b..65ecf1aa37a 100644
--- a/src/tools/clippy/tests/ui/cast.stderr
+++ b/src/tools/clippy/tests/ui/cast.stderr
@@ -44,10 +44,6 @@ LL |     1f32 as i32;
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
    = note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     i32::try_from(1f32);
-   |     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `f32` to `u32` may truncate the value
   --> $DIR/cast.rs:25:5
@@ -56,10 +52,6 @@ LL |     1f32 as u32;
    |     ^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     u32::try_from(1f32);
-   |     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `f32` to `u32` may lose the sign of the value
   --> $DIR/cast.rs:25:5
@@ -76,10 +68,6 @@ LL |     1f64 as f32;
    |     ^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     f32::try_from(1f64);
-   |     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `i32` to `i8` may truncate the value
   --> $DIR/cast.rs:27:5
@@ -112,10 +100,6 @@ LL |     1f64 as isize;
    |     ^^^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     isize::try_from(1f64);
-   |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `f64` to `usize` may truncate the value
   --> $DIR/cast.rs:30:5
@@ -124,10 +108,6 @@ LL |     1f64 as usize;
    |     ^^^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     usize::try_from(1f64);
-   |     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `f64` to `usize` may lose the sign of the value
   --> $DIR/cast.rs:30:5
@@ -154,10 +134,6 @@ LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^
    |
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
-help: ... or use `try_from` and handle the error accordingly
-   |
-LL |     u32::try_from(1f32) as u16;
-   |     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `f32` to `u32` may lose the sign of the value
   --> $DIR/cast.rs:31:5
@@ -165,8 +141,50 @@ error: casting `f32` to `u32` may lose the sign of the value
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^
 
+error: casting `i32` to `i8` may truncate the value
+  --> $DIR/cast.rs:33:22
+   |
+LL |         let _x: i8 = 1i32 as _;
+   |                      ^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+help: ... or use `try_from` and handle the error accordingly
+   |
+LL |         let _x: i8 = 1i32.try_into();
+   |                      ~~~~~~~~~~~~~~~
+
+error: casting `f32` to `i32` may truncate the value
+  --> $DIR/cast.rs:34:9
+   |
+LL |         1f32 as i32;
+   |         ^^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+
+error: casting `f64` to `i32` may truncate the value
+  --> $DIR/cast.rs:35:9
+   |
+LL |         1f64 as i32;
+   |         ^^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+
+error: casting `f32` to `u8` may truncate the value
+  --> $DIR/cast.rs:36:9
+   |
+LL |         1f32 as u8;
+   |         ^^^^^^^^^^
+   |
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
+
+error: casting `f32` to `u8` may lose the sign of the value
+  --> $DIR/cast.rs:36:9
+   |
+LL |         1f32 as u8;
+   |         ^^^^^^^^^^
+
 error: casting `u8` to `i8` may wrap around the value
-  --> $DIR/cast.rs:33:5
+  --> $DIR/cast.rs:39:5
    |
 LL |     1u8 as i8;
    |     ^^^^^^^^^
@@ -174,43 +192,43 @@ LL |     1u8 as i8;
    = note: `-D clippy::cast-possible-wrap` implied by `-D warnings`
 
 error: casting `u16` to `i16` may wrap around the value
-  --> $DIR/cast.rs:34:5
+  --> $DIR/cast.rs:40:5
    |
 LL |     1u16 as i16;
    |     ^^^^^^^^^^^
 
 error: casting `u32` to `i32` may wrap around the value
-  --> $DIR/cast.rs:35:5
+  --> $DIR/cast.rs:41:5
    |
 LL |     1u32 as i32;
    |     ^^^^^^^^^^^
 
 error: casting `u64` to `i64` may wrap around the value
-  --> $DIR/cast.rs:36:5
+  --> $DIR/cast.rs:42:5
    |
 LL |     1u64 as i64;
    |     ^^^^^^^^^^^
 
 error: casting `usize` to `isize` may wrap around the value
-  --> $DIR/cast.rs:37:5
+  --> $DIR/cast.rs:43:5
    |
 LL |     1usize as isize;
    |     ^^^^^^^^^^^^^^^
 
 error: casting `i32` to `u32` may lose the sign of the value
-  --> $DIR/cast.rs:40:5
+  --> $DIR/cast.rs:46:5
    |
 LL |     -1i32 as u32;
    |     ^^^^^^^^^^^^
 
 error: casting `isize` to `usize` may lose the sign of the value
-  --> $DIR/cast.rs:42:5
+  --> $DIR/cast.rs:48:5
    |
 LL |     -1isize as usize;
    |     ^^^^^^^^^^^^^^^^
 
 error: casting `i64` to `i8` may truncate the value
-  --> $DIR/cast.rs:109:5
+  --> $DIR/cast.rs:115:5
    |
 LL |     (-99999999999i64).min(1) as i8; // should be linted because signed
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -222,7 +240,7 @@ LL |     i8::try_from((-99999999999i64).min(1)); // should be linted because sig
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u64` to `u8` may truncate the value
-  --> $DIR/cast.rs:121:5
+  --> $DIR/cast.rs:127:5
    |
 LL |     999999u64.clamp(0, 256) as u8; // should still be linted
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -234,7 +252,7 @@ LL |     u8::try_from(999999u64.clamp(0, 256)); // should still be linted
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E2` to `u8` may truncate the value
-  --> $DIR/cast.rs:142:21
+  --> $DIR/cast.rs:148:21
    |
 LL |             let _ = self as u8;
    |                     ^^^^^^^^^^
@@ -246,7 +264,7 @@ LL |             let _ = u8::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E2::B` to `u8` will truncate the value
-  --> $DIR/cast.rs:143:21
+  --> $DIR/cast.rs:149:21
    |
 LL |             let _ = Self::B as u8;
    |                     ^^^^^^^^^^^^^
@@ -254,7 +272,7 @@ LL |             let _ = Self::B as u8;
    = note: `-D clippy::cast-enum-truncation` implied by `-D warnings`
 
 error: casting `main::E5` to `i8` may truncate the value
-  --> $DIR/cast.rs:179:21
+  --> $DIR/cast.rs:185:21
    |
 LL |             let _ = self as i8;
    |                     ^^^^^^^^^^
@@ -266,13 +284,13 @@ LL |             let _ = i8::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E5::A` to `i8` will truncate the value
-  --> $DIR/cast.rs:180:21
+  --> $DIR/cast.rs:186:21
    |
 LL |             let _ = Self::A as i8;
    |                     ^^^^^^^^^^^^^
 
 error: casting `main::E6` to `i16` may truncate the value
-  --> $DIR/cast.rs:194:21
+  --> $DIR/cast.rs:200:21
    |
 LL |             let _ = self as i16;
    |                     ^^^^^^^^^^^
@@ -284,7 +302,7 @@ LL |             let _ = i16::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
-  --> $DIR/cast.rs:209:21
+  --> $DIR/cast.rs:215:21
    |
 LL |             let _ = self as usize;
    |                     ^^^^^^^^^^^^^
@@ -296,7 +314,7 @@ LL |             let _ = usize::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `main::E10` to `u16` may truncate the value
-  --> $DIR/cast.rs:250:21
+  --> $DIR/cast.rs:256:21
    |
 LL |             let _ = self as u16;
    |                     ^^^^^^^^^^^
@@ -308,7 +326,7 @@ LL |             let _ = u16::try_from(self);
    |                     ~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `u8` may truncate the value
-  --> $DIR/cast.rs:258:13
+  --> $DIR/cast.rs:264:13
    |
 LL |     let c = (q >> 16) as u8;
    |             ^^^^^^^^^^^^^^^
@@ -316,11 +334,11 @@ LL |     let c = (q >> 16) as u8;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
-LL |     let c = u8::try_from((q >> 16));
-   |             ~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let c = u8::try_from(q >> 16);
+   |             ~~~~~~~~~~~~~~~~~~~~~
 
 error: casting `u32` to `u8` may truncate the value
-  --> $DIR/cast.rs:261:13
+  --> $DIR/cast.rs:267:13
    |
 LL |     let c = (q / 1000) as u8;
    |             ^^^^^^^^^^^^^^^^
@@ -328,8 +346,8 @@ LL |     let c = (q / 1000) as u8;
    = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
-LL |     let c = u8::try_from((q / 1000));
-   |             ~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     let c = u8::try_from(q / 1000);
+   |             ~~~~~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 36 previous errors
+error: aborting due to 41 previous errors
 
diff --git a/src/tools/clippy/tests/ui/clear_with_drain.fixed b/src/tools/clippy/tests/ui/clear_with_drain.fixed
new file mode 100644
index 00000000000..2d9545eeed1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/clear_with_drain.fixed
@@ -0,0 +1,358 @@
+// run-rustfix
+#![allow(unused)]
+#![warn(clippy::clear_with_drain)]
+
+use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
+
+fn vec_range() {
+    // Do not lint because iterator is assigned
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(0..v.len());
+
+    // Do not lint because iterator is used
+    let mut v = vec![1, 2, 3];
+    let n = v.drain(0..v.len()).count();
+
+    // Do not lint because iterator is assigned and used
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(usize::MIN..v.len());
+    let n = iter.count();
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.clear();
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.clear();
+}
+
+fn vec_range_from() {
+    // Do not lint because iterator is assigned
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(0..);
+
+    // Do not lint because iterator is assigned and used
+    let mut v = vec![1, 2, 3];
+    let mut iter = v.drain(0..);
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut v = vec![1, 2, 3];
+    let next = v.drain(usize::MIN..).next();
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.clear();
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.clear();
+}
+
+fn vec_range_full() {
+    // Do not lint because iterator is assigned
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(..);
+
+    // Do not lint because iterator is used
+    let mut v = vec![1, 2, 3];
+    for x in v.drain(..) {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.clear();
+}
+
+fn vec_range_to() {
+    // Do not lint because iterator is assigned
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(..v.len());
+
+    // Do not lint because iterator is assigned and used
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(..v.len());
+    for x in iter {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.clear();
+}
+
+fn vec_partial_drains() {
+    // Do not lint any of these because the ranges are not full
+
+    let mut v = vec![1, 2, 3];
+    v.drain(1..);
+    let mut v = vec![1, 2, 3];
+    v.drain(1..).max();
+
+    let mut v = vec![1, 2, 3];
+    v.drain(..v.len() - 1);
+    let mut v = vec![1, 2, 3];
+    v.drain(..v.len() - 1).min();
+
+    let mut v = vec![1, 2, 3];
+    v.drain(1..v.len() - 1);
+    let mut v = vec![1, 2, 3];
+    let w: Vec<i8> = v.drain(1..v.len() - 1).collect();
+}
+
+fn vec_deque_range() {
+    // Do not lint because iterator is assigned
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(0..deque.len());
+
+    // Do not lint because iterator is used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let n = deque.drain(0..deque.len()).count();
+
+    // Do not lint because iterator is assigned and used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(usize::MIN..deque.len());
+    let n = iter.count();
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.clear();
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.clear();
+}
+
+fn vec_deque_range_from() {
+    // Do not lint because iterator is assigned
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(0..);
+
+    // Do not lint because iterator is assigned and used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let mut iter = deque.drain(0..);
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let next = deque.drain(usize::MIN..).next();
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.clear();
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.clear();
+}
+
+fn vec_deque_range_full() {
+    // Do not lint because iterator is assigned
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(..);
+
+    // Do not lint because iterator is used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    for x in deque.drain(..) {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.clear();
+}
+
+fn vec_deque_range_to() {
+    // Do not lint because iterator is assigned
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(..deque.len());
+
+    // Do not lint because iterator is assigned and used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(..deque.len());
+    for x in iter {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.clear();
+}
+
+fn vec_deque_partial_drains() {
+    // Do not lint any of these because the ranges are not full
+
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(1..);
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(1..).max();
+
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(..deque.len() - 1);
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(..deque.len() - 1).min();
+
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(1..deque.len() - 1);
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let w: Vec<i8> = deque.drain(1..deque.len() - 1).collect();
+}
+
+fn string_range() {
+    // Do not lint because iterator is assigned
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(0..s.len());
+
+    // Do not lint because iterator is used
+    let mut s = String::from("Hello, world!");
+    let n = s.drain(0..s.len()).count();
+
+    // Do not lint because iterator is assigned and used
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(usize::MIN..s.len());
+    let n = iter.count();
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.clear();
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.clear();
+}
+
+fn string_range_from() {
+    // Do not lint because iterator is assigned
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(0..);
+
+    // Do not lint because iterator is assigned and used
+    let mut s = String::from("Hello, world!");
+    let mut iter = s.drain(0..);
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut s = String::from("Hello, world!");
+    let next = s.drain(usize::MIN..).next();
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.clear();
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.clear();
+}
+
+fn string_range_full() {
+    // Do not lint because iterator is assigned
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(..);
+
+    // Do not lint because iterator is used
+    let mut s = String::from("Hello, world!");
+    for x in s.drain(..) {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.clear();
+}
+
+fn string_range_to() {
+    // Do not lint because iterator is assigned
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(..s.len());
+
+    // Do not lint because iterator is assigned and used
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(..s.len());
+    for x in iter {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.clear();
+}
+
+fn string_partial_drains() {
+    // Do not lint any of these because the ranges are not full
+
+    let mut s = String::from("Hello, world!");
+    s.drain(1..);
+    let mut s = String::from("Hello, world!");
+    s.drain(1..).max();
+
+    let mut s = String::from("Hello, world!");
+    s.drain(..s.len() - 1);
+    let mut s = String::from("Hello, world!");
+    s.drain(..s.len() - 1).min();
+
+    let mut s = String::from("Hello, world!");
+    s.drain(1..s.len() - 1);
+    let mut s = String::from("Hello, world!");
+    let w: String = s.drain(1..s.len() - 1).collect();
+}
+
+fn hash_set() {
+    // Do not lint because iterator is assigned
+    let mut set = HashSet::from([1, 2, 3]);
+    let iter = set.drain();
+
+    // Do not lint because iterator is assigned and used
+    let mut set = HashSet::from([1, 2, 3]);
+    let mut iter = set.drain();
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut set = HashSet::from([1, 2, 3]);
+    let next = set.drain().next();
+
+    // Do lint
+    let mut set = HashSet::from([1, 2, 3]);
+    set.clear();
+}
+
+fn hash_map() {
+    // Do not lint because iterator is assigned
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    let iter = map.drain();
+
+    // Do not lint because iterator is assigned and used
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    let mut iter = map.drain();
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    let next = map.drain().next();
+
+    // Do lint
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    map.clear();
+}
+
+fn binary_heap() {
+    // Do not lint because iterator is assigned
+    let mut heap = BinaryHeap::from([1, 2]);
+    let iter = heap.drain();
+
+    // Do not lint because iterator is assigned and used
+    let mut heap = BinaryHeap::from([1, 2]);
+    let mut iter = heap.drain();
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut heap = BinaryHeap::from([1, 2]);
+    let next = heap.drain().next();
+
+    // Do lint
+    let mut heap = BinaryHeap::from([1, 2]);
+    heap.clear();
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/clear_with_drain.rs b/src/tools/clippy/tests/ui/clear_with_drain.rs
new file mode 100644
index 00000000000..4d60ee46e18
--- /dev/null
+++ b/src/tools/clippy/tests/ui/clear_with_drain.rs
@@ -0,0 +1,358 @@
+// run-rustfix
+#![allow(unused)]
+#![warn(clippy::clear_with_drain)]
+
+use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
+
+fn vec_range() {
+    // Do not lint because iterator is assigned
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(0..v.len());
+
+    // Do not lint because iterator is used
+    let mut v = vec![1, 2, 3];
+    let n = v.drain(0..v.len()).count();
+
+    // Do not lint because iterator is assigned and used
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(usize::MIN..v.len());
+    let n = iter.count();
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.drain(0..v.len());
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.drain(usize::MIN..v.len());
+}
+
+fn vec_range_from() {
+    // Do not lint because iterator is assigned
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(0..);
+
+    // Do not lint because iterator is assigned and used
+    let mut v = vec![1, 2, 3];
+    let mut iter = v.drain(0..);
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut v = vec![1, 2, 3];
+    let next = v.drain(usize::MIN..).next();
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.drain(0..);
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.drain(usize::MIN..);
+}
+
+fn vec_range_full() {
+    // Do not lint because iterator is assigned
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(..);
+
+    // Do not lint because iterator is used
+    let mut v = vec![1, 2, 3];
+    for x in v.drain(..) {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.drain(..);
+}
+
+fn vec_range_to() {
+    // Do not lint because iterator is assigned
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(..v.len());
+
+    // Do not lint because iterator is assigned and used
+    let mut v = vec![1, 2, 3];
+    let iter = v.drain(..v.len());
+    for x in iter {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut v = vec![1, 2, 3];
+    v.drain(..v.len());
+}
+
+fn vec_partial_drains() {
+    // Do not lint any of these because the ranges are not full
+
+    let mut v = vec![1, 2, 3];
+    v.drain(1..);
+    let mut v = vec![1, 2, 3];
+    v.drain(1..).max();
+
+    let mut v = vec![1, 2, 3];
+    v.drain(..v.len() - 1);
+    let mut v = vec![1, 2, 3];
+    v.drain(..v.len() - 1).min();
+
+    let mut v = vec![1, 2, 3];
+    v.drain(1..v.len() - 1);
+    let mut v = vec![1, 2, 3];
+    let w: Vec<i8> = v.drain(1..v.len() - 1).collect();
+}
+
+fn vec_deque_range() {
+    // Do not lint because iterator is assigned
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(0..deque.len());
+
+    // Do not lint because iterator is used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let n = deque.drain(0..deque.len()).count();
+
+    // Do not lint because iterator is assigned and used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(usize::MIN..deque.len());
+    let n = iter.count();
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(0..deque.len());
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(usize::MIN..deque.len());
+}
+
+fn vec_deque_range_from() {
+    // Do not lint because iterator is assigned
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(0..);
+
+    // Do not lint because iterator is assigned and used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let mut iter = deque.drain(0..);
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let next = deque.drain(usize::MIN..).next();
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(0..);
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(usize::MIN..);
+}
+
+fn vec_deque_range_full() {
+    // Do not lint because iterator is assigned
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(..);
+
+    // Do not lint because iterator is used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    for x in deque.drain(..) {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(..);
+}
+
+fn vec_deque_range_to() {
+    // Do not lint because iterator is assigned
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(..deque.len());
+
+    // Do not lint because iterator is assigned and used
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let iter = deque.drain(..deque.len());
+    for x in iter {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(..deque.len());
+}
+
+fn vec_deque_partial_drains() {
+    // Do not lint any of these because the ranges are not full
+
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(1..);
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(1..).max();
+
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(..deque.len() - 1);
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(..deque.len() - 1).min();
+
+    let mut deque = VecDeque::from([1, 2, 3]);
+    deque.drain(1..deque.len() - 1);
+    let mut deque = VecDeque::from([1, 2, 3]);
+    let w: Vec<i8> = deque.drain(1..deque.len() - 1).collect();
+}
+
+fn string_range() {
+    // Do not lint because iterator is assigned
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(0..s.len());
+
+    // Do not lint because iterator is used
+    let mut s = String::from("Hello, world!");
+    let n = s.drain(0..s.len()).count();
+
+    // Do not lint because iterator is assigned and used
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(usize::MIN..s.len());
+    let n = iter.count();
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.drain(0..s.len());
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.drain(usize::MIN..s.len());
+}
+
+fn string_range_from() {
+    // Do not lint because iterator is assigned
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(0..);
+
+    // Do not lint because iterator is assigned and used
+    let mut s = String::from("Hello, world!");
+    let mut iter = s.drain(0..);
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut s = String::from("Hello, world!");
+    let next = s.drain(usize::MIN..).next();
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.drain(0..);
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.drain(usize::MIN..);
+}
+
+fn string_range_full() {
+    // Do not lint because iterator is assigned
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(..);
+
+    // Do not lint because iterator is used
+    let mut s = String::from("Hello, world!");
+    for x in s.drain(..) {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.drain(..);
+}
+
+fn string_range_to() {
+    // Do not lint because iterator is assigned
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(..s.len());
+
+    // Do not lint because iterator is assigned and used
+    let mut s = String::from("Hello, world!");
+    let iter = s.drain(..s.len());
+    for x in iter {
+        let y = format!("x = {x}");
+    }
+
+    // Do lint
+    let mut s = String::from("Hello, world!");
+    s.drain(..s.len());
+}
+
+fn string_partial_drains() {
+    // Do not lint any of these because the ranges are not full
+
+    let mut s = String::from("Hello, world!");
+    s.drain(1..);
+    let mut s = String::from("Hello, world!");
+    s.drain(1..).max();
+
+    let mut s = String::from("Hello, world!");
+    s.drain(..s.len() - 1);
+    let mut s = String::from("Hello, world!");
+    s.drain(..s.len() - 1).min();
+
+    let mut s = String::from("Hello, world!");
+    s.drain(1..s.len() - 1);
+    let mut s = String::from("Hello, world!");
+    let w: String = s.drain(1..s.len() - 1).collect();
+}
+
+fn hash_set() {
+    // Do not lint because iterator is assigned
+    let mut set = HashSet::from([1, 2, 3]);
+    let iter = set.drain();
+
+    // Do not lint because iterator is assigned and used
+    let mut set = HashSet::from([1, 2, 3]);
+    let mut iter = set.drain();
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut set = HashSet::from([1, 2, 3]);
+    let next = set.drain().next();
+
+    // Do lint
+    let mut set = HashSet::from([1, 2, 3]);
+    set.drain();
+}
+
+fn hash_map() {
+    // Do not lint because iterator is assigned
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    let iter = map.drain();
+
+    // Do not lint because iterator is assigned and used
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    let mut iter = map.drain();
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    let next = map.drain().next();
+
+    // Do lint
+    let mut map = HashMap::from([(1, "a"), (2, "b")]);
+    map.drain();
+}
+
+fn binary_heap() {
+    // Do not lint because iterator is assigned
+    let mut heap = BinaryHeap::from([1, 2]);
+    let iter = heap.drain();
+
+    // Do not lint because iterator is assigned and used
+    let mut heap = BinaryHeap::from([1, 2]);
+    let mut iter = heap.drain();
+    let next = iter.next();
+
+    // Do not lint because iterator is used
+    let mut heap = BinaryHeap::from([1, 2]);
+    let next = heap.drain().next();
+
+    // Do lint
+    let mut heap = BinaryHeap::from([1, 2]);
+    heap.drain();
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/clear_with_drain.stderr b/src/tools/clippy/tests/ui/clear_with_drain.stderr
new file mode 100644
index 00000000000..20158da1121
--- /dev/null
+++ b/src/tools/clippy/tests/ui/clear_with_drain.stderr
@@ -0,0 +1,130 @@
+error: `drain` used to clear a `Vec`
+  --> $DIR/clear_with_drain.rs:23:7
+   |
+LL |     v.drain(0..v.len());
+   |       ^^^^^^^^^^^^^^^^^ help: try: `clear()`
+   |
+   = note: `-D clippy::clear-with-drain` implied by `-D warnings`
+
+error: `drain` used to clear a `Vec`
+  --> $DIR/clear_with_drain.rs:27:7
+   |
+LL |     v.drain(usize::MIN..v.len());
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `Vec`
+  --> $DIR/clear_with_drain.rs:46:7
+   |
+LL |     v.drain(0..);
+   |       ^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `Vec`
+  --> $DIR/clear_with_drain.rs:50:7
+   |
+LL |     v.drain(usize::MIN..);
+   |       ^^^^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `Vec`
+  --> $DIR/clear_with_drain.rs:66:7
+   |
+LL |     v.drain(..);
+   |       ^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `Vec`
+  --> $DIR/clear_with_drain.rs:83:7
+   |
+LL |     v.drain(..v.len());
+   |       ^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `VecDeque`
+  --> $DIR/clear_with_drain.rs:121:11
+   |
+LL |     deque.drain(0..deque.len());
+   |           ^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `VecDeque`
+  --> $DIR/clear_with_drain.rs:125:11
+   |
+LL |     deque.drain(usize::MIN..deque.len());
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `VecDeque`
+  --> $DIR/clear_with_drain.rs:144:11
+   |
+LL |     deque.drain(0..);
+   |           ^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `VecDeque`
+  --> $DIR/clear_with_drain.rs:148:11
+   |
+LL |     deque.drain(usize::MIN..);
+   |           ^^^^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `VecDeque`
+  --> $DIR/clear_with_drain.rs:164:11
+   |
+LL |     deque.drain(..);
+   |           ^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `VecDeque`
+  --> $DIR/clear_with_drain.rs:181:11
+   |
+LL |     deque.drain(..deque.len());
+   |           ^^^^^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `String`
+  --> $DIR/clear_with_drain.rs:219:7
+   |
+LL |     s.drain(0..s.len());
+   |       ^^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `String`
+  --> $DIR/clear_with_drain.rs:223:7
+   |
+LL |     s.drain(usize::MIN..s.len());
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `String`
+  --> $DIR/clear_with_drain.rs:242:7
+   |
+LL |     s.drain(0..);
+   |       ^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `String`
+  --> $DIR/clear_with_drain.rs:246:7
+   |
+LL |     s.drain(usize::MIN..);
+   |       ^^^^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `String`
+  --> $DIR/clear_with_drain.rs:262:7
+   |
+LL |     s.drain(..);
+   |       ^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `String`
+  --> $DIR/clear_with_drain.rs:279:7
+   |
+LL |     s.drain(..s.len());
+   |       ^^^^^^^^^^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `HashSet`
+  --> $DIR/clear_with_drain.rs:317:9
+   |
+LL |     set.drain();
+   |         ^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `HashMap`
+  --> $DIR/clear_with_drain.rs:336:9
+   |
+LL |     map.drain();
+   |         ^^^^^^^ help: try: `clear()`
+
+error: `drain` used to clear a `BinaryHeap`
+  --> $DIR/clear_with_drain.rs:355:10
+   |
+LL |     heap.drain();
+   |          ^^^^^^^ help: try: `clear()`
+
+error: aborting due to 21 previous errors
+
diff --git a/src/tools/clippy/tests/ui/collection_is_never_read.rs b/src/tools/clippy/tests/ui/collection_is_never_read.rs
index 068a49486cf..01259a983ab 100644
--- a/src/tools/clippy/tests/ui/collection_is_never_read.rs
+++ b/src/tools/clippy/tests/ui/collection_is_never_read.rs
@@ -84,13 +84,18 @@ fn shadowing_2() {
 }
 
 #[allow(clippy::let_unit_value)]
-fn fake_read() {
-    let mut x = vec![1, 2, 3]; // Ok
+fn fake_read_1() {
+    let mut x = vec![1, 2, 3]; // WARNING
     x.reverse();
-    // `collection_is_never_read` gets fooled, but other lints should catch this.
     let _: () = x.clear();
 }
 
+fn fake_read_2() {
+    let mut x = vec![1, 2, 3]; // WARNING
+    x.reverse();
+    println!("{:?}", x.push(5));
+}
+
 fn assignment() {
     let mut x = vec![1, 2, 3]; // WARNING
     let y = vec![4, 5, 6]; // Ok
@@ -163,3 +168,23 @@ fn function_argument() {
     let x = vec![1, 2, 3]; // Ok
     foo(&x);
 }
+
+fn string() {
+    // Do lint (write without read)
+    let mut s = String::new();
+    s.push_str("Hello, World!");
+
+    // Do not lint (read without write)
+    let mut s = String::from("Hello, World!");
+    let _ = s.len();
+
+    // Do not lint (write and read)
+    let mut s = String::from("Hello, World!");
+    s.push_str("foo, bar");
+    let _ = s.len();
+
+    // Do lint the first line, but not the second
+    let mut s = String::from("Hello, World!");
+    let t = String::from("foo, bar");
+    s = t;
+}
diff --git a/src/tools/clippy/tests/ui/collection_is_never_read.stderr b/src/tools/clippy/tests/ui/collection_is_never_read.stderr
index 7654b74be3d..cf51a53686f 100644
--- a/src/tools/clippy/tests/ui/collection_is_never_read.stderr
+++ b/src/tools/clippy/tests/ui/collection_is_never_read.stderr
@@ -25,28 +25,52 @@ LL |     let mut x = HashMap::new(); // WARNING
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: collection is never read
-  --> $DIR/collection_is_never_read.rs:95:5
+  --> $DIR/collection_is_never_read.rs:88:5
    |
 LL |     let mut x = vec![1, 2, 3]; // WARNING
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: collection is never read
-  --> $DIR/collection_is_never_read.rs:102:5
+  --> $DIR/collection_is_never_read.rs:94:5
    |
 LL |     let mut x = vec![1, 2, 3]; // WARNING
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: collection is never read
-  --> $DIR/collection_is_never_read.rs:119:5
+  --> $DIR/collection_is_never_read.rs:100:5
+   |
+LL |     let mut x = vec![1, 2, 3]; // WARNING
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+  --> $DIR/collection_is_never_read.rs:107:5
+   |
+LL |     let mut x = vec![1, 2, 3]; // WARNING
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+  --> $DIR/collection_is_never_read.rs:124:5
    |
 LL |     let mut x = HashSet::new(); // WARNING
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: collection is never read
-  --> $DIR/collection_is_never_read.rs:133:5
+  --> $DIR/collection_is_never_read.rs:138:5
    |
 LL |     let x = vec![1, 2, 3]; // WARNING
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors
+error: collection is never read
+  --> $DIR/collection_is_never_read.rs:174:5
+   |
+LL |     let mut s = String::new();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: collection is never read
+  --> $DIR/collection_is_never_read.rs:187:5
+   |
+LL |     let mut s = String::from("Hello, World!");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/double_must_use.rs b/src/tools/clippy/tests/ui/double_must_use.rs
index 05e087b08bc..26a387b3cf0 100644
--- a/src/tools/clippy/tests/ui/double_must_use.rs
+++ b/src/tools/clippy/tests/ui/double_must_use.rs
@@ -21,6 +21,17 @@ pub fn must_use_with_note() -> Result<(), ()> {
     unimplemented!();
 }
 
+// vvvv Should not lint (#10486)
+#[must_use]
+async fn async_must_use() -> usize {
+    unimplemented!();
+}
+
+#[must_use]
+async fn async_must_use_result() -> Result<(), ()> {
+    Ok(())
+}
+
 fn main() {
     must_use_result();
     must_use_tuple();
diff --git a/src/tools/clippy/tests/ui/double_must_use.stderr b/src/tools/clippy/tests/ui/double_must_use.stderr
index 3d34557a881..49ab2ea3e12 100644
--- a/src/tools/clippy/tests/ui/double_must_use.stderr
+++ b/src/tools/clippy/tests/ui/double_must_use.stderr
@@ -23,5 +23,13 @@ LL | pub fn must_use_array() -> [Result<(), ()>; 1] {
    |
    = help: either add some descriptive text or remove the attribute
 
-error: aborting due to 3 previous errors
+error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`
+  --> $DIR/double_must_use.rs:31:1
+   |
+LL | async fn async_must_use_result() -> Result<(), ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: either add some descriptive text or remove the attribute
+
+error: aborting due to 4 previous errors
 
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed b/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed
new file mode 100644
index 00000000000..19e71862558
--- /dev/null
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.fixed
@@ -0,0 +1,105 @@
+// run-rustfix
+
+#![allow(unused, clippy::needless_lifetimes)]
+#![warn(clippy::extra_unused_type_parameters)]
+
+fn unused_ty(x: u8) {
+    unimplemented!()
+}
+
+fn unused_multi(x: u8) {
+    unimplemented!()
+}
+
+fn unused_with_lt<'a>(x: &'a u8) {
+    unimplemented!()
+}
+
+fn used_ty<T>(x: T, y: u8) {}
+
+fn used_ref<'a, T>(x: &'a T) {}
+
+fn used_ret<T: Default>(x: u8) -> T {
+    T::default()
+}
+
+fn unused_bounded<U>(x: U) {
+    unimplemented!();
+}
+
+fn some_unused<B, C>(b: B, c: C) {
+    unimplemented!();
+}
+
+fn used_opaque<A>(iter: impl Iterator<Item = A>) -> usize {
+    iter.count()
+}
+
+fn used_ret_opaque<A>() -> impl Iterator<Item = A> {
+    std::iter::empty()
+}
+
+fn used_vec_box<T>(x: Vec<Box<T>>) {}
+
+fn used_body<T: Default + ToString>() -> String {
+    T::default().to_string()
+}
+
+fn used_closure<T: Default + ToString>() -> impl Fn() {
+    || println!("{}", T::default().to_string())
+}
+
+struct S;
+
+impl S {
+    fn unused_ty_impl(&self) {
+        unimplemented!()
+    }
+}
+
+// Don't lint on trait methods
+trait Foo {
+    fn bar<T>(&self);
+}
+
+impl Foo for S {
+    fn bar<T>(&self) {}
+}
+
+fn skip_index<A, Iter>(iter: Iter, index: usize) -> impl Iterator<Item = A>
+where
+    Iter: Iterator<Item = A>,
+{
+    iter.enumerate()
+        .filter_map(move |(i, a)| if i == index { None } else { Some(a) })
+}
+
+fn unused_opaque(dummy: impl Default) {
+    unimplemented!()
+}
+
+mod unexported_trait_bounds {
+    mod private {
+        pub trait Private {}
+    }
+
+    fn priv_trait_bound<T: private::Private>() {
+        unimplemented!();
+    }
+
+    fn unused_with_priv_trait_bound<T: private::Private>() {
+        unimplemented!();
+    }
+}
+
+mod issue10319 {
+    fn assert_send<T: Send>() {}
+
+    fn assert_send_where<T>()
+    where
+        T: Send,
+    {
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
index 48017434276..e53bb587e89 100644
--- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
@@ -1,3 +1,5 @@
+// run-rustfix
+
 #![allow(unused, clippy::needless_lifetimes)]
 #![warn(clippy::extra_unused_type_parameters)]
 
@@ -21,14 +23,7 @@ fn used_ret<T: Default>(x: u8) -> T {
     T::default()
 }
 
-fn unused_bounded<T: Default, U>(x: U) {
-    unimplemented!();
-}
-
-fn unused_where_clause<T, U>(x: U)
-where
-    T: Default,
-{
+fn unused_bounded<T: Default, U, V: Default>(x: U) {
     unimplemented!();
 }
 
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
index 86c88fc9bf0..c042a5a2290 100644
--- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
@@ -1,75 +1,64 @@
-error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:4:13
+error: type parameter `T` goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:6:13
    |
 LL | fn unused_ty<T>(x: u8) {
-   |             ^^^
+   |             ^^^ help: consider removing the parameter
    |
-   = help: consider removing the parameter
    = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings`
 
-error: type parameters go unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:8:16
+error: type parameters go unused in function definition: T, U
+  --> $DIR/extra_unused_type_parameters.rs:10:16
    |
 LL | fn unused_multi<T, U>(x: u8) {
-   |                ^^^^^^
-   |
-   = help: consider removing the parameters
+   |                ^^^^^^ help: consider removing the parameters
 
-error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:12:23
+error: type parameter `T` goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:14:21
    |
 LL | fn unused_with_lt<'a, T>(x: &'a u8) {
-   |                       ^
-   |
-   = help: consider removing the parameter
+   |                     ^^^ help: consider removing the parameter
 
-error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:24:19
+error: type parameters go unused in function definition: T, V
+  --> $DIR/extra_unused_type_parameters.rs:26:19
    |
-LL | fn unused_bounded<T: Default, U>(x: U) {
-   |                   ^^^^^^^^^^^
+LL | fn unused_bounded<T: Default, U, V: Default>(x: U) {
+   |                   ^^^^^^^^^^^^ ^^^^^^^^^^^^
    |
-   = help: consider removing the parameter
-
-error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:28:24
+help: consider removing the parameters
    |
-LL | fn unused_where_clause<T, U>(x: U)
-   |                        ^^
+LL - fn unused_bounded<T: Default, U, V: Default>(x: U) {
+LL + fn unused_bounded<U>(x: U) {
    |
-   = help: consider removing the parameter
 
-error: type parameters go unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:35:16
+error: type parameters go unused in function definition: A, D, E
+  --> $DIR/extra_unused_type_parameters.rs:30:16
    |
 LL | fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {
-   |                ^^       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
+   |                ^^^    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider removing the parameters
+   |
+LL - fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {
+LL + fn some_unused<B, C>(b: B, c: C) {
    |
-   = help: consider removing the parameters
 
-error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:60:22
+error: type parameter `T` goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:55:22
    |
 LL |     fn unused_ty_impl<T>(&self) {
-   |                      ^^^
-   |
-   = help: consider removing the parameter
+   |                      ^^^ help: consider removing the parameter
 
-error: type parameters go unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:82:17
+error: type parameters go unused in function definition: A, B
+  --> $DIR/extra_unused_type_parameters.rs:77:17
    |
 LL | fn unused_opaque<A, B>(dummy: impl Default) {
-   |                 ^^^^^^
-   |
-   = help: consider removing the parameters
+   |                 ^^^^^^ help: consider removing the parameters
 
-error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:95:58
+error: type parameter `U` goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:90:56
    |
 LL |     fn unused_with_priv_trait_bound<T: private::Private, U>() {
-   |                                                          ^
-   |
-   = help: consider removing the parameter
+   |                                                        ^^^ help: consider removing the parameter
 
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters_unfixable.rs b/src/tools/clippy/tests/ui/extra_unused_type_parameters_unfixable.rs
new file mode 100644
index 00000000000..10b39aa8f2c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters_unfixable.rs
@@ -0,0 +1,24 @@
+#![warn(clippy::extra_unused_type_parameters)]
+
+fn unused_where_clause<T, U>(x: U)
+where
+    T: Default,
+{
+    unimplemented!();
+}
+
+fn unused_multi_where_clause<T, U, V: Default>(x: U)
+where
+    T: Default,
+{
+    unimplemented!();
+}
+
+fn unused_all_where_clause<T, U: Default, V: Default>()
+where
+    T: Default,
+{
+    unimplemented!();
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters_unfixable.stderr b/src/tools/clippy/tests/ui/extra_unused_type_parameters_unfixable.stderr
new file mode 100644
index 00000000000..a9580cc894f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters_unfixable.stderr
@@ -0,0 +1,27 @@
+error: type parameter `T` goes unused in function definition
+  --> $DIR/extra_unused_type_parameters_unfixable.rs:3:24
+   |
+LL | fn unused_where_clause<T, U>(x: U)
+   |                        ^
+   |
+   = help: consider removing the parameter
+   = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings`
+
+error: type parameters go unused in function definition: T, V
+  --> $DIR/extra_unused_type_parameters_unfixable.rs:10:30
+   |
+LL | fn unused_multi_where_clause<T, U, V: Default>(x: U)
+   |                              ^     ^^^^^^^^^^
+   |
+   = help: consider removing the parameters
+
+error: type parameters go unused in function definition: T, U, V
+  --> $DIR/extra_unused_type_parameters_unfixable.rs:17:28
+   |
+LL | fn unused_all_where_clause<T, U: Default, V: Default>()
+   |                            ^  ^^^^^^^^^^  ^^^^^^^^^^
+   |
+   = help: consider removing the parameters
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.rs b/src/tools/clippy/tests/ui/format_args_unfixable.rs
index eb0ac15bfbf..423bfaf9796 100644
--- a/src/tools/clippy/tests/ui/format_args_unfixable.rs
+++ b/src/tools/clippy/tests/ui/format_args_unfixable.rs
@@ -1,4 +1,5 @@
 #![warn(clippy::format_in_format_args, clippy::to_string_in_format_args)]
+#![allow(unused)]
 #![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::uninlined_format_args)]
 
 use std::io::{stdout, Error, ErrorKind, Write};
@@ -57,3 +58,46 @@ fn main() {
     my_macro!();
     println!("error: {}", my_other_macro!());
 }
+
+macro_rules! _internal {
+    ($($args:tt)*) => {
+        println!("{}", format_args!($($args)*))
+    };
+}
+
+macro_rules! my_println2 {
+   ($target:expr, $($args:tt)+) => {{
+       if $target {
+           _internal!($($args)+)
+       }
+    }};
+}
+
+macro_rules! my_println2_args {
+    ($target:expr, $($args:tt)+) => {{
+       if $target {
+           _internal!("foo: {}", format_args!($($args)+))
+       }
+    }};
+}
+
+fn test2() {
+    let error = Error::new(ErrorKind::Other, "bad thing");
+
+    // None of these should be linted without the config change
+    my_println2!(true, "error: {}", format!("something failed at {}", Location::caller()));
+    my_println2!(
+        true,
+        "{}: {}",
+        error,
+        format!("something failed at {}", Location::caller())
+    );
+
+    my_println2_args!(true, "error: {}", format!("something failed at {}", Location::caller()));
+    my_println2_args!(
+        true,
+        "{}: {}",
+        error,
+        format!("something failed at {}", Location::caller())
+    );
+}
diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.stderr b/src/tools/clippy/tests/ui/format_args_unfixable.stderr
index b291d475ad9..c1be48c3b72 100644
--- a/src/tools/clippy/tests/ui/format_args_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/format_args_unfixable.stderr
@@ -1,5 +1,5 @@
 error: `format!` in `println!` args
-  --> $DIR/format_args_unfixable.rs:25:5
+  --> $DIR/format_args_unfixable.rs:26:5
    |
 LL |     println!("error: {}", format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     println!("error: {}", format!("something failed at {}", Location::calle
    = note: `-D clippy::format-in-format-args` implied by `-D warnings`
 
 error: `format!` in `println!` args
-  --> $DIR/format_args_unfixable.rs:26:5
+  --> $DIR/format_args_unfixable.rs:27:5
    |
 LL |     println!("{}: {}", error, format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL |     println!("{}: {}", error, format!("something failed at {}", Location::c
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `println!` args
-  --> $DIR/format_args_unfixable.rs:27:5
+  --> $DIR/format_args_unfixable.rs:28:5
    |
 LL |     println!("{:?}: {}", error, format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -27,7 +27,7 @@ LL |     println!("{:?}: {}", error, format!("something failed at {}", Location:
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `println!` args
-  --> $DIR/format_args_unfixable.rs:28:5
+  --> $DIR/format_args_unfixable.rs:29:5
    |
 LL |     println!("{{}}: {}", format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -36,7 +36,7 @@ LL |     println!("{{}}: {}", format!("something failed at {}", Location::caller
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `println!` args
-  --> $DIR/format_args_unfixable.rs:29:5
+  --> $DIR/format_args_unfixable.rs:30:5
    |
 LL |     println!(r#"error: "{}""#, format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL |     println!(r#"error: "{}""#, format!("something failed at {}", Location::
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `println!` args
-  --> $DIR/format_args_unfixable.rs:30:5
+  --> $DIR/format_args_unfixable.rs:31:5
    |
 LL |     println!("error: {}", format!(r#"something failed at "{}""#, Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -54,7 +54,7 @@ LL |     println!("error: {}", format!(r#"something failed at "{}""#, Location::
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `println!` args
-  --> $DIR/format_args_unfixable.rs:31:5
+  --> $DIR/format_args_unfixable.rs:32:5
    |
 LL |     println!("error: {}", format!("something failed at {} {0}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +63,7 @@ LL |     println!("error: {}", format!("something failed at {} {0}", Location::c
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `format!` args
-  --> $DIR/format_args_unfixable.rs:32:13
+  --> $DIR/format_args_unfixable.rs:33:13
    |
 LL |     let _ = format!("error: {}", format!("something failed at {}", Location::caller()));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL |     let _ = format!("error: {}", format!("something failed at {}", Location
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `write!` args
-  --> $DIR/format_args_unfixable.rs:33:13
+  --> $DIR/format_args_unfixable.rs:34:13
    |
 LL |       let _ = write!(
    |  _____________^
@@ -86,7 +86,7 @@ LL | |     );
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `writeln!` args
-  --> $DIR/format_args_unfixable.rs:38:13
+  --> $DIR/format_args_unfixable.rs:39:13
    |
 LL |       let _ = writeln!(
    |  _____________^
@@ -100,7 +100,7 @@ LL | |     );
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `print!` args
-  --> $DIR/format_args_unfixable.rs:43:5
+  --> $DIR/format_args_unfixable.rs:44:5
    |
 LL |     print!("error: {}", format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -109,7 +109,7 @@ LL |     print!("error: {}", format!("something failed at {}", Location::caller(
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `eprint!` args
-  --> $DIR/format_args_unfixable.rs:44:5
+  --> $DIR/format_args_unfixable.rs:45:5
    |
 LL |     eprint!("error: {}", format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -118,7 +118,7 @@ LL |     eprint!("error: {}", format!("something failed at {}", Location::caller
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `eprintln!` args
-  --> $DIR/format_args_unfixable.rs:45:5
+  --> $DIR/format_args_unfixable.rs:46:5
    |
 LL |     eprintln!("error: {}", format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -127,7 +127,7 @@ LL |     eprintln!("error: {}", format!("something failed at {}", Location::call
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `format_args!` args
-  --> $DIR/format_args_unfixable.rs:46:13
+  --> $DIR/format_args_unfixable.rs:47:13
    |
 LL |     let _ = format_args!("error: {}", format!("something failed at {}", Location::caller()));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -136,7 +136,7 @@ LL |     let _ = format_args!("error: {}", format!("something failed at {}", Loc
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `assert!` args
-  --> $DIR/format_args_unfixable.rs:47:5
+  --> $DIR/format_args_unfixable.rs:48:5
    |
 LL |     assert!(true, "error: {}", format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -145,7 +145,7 @@ LL |     assert!(true, "error: {}", format!("something failed at {}", Location::
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `assert_eq!` args
-  --> $DIR/format_args_unfixable.rs:48:5
+  --> $DIR/format_args_unfixable.rs:49:5
    |
 LL |     assert_eq!(0, 0, "error: {}", format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL |     assert_eq!(0, 0, "error: {}", format!("something failed at {}", Locatio
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `assert_ne!` args
-  --> $DIR/format_args_unfixable.rs:49:5
+  --> $DIR/format_args_unfixable.rs:50:5
    |
 LL |     assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -163,7 +163,7 @@ LL |     assert_ne!(0, 0, "error: {}", format!("something failed at {}", Locatio
    = help: or consider changing `format!` to `format_args!`
 
 error: `format!` in `panic!` args
-  --> $DIR/format_args_unfixable.rs:50:5
+  --> $DIR/format_args_unfixable.rs:51:5
    |
 LL |     panic!("error: {}", format!("something failed at {}", Location::caller()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/item_after_statement.rs b/src/tools/clippy/tests/ui/items_after_statement.rs
index 5e92dcab1f5..f12cb8f22e2 100644
--- a/src/tools/clippy/tests/ui/item_after_statement.rs
+++ b/src/tools/clippy/tests/ui/items_after_statement.rs
@@ -51,3 +51,20 @@ fn semicolon() {
 
     let _ = S::new(3);
 }
+
+fn item_from_macro() {
+    macro_rules! static_assert_size {
+        ($ty:ty, $size:expr) => {
+            const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
+        };
+    }
+
+    let _ = 1;
+    static_assert_size!(u32, 4);
+}
+
+fn allow_attribute() {
+    let _ = 1;
+    #[allow(clippy::items_after_statements)]
+    const _: usize = 1;
+}
diff --git a/src/tools/clippy/tests/ui/item_after_statement.stderr b/src/tools/clippy/tests/ui/items_after_statement.stderr
index 2523c53ac53..f69635a977b 100644
--- a/src/tools/clippy/tests/ui/item_after_statement.stderr
+++ b/src/tools/clippy/tests/ui/items_after_statement.stderr
@@ -1,5 +1,5 @@
 error: adding items after statements is confusing, since items exist from the start of the scope
-  --> $DIR/item_after_statement.rs:13:5
+  --> $DIR/items_after_statement.rs:13:5
    |
 LL | /     fn foo() {
 LL | |         println!("foo");
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::items-after-statements` implied by `-D warnings`
 
 error: adding items after statements is confusing, since items exist from the start of the scope
-  --> $DIR/item_after_statement.rs:20:5
+  --> $DIR/items_after_statement.rs:20:5
    |
 LL | /     fn foo() {
 LL | |         println!("foo");
@@ -17,7 +17,7 @@ LL | |     }
    | |_____^
 
 error: adding items after statements is confusing, since items exist from the start of the scope
-  --> $DIR/item_after_statement.rs:33:13
+  --> $DIR/items_after_statement.rs:33:13
    |
 LL | /             fn say_something() {
 LL | |                 println!("something");
diff --git a/src/tools/clippy/tests/ui/large_futures.rs b/src/tools/clippy/tests/ui/large_futures.rs
new file mode 100644
index 00000000000..4a8ba995da5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/large_futures.rs
@@ -0,0 +1,61 @@
+#![feature(generators)]
+#![warn(clippy::large_futures)]
+#![allow(clippy::future_not_send)]
+#![allow(clippy::manual_async_fn)]
+
+async fn big_fut(_arg: [u8; 1024 * 16]) {}
+
+async fn wait() {
+    let f = async {
+        big_fut([0u8; 1024 * 16]).await;
+    };
+    f.await
+}
+async fn calls_fut(fut: impl std::future::Future<Output = ()>) {
+    loop {
+        wait().await;
+        if true {
+            return fut.await;
+        } else {
+            wait().await;
+        }
+    }
+}
+
+pub async fn test() {
+    let fut = big_fut([0u8; 1024 * 16]);
+    foo().await;
+    calls_fut(fut).await;
+}
+
+pub fn foo() -> impl std::future::Future<Output = ()> {
+    async {
+        let x = [0i32; 1024 * 16];
+        async {}.await;
+        dbg!(x);
+    }
+}
+
+pub async fn lines() {
+    async {
+        let x = [0i32; 1024 * 16];
+        async {}.await;
+        println!("{:?}", x);
+    }
+    .await;
+}
+
+pub async fn macro_expn() {
+    macro_rules! macro_ {
+        () => {
+            async {
+                let x = [0i32; 1024 * 16];
+                async {}.await;
+                println!("macro: {:?}", x);
+            }
+        };
+    }
+    macro_!().await
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/large_futures.stderr b/src/tools/clippy/tests/ui/large_futures.stderr
new file mode 100644
index 00000000000..67e0fceff6e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/large_futures.stderr
@@ -0,0 +1,82 @@
+error: large future with a size of 16385 bytes
+  --> $DIR/large_futures.rs:10:9
+   |
+LL |         big_fut([0u8; 1024 * 16]).await;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(big_fut([0u8; 1024 * 16]))`
+   |
+   = note: `-D clippy::large-futures` implied by `-D warnings`
+
+error: large future with a size of 16386 bytes
+  --> $DIR/large_futures.rs:12:5
+   |
+LL |     f.await
+   |     ^ help: consider `Box::pin` on it: `Box::pin(f)`
+
+error: large future with a size of 16387 bytes
+  --> $DIR/large_futures.rs:16:9
+   |
+LL |         wait().await;
+   |         ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
+
+error: large future with a size of 16387 bytes
+  --> $DIR/large_futures.rs:20:13
+   |
+LL |             wait().await;
+   |             ^^^^^^ help: consider `Box::pin` on it: `Box::pin(wait())`
+
+error: large future with a size of 65540 bytes
+  --> $DIR/large_futures.rs:27:5
+   |
+LL |     foo().await;
+   |     ^^^^^ help: consider `Box::pin` on it: `Box::pin(foo())`
+
+error: large future with a size of 49159 bytes
+  --> $DIR/large_futures.rs:28:5
+   |
+LL |     calls_fut(fut).await;
+   |     ^^^^^^^^^^^^^^ help: consider `Box::pin` on it: `Box::pin(calls_fut(fut))`
+
+error: large future with a size of 65540 bytes
+  --> $DIR/large_futures.rs:40:5
+   |
+LL | /     async {
+LL | |         let x = [0i32; 1024 * 16];
+LL | |         async {}.await;
+LL | |         println!("{:?}", x);
+LL | |     }
+   | |_____^
+   |
+help: consider `Box::pin` on it
+   |
+LL ~     Box::pin(async {
+LL +         let x = [0i32; 1024 * 16];
+LL +         async {}.await;
+LL +         println!("{:?}", x);
+LL +     })
+   |
+
+error: large future with a size of 65540 bytes
+  --> $DIR/large_futures.rs:51:13
+   |
+LL | /             async {
+LL | |                 let x = [0i32; 1024 * 16];
+LL | |                 async {}.await;
+LL | |                 println!("macro: {:?}", x);
+LL | |             }
+   | |_____________^
+...
+LL |       macro_!().await
+   |       --------- in this macro invocation
+   |
+   = note: this error originates in the macro `macro_` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider `Box::pin` on it
+   |
+LL ~             Box::pin(async {
+LL +                 let x = [0i32; 1024 * 16];
+LL +                 async {}.await;
+LL +                 println!("macro: {:?}", x);
+LL +             })
+   |
+
+error: aborting due to 8 previous errors
+
diff --git a/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed b/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed
new file mode 100644
index 00000000000..f4033cd8ed8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/lines_filter_map_ok.fixed
@@ -0,0 +1,29 @@
+// run-rustfix
+
+#![allow(unused, clippy::map_identity)]
+#![warn(clippy::lines_filter_map_ok)]
+
+use std::io::{self, BufRead, BufReader};
+
+fn main() -> io::Result<()> {
+    let f = std::fs::File::open("/")?;
+    // Lint
+    BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ());
+    // Lint
+    let f = std::fs::File::open("/")?;
+    BufReader::new(f).lines().map_while(Result::ok).for_each(|_| ());
+    let s = "foo\nbar\nbaz\n";
+    // Lint
+    io::stdin().lines().map_while(Result::ok).for_each(|_| ());
+    // Lint
+    io::stdin().lines().map_while(Result::ok).for_each(|_| ());
+    // Do not lint (not a `Lines` iterator)
+    io::stdin()
+        .lines()
+        .map(std::convert::identity)
+        .filter_map(|x| x.ok())
+        .for_each(|_| ());
+    // Do not lint (not a `Result::ok()` extractor)
+    io::stdin().lines().filter_map(|x| x.err()).for_each(|_| ());
+    Ok(())
+}
diff --git a/src/tools/clippy/tests/ui/lines_filter_map_ok.rs b/src/tools/clippy/tests/ui/lines_filter_map_ok.rs
new file mode 100644
index 00000000000..7e11816b2ac
--- /dev/null
+++ b/src/tools/clippy/tests/ui/lines_filter_map_ok.rs
@@ -0,0 +1,29 @@
+// run-rustfix
+
+#![allow(unused, clippy::map_identity)]
+#![warn(clippy::lines_filter_map_ok)]
+
+use std::io::{self, BufRead, BufReader};
+
+fn main() -> io::Result<()> {
+    let f = std::fs::File::open("/")?;
+    // Lint
+    BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ());
+    // Lint
+    let f = std::fs::File::open("/")?;
+    BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ());
+    let s = "foo\nbar\nbaz\n";
+    // Lint
+    io::stdin().lines().filter_map(Result::ok).for_each(|_| ());
+    // Lint
+    io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ());
+    // Do not lint (not a `Lines` iterator)
+    io::stdin()
+        .lines()
+        .map(std::convert::identity)
+        .filter_map(|x| x.ok())
+        .for_each(|_| ());
+    // Do not lint (not a `Result::ok()` extractor)
+    io::stdin().lines().filter_map(|x| x.err()).for_each(|_| ());
+    Ok(())
+}
diff --git a/src/tools/clippy/tests/ui/lines_filter_map_ok.stderr b/src/tools/clippy/tests/ui/lines_filter_map_ok.stderr
new file mode 100644
index 00000000000..cddd403d589
--- /dev/null
+++ b/src/tools/clippy/tests/ui/lines_filter_map_ok.stderr
@@ -0,0 +1,51 @@
+error: `filter_map()` will run forever if the iterator repeatedly produces an `Err`
+  --> $DIR/lines_filter_map_ok.rs:11:31
+   |
+LL |     BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ());
+   |                               ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)`
+   |
+note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error
+  --> $DIR/lines_filter_map_ok.rs:11:5
+   |
+LL |     BufReader::new(f).lines().filter_map(Result::ok).for_each(|_| ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `-D clippy::lines-filter-map-ok` implied by `-D warnings`
+
+error: `flat_map()` will run forever if the iterator repeatedly produces an `Err`
+  --> $DIR/lines_filter_map_ok.rs:14:31
+   |
+LL |     BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ());
+   |                               ^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)`
+   |
+note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error
+  --> $DIR/lines_filter_map_ok.rs:14:5
+   |
+LL |     BufReader::new(f).lines().flat_map(Result::ok).for_each(|_| ());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `filter_map()` will run forever if the iterator repeatedly produces an `Err`
+  --> $DIR/lines_filter_map_ok.rs:17:25
+   |
+LL |     io::stdin().lines().filter_map(Result::ok).for_each(|_| ());
+   |                         ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)`
+   |
+note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error
+  --> $DIR/lines_filter_map_ok.rs:17:5
+   |
+LL |     io::stdin().lines().filter_map(Result::ok).for_each(|_| ());
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: `filter_map()` will run forever if the iterator repeatedly produces an `Err`
+  --> $DIR/lines_filter_map_ok.rs:19:25
+   |
+LL |     io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ());
+   |                         ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `map_while(Result::ok)`
+   |
+note: this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error
+  --> $DIR/lines_filter_map_ok.rs:19:5
+   |
+LL |     io::stdin().lines().filter_map(|x| x.ok()).for_each(|_| ());
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs b/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs
new file mode 100644
index 00000000000..5082f931f3c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_slice_size_calculation.rs
@@ -0,0 +1,36 @@
+#![allow(unused)]
+#![warn(clippy::manual_slice_size_calculation)]
+
+use core::mem::{align_of, size_of};
+
+fn main() {
+    let v_i32 = Vec::<i32>::new();
+    let s_i32 = v_i32.as_slice();
+
+    // True positives:
+    let _ = s_i32.len() * size_of::<i32>(); // WARNING
+    let _ = size_of::<i32>() * s_i32.len(); // WARNING
+    let _ = size_of::<i32>() * s_i32.len() * 5; // WARNING
+
+    let len = s_i32.len();
+    let size = size_of::<i32>();
+    let _ = len * size_of::<i32>(); // WARNING
+    let _ = s_i32.len() * size; // WARNING
+    let _ = len * size; // WARNING
+
+    // True negatives:
+    let _ = size_of::<i32>() + s_i32.len(); // Ok, not a multiplication
+    let _ = size_of::<i32>() * s_i32.partition_point(|_| true); // Ok, not len()
+    let _ = size_of::<i32>() * v_i32.len(); // Ok, not a slice
+    let _ = align_of::<i32>() * s_i32.len(); // Ok, not size_of()
+    let _ = size_of::<u32>() * s_i32.len(); // Ok, different types
+
+    // False negatives:
+    let _ = 5 * size_of::<i32>() * s_i32.len(); // Ok (MISSED OPPORTUNITY)
+    let _ = size_of::<i32>() * 5 * s_i32.len(); // Ok (MISSED OPPORTUNITY)
+}
+
+const fn _const(s_i32: &[i32]) {
+    // True negative:
+    let _ = s_i32.len() * size_of::<i32>(); // Ok, can't use size_of_val in const
+}
diff --git a/src/tools/clippy/tests/ui/manual_slice_size_calculation.stderr b/src/tools/clippy/tests/ui/manual_slice_size_calculation.stderr
new file mode 100644
index 00000000000..4a24fc60a0f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_slice_size_calculation.stderr
@@ -0,0 +1,51 @@
+error: manual slice size calculation
+  --> $DIR/manual_slice_size_calculation.rs:11:13
+   |
+LL |     let _ = s_i32.len() * size_of::<i32>(); // WARNING
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using std::mem::size_of_value instead
+   = note: `-D clippy::manual-slice-size-calculation` implied by `-D warnings`
+
+error: manual slice size calculation
+  --> $DIR/manual_slice_size_calculation.rs:12:13
+   |
+LL |     let _ = size_of::<i32>() * s_i32.len(); // WARNING
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using std::mem::size_of_value instead
+
+error: manual slice size calculation
+  --> $DIR/manual_slice_size_calculation.rs:13:13
+   |
+LL |     let _ = size_of::<i32>() * s_i32.len() * 5; // WARNING
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using std::mem::size_of_value instead
+
+error: manual slice size calculation
+  --> $DIR/manual_slice_size_calculation.rs:17:13
+   |
+LL |     let _ = len * size_of::<i32>(); // WARNING
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using std::mem::size_of_value instead
+
+error: manual slice size calculation
+  --> $DIR/manual_slice_size_calculation.rs:18:13
+   |
+LL |     let _ = s_i32.len() * size; // WARNING
+   |             ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using std::mem::size_of_value instead
+
+error: manual slice size calculation
+  --> $DIR/manual_slice_size_calculation.rs:19:13
+   |
+LL |     let _ = len * size; // WARNING
+   |             ^^^^^^^^^^
+   |
+   = help: consider using std::mem::size_of_value instead
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/mem_replace.fixed b/src/tools/clippy/tests/ui/mem_replace.fixed
index 874d5584330..7fd340173af 100644
--- a/src/tools/clippy/tests/ui/mem_replace.fixed
+++ b/src/tools/clippy/tests/ui/mem_replace.fixed
@@ -90,3 +90,37 @@ fn msrv_1_40() {
     let mut s = String::from("foo");
     let _ = std::mem::take(&mut s);
 }
+
+fn issue9824() {
+    struct Foo<'a>(Option<&'a str>);
+    impl<'a> std::ops::Deref for Foo<'a> {
+        type Target = Option<&'a str>;
+
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<'a> std::ops::DerefMut for Foo<'a> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            &mut self.0
+        }
+    }
+
+    struct Bar {
+        opt: Option<u8>,
+        val: String,
+    }
+
+    let mut f = Foo(Some("foo"));
+    let mut b = Bar {
+        opt: Some(1),
+        val: String::from("bar"),
+    };
+
+    // replace option with none
+    let _ = f.0.take();
+    let _ = (*f).take();
+    let _ = b.opt.take();
+    // replace with default
+    let _ = std::mem::take(&mut b.val);
+}
diff --git a/src/tools/clippy/tests/ui/mem_replace.rs b/src/tools/clippy/tests/ui/mem_replace.rs
index f4f3bff5144..fa2903addbc 100644
--- a/src/tools/clippy/tests/ui/mem_replace.rs
+++ b/src/tools/clippy/tests/ui/mem_replace.rs
@@ -90,3 +90,37 @@ fn msrv_1_40() {
     let mut s = String::from("foo");
     let _ = std::mem::replace(&mut s, String::default());
 }
+
+fn issue9824() {
+    struct Foo<'a>(Option<&'a str>);
+    impl<'a> std::ops::Deref for Foo<'a> {
+        type Target = Option<&'a str>;
+
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<'a> std::ops::DerefMut for Foo<'a> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            &mut self.0
+        }
+    }
+
+    struct Bar {
+        opt: Option<u8>,
+        val: String,
+    }
+
+    let mut f = Foo(Some("foo"));
+    let mut b = Bar {
+        opt: Some(1),
+        val: String::from("bar"),
+    };
+
+    // replace option with none
+    let _ = std::mem::replace(&mut f.0, None);
+    let _ = std::mem::replace(&mut *f, None);
+    let _ = std::mem::replace(&mut b.opt, None);
+    // replace with default
+    let _ = std::mem::replace(&mut b.val, String::default());
+}
diff --git a/src/tools/clippy/tests/ui/mem_replace.stderr b/src/tools/clippy/tests/ui/mem_replace.stderr
index caa127f76ee..58b57be7507 100644
--- a/src/tools/clippy/tests/ui/mem_replace.stderr
+++ b/src/tools/clippy/tests/ui/mem_replace.stderr
@@ -122,5 +122,29 @@ error: replacing a value of type `T` with `T::default()` is better expressed usi
 LL |     let _ = std::mem::replace(&mut s, String::default());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)`
 
-error: aborting due to 20 previous errors
+error: replacing an `Option` with `None`
+  --> $DIR/mem_replace.rs:121:13
+   |
+LL |     let _ = std::mem::replace(&mut f.0, None);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()`
+
+error: replacing an `Option` with `None`
+  --> $DIR/mem_replace.rs:122:13
+   |
+LL |     let _ = std::mem::replace(&mut *f, None);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()`
+
+error: replacing an `Option` with `None`
+  --> $DIR/mem_replace.rs:123:13
+   |
+LL |     let _ = std::mem::replace(&mut b.opt, None);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+  --> $DIR/mem_replace.rs:125:13
+   |
+LL |     let _ = std::mem::replace(&mut b.val, String::default());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut b.val)`
+
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index 0f525dd294c..57c08996ce2 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -307,4 +307,13 @@ mod issue10049 {
     }
 }
 
+fn test_match_as_stmt() {
+    let x = 9;
+    match x {
+        1 => 2,
+        2 => return,
+        _ => 0,
+    };
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index a1db8375d95..7c1feefbe32 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -317,4 +317,13 @@ mod issue10049 {
     }
 }
 
+fn test_match_as_stmt() {
+    let x = 9;
+    match x {
+        1 => 2,
+        2 => return,
+        _ => 0,
+    };
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs
index 3b5a374b4a7..80cc7c60f56 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs
@@ -92,3 +92,21 @@ fn issue_10523_2() {
     }
     if a!() {}
 }
+
+fn issue_10435() {
+    let x = vec![0];
+    let y = vec![1];
+    let z = vec![2];
+
+    // vvv Should not lint
+    #[allow(clippy::nonminimal_bool)]
+    if !x.is_empty() && !(y.is_empty() || z.is_empty()) {
+        println!("{}", line!());
+    }
+
+    // vvv Should not lint (#10435 talks about a bug where it lints)
+    #[allow(clippy::nonminimal_bool)]
+    if !(x == [0]) {
+        println!("{}", line!());
+    }
+}
diff --git a/src/tools/clippy/tests/ui/print_literal.rs b/src/tools/clippy/tests/ui/print_literal.rs
index 86f908f66b8..538513e9156 100644
--- a/src/tools/clippy/tests/ui/print_literal.rs
+++ b/src/tools/clippy/tests/ui/print_literal.rs
@@ -38,4 +38,8 @@ fn main() {
     // named args shouldn't change anything either
     println!("{foo} {bar}", foo = "hello", bar = "world");
     println!("{bar} {foo}", foo = "hello", bar = "world");
+
+    // The string literal from `file!()` has a callsite span that isn't marked as coming from an
+    // expansion
+    println!("file: {}", file!());
 }
diff --git a/src/tools/clippy/tests/ui/redundant_async_block.fixed b/src/tools/clippy/tests/ui/redundant_async_block.fixed
index d26b7a332cb..ad96993c4a7 100644
--- a/src/tools/clippy/tests/ui/redundant_async_block.fixed
+++ b/src/tools/clippy/tests/ui/redundant_async_block.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused)]
+#![allow(unused, clippy::manual_async_fn)]
 #![warn(clippy::redundant_async_block)]
 
 use std::future::Future;
@@ -16,40 +16,16 @@ async fn func2() -> String {
     x.await
 }
 
-macro_rules! await_in_macro {
-    ($e:expr) => {
-        std::convert::identity($e).await
-    };
-}
-
-async fn func3(n: usize) -> usize {
-    // Do not lint (suggestion would be `std::convert::identity(func1(n))`
-    // which copies code from inside the macro)
-    async move { await_in_macro!(func1(n)) }.await
-}
-
-// This macro should never be linted as `$e` might contain `.await`
-macro_rules! async_await_parameter_in_macro {
-    ($e:expr) => {
-        async { $e.await }
-    };
-}
-
-// MISSED OPPORTUNITY: this macro could be linted as the `async` block does not
-// contain code coming from the parameters
-macro_rules! async_await_in_macro {
-    ($f:expr) => {
-        ($f)(async { func2().await })
-    };
-}
-
 fn main() {
     let fut1 = async { 17 };
+    // Lint
     let fut2 = fut1;
 
     let fut1 = async { 25 };
+    // Lint
     let fut2 = fut1;
 
+    // Lint
     let fut = async { 42 };
 
     // Do not lint: not a single expression
@@ -60,15 +36,12 @@ fn main() {
 
     // Do not lint: expression contains `.await`
     let fut = async { func1(func2().await.len()).await };
-
-    let fut = async_await_parameter_in_macro!(func2());
-    let fut = async_await_in_macro!(std::convert::identity);
 }
 
 #[allow(clippy::let_and_return)]
 fn capture_local() -> impl Future<Output = i32> {
-    // Lint
     let fut = async { 17 };
+    // Lint
     fut
 }
 
@@ -80,11 +53,39 @@ fn capture_local_closure(s: &str) -> impl Future<Output = &str> {
 
 #[allow(clippy::let_and_return)]
 fn capture_arg(s: &str) -> impl Future<Output = &str> {
-    // Lint
     let fut = async move { s };
+    // Lint
     fut
 }
 
+fn capture_future_arg<T>(f: impl Future<Output = T>) -> impl Future<Output = T> {
+    // Lint
+    f
+}
+
+fn capture_func_result<FN, F, T>(f: FN) -> impl Future<Output = T>
+where
+    F: Future<Output = T>,
+    FN: FnOnce() -> F,
+{
+    // Do not lint, as f() would be evaluated prematurely
+    async { f().await }
+}
+
+fn double_future(f: impl Future<Output = impl Future<Output = u32>>) -> impl Future<Output = u32> {
+    // Do not lint, we will get a `.await` outside a `.async`
+    async { f.await.await }
+}
+
+fn await_in_async<F, R>(f: F) -> impl Future<Output = u32>
+where
+    F: FnOnce() -> R,
+    R: Future<Output = u32>,
+{
+    // Lint
+    async { f().await + 1 }
+}
+
 #[derive(Debug, Clone)]
 struct F {}
 
@@ -109,3 +110,84 @@ fn capture() {
     // Do not lint: `val` would not live long enough
     spawn(async { work(&{ val }).await });
 }
+
+fn await_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e:expr) => {
+            $e.await
+        };
+    }
+    // Do not lint: the macro may change in the future
+    // or return different things depending on its argument
+    async { mac!(async { 42 }) }
+}
+
+fn async_expr_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        () => {
+            async { 42 }
+        };
+    }
+    // Do not lint: the macro may change in the future
+    async { mac!().await }
+}
+
+fn async_expr_from_macro_deep() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        () => {
+            async { 42 }
+        };
+    }
+    // Do not lint: the macro may change in the future
+    async { ({ mac!() }).await }
+}
+
+fn all_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        () => {
+            // Lint
+            async { 42 }
+        };
+    }
+    mac!()
+}
+
+fn parts_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e: expr) => {
+            // Do not lint: `$e` might not always be side-effect free
+            async { $e.await }
+        };
+    }
+    mac!(async { 42 })
+}
+
+fn safe_parts_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e: expr) => {
+            // Lint
+            async { $e }
+        };
+    }
+    mac!(42)
+}
+
+fn parts_from_macro_deep() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e: expr) => {
+            // Do not lint: `$e` might not always be side-effect free
+            async { ($e,).0.await }
+        };
+    }
+    let f = std::future::ready(42);
+    mac!(f)
+}
+
+fn await_from_macro_deep() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e:expr) => {{ $e }.await};
+    }
+    // Do not lint: the macro may change in the future
+    // or return different things depending on its argument
+    async { mac!(async { 42 }) }
+}
diff --git a/src/tools/clippy/tests/ui/redundant_async_block.rs b/src/tools/clippy/tests/ui/redundant_async_block.rs
index 04726e62805..7ae23558369 100644
--- a/src/tools/clippy/tests/ui/redundant_async_block.rs
+++ b/src/tools/clippy/tests/ui/redundant_async_block.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![allow(unused)]
+#![allow(unused, clippy::manual_async_fn)]
 #![warn(clippy::redundant_async_block)]
 
 use std::future::Future;
@@ -16,40 +16,16 @@ async fn func2() -> String {
     x.await
 }
 
-macro_rules! await_in_macro {
-    ($e:expr) => {
-        std::convert::identity($e).await
-    };
-}
-
-async fn func3(n: usize) -> usize {
-    // Do not lint (suggestion would be `std::convert::identity(func1(n))`
-    // which copies code from inside the macro)
-    async move { await_in_macro!(func1(n)) }.await
-}
-
-// This macro should never be linted as `$e` might contain `.await`
-macro_rules! async_await_parameter_in_macro {
-    ($e:expr) => {
-        async { $e.await }
-    };
-}
-
-// MISSED OPPORTUNITY: this macro could be linted as the `async` block does not
-// contain code coming from the parameters
-macro_rules! async_await_in_macro {
-    ($f:expr) => {
-        ($f)(async { func2().await })
-    };
-}
-
 fn main() {
     let fut1 = async { 17 };
+    // Lint
     let fut2 = async { fut1.await };
 
     let fut1 = async { 25 };
+    // Lint
     let fut2 = async move { fut1.await };
 
+    // Lint
     let fut = async { async { 42 }.await };
 
     // Do not lint: not a single expression
@@ -60,15 +36,12 @@ fn main() {
 
     // Do not lint: expression contains `.await`
     let fut = async { func1(func2().await.len()).await };
-
-    let fut = async_await_parameter_in_macro!(func2());
-    let fut = async_await_in_macro!(std::convert::identity);
 }
 
 #[allow(clippy::let_and_return)]
 fn capture_local() -> impl Future<Output = i32> {
-    // Lint
     let fut = async { 17 };
+    // Lint
     async move { fut.await }
 }
 
@@ -80,11 +53,39 @@ fn capture_local_closure(s: &str) -> impl Future<Output = &str> {
 
 #[allow(clippy::let_and_return)]
 fn capture_arg(s: &str) -> impl Future<Output = &str> {
-    // Lint
     let fut = async move { s };
+    // Lint
     async move { fut.await }
 }
 
+fn capture_future_arg<T>(f: impl Future<Output = T>) -> impl Future<Output = T> {
+    // Lint
+    async { f.await }
+}
+
+fn capture_func_result<FN, F, T>(f: FN) -> impl Future<Output = T>
+where
+    F: Future<Output = T>,
+    FN: FnOnce() -> F,
+{
+    // Do not lint, as f() would be evaluated prematurely
+    async { f().await }
+}
+
+fn double_future(f: impl Future<Output = impl Future<Output = u32>>) -> impl Future<Output = u32> {
+    // Do not lint, we will get a `.await` outside a `.async`
+    async { f.await.await }
+}
+
+fn await_in_async<F, R>(f: F) -> impl Future<Output = u32>
+where
+    F: FnOnce() -> R,
+    R: Future<Output = u32>,
+{
+    // Lint
+    async { async { f().await + 1 }.await }
+}
+
 #[derive(Debug, Clone)]
 struct F {}
 
@@ -109,3 +110,84 @@ fn capture() {
     // Do not lint: `val` would not live long enough
     spawn(async { work(&{ val }).await });
 }
+
+fn await_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e:expr) => {
+            $e.await
+        };
+    }
+    // Do not lint: the macro may change in the future
+    // or return different things depending on its argument
+    async { mac!(async { 42 }) }
+}
+
+fn async_expr_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        () => {
+            async { 42 }
+        };
+    }
+    // Do not lint: the macro may change in the future
+    async { mac!().await }
+}
+
+fn async_expr_from_macro_deep() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        () => {
+            async { 42 }
+        };
+    }
+    // Do not lint: the macro may change in the future
+    async { ({ mac!() }).await }
+}
+
+fn all_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        () => {
+            // Lint
+            async { async { 42 }.await }
+        };
+    }
+    mac!()
+}
+
+fn parts_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e: expr) => {
+            // Do not lint: `$e` might not always be side-effect free
+            async { $e.await }
+        };
+    }
+    mac!(async { 42 })
+}
+
+fn safe_parts_from_macro() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e: expr) => {
+            // Lint
+            async { async { $e }.await }
+        };
+    }
+    mac!(42)
+}
+
+fn parts_from_macro_deep() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e: expr) => {
+            // Do not lint: `$e` might not always be side-effect free
+            async { ($e,).0.await }
+        };
+    }
+    let f = std::future::ready(42);
+    mac!(f)
+}
+
+fn await_from_macro_deep() -> impl Future<Output = u32> {
+    macro_rules! mac {
+        ($e:expr) => {{ $e }.await};
+    }
+    // Do not lint: the macro may change in the future
+    // or return different things depending on its argument
+    async { mac!(async { 42 }) }
+}
diff --git a/src/tools/clippy/tests/ui/redundant_async_block.stderr b/src/tools/clippy/tests/ui/redundant_async_block.stderr
index 1a1c1603e08..f3dcb09b444 100644
--- a/src/tools/clippy/tests/ui/redundant_async_block.stderr
+++ b/src/tools/clippy/tests/ui/redundant_async_block.stderr
@@ -7,34 +7,68 @@ LL |     let x = async { f.await };
    = note: `-D clippy::redundant-async-block` implied by `-D warnings`
 
 error: this async expression only awaits a single future
-  --> $DIR/redundant_async_block.rs:48:16
+  --> $DIR/redundant_async_block.rs:22:16
    |
 LL |     let fut2 = async { fut1.await };
    |                ^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1`
 
 error: this async expression only awaits a single future
-  --> $DIR/redundant_async_block.rs:51:16
+  --> $DIR/redundant_async_block.rs:26:16
    |
 LL |     let fut2 = async move { fut1.await };
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut1`
 
 error: this async expression only awaits a single future
-  --> $DIR/redundant_async_block.rs:53:15
+  --> $DIR/redundant_async_block.rs:29:15
    |
 LL |     let fut = async { async { 42 }.await };
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }`
 
 error: this async expression only awaits a single future
-  --> $DIR/redundant_async_block.rs:72:5
+  --> $DIR/redundant_async_block.rs:45:5
    |
 LL |     async move { fut.await }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut`
 
 error: this async expression only awaits a single future
-  --> $DIR/redundant_async_block.rs:85:5
+  --> $DIR/redundant_async_block.rs:58:5
    |
 LL |     async move { fut.await }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `fut`
 
-error: aborting due to 6 previous errors
+error: this async expression only awaits a single future
+  --> $DIR/redundant_async_block.rs:63:5
+   |
+LL |     async { f.await }
+   |     ^^^^^^^^^^^^^^^^^ help: you can reduce it to: `f`
+
+error: this async expression only awaits a single future
+  --> $DIR/redundant_async_block.rs:86:5
+   |
+LL |     async { async { f().await + 1 }.await }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { f().await + 1 }`
+
+error: this async expression only awaits a single future
+  --> $DIR/redundant_async_block.rs:149:13
+   |
+LL |             async { async { 42 }.await }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }`
+...
+LL |     mac!()
+   |     ------ in this macro invocation
+   |
+   = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: this async expression only awaits a single future
+  --> $DIR/redundant_async_block.rs:169:13
+   |
+LL |             async { async { $e }.await }
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { $e }`
+...
+LL |     mac!(42)
+   |     -------- in this macro invocation
+   |
+   = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.fixed b/src/tools/clippy/tests/ui/single_component_path_imports.fixed
index 4c40739d6f5..8c96c4715d3 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports.fixed
+++ b/src/tools/clippy/tests/ui/single_component_path_imports.fixed
@@ -2,9 +2,11 @@
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
+use core;
 
 use serde as edres;
 pub use serde;
+use std;
 
 macro_rules! m {
     () => {
@@ -17,6 +19,10 @@ fn main() {
 
     // False positive #5154, shouldn't trigger lint.
     m!();
+
+    // False positive #10549
+    let _ = self::std::io::stdout();
+    let _ = 0 as self::core::ffi::c_uint;
 }
 
 mod hello_mod {
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.rs b/src/tools/clippy/tests/ui/single_component_path_imports.rs
index 9280bab3c71..8434bf7eaf1 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports.rs
+++ b/src/tools/clippy/tests/ui/single_component_path_imports.rs
@@ -2,9 +2,11 @@
 #![warn(clippy::single_component_path_imports)]
 #![allow(unused_imports)]
 
+use core;
 use regex;
 use serde as edres;
 pub use serde;
+use std;
 
 macro_rules! m {
     () => {
@@ -17,6 +19,10 @@ fn main() {
 
     // False positive #5154, shouldn't trigger lint.
     m!();
+
+    // False positive #10549
+    let _ = self::std::io::stdout();
+    let _ = 0 as self::core::ffi::c_uint;
 }
 
 mod hello_mod {
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports.stderr b/src/tools/clippy/tests/ui/single_component_path_imports.stderr
index 71dcc25d6e5..d69a86470a5 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports.stderr
+++ b/src/tools/clippy/tests/ui/single_component_path_imports.stderr
@@ -1,5 +1,5 @@
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:5:1
+  --> $DIR/single_component_path_imports.rs:6:1
    |
 LL | use regex;
    | ^^^^^^^^^^ help: remove it entirely
@@ -7,7 +7,7 @@ LL | use regex;
    = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
 
 error: this import is redundant
-  --> $DIR/single_component_path_imports.rs:23:5
+  --> $DIR/single_component_path_imports.rs:29:5
    |
 LL |     use regex;
    |     ^^^^^^^^^^ help: remove it entirely
diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed b/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed
new file mode 100644
index 00000000000..b404df94d3c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_doc_comments.fixed
@@ -0,0 +1,81 @@
+// run-rustfix
+#![allow(unused)]
+#![warn(clippy::suspicious_doc_comments)]
+
+//! Real module documentation.
+//! Fake module documentation.
+fn baz() {}
+
+pub mod singleline_outer_doc {
+    //! This module contains useful functions.
+
+    pub fn bar() {}
+}
+
+pub mod singleline_inner_doc {
+    //! This module contains useful functions.
+
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc {
+    /*! This module contains useful functions.
+     */
+
+    pub fn bar() {}
+}
+
+pub mod multiline_inner_doc {
+    /*! This module contains useful functions.
+     */
+
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc2 {
+    //! This module
+    //! contains
+    //! useful functions.
+
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc3 {
+    //! a
+    //! b
+
+    /// c
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc4 {
+    //! a
+    /// b
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc_gap {
+    //! a
+
+    //! b
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc_commented {
+    /////! This outer doc comment was commented out.
+    pub fn bar() {}
+}
+
+pub mod outer_doc_macro {
+    //! Very cool macro
+    macro_rules! x {
+        () => {};
+    }
+}
+
+pub mod useless_outer_doc {
+    //! Huh.
+    use std::mem;
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments.rs b/src/tools/clippy/tests/ui/suspicious_doc_comments.rs
new file mode 100644
index 00000000000..46eff51e220
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_doc_comments.rs
@@ -0,0 +1,81 @@
+// run-rustfix
+#![allow(unused)]
+#![warn(clippy::suspicious_doc_comments)]
+
+//! Real module documentation.
+///! Fake module documentation.
+fn baz() {}
+
+pub mod singleline_outer_doc {
+    ///! This module contains useful functions.
+
+    pub fn bar() {}
+}
+
+pub mod singleline_inner_doc {
+    //! This module contains useful functions.
+
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc {
+    /**! This module contains useful functions.
+     */
+
+    pub fn bar() {}
+}
+
+pub mod multiline_inner_doc {
+    /*! This module contains useful functions.
+     */
+
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc2 {
+    ///! This module
+    ///! contains
+    ///! useful functions.
+
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc3 {
+    ///! a
+    ///! b
+
+    /// c
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc4 {
+    ///! a
+    /// b
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc_gap {
+    ///! a
+
+    ///! b
+    pub fn bar() {}
+}
+
+pub mod multiline_outer_doc_commented {
+    /////! This outer doc comment was commented out.
+    pub fn bar() {}
+}
+
+pub mod outer_doc_macro {
+    ///! Very cool macro
+    macro_rules! x {
+        () => {};
+    }
+}
+
+pub mod useless_outer_doc {
+    ///! Huh.
+    use std::mem;
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments.stderr b/src/tools/clippy/tests/ui/suspicious_doc_comments.stderr
new file mode 100644
index 00000000000..6c167df2787
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_doc_comments.stderr
@@ -0,0 +1,114 @@
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments.rs:6:1
+   |
+LL | ///! Fake module documentation.
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::suspicious-doc-comments` implied by `-D warnings`
+help: use an inner doc comment to document the parent module or crate
+   |
+LL | //! Fake module documentation.
+   |
+
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments.rs:10:5
+   |
+LL |     ///! This module contains useful functions.
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use an inner doc comment to document the parent module or crate
+   |
+LL |     //! This module contains useful functions.
+   |
+
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments.rs:22:5
+   |
+LL | /     /**! This module contains useful functions.
+LL | |      */
+   | |_______^
+   |
+help: use an inner doc comment to document the parent module or crate
+   |
+LL ~     /*! This module contains useful functions.
+LL +      */
+   |
+
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments.rs:36:5
+   |
+LL | /     ///! This module
+LL | |     ///! contains
+LL | |     ///! useful functions.
+   | |__________________________^
+   |
+help: use an inner doc comment to document the parent module or crate
+   |
+LL ~     //! This module
+LL ~     //! contains
+LL ~     //! useful functions.
+   |
+
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments.rs:44:5
+   |
+LL | /     ///! a
+LL | |     ///! b
+   | |__________^
+   |
+help: use an inner doc comment to document the parent module or crate
+   |
+LL ~     //! a
+LL ~     //! b
+   |
+
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments.rs:52:5
+   |
+LL |     ///! a
+   |     ^^^^^^
+   |
+help: use an inner doc comment to document the parent module or crate
+   |
+LL |     //! a
+   |
+
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments.rs:58:5
+   |
+LL | /     ///! a
+LL | |
+LL | |     ///! b
+   | |__________^
+   |
+help: use an inner doc comment to document the parent module or crate
+   |
+LL ~     //! a
+LL | 
+LL ~     //! b
+   |
+
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments.rs:70:5
+   |
+LL |     ///! Very cool macro
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+help: use an inner doc comment to document the parent module or crate
+   |
+LL |     //! Very cool macro
+   |
+
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments.rs:77:5
+   |
+LL |     ///! Huh.
+   |     ^^^^^^^^^
+   |
+help: use an inner doc comment to document the parent module or crate
+   |
+LL |     //! Huh.
+   |
+
+error: aborting due to 9 previous errors
+
diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments_unfixable.rs b/src/tools/clippy/tests/ui/suspicious_doc_comments_unfixable.rs
new file mode 100644
index 00000000000..ad98c7f4966
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_doc_comments_unfixable.rs
@@ -0,0 +1,16 @@
+#![allow(unused)]
+#![warn(clippy::suspicious_doc_comments)]
+
+///! a
+///! b
+/// c
+///! d
+pub fn foo() {}
+
+///! a
+///! b
+/// c
+///! d
+use std::mem;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/suspicious_doc_comments_unfixable.stderr b/src/tools/clippy/tests/ui/suspicious_doc_comments_unfixable.stderr
new file mode 100644
index 00000000000..f89146dad36
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_doc_comments_unfixable.stderr
@@ -0,0 +1,37 @@
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments_unfixable.rs:4:1
+   |
+LL | / ///! a
+LL | | ///! b
+LL | | /// c
+LL | | ///! d
+   | |______^
+   |
+   = note: `-D clippy::suspicious-doc-comments` implied by `-D warnings`
+help: use an inner doc comment to document the parent module or crate
+   |
+LL + //! a
+LL + //! b
+LL | /// c
+LL + //! d
+   |
+
+error: this is an outer doc comment and does not apply to the parent module or crate
+  --> $DIR/suspicious_doc_comments_unfixable.rs:10:1
+   |
+LL | / ///! a
+LL | | ///! b
+LL | | /// c
+LL | | ///! d
+   | |______^
+   |
+help: use an inner doc comment to document the parent module or crate
+   |
+LL + //! a
+LL + //! b
+LL | /// c
+LL + //! d
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/tests_outside_test_module.rs b/src/tools/clippy/tests/ui/tests_outside_test_module.rs
new file mode 100644
index 00000000000..1982b1d0107
--- /dev/null
+++ b/src/tools/clippy/tests/ui/tests_outside_test_module.rs
@@ -0,0 +1,18 @@
+// compile-flags: --test
+#![allow(unused)]
+#![warn(clippy::tests_outside_test_module)]
+
+fn main() {
+    // test code goes here
+}
+
+// Should lint
+#[test]
+fn my_test() {}
+
+#[cfg(test)]
+mod tests {
+    // Should not lint
+    #[test]
+    fn my_test() {}
+}
diff --git a/src/tools/clippy/tests/ui/tests_outside_test_module.stderr b/src/tools/clippy/tests/ui/tests_outside_test_module.stderr
new file mode 100644
index 00000000000..125a79d6edf
--- /dev/null
+++ b/src/tools/clippy/tests/ui/tests_outside_test_module.stderr
@@ -0,0 +1,11 @@
+error: this function marked with #[test] is outside a #[cfg(test)] module
+  --> $DIR/tests_outside_test_module.rs:11:1
+   |
+LL | fn my_test() {}
+   | ^^^^^^^^^^^^^^^
+   |
+   = note: move it to a testing module marked with #[cfg(test)]
+   = note: `-D clippy::tests-outside-test-module` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index 55307506eb3..cc84ba25bd0 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -4,7 +4,7 @@
 // would otherwise be responsible for
 #![warn(clippy::useless_transmute)]
 #![warn(clippy::transmute_ptr_to_ptr)]
-#![allow(dead_code, unused_unsafe, clippy::borrow_as_ptr)]
+#![allow(unused, clippy::borrow_as_ptr)]
 
 use std::mem::{size_of, transmute};
 
@@ -77,3 +77,9 @@ fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair {
 
     unsafe { transmute::<Single, Pair>(in_param) }
 }
+
+fn issue_10449() {
+    fn f() {}
+
+    let _x: u8 = unsafe { *(f as *const u8) };
+}
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
index e7360f3f9dc..aa65ab4dd24 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
@@ -4,7 +4,7 @@
 // would otherwise be responsible for
 #![warn(clippy::useless_transmute)]
 #![warn(clippy::transmute_ptr_to_ptr)]
-#![allow(dead_code, unused_unsafe, clippy::borrow_as_ptr)]
+#![allow(unused, clippy::borrow_as_ptr)]
 
 use std::mem::{size_of, transmute};
 
@@ -77,3 +77,9 @@ fn cannot_be_expressed_as_pointer_cast(in_param: Single) -> Pair {
 
     unsafe { transmute::<Single, Pair>(in_param) }
 }
+
+fn issue_10449() {
+    fn f() {}
+
+    let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) };
+}
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
index e862fcb67a4..58f5162c78e 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
@@ -58,5 +58,11 @@ error: transmute from a reference to a pointer
 LL |     unsafe { transmute::<&[i32; 1], *const u8>(in_param) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8`
 
-error: aborting due to 9 previous errors
+error: transmute from `fn()` to `*const u8` which could be expressed as a pointer cast instead
+  --> $DIR/transmutes_expressible_as_ptr_casts.rs:84:28
+   |
+LL |     let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(f as *const u8)`
+
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy/tests/ui/uninit.rs b/src/tools/clippy/tests/ui/uninit.rs
index 412b36b4ee8..c996de89422 100644
--- a/src/tools/clippy/tests/ui/uninit.rs
+++ b/src/tools/clippy/tests/ui/uninit.rs
@@ -1,7 +1,7 @@
 #![feature(stmt_expr_attributes)]
 #![allow(clippy::let_unit_value, invalid_value)]
 
-use std::mem::{self, MaybeUninit};
+use std::mem::MaybeUninit;
 
 union MyOwnMaybeUninit {
     value: u8,
@@ -30,12 +30,24 @@ fn main() {
     let _: [u8; 0] = unsafe { MaybeUninit::uninit().assume_init() };
 
     // Was a false negative.
-    let _: usize = unsafe { mem::MaybeUninit::uninit().assume_init() };
+    let _: usize = unsafe { MaybeUninit::uninit().assume_init() };
 
     polymorphic::<()>();
+    polymorphic_maybe_uninit_array::<10>();
+    polymorphic_maybe_uninit::<u8>();
 
     fn polymorphic<T>() {
         // We are conservative around polymorphic types.
-        let _: T = unsafe { mem::MaybeUninit::uninit().assume_init() };
+        let _: T = unsafe { MaybeUninit::uninit().assume_init() };
+    }
+
+    fn polymorphic_maybe_uninit_array<const N: usize>() {
+        // While the type is polymorphic, MaybeUninit<u8> is not.
+        let _: [MaybeUninit<u8>; N] = unsafe { MaybeUninit::uninit().assume_init() };
+    }
+
+    fn polymorphic_maybe_uninit<T>() {
+        // The entire type is polymorphic, but it's wrapped in a MaybeUninit.
+        let _: MaybeUninit<T> = unsafe { MaybeUninit::uninit().assume_init() };
     }
 }
diff --git a/src/tools/clippy/tests/ui/uninit.stderr b/src/tools/clippy/tests/ui/uninit.stderr
index 9e01b9a4aa8..248de56da76 100644
--- a/src/tools/clippy/tests/ui/uninit.stderr
+++ b/src/tools/clippy/tests/ui/uninit.stderr
@@ -9,14 +9,14 @@ LL |     let _: usize = unsafe { MaybeUninit::uninit().assume_init() };
 error: this call for this type may be undefined behavior
   --> $DIR/uninit.rs:33:29
    |
-LL |     let _: usize = unsafe { mem::MaybeUninit::uninit().assume_init() };
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let _: usize = unsafe { MaybeUninit::uninit().assume_init() };
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this call for this type may be undefined behavior
-  --> $DIR/uninit.rs:39:29
+  --> $DIR/uninit.rs:41:29
    |
-LL |         let _: T = unsafe { mem::MaybeUninit::uninit().assume_init() };
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         let _: T = unsafe { MaybeUninit::uninit().assume_init() };
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/uninit_vec.rs b/src/tools/clippy/tests/ui/uninit_vec.rs
index 59ec64a7ab1..79effc82fdf 100644
--- a/src/tools/clippy/tests/ui/uninit_vec.rs
+++ b/src/tools/clippy/tests/ui/uninit_vec.rs
@@ -124,4 +124,12 @@ fn main() {
             vec.set_len(10);
         }
     }
+
+    fn poly_maybe_uninit<T>() {
+        // We are conservative around polymorphic types.
+        let mut vec: Vec<MaybeUninit<T>> = Vec::with_capacity(1000);
+        unsafe {
+            vec.set_len(10);
+        }
+    }
 }
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.fixed b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
index 1475d781c67..3122081a44f 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
@@ -1,7 +1,7 @@
 // aux-build:proc_macros.rs
 // run-rustfix
 #![warn(clippy::uninlined_format_args)]
-#![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)]
+#![allow(named_arguments_used_positionally, unused)]
 #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
 
 extern crate proc_macros;
@@ -119,7 +119,7 @@ fn tester(fn_arg: i32) {
     println!("Width = {local_i32}, value with width = {local_f64:local_i32$}");
     println!("{local_i32:width$.prec$}");
     println!("{width:width$.prec$}");
-    println!("{}", format!("{local_i32}"));
+    println!("{}", format!("{}", local_i32));
     my_println!("{}", local_i32);
     my_println_args!("{}", local_i32);
 
@@ -178,3 +178,87 @@ fn _meets_msrv() {
 fn _do_not_fire() {
     println!("{:?}", None::<()>);
 }
+
+macro_rules! _internal {
+    ($($args:tt)*) => {
+        println!("{}", format_args!($($args)*))
+    };
+}
+
+macro_rules! my_println2 {
+   ($target:expr, $($args:tt)+) => {{
+       if $target {
+           _internal!($($args)+)
+       }
+    }};
+}
+
+macro_rules! my_println2_args {
+    ($target:expr, $($args:tt)+) => {{
+       if $target {
+           _internal!("foo: {}", format_args!($($args)+))
+       }
+    }};
+}
+
+macro_rules! my_concat {
+    ($fmt:literal $(, $e:expr)*) => {
+        println!(concat!("ERROR: ", $fmt), $($e,)*)
+    }
+}
+
+macro_rules! my_good_macro {
+    ($fmt:literal $(, $e:expr)* $(,)?) => {
+        println!($fmt $(, $e)*)
+    }
+}
+
+macro_rules! my_bad_macro {
+    ($fmt:literal, $($e:expr),*) => {
+        println!($fmt, $($e,)*)
+    }
+}
+
+macro_rules! my_bad_macro2 {
+    ($fmt:literal) => {
+        let s = $fmt.clone();
+        println!("{}", s);
+    };
+    ($fmt:literal, $($e:expr)+) => {
+        println!($fmt, $($e,)*)
+    };
+}
+
+// This abomination was suggested by @Alexendoo, may the Rust gods have mercy on their soul...
+// https://github.com/rust-lang/rust-clippy/pull/9948#issuecomment-1327965962
+macro_rules! used_twice {
+    (
+        large = $large:literal,
+        small = $small:literal,
+        $val:expr,
+    ) => {
+        if $val < 5 {
+            println!($small, $val);
+        } else {
+            println!($large, $val);
+        }
+    };
+}
+
+fn tester2() {
+    let local_i32 = 1;
+    my_println2_args!(true, "{}", local_i32);
+    my_println2!(true, "{}", local_i32);
+    my_concat!("{}", local_i32);
+    my_good_macro!("{}", local_i32);
+    my_good_macro!("{}", local_i32,);
+
+    // FIXME: Broken false positives, currently unhandled
+    my_bad_macro!("{}", local_i32);
+    my_bad_macro2!("{}", local_i32);
+    used_twice! {
+        large = "large value: {}",
+        small = "small value: {}",
+        local_i32,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.rs b/src/tools/clippy/tests/ui/uninlined_format_args.rs
index 835afac393f..b153ef256e0 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.rs
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.rs
@@ -1,7 +1,7 @@
 // aux-build:proc_macros.rs
 // run-rustfix
 #![warn(clippy::uninlined_format_args)]
-#![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)]
+#![allow(named_arguments_used_positionally, unused)]
 #![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
 
 extern crate proc_macros;
@@ -183,3 +183,87 @@ fn _meets_msrv() {
 fn _do_not_fire() {
     println!("{:?}", None::<()>);
 }
+
+macro_rules! _internal {
+    ($($args:tt)*) => {
+        println!("{}", format_args!($($args)*))
+    };
+}
+
+macro_rules! my_println2 {
+   ($target:expr, $($args:tt)+) => {{
+       if $target {
+           _internal!($($args)+)
+       }
+    }};
+}
+
+macro_rules! my_println2_args {
+    ($target:expr, $($args:tt)+) => {{
+       if $target {
+           _internal!("foo: {}", format_args!($($args)+))
+       }
+    }};
+}
+
+macro_rules! my_concat {
+    ($fmt:literal $(, $e:expr)*) => {
+        println!(concat!("ERROR: ", $fmt), $($e,)*)
+    }
+}
+
+macro_rules! my_good_macro {
+    ($fmt:literal $(, $e:expr)* $(,)?) => {
+        println!($fmt $(, $e)*)
+    }
+}
+
+macro_rules! my_bad_macro {
+    ($fmt:literal, $($e:expr),*) => {
+        println!($fmt, $($e,)*)
+    }
+}
+
+macro_rules! my_bad_macro2 {
+    ($fmt:literal) => {
+        let s = $fmt.clone();
+        println!("{}", s);
+    };
+    ($fmt:literal, $($e:expr)+) => {
+        println!($fmt, $($e,)*)
+    };
+}
+
+// This abomination was suggested by @Alexendoo, may the Rust gods have mercy on their soul...
+// https://github.com/rust-lang/rust-clippy/pull/9948#issuecomment-1327965962
+macro_rules! used_twice {
+    (
+        large = $large:literal,
+        small = $small:literal,
+        $val:expr,
+    ) => {
+        if $val < 5 {
+            println!($small, $val);
+        } else {
+            println!($large, $val);
+        }
+    };
+}
+
+fn tester2() {
+    let local_i32 = 1;
+    my_println2_args!(true, "{}", local_i32);
+    my_println2!(true, "{}", local_i32);
+    my_concat!("{}", local_i32);
+    my_good_macro!("{}", local_i32);
+    my_good_macro!("{}", local_i32,);
+
+    // FIXME: Broken false positives, currently unhandled
+    my_bad_macro!("{}", local_i32);
+    my_bad_macro2!("{}", local_i32);
+    used_twice! {
+        large = "large value: {}",
+        small = "small value: {}",
+        local_i32,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.stderr b/src/tools/clippy/tests/ui/uninlined_format_args.stderr
index a12abf8bef8..dc4af6ef42e 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.stderr
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.stderr
@@ -775,18 +775,6 @@ LL +     println!("{width:width$.prec$}");
    |
 
 error: variables can be used directly in the `format!` string
-  --> $DIR/uninlined_format_args.rs:125:20
-   |
-LL |     println!("{}", format!("{}", local_i32));
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: change this to
-   |
-LL -     println!("{}", format!("{}", local_i32));
-LL +     println!("{}", format!("{local_i32}"));
-   |
-
-error: variables can be used directly in the `format!` string
   --> $DIR/uninlined_format_args.rs:143:5
    |
 LL | /     println!(
@@ -856,5 +844,5 @@ LL -     println!("expand='{}'", local_i32);
 LL +     println!("expand='{local_i32}'");
    |
 
-error: aborting due to 72 previous errors
+error: aborting due to 71 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_box_returns.rs b/src/tools/clippy/tests/ui/unnecessary_box_returns.rs
new file mode 100644
index 00000000000..fe60d929759
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_box_returns.rs
@@ -0,0 +1,60 @@
+#![warn(clippy::unnecessary_box_returns)]
+
+trait Bar {
+    // lint
+    fn baz(&self) -> Box<usize>;
+}
+
+pub struct Foo {}
+
+impl Bar for Foo {
+    // don't lint: this is a problem with the trait, not the implementation
+    fn baz(&self) -> Box<usize> {
+        Box::new(42)
+    }
+}
+
+impl Foo {
+    fn baz(&self) -> Box<usize> {
+        // lint
+        Box::new(13)
+    }
+}
+
+// lint
+fn bxed_usize() -> Box<usize> {
+    Box::new(5)
+}
+
+// lint
+fn _bxed_foo() -> Box<Foo> {
+    Box::new(Foo {})
+}
+
+// don't lint: this is exported
+pub fn bxed_foo() -> Box<Foo> {
+    Box::new(Foo {})
+}
+
+// don't lint: str is unsized
+fn bxed_str() -> Box<str> {
+    "Hello, world!".to_string().into_boxed_str()
+}
+
+// don't lint: function contains the word, "box"
+fn boxed_usize() -> Box<usize> {
+    Box::new(7)
+}
+
+// don't lint: this has an unspecified return type
+fn default() {}
+
+// don't lint: this doesn't return a Box
+fn string() -> String {
+    String::from("Hello, world")
+}
+
+fn main() {
+    // don't lint: this is a closure
+    let a = || -> Box<usize> { Box::new(5) };
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_box_returns.stderr b/src/tools/clippy/tests/ui/unnecessary_box_returns.stderr
new file mode 100644
index 00000000000..b17512c10a1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unnecessary_box_returns.stderr
@@ -0,0 +1,35 @@
+error: boxed return of the sized type `usize`
+  --> $DIR/unnecessary_box_returns.rs:5:22
+   |
+LL |     fn baz(&self) -> Box<usize>;
+   |                      ^^^^^^^^^^ help: try: `usize`
+   |
+   = help: changing this also requires a change to the return expressions in this function
+   = note: `-D clippy::unnecessary-box-returns` implied by `-D warnings`
+
+error: boxed return of the sized type `usize`
+  --> $DIR/unnecessary_box_returns.rs:18:22
+   |
+LL |     fn baz(&self) -> Box<usize> {
+   |                      ^^^^^^^^^^ help: try: `usize`
+   |
+   = help: changing this also requires a change to the return expressions in this function
+
+error: boxed return of the sized type `usize`
+  --> $DIR/unnecessary_box_returns.rs:25:20
+   |
+LL | fn bxed_usize() -> Box<usize> {
+   |                    ^^^^^^^^^^ help: try: `usize`
+   |
+   = help: changing this also requires a change to the return expressions in this function
+
+error: boxed return of the sized type `Foo`
+  --> $DIR/unnecessary_box_returns.rs:30:19
+   |
+LL | fn _bxed_foo() -> Box<Foo> {
+   |                   ^^^^^^^^ help: try: `Foo`
+   |
+   = help: changing this also requires a change to the return expressions in this function
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.fixed b/src/tools/clippy/tests/ui/unused_format_specs.fixed
deleted file mode 100644
index 2930722b42d..00000000000
--- a/src/tools/clippy/tests/ui/unused_format_specs.fixed
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-rustfix
-
-#![warn(clippy::unused_format_specs)]
-#![allow(unused)]
-
-fn main() {
-    let f = 1.0f64;
-    println!("{}", 1.0);
-    println!("{f} {f:?}");
-
-    println!("{}", 1);
-}
-
-fn should_not_lint() {
-    let f = 1.0f64;
-    println!("{:.1}", 1.0);
-    println!("{f:.w$} {f:.*?}", 3, w = 2);
-}
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.rs b/src/tools/clippy/tests/ui/unused_format_specs.rs
deleted file mode 100644
index ee192a000d4..00000000000
--- a/src/tools/clippy/tests/ui/unused_format_specs.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// run-rustfix
-
-#![warn(clippy::unused_format_specs)]
-#![allow(unused)]
-
-fn main() {
-    let f = 1.0f64;
-    println!("{:.}", 1.0);
-    println!("{f:.} {f:.?}");
-
-    println!("{:.}", 1);
-}
-
-fn should_not_lint() {
-    let f = 1.0f64;
-    println!("{:.1}", 1.0);
-    println!("{f:.w$} {f:.*?}", 3, w = 2);
-}
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.stderr b/src/tools/clippy/tests/ui/unused_format_specs.stderr
deleted file mode 100644
index 7231c17e74c..00000000000
--- a/src/tools/clippy/tests/ui/unused_format_specs.stderr
+++ /dev/null
@@ -1,54 +0,0 @@
-error: empty precision specifier has no effect
-  --> $DIR/unused_format_specs.rs:8:17
-   |
-LL |     println!("{:.}", 1.0);
-   |                 ^
-   |
-   = note: a precision specifier is not required to format floats
-   = note: `-D clippy::unused-format-specs` implied by `-D warnings`
-help: remove the `.`
-   |
-LL -     println!("{:.}", 1.0);
-LL +     println!("{}", 1.0);
-   |
-
-error: empty precision specifier has no effect
-  --> $DIR/unused_format_specs.rs:9:18
-   |
-LL |     println!("{f:.} {f:.?}");
-   |                  ^
-   |
-   = note: a precision specifier is not required to format floats
-help: remove the `.`
-   |
-LL -     println!("{f:.} {f:.?}");
-LL +     println!("{f} {f:.?}");
-   |
-
-error: empty precision specifier has no effect
-  --> $DIR/unused_format_specs.rs:9:24
-   |
-LL |     println!("{f:.} {f:.?}");
-   |                        ^
-   |
-   = note: a precision specifier is not required to format floats
-help: remove the `.`
-   |
-LL -     println!("{f:.} {f:.?}");
-LL +     println!("{f:.} {f:?}");
-   |
-
-error: empty precision specifier has no effect
-  --> $DIR/unused_format_specs.rs:11:17
-   |
-LL |     println!("{:.}", 1);
-   |                 ^
-   |
-help: remove the `.`
-   |
-LL -     println!("{:.}", 1);
-LL +     println!("{}", 1);
-   |
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui/unused_format_specs_unfixable.stderr b/src/tools/clippy/tests/ui/unused_format_specs_unfixable.stderr
index 9f1890282e6..cb7156b6baf 100644
--- a/src/tools/clippy/tests/ui/unused_format_specs_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/unused_format_specs_unfixable.stderr
@@ -37,11 +37,7 @@ error: format specifiers have no effect on `format_args!()`
 LL |     println!("{:5}.", format_args_from_macro!());
    |               ^^^^
    |
-help: for the width to apply consider using `format!()`
-  --> $DIR/unused_format_specs_unfixable.rs:16:17
-   |
-LL |     println!("{:5}.", format_args_from_macro!());
-   |                 ^
+   = help: for the width to apply consider using `format!()`
 help: if the current behavior is intentional, remove the format specifiers
    |
 LL -     println!("{:5}.", format_args_from_macro!());
@@ -54,11 +50,7 @@ error: format specifiers have no effect on `format_args!()`
 LL |     println!("{args:5}");
    |               ^^^^^^^^
    |
-help: for the width to apply consider using `format!()`
-  --> $DIR/unused_format_specs_unfixable.rs:19:21
-   |
-LL |     println!("{args:5}");
-   |                     ^
+   = help: for the width to apply consider using `format!()`
 help: if the current behavior is intentional, remove the format specifiers
    |
 LL -     println!("{args:5}");
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 98b27a5c6b6..d2f494942cf 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -313,7 +313,8 @@ pub struct Config {
     pub cflags: String,
     pub cxxflags: String,
     pub ar: String,
-    pub linker: Option<String>,
+    pub target_linker: Option<String>,
+    pub host_linker: Option<String>,
     pub llvm_components: String,
 
     /// Path to a NodeJS executable. Used for JS doctests, emscripten and WASM tests
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index cfb1ee34f67..6a91d25a824 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -134,7 +134,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
         .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
         .reqopt("", "cxxflags", "flags for the CXX compiler", "FLAGS")
         .optopt("", "ar", "path to an archiver", "PATH")
-        .optopt("", "linker", "path to a linker", "PATH")
+        .optopt("", "target-linker", "path to a linker for the target", "PATH")
+        .optopt("", "host-linker", "path to a linker for the host", "PATH")
         .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
         .optopt("", "llvm-bin-dir", "Path to LLVM's `bin` directory", "PATH")
         .optopt("", "nodejs", "the name of nodejs", "PATH")
@@ -307,7 +308,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
         cflags: matches.opt_str("cflags").unwrap(),
         cxxflags: matches.opt_str("cxxflags").unwrap(),
         ar: matches.opt_str("ar").unwrap_or_else(|| String::from("ar")),
-        linker: matches.opt_str("linker"),
+        target_linker: matches.opt_str("target-linker"),
+        host_linker: matches.opt_str("host-linker"),
         llvm_components: matches.opt_str("llvm-components").unwrap(),
         nodejs: matches.opt_str("nodejs"),
         npm: matches.opt_str("npm"),
@@ -350,7 +352,8 @@ pub fn log_config(config: &Config) {
     logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
     logv(c, format!("adb_device_status: {}", config.adb_device_status));
     logv(c, format!("ar: {}", config.ar));
-    logv(c, format!("linker: {:?}", config.linker));
+    logv(c, format!("target-linker: {:?}", config.target_linker));
+    logv(c, format!("host-linker: {:?}", config.host_linker));
     logv(c, format!("verbose: {}", config.verbose));
     logv(c, format!("format: {:?}", config.format));
     logv(c, "\n".to_string());
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index e55c82c4b63..0fa5c54ae8e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1570,7 +1570,7 @@ impl<'test> TestCx<'test> {
             rustdoc.arg("--output-format").arg("json").arg("-Zunstable-options");
         }
 
-        if let Some(ref linker) = self.config.linker {
+        if let Some(ref linker) = self.config.target_linker {
             rustdoc.arg(format!("-Clinker={}", linker));
         }
 
@@ -2083,10 +2083,15 @@ impl<'test> TestCx<'test> {
 
         if self.props.force_host {
             self.maybe_add_external_args(&mut rustc, &self.config.host_rustcflags);
+            if !is_rustdoc {
+                if let Some(ref linker) = self.config.host_linker {
+                    rustc.arg(format!("-Clinker={}", linker));
+                }
+            }
         } else {
             self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags);
             if !is_rustdoc {
-                if let Some(ref linker) = self.config.linker {
+                if let Some(ref linker) = self.config.target_linker {
                     rustc.arg(format!("-Clinker={}", linker));
                 }
             }
@@ -3039,7 +3044,7 @@ impl<'test> TestCx<'test> {
             cmd.env("NODE", node);
         }
 
-        if let Some(ref linker) = self.config.linker {
+        if let Some(ref linker) = self.config.target_linker {
             cmd.env("RUSTC_LINKER", linker);
         }
 
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index b71f48e4644..da1c2f770ac 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -174,7 +174,12 @@ jobs:
           ~/.local/bin/zulip-send --stream miri --subject "Cron Job Failure (miri, $(date -u +%Y-%m))" \
             --message 'Dear @*T-miri*,
 
-          It would appear that the Miri cron job build failed. Would you mind investigating this issue?
+          It would appear that the [Miri cron job build]('"https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"') failed.
+          
+          This likely means that rustc changed the miri directory and
+          we now need to do a [`./miri rustc-pull`](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#importing-changes-from-the-rustc-repo).
+
+          Would you mind investigating this issue?
 
           Thanks in advance!
           Sincerely,
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index d17bb9533b4..46deebf2cdd 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -282,9 +282,9 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
 
 [[package]]
 name = "libffi"
-version = "3.0.1"
+version = "3.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e454b3efb16fba3b17810ae5e41df02b649e564ab3c5a34b3b93ed07ad287e6"
+checksum = "ce826c243048e3d5cec441799724de52e2d42f820468431fc3fceee2341871e2"
 dependencies = [
  "libc",
  "libffi-sys",
@@ -292,9 +292,9 @@ dependencies = [
 
 [[package]]
 name = "libffi-sys"
-version = "2.0.1"
+version = "2.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84e78d02e5a8eae9c24c38ce6e6026f80e16dff76adcdae4bc5c6c52c2de4a60"
+checksum = "dc65067b78c0fc069771e8b9a9e02df71e08858bec92c1f101377c67b9dca7c7"
 dependencies = [
  "cc",
 ]
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index b70f7e0e556..4c735187987 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -15,7 +15,7 @@ for example:
   or an invalid enum discriminant)
 * **Experimental**: Violations of the [Stacked Borrows] rules governing aliasing
   for reference types
-* **Experimental**: Violations of the Tree Borrows aliasing rules, as an optional
+* **Experimental**: Violations of the [Tree Borrows] aliasing rules, as an optional
   alternative to [Stacked Borrows]
 * **Experimental**: Data races
 
@@ -79,6 +79,7 @@ behavior** in your program, and cannot run all programs:
 [`unreachable_unchecked`]: https://doc.rust-lang.org/stable/std/hint/fn.unreachable_unchecked.html
 [`copy_nonoverlapping`]: https://doc.rust-lang.org/stable/std/ptr/fn.copy_nonoverlapping.html
 [Stacked Borrows]: https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md
+[Tree Borrows]: https://perso.crans.org/vanille/treebor/
 
 
 ## Using Miri
@@ -359,7 +360,7 @@ to Miri failing to detect cases of undefined behavior in a program.
 * `-Zmiri-disable-data-race-detector` disables checking for data races.  Using
   this flag is **unsound**. This implies `-Zmiri-disable-weak-memory-emulation`.
 * `-Zmiri-disable-stacked-borrows` disables checking the experimental
-  aliasing rules to track borrows ([Stacked Borrows] and Tree Borrows).
+  aliasing rules to track borrows ([Stacked Borrows] and [Tree Borrows]).
   This can make Miri run faster, but it also means no aliasing violations will
   be detected. Using this flag is **unsound** (but the affected soundness rules
   are experimental). Later flags take precedence: borrow tracking can be reactivated
@@ -425,7 +426,7 @@ to Miri failing to detect cases of undefined behavior in a program.
 * `-Zmiri-track-weak-memory-loads` shows a backtrace when weak memory emulation returns an outdated
   value from a load. This can help diagnose problems that disappear under
   `-Zmiri-disable-weak-memory-emulation`.
-* `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the Tree Borrows rules.
+* `-Zmiri-tree-borrows` replaces [Stacked Borrows] with the [Tree Borrows] rules.
   The soundness rules are already experimental without this flag, but even more
   so with this flag.
 * `-Zmiri-force-page-size=<num>` overrides the default page size for an architecture, in multiples of 1k.
@@ -442,7 +443,7 @@ Some native rustc `-Z` flags are also very relevant for Miri:
   functions.  This is needed so that Miri can execute such functions, so Miri
   sets this flag per default.
 * `-Zmir-emit-retag` controls whether `Retag` statements are emitted. Miri
-  enables this per default because it is needed for [Stacked Borrows] and Tree Borrows.
+  enables this per default because it is needed for [Stacked Borrows] and [Tree Borrows].
 
 Moreover, Miri recognizes some environment variables:
 
diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh
index ef52a37fe31..b5b3b211b05 100755
--- a/src/tools/miri/ci.sh
+++ b/src/tools/miri/ci.sh
@@ -43,7 +43,9 @@ function run_tests {
     # optimizations up all the way, too).
     # Optimizations change diagnostics (mostly backtraces), so we don't check
     # them. Also error locations change so we don't run the failing tests.
-    MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
+    # We explicitly enable debug-assertions here, they are disabled by -O but we have tests
+    # which exist to check that we panic on debug assertion failures.
+    MIRIFLAGS="${MIRIFLAGS:-} -O -Zmir-opt-level=4 -Cdebug-assertions=yes" MIRI_SKIP_UI_CHECKS=1 ./miri test -- tests/{pass,panic}
 
     # Also run some many-seeds tests. 64 seeds means this takes around a minute per test.
     for FILE in tests/many-seeds/*.rs; do
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 18c2561242a..f1ed3be2edd 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-511364e7874dba9649a264100407e4bffe7b5425
+d4be8efc6296bace5b1e165f1b34d3c6da76aa8e
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index 0aea105ccc4..26a7ead2407 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -28,9 +28,11 @@ use rustc_middle::{
     middle::exported_symbols::{
         ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel,
     },
-    ty::{query::ExternProviders, TyCtxt},
     query::LocalCrate,
+    ty::{query::ExternProviders, TyCtxt},
 };
+use rustc_session::config::OptLevel;
+
 use rustc_session::{config::CrateType, search_paths::PathKind, CtfeBacktrace};
 
 use miri::{BacktraceStyle, BorrowTrackerMethod, ProvenanceMode, RetagFields};
@@ -83,6 +85,21 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
                 env::set_current_dir(cwd).unwrap();
             }
 
+            if tcx.sess.opts.optimize != OptLevel::No {
+                tcx.sess.warn("Miri does not support optimizations. If you have enabled optimizations \
+                    by selecting a Cargo profile (such as --release) which changes other profile settings \
+                    such as whether debug assertions and overflow checks are enabled, those settings are \
+                    still applied.");
+            }
+            if tcx.sess.mir_opt_level() > 0 {
+                tcx.sess.warn("You have explicitly enabled MIR optimizations, overriding Miri's default \
+                    which is to completely disable them. Any optimizations may hide UB that Miri would \
+                    otherwise detect, and it is not necessarily possible to predict what kind of UB will \
+                    be missed. If you are enabling optimizations to make Miri run faster, we advise using \
+                    cfg(miri) to shrink your workload instead. The performance benefit of enabling MIR \
+                    optimizations is usually marginal at best.");
+            }
+
             if let Some(return_code) = miri::eval_entry(tcx, entry_def_id, entry_type, config) {
                 std::process::exit(
                     i32::try_from(return_code).expect("Return value was too large!"),
diff --git a/src/tools/miri/src/clock.rs b/src/tools/miri/src/clock.rs
index 3f33273e1e5..24bf90f104f 100644
--- a/src/tools/miri/src/clock.rs
+++ b/src/tools/miri/src/clock.rs
@@ -3,7 +3,10 @@ use std::time::{Duration, Instant as StdInstant};
 
 /// When using a virtual clock, this defines how many nanoseconds we pretend are passing for each
 /// basic block.
-const NANOSECONDS_PER_BASIC_BLOCK: u64 = 10;
+/// This number is pretty random, but it has been shown to approximately cause
+/// some sample programs to run within an order of magnitude of real time on desktop CPUs.
+/// (See `tests/pass/shims/time-with-isolation*.rs`.)
+const NANOSECONDS_PER_BASIC_BLOCK: u64 = 5000;
 
 #[derive(Debug)]
 pub struct Instant {
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index fb4e59acd00..5c8aba6d441 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -124,11 +124,13 @@ pub use crate::tag_gc::{EvalContextExt as _, VisitTags};
 
 /// Insert rustc arguments at the beginning of the argument list that Miri wants to be
 /// set per default, for maximal validation power.
+/// Also disable the MIR pass that inserts an alignment check on every pointer dereference. Miri
+/// does that too, and with a better error message.
 pub const MIRI_DEFAULT_ARGS: &[&str] = &[
+    "--cfg=miri",
     "-Zalways-encode-mir",
+    "-Zextra-const-ub-checks",
     "-Zmir-emit-retag",
     "-Zmir-opt-level=0",
-    "--cfg=miri",
-    "-Cdebug-assertions=on",
-    "-Zextra-const-ub-checks",
+    "-Zmir-enable-passes=-CheckAlignment",
 ];
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 2cca2f3f391..18ae01a19f9 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -157,7 +157,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 &[catch_unwind.data.into(), payload.into()],
                 None,
                 // Directly return to caller of `try`.
-                StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: mir::UnwindAction::Continue },
+                StackPopCleanup::Goto {
+                    ret: Some(catch_unwind.ret),
+                    unwind: mir::UnwindAction::Continue,
+                },
             )?;
 
             // We pushed a new stack frame, the engine should not do any jumping now!
@@ -211,10 +214,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     Abi::Rust,
                     &[index.into(), len.into()],
                     None,
-                    StackPopCleanup::Goto {
-                        ret: None,
-                        unwind,
-                    },
+                    StackPopCleanup::Goto { ret: None, unwind },
                 )?;
             }
             MisalignedPointerDereference { required, found } => {
@@ -235,19 +235,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     Abi::Rust,
                     &[required.into(), found.into()],
                     None,
-                    StackPopCleanup::Goto {
-                        ret: None,
-                        unwind,
-                    },
+                    StackPopCleanup::Goto { ret: None, unwind },
                 )?;
             }
 
             _ => {
                 // Forward everything else to `panic` lang item.
-                this.start_panic(
-                    msg.description(),
-                    unwind,
-                )?;
+                this.start_panic(msg.description(), unwind)?;
             }
         }
         Ok(())
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 1eca389e984..de271548217 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -628,13 +628,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let fd = this.read_scalar(&args[0])?.to_i32()?;
         let cmd = this.read_scalar(&args[1])?.to_i32()?;
 
-        // Reject if isolation is enabled.
-        if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
-            this.reject_in_isolation("`fcntl`", reject_with)?;
-            this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
-            return Ok(-1);
-        }
-
         // We only support getting the flags for a descriptor.
         if cmd == this.eval_libc_i32("F_GETFD") {
             // Currently this is the only flag that `F_GETFD` returns. It is OK to just return the
@@ -677,6 +670,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 None => this.handle_not_found(),
             }
         } else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") {
+            // Reject if isolation is enabled.
+            if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
+                this.reject_in_isolation("`fcntl`", reject_with)?;
+                this.set_last_error_from_io_error(ErrorKind::PermissionDenied)?;
+                return Ok(-1);
+            }
+
             if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
                 // FIXME: Support fullfsync for all FDs
                 let FileHandle { file, writable } =
diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr
index 3befd83007b..c046678f73f 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.stderr
+++ b/src/tools/miri/tests/fail/terminate-terminator.stderr
@@ -1,3 +1,5 @@
+warning: You have explicitly enabled MIR optimizations, overriding Miri's default which is to completely disable them. Any optimizations may hide UB that Miri would otherwise detect, and it is not necessarily possible to predict what kind of UB will be missed. If you are enabling optimizations to make Miri run faster, we advise using cfg(miri) to shrink your workload instead. The performance benefit of enabling MIR optimizations is usually marginal at best.
+
 thread 'main' panicked at 'explicit panic', $DIR/terminate-terminator.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 error: abnormal termination: panic in a function that cannot unwind
@@ -23,5 +25,5 @@ LL |     panic_abort();
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/tools/miri/tests/panic/alignment-assertion.rs b/src/tools/miri/tests/panic/alignment-assertion.rs
deleted file mode 100644
index 68aa19a88db..00000000000
--- a/src/tools/miri/tests/panic/alignment-assertion.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@compile-flags: -Zmiri-disable-alignment-check -Cdebug-assertions=yes
-
-fn main() {
-    let mut x = [0u32; 2];
-    let ptr: *mut u8 = x.as_mut_ptr().cast::<u8>();
-    unsafe {
-        *(ptr.add(1).cast::<u32>()) = 42;
-    }
-}
diff --git a/src/tools/miri/tests/panic/alignment-assertion.stderr b/src/tools/miri/tests/panic/alignment-assertion.stderr
deleted file mode 100644
index 26cf51b0cd2..00000000000
--- a/src/tools/miri/tests/panic/alignment-assertion.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-thread 'main' panicked at 'misaligned pointer dereference: address must be a multiple of 0x4 but is $HEX', $DIR/alignment-assertion.rs:LL:CC
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/tools/miri/tests/pass-dep/shims/fcntl_f-fullfsync_apple.rs b/src/tools/miri/tests/pass-dep/shims/fcntl_f-fullfsync_apple.rs
new file mode 100644
index 00000000000..307906f2583
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/shims/fcntl_f-fullfsync_apple.rs
@@ -0,0 +1,12 @@
+//@only-target-apple: F_FULLFSYNC only on apple systems
+//@compile-flags: -Zmiri-isolation-error=warn-nobacktrace
+
+use std::io::Error;
+
+fn main() {
+    // test `fcntl(F_FULLFSYNC)`
+    unsafe {
+        assert_eq!(libc::fcntl(1, libc::F_FULLFSYNC, 0), -1);
+        assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EPERM));
+    }
+}
diff --git a/src/tools/miri/tests/pass-dep/shims/fcntl_f-fullfsync_apple.stderr b/src/tools/miri/tests/pass-dep/shims/fcntl_f-fullfsync_apple.stderr
new file mode 100644
index 00000000000..09a24e1e5d7
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/shims/fcntl_f-fullfsync_apple.stderr
@@ -0,0 +1,2 @@
+warning: `fcntl` was made to return an error due to isolation
+
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs
index d6d19a3fe81..5185db0b0e2 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs
@@ -7,10 +7,9 @@ use std::fs;
 use std::io::{Error, ErrorKind};
 
 fn main() {
-    // test `fcntl`
+    // test `fcntl(F_DUPFD): should work even with isolation.`
     unsafe {
-        assert_eq!(libc::fcntl(1, libc::F_DUPFD, 0), -1);
-        assert_eq!(Error::last_os_error().raw_os_error(), Some(libc::EPERM));
+        assert!(libc::fcntl(1, libc::F_DUPFD, 0) >= 0);
     }
 
     // test `readlink`
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.stderr b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.stderr
index 21fcb65243e..b0cadfb970b 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.stderr
+++ b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.stderr
@@ -1,5 +1,3 @@
-warning: `fcntl` was made to return an error due to isolation
-
 warning: `readlink` was made to return an error due to isolation
 
 warning: `$STAT` was made to return an error due to isolation
diff --git a/src/tools/miri/tests/pass-dep/tokio/sleep.rs b/src/tools/miri/tests/pass-dep/tokio/sleep.rs
index 1341484dda4..00cc68eba3e 100644
--- a/src/tools/miri/tests/pass-dep/tokio/sleep.rs
+++ b/src/tools/miri/tests/pass-dep/tokio/sleep.rs
@@ -1,4 +1,4 @@
-//@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance -Zmiri-backtrace=full
+//@compile-flags: -Zmiri-permissive-provenance -Zmiri-backtrace=full
 //@only-target-x86_64-unknown-linux: support for tokio only on linux and x86
 
 use tokio::time::{sleep, Duration, Instant};
@@ -7,8 +7,6 @@ use tokio::time::{sleep, Duration, Instant};
 async fn main() {
     let start = Instant::now();
     sleep(Duration::from_secs(1)).await;
-    // It takes 96 millisecond to sleep for 1 millisecond
-    // It takes 1025 millisecond to sleep for 1 second
     let time_elapsed = &start.elapsed().as_millis();
-    assert!(time_elapsed > &1000, "{}", time_elapsed);
+    assert!((1000..1100).contains(time_elapsed), "{}", time_elapsed);
 }
diff --git a/src/tools/miri/tests/pass-dep/tokio/tokio_mvp.rs b/src/tools/miri/tests/pass-dep/tokio/tokio_mvp.rs
index 0bca7cc069a..0ed2a941bc4 100644
--- a/src/tools/miri/tests/pass-dep/tokio/tokio_mvp.rs
+++ b/src/tools/miri/tests/pass-dep/tokio/tokio_mvp.rs
@@ -1,5 +1,5 @@
 // Need to disable preemption to stay on the supported MVP codepath in mio.
-//@compile-flags: -Zmiri-disable-isolation -Zmiri-permissive-provenance
+//@compile-flags: -Zmiri-permissive-provenance
 //@only-target-x86_64-unknown-linux: support for tokio exists only on linux and x86
 
 #[tokio::main]
diff --git a/src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs b/src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs
index bf004012e84..7852d495e28 100644
--- a/src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs
+++ b/src/tools/miri/tests/pass/concurrency/thread_park_isolated.rs
@@ -7,6 +7,6 @@ fn main() {
 
     thread::park_timeout(Duration::from_millis(200));
 
-    // Thanks to deterministic execution, this will wiat *exactly* 200ms (rounded to 1ms).
-    assert!((200..201).contains(&start.elapsed().as_millis()));
+    // Thanks to deterministic execution, this will wait *exactly* 200ms, plus the time for the surrounding code.
+    assert!((200..210).contains(&start.elapsed().as_millis()), "{}", start.elapsed().as_millis());
 }
diff --git a/src/tools/miri/tests/pass/shims/time-with-isolation.rs b/src/tools/miri/tests/pass/shims/time-with-isolation.rs
index b6444319b59..a0c3c6bbaa9 100644
--- a/src/tools/miri/tests/pass/shims/time-with-isolation.rs
+++ b/src/tools/miri/tests/pass/shims/time-with-isolation.rs
@@ -22,14 +22,23 @@ fn test_time_passes() {
     let diff = now2.duration_since(now1);
     assert_eq!(now1 + diff, now2);
     assert_eq!(now2 - diff, now1);
-    // The virtual clock is deterministic and I got 29us on a 64-bit Linux machine. However, this
+    // The virtual clock is deterministic and I got 15ms on a 64-bit Linux machine. However, this
     // changes according to the platform so we use an interval to be safe. This should be updated
     // if `NANOSECONDS_PER_BASIC_BLOCK` changes.
-    assert!(diff.as_micros() > 10);
-    assert!(diff.as_micros() < 40);
+    assert!(diff.as_millis() > 5);
+    assert!(diff.as_millis() < 20);
+}
+
+fn test_block_for_one_second() {
+    let end = Instant::now() + Duration::from_secs(1);
+    // This takes a long time, as we only increment when statements are executed.
+    // When we sleep on all threads, we fast forward to the sleep duration, which we can't
+    // do with busy waiting.
+    while Instant::now() < end {}
 }
 
 fn main() {
     test_time_passes();
+    test_block_for_one_second();
     test_sleep();
 }
diff --git a/src/tools/miri/tests/pass/shims/time-with-isolation2.rs b/src/tools/miri/tests/pass/shims/time-with-isolation2.rs
new file mode 100644
index 00000000000..24e72e22fd8
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/time-with-isolation2.rs
@@ -0,0 +1,8 @@
+use std::time::Instant;
+
+fn main() {
+    let begin = Instant::now();
+    for _ in 0..100_000 {}
+    let time = begin.elapsed();
+    println!("The loop took around {}s", time.as_secs());
+}
diff --git a/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout b/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout
new file mode 100644
index 00000000000..641e469f50c
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/time-with-isolation2.stdout
@@ -0,0 +1 @@
+The loop took around 13s
diff --git a/tests/rustdoc-gui/anchor-navigable.goml b/tests/rustdoc-gui/anchor-navigable.goml
index 9d5c55a1e1d..61d7c89d434 100644
--- a/tests/rustdoc-gui/anchor-navigable.goml
+++ b/tests/rustdoc-gui/anchor-navigable.goml
@@ -4,7 +4,7 @@
 // anchor and the `impl Foo`. If there were a gap, this would cause an annoying
 // problem: you hover `impl Foo` to see the anchor, then when you move your
 // mouse to the left, the anchor disappears before you reach it.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 // We check that ".item-info" is bigger than its content.
 move-cursor-to: ".impl"
 assert-property: (".impl > a.anchor", {"offsetWidth": "8"})
diff --git a/tests/rustdoc-gui/anchors.goml b/tests/rustdoc-gui/anchors.goml
index 85cb7227420..0904aa90e1b 100644
--- a/tests/rustdoc-gui/anchors.goml
+++ b/tests/rustdoc-gui/anchors.goml
@@ -4,12 +4,12 @@ define-function: (
     "check-colors",
     (theme, main_color, title_color, main_heading_color, main_heading_type_color, src_link_color, sidebar_link_color),
     block {
-        goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
+        go-to: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
         // This is needed to ensure that the text color is computed.
         show-text: true
 
         // Setting the theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
         reload:
 
@@ -48,9 +48,9 @@ define-function: (
              {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|},
         )
 
-        goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
         // Since we changed page, we need to set the theme again.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
         reload:
 
diff --git a/tests/rustdoc-gui/basic-code.goml b/tests/rustdoc-gui/basic-code.goml
index 971c2f9480e..e372f711974 100644
--- a/tests/rustdoc-gui/basic-code.goml
+++ b/tests/rustdoc-gui/basic-code.goml
@@ -1,6 +1,6 @@
 // Small test to ensure the "src-line-numbers" element is only present once on
 // the page.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 click: ".srclink"
 wait-for: ".src-line-numbers"
 assert-count: (".src-line-numbers", 1)
diff --git a/tests/rustdoc-gui/check-code-blocks-margin.goml b/tests/rustdoc-gui/check-code-blocks-margin.goml
index c2cec00204d..8c2cbc4d90e 100644
--- a/tests/rustdoc-gui/check-code-blocks-margin.goml
+++ b/tests/rustdoc-gui/check-code-blocks-margin.goml
@@ -1,5 +1,5 @@
 // This test ensures that the docblock elements have the appropriate left margin.
-goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
 // The top docblock elements shouldn't have left margin...
 assert-css: ("#main-content .item-decl", {"margin-left": "0px"})
 // ... but all the others should!
diff --git a/tests/rustdoc-gui/check-stab-in-docblock.goml b/tests/rustdoc-gui/check-stab-in-docblock.goml
index 266fa999728..2f62636211b 100644
--- a/tests/rustdoc-gui/check-stab-in-docblock.goml
+++ b/tests/rustdoc-gui/check-stab-in-docblock.goml
@@ -1,9 +1,9 @@
 // This test checks that using `.stab` attributes in `.docblock` elements doesn't
 // create scrollable paragraphs.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 // Needs the text to be display to check for scrollable content.
 show-text: true
-size: (786, 600)
+set-window-size: (786, 600)
 // Confirms that there 3 paragraphs.
 assert-count: (".top-doc .docblock p", 3)
 // Checking that there is no scrollable content.
diff --git a/tests/rustdoc-gui/check_info_sign_position.goml b/tests/rustdoc-gui/check_info_sign_position.goml
index f36e73fc5e9..c9a4ea94cfe 100644
--- a/tests/rustdoc-gui/check_info_sign_position.goml
+++ b/tests/rustdoc-gui/check_info_sign_position.goml
@@ -1,7 +1,7 @@
 // This test checks the position of the information on the code blocks (like
 // `compile_fail` or `ignore`).
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-goto: "./fn.check_list_code_block.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "./fn.check_list_code_block.html"
 // If the codeblock is the first element of the docblock, the information tooltip must have
 // have some top margin to avoid going over the toggle (the "[+]").
 assert-css: (".docblock > .example-wrap.compile_fail .tooltip", { "margin-top": "16px" })
diff --git a/tests/rustdoc-gui/code-blocks-overflow.goml b/tests/rustdoc-gui/code-blocks-overflow.goml
index fbf0e890bdc..a23136f4b76 100644
--- a/tests/rustdoc-gui/code-blocks-overflow.goml
+++ b/tests/rustdoc-gui/code-blocks-overflow.goml
@@ -1,6 +1,6 @@
 // This test ensures that codeblocks content don't overflow.
-goto: "file://" + |DOC_PATH| + "/lib2/sub_mod/struct.Foo.html"
-size: (1080, 600)
+go-to: "file://" + |DOC_PATH| + "/lib2/sub_mod/struct.Foo.html"
+set-window-size: (1080, 600)
 // There should be two codeblocks: a rust one and a non-rust one.
 assert-count: (".docblock > .example-wrap", 2)
 assert: ".docblock > .example-wrap > .language-txt"
diff --git a/tests/rustdoc-gui/code-color.goml b/tests/rustdoc-gui/code-color.goml
index cb550a4573a..833fa05db42 100644
--- a/tests/rustdoc-gui/code-color.goml
+++ b/tests/rustdoc-gui/code-color.goml
@@ -2,7 +2,7 @@
 // check that the rule isn't applied on other "<code>" elements.
 //
 // While we're at it, we also check it for the other themes.
-goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
 // If the text isn't displayed, the browser doesn't compute color style correctly...
 show-text: true
 
@@ -11,7 +11,7 @@ define-function: (
     (theme, doc_code_color, doc_inline_code_color),
     block {
         // Set the theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
         reload:
         assert-css: (".docblock pre > code", {"color": |doc_code_color|}, ALL)
diff --git a/tests/rustdoc-gui/code-sidebar-toggle.goml b/tests/rustdoc-gui/code-sidebar-toggle.goml
index df665bd46c0..28c3712f307 100644
--- a/tests/rustdoc-gui/code-sidebar-toggle.goml
+++ b/tests/rustdoc-gui/code-sidebar-toggle.goml
@@ -1,7 +1,7 @@
 // This test checks that the source code pages sidebar toggle is working as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 click: ".srclink"
 wait-for: "#src-sidebar-toggle"
 click: "#src-sidebar-toggle"
-fail: true
+expect-failure: true
 assert-css: ("#source-sidebar", { "left": "-300px" })
diff --git a/tests/rustdoc-gui/code-tags.goml b/tests/rustdoc-gui/code-tags.goml
index ca337cbc323..3405d3295e6 100644
--- a/tests/rustdoc-gui/code-tags.goml
+++ b/tests/rustdoc-gui/code-tags.goml
@@ -3,22 +3,22 @@
 // We need to disable this check because `implementors/test_docs/trait.AnotherOne.js`
 // doesn't exist.
 fail-on-request-error: false
-goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
-size: (1080, 600)
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+set-window-size: (1080, 600)
 // There should be four doc codeblocks.
 // Check that their content is inside <pre><code>
 assert-count: (".example-wrap pre > code", 4)
 // Check that function signature is inside <pre><code>
 assert: "pre.rust.item-decl > code"
 
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 assert: "pre.rust.item-decl > code"
 
-goto: "file://" + |DOC_PATH| + "/test_docs/enum.AnEnum.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/enum.AnEnum.html"
 assert: "pre.rust.item-decl > code"
 
-goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
 assert: "pre.rust.item-decl > code"
 
-goto: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
 assert: "pre.rust.item-decl > code"
diff --git a/tests/rustdoc-gui/codeblock-sub.goml b/tests/rustdoc-gui/codeblock-sub.goml
index cbd314d2791..03575cc6aaa 100644
--- a/tests/rustdoc-gui/codeblock-sub.goml
+++ b/tests/rustdoc-gui/codeblock-sub.goml
@@ -1,5 +1,5 @@
 // Test that code blocks nested within <sub> do not have a line height of 0.
-goto: "file://" + |DOC_PATH| + "/test_docs/codeblock_sub/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/codeblock_sub/index.html"
 
 store-property: (codeblock_sub_1, "#codeblock-sub-1", "offsetHeight")
 assert-property-false: ("#codeblock-sub-3", { "offsetHeight": |codeblock_sub_1| })
diff --git a/tests/rustdoc-gui/codeblock-tooltip.goml b/tests/rustdoc-gui/codeblock-tooltip.goml
index 36b67073a03..2ed0579d314 100644
--- a/tests/rustdoc-gui/codeblock-tooltip.goml
+++ b/tests/rustdoc-gui/codeblock-tooltip.goml
@@ -1,5 +1,5 @@
 // Checking the colors of the codeblocks tooltips.
-goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
 show-text: true
 
 define-function: (
@@ -7,7 +7,7 @@ define-function: (
     (theme, background, color, border),
     block {
         // Setting the theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
 
         // compile_fail block
diff --git a/tests/rustdoc-gui/cursor.goml b/tests/rustdoc-gui/cursor.goml
index 59b1397970b..f318b05ceda 100644
--- a/tests/rustdoc-gui/cursor.goml
+++ b/tests/rustdoc-gui/cursor.goml
@@ -1,5 +1,5 @@
 // This test ensures that several clickable items actually have the pointer cursor.
-goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
 
 // the `[+]/[-]` button
 assert-css: ("#toggle-all-docs", {"cursor": "pointer"})
@@ -16,9 +16,9 @@ wait-for: "#search-tabs"
 assert-css: ("#search-tabs > button", {"cursor": "pointer"})
 
 // mobile sidebar toggle button
-size: (500, 700)
+set-window-size: (500, 700)
 assert-css: (".sidebar-menu-toggle", {"cursor": "pointer"})
 
 // the sidebar toggle button on the source code pages
-goto: "file://" + |DOC_PATH| + "/src/lib2/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/lib2/lib.rs.html"
 assert-css: ("#src-sidebar-toggle > button", {"cursor": "pointer"})
diff --git a/tests/rustdoc-gui/default-settings.goml b/tests/rustdoc-gui/default-settings.goml
index ab27b001eb6..3466f3693f9 100644
--- a/tests/rustdoc-gui/default-settings.goml
+++ b/tests/rustdoc-gui/default-settings.goml
@@ -2,7 +2,7 @@
 //
 // The "settings" crate uses "ayu" as default setting, which is what we will
 // check.
-goto: "file://" + |DOC_PATH| + "/settings/index.html"
+go-to: "file://" + |DOC_PATH| + "/settings/index.html"
 // Wait a bit to be sure the default theme is applied.
 // If the theme isn't applied, the command will time out.
 wait-for-css: ("body", {"background-color": "rgb(15, 20, 25)"})
diff --git a/tests/rustdoc-gui/docblock-big-code-mobile.goml b/tests/rustdoc-gui/docblock-big-code-mobile.goml
index 3ce921c2c91..6fc6834768e 100644
--- a/tests/rustdoc-gui/docblock-big-code-mobile.goml
+++ b/tests/rustdoc-gui/docblock-big-code-mobile.goml
@@ -1,7 +1,7 @@
 // If we have a long `<code>`, we need to ensure that it'll be fully displayed on mobile, meaning
 // that it'll be on two lines.
 emulate: "iPhone 8" // it has the following size: (375, 667)
-goto: "file://" + |DOC_PATH| + "/test_docs/long_code_block/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/long_code_block/index.html"
 // We now check that the block is on two lines:
 show-text: true // We need to enable text draw to be able to have the "real" size
 // Little explanations for this test: if the text wasn't displayed on two lines, it would take
@@ -9,5 +9,5 @@ show-text: true // We need to enable text draw to be able to have the "real" siz
 assert-property: (".docblock p > code", {"offsetHeight": "44"})
 
 // Same check, but where the long code block is also a link
-goto: "file://" + |DOC_PATH| + "/test_docs/long_code_block_link/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/long_code_block_link/index.html"
 assert-property: (".docblock p > a > code", {"offsetHeight": "44"})
diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml
index 69bcf5339ef..4c36394a30c 100644
--- a/tests/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml
@@ -1,5 +1,5 @@
 // Checks that the setting "line numbers" is working as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
 
 // Otherwise, we can't check text color
 show-text: true
@@ -13,7 +13,7 @@ define-function: (
     (theme, color),
     block {
         // We now set the setting to show the line numbers on code examples.
-        local-storage: {
+        set-local-storage: {
             "rustdoc-theme": |theme|,
             "rustdoc-use-system-theme": "false",
             "rustdoc-line-numbers": "true"
diff --git a/tests/rustdoc-gui/docblock-details.goml b/tests/rustdoc-gui/docblock-details.goml
index 9ae571efbb5..58ff17619f6 100644
--- a/tests/rustdoc-gui/docblock-details.goml
+++ b/tests/rustdoc-gui/docblock-details.goml
@@ -1,7 +1,7 @@
 // This ensures that the `<details>`/`<summary>` elements are displayed as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/details/struct.Details.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/details/struct.Details.html"
 show-text: true
-local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
+set-local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
 reload:
 
 // We first check that the headers in the `.top-doc` doc block still have their
diff --git a/tests/rustdoc-gui/docblock-table-overflow.goml b/tests/rustdoc-gui/docblock-table-overflow.goml
index d8670089ad8..1ca919d1eab 100644
--- a/tests/rustdoc-gui/docblock-table-overflow.goml
+++ b/tests/rustdoc-gui/docblock-table-overflow.goml
@@ -1,7 +1,7 @@
 // This test ensures that the type declaration content overflow is handled inside the <pre> directly.
-goto: "file://" + |DOC_PATH| + "/lib2/long_table/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/long_table/struct.Foo.html"
 // We set a fixed size so there is no chance of "random" resize.
-size: (1100, 800)
+set-window-size: (1100, 800)
 // Logically, the ".docblock" and the "<p>" should have the same scroll width.
 compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["scrollWidth"])
 assert-property: (".top-doc .docblock", {"scrollWidth": "816"})
diff --git a/tests/rustdoc-gui/docblock-table.goml b/tests/rustdoc-gui/docblock-table.goml
index 3dcb8abd415..011451ef4f3 100644
--- a/tests/rustdoc-gui/docblock-table.goml
+++ b/tests/rustdoc-gui/docblock-table.goml
@@ -1,5 +1,5 @@
 // This test checks the appearance of the tables in the doc comments.
-goto: "file://" + |DOC_PATH| + "/test_docs/doc_block_table/struct.DocBlockTable.html#method.func"
+go-to: "file://" + |DOC_PATH| + "/test_docs/doc_block_table/struct.DocBlockTable.html#method.func"
 
 compare-elements-css: (".impl-items .docblock table th", ".top-doc .docblock table th", ["border"])
 compare-elements-css: (".impl-items .docblock table td", ".top-doc .docblock table td", ["border"])
@@ -8,7 +8,7 @@ define-function: (
     "check-colors",
     (theme, border_color, zebra_stripe_color),
     block {
-        local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}
+        set-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}
         reload:
         assert-css: (".top-doc .docblock table tbody tr:nth-child(1)", {
             "background-color": "rgba(0, 0, 0, 0)",
diff --git a/tests/rustdoc-gui/duplicate-macro-reexport.goml b/tests/rustdoc-gui/duplicate-macro-reexport.goml
index 496203c128e..7d01c88f31b 100644
--- a/tests/rustdoc-gui/duplicate-macro-reexport.goml
+++ b/tests/rustdoc-gui/duplicate-macro-reexport.goml
@@ -1,5 +1,5 @@
 // This test ensures that there is no macro duplicates in the sidebar.
-goto: "file://" + |DOC_PATH| + "/test_docs/macro.a.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/macro.a.html"
 // Waiting for the elements in the sidebar to be rendered.
 wait-for: ".sidebar-elems .macro"
 // Check there is only one macro named "a" listed in the sidebar.
diff --git a/tests/rustdoc-gui/enum-variants.goml b/tests/rustdoc-gui/enum-variants.goml
index 8dfc49285f2..a1f60986ac3 100644
--- a/tests/rustdoc-gui/enum-variants.goml
+++ b/tests/rustdoc-gui/enum-variants.goml
@@ -1,5 +1,5 @@
 // Verifies that there is non-zero margin on variants and their docblocks.
-goto: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/enum.WhoLetTheDogOut.html"
 
 assert-css: (".variants > .variant", {"margin": "0px 0px 12px"})
 assert-css: (".variants > .docblock", {"margin": "0px 0px 32px 24px"})
diff --git a/tests/rustdoc-gui/escape-key.goml b/tests/rustdoc-gui/escape-key.goml
index 5d80d24969d..3ea20fd118e 100644
--- a/tests/rustdoc-gui/escape-key.goml
+++ b/tests/rustdoc-gui/escape-key.goml
@@ -1,6 +1,6 @@
 // This test ensures that the "Escape" shortcut is handled correctly based on the
 // current content displayed.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 // First, we check that the search results are hidden when the Escape key is pressed.
 write: (".search-input", "test")
 // To be SURE that the search will be run.
diff --git a/tests/rustdoc-gui/font-weight.goml b/tests/rustdoc-gui/font-weight.goml
index aad334d2bd2..6fad128dab8 100644
--- a/tests/rustdoc-gui/font-weight.goml
+++ b/tests/rustdoc-gui/font-weight.goml
@@ -1,5 +1,5 @@
 // This test checks that the font weight is correctly applied.
-goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
 assert-css: ("//*[@class='rust item-decl']//a[text()='Alias']", {"font-weight": "400"})
 assert-css: (
     "//*[@class='structfield small-section-header']//a[text()='Alias']",
@@ -9,13 +9,13 @@ assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"})
 assert-css: ("#associatedtype\.X > .code-header", {"font-weight": "600"})
 assert-css: ("#associatedconstant\.Y > .code-header", {"font-weight": "600"})
 
-goto: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
 assert-css: (".top-doc .docblock p", {"font-weight": "400"}, ALL)
 
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 assert-css: (".impl-items .method > .code-header", {"font-weight": "600"}, ALL)
 
-goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
 
 // This is a complex selector, so here's how it works:
 //
diff --git a/tests/rustdoc-gui/go-to-collapsed-elem.goml b/tests/rustdoc-gui/go-to-collapsed-elem.goml
index ec423125236..80e9791775e 100644
--- a/tests/rustdoc-gui/go-to-collapsed-elem.goml
+++ b/tests/rustdoc-gui/go-to-collapsed-elem.goml
@@ -1,10 +1,10 @@
 // This test ensures that when clicking on a link which leads to an item inside a collapsed element,
 // the collapsed element will be expanded.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 // We check that the implementors block is expanded.
 assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
 // We now collapse the implementors block.
-property: ("#implementations-list .implementors-toggle", {"open": "false"})
+set-property: ("#implementations-list .implementors-toggle", {"open": "false"})
 // And now we click on the link to the method to ensure it'll expand the implementors block.
 click: "//*[@class='sidebar']//a[@href='#method.must_use']"
 assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
@@ -12,9 +12,9 @@ assert-property: ("#implementations-list .implementors-toggle", {"open": "true"}
 define-function: ("collapsed-from-search", (), block {
     // Now we do the same through search result.
     // First we reload the page without the anchor in the URL.
-    goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+    go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
     // Then we collapse the section again...
-    property: ("#implementations-list .implementors-toggle", {"open": "false"})
+    set-property: ("#implementations-list .implementors-toggle", {"open": "false"})
     // Then we run the search.
     write: (".search-input", "foo::must_use")
     wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
@@ -25,12 +25,12 @@ define-function: ("collapsed-from-search", (), block {
 call-function: ("collapsed-from-search", {})
 
 // Now running the same check but with mobile.
-size: (600, 600)
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+set-window-size: (600, 600)
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 // We check that the implementors block is expanded.
 assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
 // We now collapse the implementors block.
-property: ("#implementations-list .implementors-toggle", {"open": "false"})
+set-property: ("#implementations-list .implementors-toggle", {"open": "false"})
 // First we expand the mobile menu.
 click: ".sidebar-menu-toggle"
 // Then we click on the link to the method to ensure it'll expand the implementors block.
diff --git a/tests/rustdoc-gui/hash-item-expansion.goml b/tests/rustdoc-gui/hash-item-expansion.goml
index 3cf94f624fe..a7a5c3cb483 100644
--- a/tests/rustdoc-gui/hash-item-expansion.goml
+++ b/tests/rustdoc-gui/hash-item-expansion.goml
@@ -1,5 +1,5 @@
 // This test ensures that the element corresponding to the hash is displayed.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.borrow"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.borrow"
 // In the blanket implementations list, "Borrow" is the second one, hence the ":nth(2)".
 assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""})
 // We first check that the impl block is open by default.
diff --git a/tests/rustdoc-gui/headers-color.goml b/tests/rustdoc-gui/headers-color.goml
index 92cf050a514..7d83833a8bd 100644
--- a/tests/rustdoc-gui/headers-color.goml
+++ b/tests/rustdoc-gui/headers-color.goml
@@ -4,10 +4,10 @@ define-function: (
     "check-colors",
     (theme, color, code_header_color, focus_background_color, headings_color),
     block {
-        goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
         // This is needed so that the text color is computed.
         show-text: true
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         assert-css: (
             ".impl",
@@ -19,20 +19,20 @@ define-function: (
             {"color": |code_header_color|, "background-color": "rgba(0, 0, 0, 0)"},
             ALL,
         )
-        goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo"
         assert-css: (
             "#impl-Foo",
             {"color": |color|, "background-color": |focus_background_color|},
         )
-        goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use"
         assert-css: (
             "#method\.must_use",
             {"color": |color|, "background-color": |focus_background_color|},
             ALL,
         )
-        goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
         assert-css: (".small-section-header a", {"color": |color|}, ALL)
-        goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
         // We select headings (h2, h3, h...).
         assert-css: (".docblock > :not(p) > a", {"color": |headings_color|}, ALL)
     },
diff --git a/tests/rustdoc-gui/headings.goml b/tests/rustdoc-gui/headings.goml
index e4ba5f1246d..089e2203a04 100644
--- a/tests/rustdoc-gui/headings.goml
+++ b/tests/rustdoc-gui/headings.goml
@@ -11,7 +11,7 @@
 // 18px  1.125em
 // 16px  1rem
 // 14px  0.875rem
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
 
 assert-css: (".main-heading h1", {"font-size": "24px"})
 
@@ -50,7 +50,7 @@ assert-css: ("h6#sub-heading-for-struct-impl-item-doc", {"font-size": "14px"})
 assert-css: ("h6#sub-heading-for-struct-impl-item-doc", {"border-bottom-width": "0px"})
 assert-css: ("h6#sub-sub-heading-for-struct-impl-item-doc", {"font-size": "14px"})
 
-goto: "file://" + |DOC_PATH| + "/test_docs/enum.HeavilyDocumentedEnum.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/enum.HeavilyDocumentedEnum.html"
 
 assert-css: (".main-heading h1", {"font-size": "24px"})
 
@@ -109,7 +109,7 @@ assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width"
 assert-text: ("//ul[@class='block mod']/preceding-sibling::h3", "Modules")
 assert-css: ("//ul[@class='block mod']/preceding-sibling::h3", {"border-bottom-width": "0px"}, ALL)
 
-goto: "file://" + |DOC_PATH| + "/test_docs/union.HeavilyDocumentedUnion.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/union.HeavilyDocumentedUnion.html"
 
 assert-css: (".main-heading h1", {"font-size": "24px"})
 
@@ -141,7 +141,7 @@ assert-css: ("h5#title-for-union-impl-item-doc", {"border-bottom-width": "0px"})
 assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"font-size": "14px"})
 assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"border-bottom-width": "0px"})
 
-goto: "file://" + |DOC_PATH| + "/test_docs/macro.heavily_documented_macro.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/macro.heavily_documented_macro.html"
 
 assert-css: (".main-heading h1", {"font-size": "24px"})
 
@@ -152,13 +152,13 @@ assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
 
 // Needed to check colors
 show-text: true
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
 
 define-function: (
     "check-colors",
     (theme, heading_color, small_heading_color, heading_border_color),
     block {
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         assert-css: (
             ".top-doc .docblock h2",
@@ -222,13 +222,13 @@ define-function: (
     "check-since-color",
     (theme),
     block {
-        local-storage: {"rustdoc-theme": |theme|}
+        set-local-storage: {"rustdoc-theme": |theme|}
         reload:
         assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
     },
 )
 
-goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
 call-function: ("check-since-color", ("ayu"))
 call-function: ("check-since-color", ("dark"))
 call-function: ("check-since-color", ("light"))
diff --git a/tests/rustdoc-gui/help-page.goml b/tests/rustdoc-gui/help-page.goml
index 6e2321a6963..1a1c1b28f61 100644
--- a/tests/rustdoc-gui/help-page.goml
+++ b/tests/rustdoc-gui/help-page.goml
@@ -1,6 +1,6 @@
 // This test ensures that opening the help page in its own tab works.
-goto: "file://" + |DOC_PATH| + "/help.html"
-size: (1000, 1000) // Try desktop size first.
+go-to: "file://" + |DOC_PATH| + "/help.html"
+set-window-size: (1000, 1000) // Try desktop size first.
 wait-for: "#help"
 assert-css: ("#help", {"display": "block"})
 assert-css: ("#help dd", {"font-size": "16px"})
@@ -8,7 +8,7 @@ click: "#help-button > a"
 assert-css: ("#help", {"display": "block"})
 compare-elements-property: (".sub", "#help", ["offsetWidth"])
 compare-elements-position: (".sub", "#help", ("x"))
-size: (500, 1000) // Try mobile next.
+set-window-size: (500, 1000) // Try mobile next.
 assert-css: ("#help", {"display": "block"})
 compare-elements-property: (".sub", "#help", ["offsetWidth"])
 compare-elements-position: (".sub", "#help", ("x"))
@@ -20,7 +20,7 @@ define-function: (
     (theme, color, background, box_shadow),
     block {
         // Setting the theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
         reload:
         assert-css: ("#help kbd", {
@@ -51,8 +51,8 @@ call-function: ("check-colors", {
 })
 
 // This test ensures that opening the help popover without switching pages works.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-size: (1000, 1000) // Only supported on desktop.
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+set-window-size: (1000, 1000) // Only supported on desktop.
 assert-false: "#help"
 click: "#help-button > a"
 assert-css: ("#help", {"display": "block"})
@@ -63,8 +63,8 @@ compare-elements-property-false: (".sub", "#help", ["offsetWidth"])
 compare-elements-position-false: (".sub", "#help", ("x"))
 
 // This test ensures that the "the rustdoc book" anchor link within the help popover works.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-size: (1000, 1000) // Popover only appears when the screen width is >700px.
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+set-window-size: (1000, 1000) // Popover only appears when the screen width is >700px.
 assert-false: "#help"
 click: "#help-button > a"
 click: ".popover a[href='https://doc.rust-lang.org/rustdoc/']"
diff --git a/tests/rustdoc-gui/highlight-colors.goml b/tests/rustdoc-gui/highlight-colors.goml
index b182150a577..4f5e1c110f2 100644
--- a/tests/rustdoc-gui/highlight-colors.goml
+++ b/tests/rustdoc-gui/highlight-colors.goml
@@ -1,5 +1,5 @@
 // This test checks the highlight colors in the source code pages.
-goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 show-text: true
 
 define-function: (
@@ -22,7 +22,7 @@ define-function: (
         doc_comment,
     ),
     block {
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         assert-css: ("pre.rust .kw", {"color": |kw|}, ALL)
         assert-css: ("pre.rust .kw-2", {"color": |kw2|}, ALL)
diff --git a/tests/rustdoc-gui/huge-collection-of-constants.goml b/tests/rustdoc-gui/huge-collection-of-constants.goml
index 636382a9169..387aca6f66c 100644
--- a/tests/rustdoc-gui/huge-collection-of-constants.goml
+++ b/tests/rustdoc-gui/huge-collection-of-constants.goml
@@ -1,6 +1,6 @@
 // Make sure that the last two entries are more than 12 pixels apart and not stacked on each other.
 
-goto: "file://" + |DOC_PATH| + "/test_docs/huge_amount_of_consts/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/huge_amount_of_consts/index.html"
 
 compare-elements-position-near-false: (
     "//ul[@class='item-table']/li[last()-1]",
diff --git a/tests/rustdoc-gui/huge-logo.goml b/tests/rustdoc-gui/huge-logo.goml
index 69459bd3e23..6d3eb66068c 100644
--- a/tests/rustdoc-gui/huge-logo.goml
+++ b/tests/rustdoc-gui/huge-logo.goml
@@ -1,23 +1,23 @@
 // huge_logo crate has a custom 712x860 logo
 // test to ensure the maximum size in the layout works correctly
-goto: "file://" + |DOC_PATH| + "/huge_logo/index.html"
+go-to: "file://" + |DOC_PATH| + "/huge_logo/index.html"
 
-size: (1280, 1024)
+set-window-size: (1280, 1024)
 // offsetWidth = width of sidebar
 assert-property: (".sidebar .logo-container", {"offsetWidth": "200", "offsetHeight": 100})
 assert-property: (".sidebar .logo-container img", {"offsetWidth": "100", "offsetHeight": 100})
 
-size: (400, 600)
+set-window-size: (400, 600)
 // offset = size + margin
 assert-property: (".mobile-topbar .logo-container", {"offsetWidth": "55", "offsetHeight": 45})
 assert-property: (".mobile-topbar .logo-container img", {"offsetWidth": "35", "offsetHeight": 35})
 
-goto: "file://" + |DOC_PATH| + "/src/huge_logo/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/huge_logo/lib.rs.html"
 
-size: (1280, 1024)
+set-window-size: (1280, 1024)
 assert-property: (".sub-logo-container", {"offsetWidth": "60", "offsetHeight": 60})
 
-size: (400, 600)
+set-window-size: (400, 600)
 // 43 because 35px + 8px of margin
 assert-css: (".sub-logo-container > img", {"margin-bottom": "8px"})
 assert-property: (".sub-logo-container", {"offsetWidth": "35", "offsetHeight": 43})
diff --git a/tests/rustdoc-gui/impl-default-expansion.goml b/tests/rustdoc-gui/impl-default-expansion.goml
index c3f9240cc93..45bd7beb6e6 100644
--- a/tests/rustdoc-gui/impl-default-expansion.goml
+++ b/tests/rustdoc-gui/impl-default-expansion.goml
@@ -1,3 +1,3 @@
 // This test ensures that the impl blocks are open by default.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 assert-attribute: ("#implementations-list details.implementors-toggle", {"open": ""})
diff --git a/tests/rustdoc-gui/impl-doc.goml b/tests/rustdoc-gui/impl-doc.goml
index 6caffb9c39f..4ec46de404f 100644
--- a/tests/rustdoc-gui/impl-doc.goml
+++ b/tests/rustdoc-gui/impl-doc.goml
@@ -1,5 +1,5 @@
 // A docblock on an impl must have a margin to separate it from the contents.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html"
 
 // The text is about 24px tall, so if there's a margin, then their position will be >24px apart
 compare-elements-position-near-false: (
diff --git a/tests/rustdoc-gui/implementors.goml b/tests/rustdoc-gui/implementors.goml
index 997c0ed8f01..b39b95c1a9b 100644
--- a/tests/rustdoc-gui/implementors.goml
+++ b/tests/rustdoc-gui/implementors.goml
@@ -1,6 +1,6 @@
 // The goal of this test is to check that the external trait implementors, generated with JS,
 // have the same display than the "local" ones.
-goto: "file://" + |DOC_PATH| + "/implementors/trait.Whatever.html"
+go-to: "file://" + |DOC_PATH| + "/implementors/trait.Whatever.html"
 assert: "#implementors-list"
 // There are supposed to be two implementors listed.
 assert-count: ("#implementors-list .impl", 2)
@@ -15,7 +15,7 @@ assert-attribute: ("#implementors-list .impl:nth-child(2)", {"id": "impl-Whateve
 assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"})
 assert: "#implementors-list .impl:nth-child(2) > .code-header"
 
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.HasEmptyTraits.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HasEmptyTraits.html"
 compare-elements-position-near-false: (
     "#impl-EmptyTrait1-for-HasEmptyTraits",
     "#impl-EmptyTrait2-for-HasEmptyTraits",
@@ -29,13 +29,13 @@ compare-elements-position-near: (
 
 // Now check that re-exports work correctly.
 // There should be exactly one impl shown on both of these pages.
-goto: "file://" + |DOC_PATH| + "/lib2/trait.TraitToReexport.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/trait.TraitToReexport.html"
 assert-count: ("#implementors-list .impl", 1)
-goto: "file://" + |DOC_PATH| + "/implementors/trait.TraitToReexport.html"
+go-to: "file://" + |DOC_PATH| + "/implementors/trait.TraitToReexport.html"
 assert-count: ("#implementors-list .impl", 1)
 
 // Now check that the link is properly rewritten for a crate called `http`.
 // An older version of rustdoc had a buggy check for absolute links.
-goto: "file://" + |DOC_PATH| + "/http/trait.HttpTrait.html"
+go-to: "file://" + |DOC_PATH| + "/http/trait.HttpTrait.html"
 assert-count: ("#implementors-list .impl", 1)
 assert-attribute: ("#implementors-list .impl a.trait", {"href": "../http/trait.HttpTrait.html"})
diff --git a/tests/rustdoc-gui/item-decl-colors.goml b/tests/rustdoc-gui/item-decl-colors.goml
index c58e3eb7c23..5732dd8eea2 100644
--- a/tests/rustdoc-gui/item-decl-colors.goml
+++ b/tests/rustdoc-gui/item-decl-colors.goml
@@ -18,9 +18,9 @@ define-function: (
         assoc_type_color,
     ),
     block {
-        goto: "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html"
         show-text: true
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         assert-css: (".item-decl .code-attribute", {"color": |attr_color|}, ALL)
         assert-css: (".item-decl .trait", {"color": |trait_color|}, ALL)
@@ -29,7 +29,7 @@ define-function: (
         assert-css: (".item-decl .enum", {"color": |enum_color|}, ALL)
         assert-css: (".item-decl .primitive", {"color": |primitive_color|}, ALL)
 
-        goto: "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithoutGenerics.html"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithoutGenerics.html"
         assert-css: (".item-decl .constant", {"color": |constant_color|}, ALL)
         assert-css: (".item-decl .fn", {"color": |fn_color|}, ALL)
         assert-css: (".item-decl .associatedtype", {"color": |assoc_type_color|}, ALL)
diff --git a/tests/rustdoc-gui/item-info-alignment.goml b/tests/rustdoc-gui/item-info-alignment.goml
index 94b52f0056b..6fc365d1f19 100644
--- a/tests/rustdoc-gui/item-info-alignment.goml
+++ b/tests/rustdoc-gui/item-info-alignment.goml
@@ -1,10 +1,10 @@
 // This test ensures that the "item-info" looks about the same
 // whether or not it's inside a toggle.
-goto: "file://" + |DOC_PATH| + "/lib2/struct.ItemInfoAlignmentTest.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.ItemInfoAlignmentTest.html"
 
 // First, we try it in "desktop" mode.
-size: (1200, 870)
+set-window-size: (1200, 870)
 compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x"))
 // Next, we try it in "mobile" mode (max-width: 700px).
-size: (650, 650)
+set-window-size: (650, 650)
 compare-elements-position: (".impl-items > .item-info", "summary > .item-info", ("x"))
diff --git a/tests/rustdoc-gui/item-info-overflow.goml b/tests/rustdoc-gui/item-info-overflow.goml
index 8ea14621cbf..23c53c03762 100644
--- a/tests/rustdoc-gui/item-info-overflow.goml
+++ b/tests/rustdoc-gui/item-info-overflow.goml
@@ -1,7 +1,7 @@
 // This test ensures that the "item-info" elements don't overflow.
-goto: "file://" + |DOC_PATH| + "/lib2/struct.LongItemInfo.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.LongItemInfo.html"
 // We set a fixed size so there is no chance of "random" resize.
-size: (1200, 870)
+set-window-size: (1200, 870)
 // Logically, the "item-decl" and the "item-info" should have the same scroll width.
 compare-elements-property: (".item-decl", ".item-info", ["scrollWidth"])
 assert-property: (".item-info", {"scrollWidth": "940"})
@@ -13,7 +13,7 @@ assert-text: (
 )
 
 // Checking the "item-info" on an impl block as well:
-goto: "file://" + |DOC_PATH| + "/lib2/struct.LongItemInfo2.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.LongItemInfo2.html"
 compare-elements-property: (
     "#impl-SimpleTrait-for-LongItemInfo2 .item-info",
     "#impl-SimpleTrait-for-LongItemInfo2 + .docblock",
diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml
index 6780dfca68a..60fd7c4e198 100644
--- a/tests/rustdoc-gui/item-info.goml
+++ b/tests/rustdoc-gui/item-info.goml
@@ -1,15 +1,15 @@
 // This test ensures a few things for item info elements.
-goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
 // Ensuring that the item information don't take 100% of the width if unnecessary.
 // We set a fixed size so there is no chance of "random" resize.
-size: (1100, 800)
+set-window-size: (1100, 800)
 // We check that ".item-info" is bigger than its content.
 assert-css: (".item-info", {"width": "840px"})
 assert-css: (".item-info .stab", {"width": "289px"})
 assert-position: (".item-info .stab", {"x": 245})
 
 // Now we ensure that they're not rendered on the same line.
-goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
 // We first ensure that there are two item info on the trait.
 assert-count: ("#main-content > .item-info .stab", 2)
 // They should not have the same `y` position!
diff --git a/tests/rustdoc-gui/item-summary-table.goml b/tests/rustdoc-gui/item-summary-table.goml
index 7a219bd54c3..89306030329 100644
--- a/tests/rustdoc-gui/item-summary-table.goml
+++ b/tests/rustdoc-gui/item-summary-table.goml
@@ -1,5 +1,5 @@
 // This test ensures that <table> elements aren't display in items summary.
-goto: "file://" + |DOC_PATH| + "/lib2/summary_table/index.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/summary_table/index.html"
 // We check that we picked the right item first.
 assert-text: (".item-table .item-name", "Foo")
 // Then we check that its summary is empty.
diff --git a/tests/rustdoc-gui/javascript-disabled.goml b/tests/rustdoc-gui/javascript-disabled.goml
index edf179d0d5e..a0872d553af 100644
--- a/tests/rustdoc-gui/javascript-disabled.goml
+++ b/tests/rustdoc-gui/javascript-disabled.goml
@@ -2,5 +2,5 @@
 // can't be used without JS.
 javascript: false
 
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 assert-css: (".sub", {"display": "none"})
diff --git a/tests/rustdoc-gui/jump-to-def-background.goml b/tests/rustdoc-gui/jump-to-def-background.goml
index 8ee3ccf4a21..3a7d48284d7 100644
--- a/tests/rustdoc-gui/jump-to-def-background.goml
+++ b/tests/rustdoc-gui/jump-to-def-background.goml
@@ -1,12 +1,12 @@
 // We check the background color on the jump to definition links in the source code page.
-goto: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html"
 
 define-function: (
     "check-background-color",
     (theme, background_color),
     block {
         // Set the theme.
-        local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }
+        set-local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }
         // We reload the page so the local storage settings are being used.
         reload:
         assert-css: (
diff --git a/tests/rustdoc-gui/label-next-to-symbol.goml b/tests/rustdoc-gui/label-next-to-symbol.goml
index 412e475dcc9..6c6380256bd 100644
--- a/tests/rustdoc-gui/label-next-to-symbol.goml
+++ b/tests/rustdoc-gui/label-next-to-symbol.goml
@@ -1,9 +1,9 @@
 // These tests verify that labels like "UNIX" and "Deprecated" stay on the same line as their symbol.
 // It also verifies the staggered layout on mobile.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 
 // Desktop view
-size: (1080, 600)
+set-window-size: (1080, 600)
 assert: (".stab.deprecated")
 assert: (".stab.portability")
 
@@ -39,7 +39,7 @@ compare-elements-position: (
 
 
 // Mobile view
-size: (600, 600)
+set-window-size: (600, 600)
 // staggered layout with 2em spacing
 assert-css: (".desc.docblock-short", { "padding-left": "32px" })
 compare-elements-position-near: (
diff --git a/tests/rustdoc-gui/links-color.goml b/tests/rustdoc-gui/links-color.goml
index 14f7d99351a..2ee4bce1015 100644
--- a/tests/rustdoc-gui/links-color.goml
+++ b/tests/rustdoc-gui/links-color.goml
@@ -1,5 +1,5 @@
 // This test checks links colors.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 
 // This is needed so that the text color is computed.
 show-text: true
@@ -9,7 +9,7 @@ define-function: (
     (theme, mod, macro, struct, enum, trait, fn, type, union, keyword,
      sidebar, sidebar_current, sidebar_current_background),
     block {
-        local-storage: {
+        set-local-storage: {
             "rustdoc-theme": |theme|,
             "rustdoc-use-system-theme": "false",
         }
diff --git a/tests/rustdoc-gui/list_code_block.goml b/tests/rustdoc-gui/list_code_block.goml
index 4c477d70c89..25ddea319c8 100644
--- a/tests/rustdoc-gui/list_code_block.goml
+++ b/tests/rustdoc-gui/list_code_block.goml
@@ -1,4 +1,4 @@
 // This test checks that code blocks in list are supported.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-goto: "./fn.check_list_code_block.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "./fn.check_list_code_block.html"
 assert: ("pre.rust.item-decl")
diff --git a/tests/rustdoc-gui/method-margins.goml b/tests/rustdoc-gui/method-margins.goml
index 720268a9e7e..ac3caeb237f 100644
--- a/tests/rustdoc-gui/method-margins.goml
+++ b/tests/rustdoc-gui/method-margins.goml
@@ -1,5 +1,5 @@
 // This test ensures that the margins on methods are coherent inside an impl block.
-goto: "file://" + |DOC_PATH| + "/test_docs/trait_members/struct.HasTrait.html#impl-TraitMembers-for-HasTrait"
+go-to: "file://" + |DOC_PATH| + "/test_docs/trait_members/struct.HasTrait.html#impl-TraitMembers-for-HasTrait"
 
 assert-count: ("#trait-implementations-list > .toggle", 1)
 
diff --git a/tests/rustdoc-gui/mobile.goml b/tests/rustdoc-gui/mobile.goml
index 8c8516ebff8..e576385cd53 100644
--- a/tests/rustdoc-gui/mobile.goml
+++ b/tests/rustdoc-gui/mobile.goml
@@ -1,8 +1,8 @@
 // Test various properties of the mobile UI
-goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
-size: (400, 600)
+go-to: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
+set-window-size: (400, 600)
 
-font-size: 18
+set-font-size: 18
 wait-for: 100 // wait a bit for the resize and the font-size change to be fully taken into account.
 
 // The out-of-band info (source, stable version, collapse) should be below the
@@ -18,14 +18,14 @@ assert-property: (".mobile-topbar h2", {"offsetHeight": 33})
 // is therefore not part of the DOM.
 assert-css: (".content .out-of-band .since::before", { "content": "\"Since \"" })
 
-size: (1000, 1000)
+set-window-size: (1000, 1000)
 wait-for: 100 // wait a bit for the resize to be fully taken into account.
 assert-css-false: (".content .out-of-band .since::before", { "content": "\"Since \"" })
 
 // On the settings page, the theme buttons should not line-wrap. Instead, they should
 // all be placed as a group on a line below the setting name "Theme."
-goto: "file://" + |DOC_PATH| + "/settings.html"
-size: (400, 600)
+go-to: "file://" + |DOC_PATH| + "/settings.html"
+set-window-size: (400, 600)
 // Ignored for now https://github.com/rust-lang/rust/issues/93784.
 // compare-elements-position-near-false: (
 //     "#preferred-light-theme .setting-radio-name",
diff --git a/tests/rustdoc-gui/module-items-font.goml b/tests/rustdoc-gui/module-items-font.goml
index 23823f8b6c7..54c8131c3b9 100644
--- a/tests/rustdoc-gui/module-items-font.goml
+++ b/tests/rustdoc-gui/module-items-font.goml
@@ -1,5 +1,5 @@
 // This test checks that the correct font is used on module items (in index.html pages).
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 assert-css: (
     ".item-table .item-name > a",
     {"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
diff --git a/tests/rustdoc-gui/no-docblock.goml b/tests/rustdoc-gui/no-docblock.goml
index 17a955064d7..1b4638ef067 100644
--- a/tests/rustdoc-gui/no-docblock.goml
+++ b/tests/rustdoc-gui/no-docblock.goml
@@ -4,10 +4,10 @@
 // doesn't exist.
 fail-on-request-error: false
 
-goto: "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithNoDocblocks.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithNoDocblocks.html"
 // Check that the two methods are more than 24px apart.
 compare-elements-position-near-false: ("//*[@id='tymethod.first_fn']", "//*[@id='tymethod.second_fn']", {"y": 24})
 
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithNoDocblocks.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithNoDocblocks.html"
 // Check that the two methods are more than 24px apart.
 compare-elements-position-near-false: ("//*[@id='method.first_fn']", "//*[@id='method.second_fn']", {"y": 24})
diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml
index 20728915199..f65da577478 100644
--- a/tests/rustdoc-gui/notable-trait.goml
+++ b/tests/rustdoc-gui/notable-trait.goml
@@ -1,8 +1,8 @@
 // This test checks the position of the `i` for the notable traits.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"
 show-text: true
 // We start with a wide screen.
-size: (1100, 600)
+set-window-size: (1100, 600)
 // Checking they have the same y position.
 compare-elements-position: (
     "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
@@ -44,7 +44,7 @@ move-cursor-to: "//h1"
 assert-count: ("//*[@class='tooltip popover']", 0)
 
 // Now only the `i` should be on the next line.
-size: (1055, 600)
+set-window-size: (1055, 600)
 compare-elements-position-false: (
     "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
     "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
@@ -52,7 +52,7 @@ compare-elements-position-false: (
 )
 
 // Now both the `i` and the struct name should be on the next line.
-size: (980, 600)
+set-window-size: (980, 600)
 // Checking they have the same y position.
 compare-elements-position: (
     "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
@@ -76,7 +76,7 @@ assert-position: (
 )
 
 // Checking on mobile now.
-size: (650, 600)
+set-window-size: (650, 600)
 // Checking they have the same y position.
 compare-elements-position: (
     "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
@@ -124,12 +124,12 @@ define-function: (
     "check-colors",
     (theme, header_color, content_color, type_color, trait_color),
     block {
-        goto: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"
         // This is needed to ensure that the text color is computed.
         show-text: true
 
         // Setting the theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
         reload:
 
@@ -253,7 +253,7 @@ press-key: "Escape"
 assert-window-property-false: {"scrollY": |scroll|}
 
 // Opening the mobile sidebar should close the popover.
-size: (650, 600)
+set-window-size: (650, 600)
 click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
 assert-count: ("//*[@class='tooltip popover']", 1)
 click: ".sidebar-menu-toggle"
@@ -266,7 +266,7 @@ assert-count: ("//*[@class='tooltip popover']", 1)
 assert-false: "//*[@class='sidebar shown']"
 
 // Also check the focus handling for the help button.
-size: (1100, 600)
+set-window-size: (1100, 600)
 reload:
 assert-count: ("//*[@class='tooltip popover']", 0)
 click: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
diff --git a/tests/rustdoc-gui/overflow-tooltip-information.goml b/tests/rustdoc-gui/overflow-tooltip-information.goml
index 09ad6cdd7ac..ab7ffc24ccf 100644
--- a/tests/rustdoc-gui/overflow-tooltip-information.goml
+++ b/tests/rustdoc-gui/overflow-tooltip-information.goml
@@ -1,7 +1,7 @@
 // The goal of this test is to ensure that the tooltip `.information` class doesn't
 // have overflow and max-width CSS rules set because they create a bug in firefox on
 // mac. For more information: https://github.com/rust-lang/rust/issues/89185
-goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
 assert-css: (".docblock > .example-wrap .tooltip", {
     "overflow-x": "visible",
     "max-width": "none"
diff --git a/tests/rustdoc-gui/pocket-menu.goml b/tests/rustdoc-gui/pocket-menu.goml
index c3649dc7bda..4bdf31ecb19 100644
--- a/tests/rustdoc-gui/pocket-menu.goml
+++ b/tests/rustdoc-gui/pocket-menu.goml
@@ -1,5 +1,5 @@
 // This test ensures that the "pocket menus" are working as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 // First we check that the help menu doesn't exist yet.
 assert-false: "#help-button .popover"
 // Then we display the help menu.
@@ -32,7 +32,7 @@ assert-css: ("#settings-menu .popover", {"display": "none"})
 // We check the borders color now:
 
 // Ayu theme
-local-storage: {
+set-local-storage: {
     "rustdoc-theme": "ayu",
     "rustdoc-use-system-theme": "false",
 }
@@ -47,7 +47,7 @@ compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-co
 compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
 
 // Dark theme
-local-storage: {
+set-local-storage: {
     "rustdoc-theme": "dark",
     "rustdoc-use-system-theme": "false",
 }
@@ -62,7 +62,7 @@ compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-co
 compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
 
 // Light theme
-local-storage: {
+set-local-storage: {
     "rustdoc-theme": "light",
     "rustdoc-use-system-theme": "false",
 }
@@ -77,7 +77,7 @@ compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-co
 compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
 
 // Opening the mobile sidebar should close the settings popover.
-size: (650, 600)
+set-window-size: (650, 600)
 click: "#settings-menu a"
 assert-css: ("#settings-menu .popover", {"display": "block"})
 click: ".sidebar-menu-toggle"
diff --git a/tests/rustdoc-gui/run-on-hover.goml b/tests/rustdoc-gui/run-on-hover.goml
index 8dcb62c10aa..b5fc49eacac 100644
--- a/tests/rustdoc-gui/run-on-hover.goml
+++ b/tests/rustdoc-gui/run-on-hover.goml
@@ -2,14 +2,14 @@
 // Playground. That button is hidden until the user hovers over the code block.
 // This test checks that it is hidden, and that it shows on hover. It also
 // checks for its color.
-goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
 show-text: true
 
 define-function: (
     "check-run-button",
     (theme, color, background, hover_color, hover_background),
     block {
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         assert-css: (".test-arrow", {"visibility": "hidden"})
         move-cursor-to: ".example-wrap"
diff --git a/tests/rustdoc-gui/rust-logo.goml b/tests/rustdoc-gui/rust-logo.goml
index 2d15e8b9699..640ed152b0d 100644
--- a/tests/rustdoc-gui/rust-logo.goml
+++ b/tests/rustdoc-gui/rust-logo.goml
@@ -1,26 +1,26 @@
 // This test ensures that the correct style is applied to the rust logo in the sidebar.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 
 define-function: (
     "check-logo",
     (theme, filter),
     block {
         // Going to the doc page.
-        goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
         // Changing theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         assert-css: (".rust-logo", {"filter": |filter|})
         // Going to the source code page.
-        goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+        go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
         // Changing theme (since it's local files, the local storage works by folder).
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         assert-css: (".rust-logo", {"filter": |filter|})
         // Now we check that the non-rust logos don't have a CSS filter set.
-        goto: "file://" + |DOC_PATH| + "/huge_logo/index.html"
+        go-to: "file://" + |DOC_PATH| + "/huge_logo/index.html"
         // Changing theme on the new page (again...).
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         // Check there is no rust logo
         assert-false: ".rust-logo"
diff --git a/tests/rustdoc-gui/scrape-examples-button-focus.goml b/tests/rustdoc-gui/scrape-examples-button-focus.goml
index 16f0ced8c6e..77061ea2a3f 100644
--- a/tests/rustdoc-gui/scrape-examples-button-focus.goml
+++ b/tests/rustdoc-gui/scrape-examples-button-focus.goml
@@ -1,6 +1,6 @@
 // This test ensures that the scraped examples buttons are working as expecting
 // when 'Enter' key is pressed when they're focused.
-goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
 
 // The next/prev buttons vertically scroll the code viewport between examples
 store-property: (initialScrollTop, ".scraped-example-list > .scraped-example pre", "scrollTop")
diff --git a/tests/rustdoc-gui/scrape-examples-color.goml b/tests/rustdoc-gui/scrape-examples-color.goml
index 67c58826efc..8ddb06fccfc 100644
--- a/tests/rustdoc-gui/scrape-examples-color.goml
+++ b/tests/rustdoc-gui/scrape-examples-color.goml
@@ -1,5 +1,5 @@
 // Check that scrape example code blocks have the expected colors.
-goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
 show-text: true
 
 define-function: (
@@ -7,7 +7,7 @@ define-function: (
     (theme, highlight, highlight_focus, help_border, help_color, help_hover_border,
      help_hover_color),
     block {
-        local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }
+        set-local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }
         reload:
         wait-for: ".more-examples-toggle"
         assert-css: (".scraped-example .example-wrap .rust span.highlight:not(.focus)", {
@@ -60,13 +60,13 @@ call-function: ("check-colors", {
 })
 
 // Now testing the top and bottom background in case there is only one scraped examples.
-goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
 
 define-function: (
     "check-background",
     (theme, background_color_start, background_color_end),
     block {
-        local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }
+        set-local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }
         reload:
         assert-css: (".scraped-example:not(.expanded) .code-wrapper::before", {
             "background-image": "linear-gradient(" + |background_color_start| + ", " +
diff --git a/tests/rustdoc-gui/scrape-examples-fonts.goml b/tests/rustdoc-gui/scrape-examples-fonts.goml
index 142f337cb74..4c325bace97 100644
--- a/tests/rustdoc-gui/scrape-examples-fonts.goml
+++ b/tests/rustdoc-gui/scrape-examples-fonts.goml
@@ -1,5 +1,5 @@
 // This test ensures that the correct font is used in scraped examples.
-goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
 
 store-value: (font, '"Fira Sans", Arial, NanumBarunGothic, sans-serif')
 
diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml
index dad727c7757..160056d6d05 100644
--- a/tests/rustdoc-gui/scrape-examples-layout.goml
+++ b/tests/rustdoc-gui/scrape-examples-layout.goml
@@ -1,5 +1,5 @@
 // Check that the line number column has the correct layout.
-goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
 
 // Check that it's not zero.
 assert-property-false: (
@@ -44,6 +44,6 @@ assert-position: (".scraped-example .code-wrapper", {"y": 253})
 assert-position: (".scraped-example .code-wrapper .prev", {"y": 253 + |offset_y|})
 
 // Then with mobile
-size: (600, 600)
+set-window-size: (600, 600)
 assert-position: (".scraped-example .code-wrapper", {"y": 308})
 assert-position: (".scraped-example .code-wrapper .prev", {"y": 308 + |offset_y|})
diff --git a/tests/rustdoc-gui/scrape-examples-toggle.goml b/tests/rustdoc-gui/scrape-examples-toggle.goml
index 2d5df6a5d25..9cec6d2bbe8 100644
--- a/tests/rustdoc-gui/scrape-examples-toggle.goml
+++ b/tests/rustdoc-gui/scrape-examples-toggle.goml
@@ -1,5 +1,5 @@
 // This tests checks that the "scraped examples" toggle is working as expected.
-goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
 
 // Checking the color of the toggle line.
 show-text: true
@@ -7,7 +7,7 @@ define-function: (
     "check-color",
     (theme, toggle_line_color, toggle_line_hover_color),
     block {
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
 
         // Clicking "More examples..." will open additional examples
diff --git a/tests/rustdoc-gui/search-error.goml b/tests/rustdoc-gui/search-error.goml
index 2a10a647b53..d21905e90ae 100644
--- a/tests/rustdoc-gui/search-error.goml
+++ b/tests/rustdoc-gui/search-error.goml
@@ -1,5 +1,5 @@
 // Checks that the crate search filtering is handled correctly and changes the results.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds"
 show-text: true
 
 define-function: (
@@ -7,7 +7,7 @@ define-function: (
     (theme, error_background),
     block {
         // Setting the theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
         reload:
 
diff --git a/tests/rustdoc-gui/search-filter.goml b/tests/rustdoc-gui/search-filter.goml
index 5bc6e87d6d2..f114c57ff21 100644
--- a/tests/rustdoc-gui/search-filter.goml
+++ b/tests/rustdoc-gui/search-filter.goml
@@ -1,5 +1,5 @@
 // Checks that the crate search filtering is handled correctly and changes the results.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 show-text: true
 write: (".search-input", "test")
 // To be SURE that the search will be run.
@@ -47,7 +47,7 @@ wait-for: "#search-tabs"
 assert-property: ("#crate-search", {"value": "all crates"})
 
 // Checking that the URL parameter is taken into account for crate filtering.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=test&filter-crate=lib2"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=test&filter-crate=lib2"
 wait-for: "#crate-search"
 assert-property: ("#crate-search", {"value": "lib2"})
 assert-false: "#results .externcrate"
@@ -57,10 +57,10 @@ assert-text: (".search-results-title", "Results in all crates", STARTS_WITH)
 
 // Checking the display of the crate filter.
 // We start with the light theme.
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+set-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
 reload:
 
-timeout: 2000
+set-timeout: 2000
 wait-for: "#crate-search"
 assert-css: ("#crate-search", {
     "border": "1px solid rgb(224, 224, 224)",
diff --git a/tests/rustdoc-gui/search-form-elements.goml b/tests/rustdoc-gui/search-form-elements.goml
index 542db348c3b..83c6980909c 100644
--- a/tests/rustdoc-gui/search-form-elements.goml
+++ b/tests/rustdoc-gui/search-form-elements.goml
@@ -1,9 +1,9 @@
 // This test ensures that the elements in ".search-form" have the expected display.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 show-text: true
 
 // Ayu theme
-local-storage: {
+set-local-storage: {
     "rustdoc-theme": "ayu",
     "rustdoc-use-system-theme": "false",
 }
@@ -89,7 +89,7 @@ assert-css: (
 )
 
 // Dark theme
-local-storage: {
+set-local-storage: {
     "rustdoc-theme": "dark",
     "rustdoc-use-system-theme": "false",
 }
@@ -176,7 +176,7 @@ assert-css: (
 )
 
 // Light theme
-local-storage: {
+set-local-storage: {
     "rustdoc-theme": "light",
     "rustdoc-use-system-theme": "false",
 }
diff --git a/tests/rustdoc-gui/search-input-mobile.goml b/tests/rustdoc-gui/search-input-mobile.goml
index ce0cef77ce4..adcb3658a27 100644
--- a/tests/rustdoc-gui/search-input-mobile.goml
+++ b/tests/rustdoc-gui/search-input-mobile.goml
@@ -1,11 +1,11 @@
 // Test to ensure that you can click on the search input, whatever the width.
 // The PR which fixed it is: https://github.com/rust-lang/rust/pull/81592
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-size: (463, 700)
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+set-window-size: (463, 700)
 // We first check that the search input isn't already focused.
 assert-false: ("input.search-input:focus")
 click: "input.search-input"
 reload:
-size: (750, 700)
+set-window-size: (750, 700)
 click: "input.search-input"
 assert: ("input.search-input:focus")
diff --git a/tests/rustdoc-gui/search-keyboard.goml b/tests/rustdoc-gui/search-keyboard.goml
index ed975664c66..f1d8024616b 100644
--- a/tests/rustdoc-gui/search-keyboard.goml
+++ b/tests/rustdoc-gui/search-keyboard.goml
@@ -1,6 +1,6 @@
 // Checks that the search tab results work correctly with function signature syntax
 // First, try a search-by-name
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 write: (".search-input", "Foo")
 // To be SURE that the search will be run.
 press-key: 'Enter'
diff --git a/tests/rustdoc-gui/search-no-result.goml b/tests/rustdoc-gui/search-no-result.goml
index b76a44fa992..46d1856b4d6 100644
--- a/tests/rustdoc-gui/search-no-result.goml
+++ b/tests/rustdoc-gui/search-no-result.goml
@@ -1,5 +1,5 @@
 // The goal of this test is to check the color of the "no result" links.
-goto: "file://" + |DOC_PATH| + "/lib2/index.html?search=sdkfskjfsdks"
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html?search=sdkfskjfsdks"
 show-text: true
 
 define-function: (
@@ -7,7 +7,7 @@ define-function: (
     (theme, link, link_hover),
     block {
         // Changing theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         wait-for: "#results"
         assert: ".search-failed.active"
diff --git a/tests/rustdoc-gui/search-reexport.goml b/tests/rustdoc-gui/search-reexport.goml
index dd19f03bd1e..fd817b58990 100644
--- a/tests/rustdoc-gui/search-reexport.goml
+++ b/tests/rustdoc-gui/search-reexport.goml
@@ -1,7 +1,7 @@
 // Checks that the reexports are present in the search index, can have
 // doc aliases and are highligted when their ID is the hash of the page.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+set-local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
 reload:
 // First we check that the reexport has the correct ID and no background color.
 assert-text: ("//*[@id='reexport.TheStdReexport']", "pub use ::std as TheStdReexport;")
diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml
index d6d54ec4bee..da46a90df90 100644
--- a/tests/rustdoc-gui/search-result-color.goml
+++ b/tests/rustdoc-gui/search-result-color.goml
@@ -31,13 +31,13 @@ define-function: (
     },
 )
 
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=coo"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=coo"
 
 // This is needed so that the text color is computed.
 show-text: true
 
 // Ayu theme
-local-storage: {
+set-local-storage: {
     "rustdoc-theme": "ayu",
     "rustdoc-use-system-theme": "false",
 }
@@ -154,7 +154,7 @@ assert-css: (
 )
 
 // Dark theme
-local-storage: {
+set-local-storage: {
     "rustdoc-theme": "dark",
     "rustdoc-use-system-theme": "false",
 }
@@ -259,7 +259,7 @@ assert-css: (
 )
 
 // Light theme
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
+set-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
 reload:
 
 // Waiting for the search results to appear...
@@ -361,7 +361,7 @@ assert-css: (
 )
 
 // Check the alias.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 // If the text isn't displayed, the browser doesn't compute color style correctly...
 show-text: true
 
@@ -369,7 +369,7 @@ define-function: (
     "check-alias",
     (theme, alias, grey),
     block {
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         write: (".search-input", "thisisanalias")
         // To be SURE that the search will be run.
diff --git a/tests/rustdoc-gui/search-result-description.goml b/tests/rustdoc-gui/search-result-description.goml
index 9fa2108045d..745ef31e6cb 100644
--- a/tests/rustdoc-gui/search-result-description.goml
+++ b/tests/rustdoc-gui/search-result-description.goml
@@ -1,5 +1,5 @@
 // This test is to ensure that the codeblocks are correctly rendered in the search results.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=some_more_function"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=some_more_function"
 // Waiting for the search results to appear...
 wait-for: "#search-tabs"
 assert-text: (".search-results .desc code", "format!")
diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml
index 20a88c36edb..93c71f23f24 100644
--- a/tests/rustdoc-gui/search-result-display.goml
+++ b/tests/rustdoc-gui/search-result-display.goml
@@ -1,6 +1,6 @@
 // Checks that the search results have the expected width.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-size: (900, 1000)
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+set-window-size: (900, 1000)
 write: (".search-input", "test")
 // To be SURE that the search will be run.
 press-key: 'Enter'
@@ -8,7 +8,7 @@ wait-for: "#crate-search"
 // The width is returned by "getComputedStyle" which returns the exact number instead of the
 // CSS rule which is "50%"...
 assert-css: (".search-results div.desc", {"width": "310px"})
-size: (600, 100)
+set-window-size: (600, 100)
 // As counter-intuitive as it may seem, in this width, the width is "100%", which is why
 // when computed it's larger.
 assert-css: (".search-results div.desc", {"width": "566px"})
@@ -18,7 +18,7 @@ assert-css: (".search-results .result-name > span", {"display": "inline"})
 
 // Check that the crate filter `<select>` is correctly handled when it goes to next line.
 // To do so we need to update the length of one of its `<option>`.
-size: (900, 900)
+set-window-size: (900, 900)
 
 // First we check the current width, height and position.
 assert-css: ("#crate-search", {"width": "223px"})
@@ -26,7 +26,7 @@ assert-css: (".search-results-title", {"height": "50px", "width": "640px"})
 assert-css: ("#search", {"width": "640px"})
 
 // Then we update the text of one of the `<option>`.
-text: (
+set-text: (
     "#crate-search option",
     "sdjfaksdjfaksjdbfkadsbfkjsadbfkdsbkfbsadkjfbkdsabfkadsfkjdsafa",
 )
@@ -43,7 +43,7 @@ define-function: (
     "check-filter",
     (theme, border, filter, hover_border, hover_filter),
     block {
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         wait-for: "#crate-search"
         assert-css: ("#crate-search", {"border": "1px solid " + |border|})
diff --git a/tests/rustdoc-gui/search-result-go-to-first.goml b/tests/rustdoc-gui/search-result-go-to-first.goml
index f444baa6ce1..a0bc2bb16ba 100644
--- a/tests/rustdoc-gui/search-result-go-to-first.goml
+++ b/tests/rustdoc-gui/search-result-go-to-first.goml
@@ -2,11 +2,11 @@
 
 // First, we check that the first page doesn't have the string we're looking for to ensure
 // that the feature is changing page as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 assert-text-false: (".main-heading h1", "Struct test_docs::Foo")
 
 // We now check that we land on the search result page if "go_to_first" isn't set.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo"
 // Waiting for the search results to appear...
 wait-for: "#search-tabs"
 assert-text-false: (".main-heading h1", "Struct test_docs::Foo")
@@ -14,6 +14,6 @@ assert-text-false: (".main-heading h1", "Struct test_docs::Foo")
 assert-css: ("#main-content", {"display": "none"})
 
 // Now we can check that the feature is working as expected!
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo&go_to_first=true"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo&go_to_first=true"
 // Waiting for the page to load...
 wait-for-text: (".main-heading h1", "Struct test_docs::Foo")
diff --git a/tests/rustdoc-gui/search-result-keyword.goml b/tests/rustdoc-gui/search-result-keyword.goml
index 8c3577d9fd3..5d56e9d9cd4 100644
--- a/tests/rustdoc-gui/search-result-keyword.goml
+++ b/tests/rustdoc-gui/search-result-keyword.goml
@@ -1,5 +1,5 @@
 // Checks that the "keyword" results have the expected text alongside them.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 write: (".search-input", "CookieMonster")
 // To be SURE that the search will be run.
 press-key: 'Enter'
diff --git a/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml b/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml
index 1433dc4d7e5..b3f9ae9283f 100644
--- a/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml
+++ b/tests/rustdoc-gui/search-tab-change-title-fn-sig.goml
@@ -1,6 +1,6 @@
 // Checks that the search tab results work correctly with function signature syntax
 // First, try a search-by-name
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 write: (".search-input", "Foo")
 // To be SURE that the search will be run.
 press-key: 'Enter'
@@ -22,7 +22,7 @@ press-key: "ArrowLeft"
 wait-for-attribute: ("#search-tabs > button:nth-of-type(3)", {"class": "selected"})
 
 // Now try search-by-return
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 write: (".search-input", "-> String")
 // To be SURE that the search will be run.
 press-key: 'Enter'
@@ -44,7 +44,7 @@ press-key: "ArrowLeft"
 wait-for-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"})
 
 // Try with a search-by-return with no results
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 write: (".search-input", "-> Something")
 // To be SURE that the search will be run.
 press-key: 'Enter'
@@ -54,7 +54,7 @@ assert-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"}
 assert-text: ("#search-tabs > button:nth-of-type(1)", "In Function Return Types", STARTS_WITH)
 
 // Try with a search-by-parameter
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 write: (".search-input", "usize pattern")
 // To be SURE that the search will be run.
 press-key: 'Enter'
@@ -64,7 +64,7 @@ assert-attribute: ("#search-tabs > button:nth-of-type(1)", {"class": "selected"}
 assert-text: ("#search-tabs > button:nth-of-type(1)", "In Function Parameters", STARTS_WITH)
 
 // Try with a search-by-parameter-and-return
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 write: (".search-input", "pattern -> str")
 // To be SURE that the search will be run.
 press-key: 'Enter'
diff --git a/tests/rustdoc-gui/search-tab.goml b/tests/rustdoc-gui/search-tab.goml
index 36958f70044..2223598f029 100644
--- a/tests/rustdoc-gui/search-tab.goml
+++ b/tests/rustdoc-gui/search-tab.goml
@@ -1,5 +1,5 @@
 // Checking the colors of the search tab headers.
-goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html?search=something"
+go-to: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html?search=something"
 show-text: true
 
 define-function: (
@@ -9,7 +9,7 @@ define-function: (
      border_top_hover),
     block {
         // Setting the theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
 
         // These two commands are used to be sure the search will be run.
diff --git a/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml b/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml
index 0ebb96d7870..6cd725043f4 100644
--- a/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml
+++ b/tests/rustdoc-gui/setting-auto-hide-content-large-items.goml
@@ -16,7 +16,7 @@ define-function: (
     }
 )
 
-goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html"
 
 // We check that the setting is enabled by default and is working.
 call-function: ("check-setting", {
diff --git a/tests/rustdoc-gui/setting-auto-hide-item-methods-docs.goml b/tests/rustdoc-gui/setting-auto-hide-item-methods-docs.goml
index e34fee33beb..5210ad8f793 100644
--- a/tests/rustdoc-gui/setting-auto-hide-item-methods-docs.goml
+++ b/tests/rustdoc-gui/setting-auto-hide-item-methods-docs.goml
@@ -13,7 +13,7 @@ define-function: (
     }
 )
 
-goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
 
 // We check that the setting is disabled by default.
 call-function: ("check-setting", {
diff --git a/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml b/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml
index 7355dddd39d..ecadd8fa80e 100644
--- a/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml
+++ b/tests/rustdoc-gui/setting-auto-hide-trait-implementations.goml
@@ -12,7 +12,7 @@ define-function: (
     }
 )
 
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 
 // By default, the trait implementations are not collapsed.
 call-function: ("check-setting", {
diff --git a/tests/rustdoc-gui/setting-go-to-only-result.goml b/tests/rustdoc-gui/setting-go-to-only-result.goml
index 3811011a64e..c5720b4bf1a 100644
--- a/tests/rustdoc-gui/setting-go-to-only-result.goml
+++ b/tests/rustdoc-gui/setting-go-to-only-result.goml
@@ -11,7 +11,7 @@ define-function: (
     }
 )
 
-goto: "file://" + |DOC_PATH| + "/lib2/index.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html"
 
 call-function: ("check-setting", {
     "storage_value": null,
@@ -19,7 +19,7 @@ call-function: ("check-setting", {
 })
 
 // By default, the search doesn't automatically go to the page if there is only one result.
-goto: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"
 // It will timeout if the setting isn't working.
 wait-for: "#search"
 assert-document-property: ({"URL": "/lib2/index.html"}, CONTAINS)
@@ -30,14 +30,14 @@ wait-for: "#settings"
 click: "#go-to-only-result"
 assert-local-storage: {"rustdoc-go-to-only-result": "true"}
 
-goto: "file://" + |DOC_PATH| + "/lib2/index.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html"
 // We enter it into the search.
 write: (".search-input", "HasALongTraitWithParams")
 wait-for-document-property: {"title": "HasALongTraitWithParams in lib2 - Rust"}
 assert-document-property: ({"URL": "/lib2/struct.HasALongTraitWithParams.html"}, ENDS_WITH)
 
 // We try again to see if it goes to the only result
-goto: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"
 wait-for-document-property: {"title": "HasALongTraitWithParams in lib2 - Rust"}
 assert-document-property: ({"URL": "/lib2/struct.HasALongTraitWithParams.html"}, ENDS_WITH)
 
@@ -51,7 +51,7 @@ call-function: ("check-setting", {
 click: "#go-to-only-result"
 assert-local-storage: {"rustdoc-go-to-only-result": "false"}
 
-goto: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html?search=HasALongTraitWithParams"
 // It will timeout if the setting isn't working.
 wait-for: "#search"
 assert-document-property: ({"URL": "/lib2/index.html"}, CONTAINS)
diff --git a/tests/rustdoc-gui/settings.goml b/tests/rustdoc-gui/settings.goml
index a8417288578..cfb037245d1 100644
--- a/tests/rustdoc-gui/settings.goml
+++ b/tests/rustdoc-gui/settings.goml
@@ -1,6 +1,6 @@
 // This test ensures that the settings menu display is working as expected and that
 // the settings page is also rendered as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 show-text: true // needed when we check for colors below.
 // First, we check that the settings page doesn't exist.
 assert-false: "#settings"
@@ -35,7 +35,7 @@ wait-for: "#alternative-display #search"
 assert: "#main-content.hidden"
 
 // Now let's check the content of the settings menu.
-local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
+set-local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
 reload:
 click: "#settings-menu"
 wait-for: "#settings"
@@ -189,7 +189,7 @@ assert-text: ("#preferred-light-theme .setting-radio-name", "Preferred light the
 
 // We now check that clicking on the toggles' text is like clicking on the checkbox.
 // To test it, we use the "Disable keyboard shortcuts".
-local-storage: {"rustdoc-disable-shortcuts": "false"}
+set-local-storage: {"rustdoc-disable-shortcuts": "false"}
 click: ".setting-line:last-child .setting-check span"
 assert-local-storage: {"rustdoc-disable-shortcuts": "true"}
 
@@ -227,7 +227,7 @@ wait-for-css: ("#settings-menu .popover", {"display": "none"})
 wait-for-css: ("#help-button .popover", {"display": "block"})
 
 // Now we go to the settings page to check that the CSS is loaded as expected.
-goto: "file://" + |DOC_PATH| + "/settings.html"
+go-to: "file://" + |DOC_PATH| + "/settings.html"
 wait-for: "#settings"
 assert-css: (".setting-line", {"position": "relative"})
 
@@ -247,7 +247,7 @@ javascript: true
 // Check for the display on small screen
 show-text: true
 reload:
-size: (300, 1000)
+set-window-size: (300, 1000)
 click: "#settings-menu"
 wait-for: "#settings"
 assert-css: (".setting-line", {"position": "relative"})
diff --git a/tests/rustdoc-gui/shortcuts.goml b/tests/rustdoc-gui/shortcuts.goml
index 9068680d640..667df89ec9b 100644
--- a/tests/rustdoc-gui/shortcuts.goml
+++ b/tests/rustdoc-gui/shortcuts.goml
@@ -1,5 +1,5 @@
 // Check that the various shortcuts are working.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 // We first check that the search input isn't already focused.
 assert-false: "input.search-input:focus"
 press-key: "s"
diff --git a/tests/rustdoc-gui/sidebar-links-color.goml b/tests/rustdoc-gui/sidebar-links-color.goml
index 1d5fdb7a48f..cec1a799926 100644
--- a/tests/rustdoc-gui/sidebar-links-color.goml
+++ b/tests/rustdoc-gui/sidebar-links-color.goml
@@ -1,5 +1,5 @@
 // This test checks links colors in sidebar before and after hover.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 
 // This is needed so that the text color is computed.
 show-text: true
@@ -13,7 +13,7 @@ define-function: (
         type_hover_background, keyword, keyword_hover, keyword_hover_background,
     ),
     block {
-        local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }
+        set-local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }
         reload:
         // Struct
         assert-css: (
diff --git a/tests/rustdoc-gui/sidebar-macro-reexport.goml b/tests/rustdoc-gui/sidebar-macro-reexport.goml
index b5c1b6a4390..0f7ef6c3558 100644
--- a/tests/rustdoc-gui/sidebar-macro-reexport.goml
+++ b/tests/rustdoc-gui/sidebar-macro-reexport.goml
@@ -1,5 +1,5 @@
 // This test ensures that the reexport of a macro doesn't make the original macro
 // displayed twice in the sidebar.
-goto: "file://" + |DOC_PATH| + "/test_docs/macro.repro.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/macro.repro.html"
 wait-for: ".sidebar-elems .block.macro a"
 assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[text()='repro']", 1)
diff --git a/tests/rustdoc-gui/sidebar-mobile-scroll.goml b/tests/rustdoc-gui/sidebar-mobile-scroll.goml
index 4442b263e9a..84811437eb2 100644
--- a/tests/rustdoc-gui/sidebar-mobile-scroll.goml
+++ b/tests/rustdoc-gui/sidebar-mobile-scroll.goml
@@ -1,7 +1,7 @@
 // This test ensures that the mobile sidebar preserves scroll position.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 // Switching to "mobile view" by reducing the width to 600px.
-size: (700, 600)
+set-window-size: (700, 600)
 assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 
 // Scroll down.
@@ -27,5 +27,5 @@ assert-window-property: {"pageYOffset": "622"}
 click: ".sidebar-menu-toggle"
 wait-for-css: (".sidebar", {"left": "0px"})
 assert-window-property: {"pageYOffset": "0"}
-size: (900, 600)
+set-window-size: (900, 600)
 assert-window-property: {"pageYOffset": "622"}
diff --git a/tests/rustdoc-gui/sidebar-mobile.goml b/tests/rustdoc-gui/sidebar-mobile.goml
index cc6267c3dc9..3b022c7e9d0 100644
--- a/tests/rustdoc-gui/sidebar-mobile.goml
+++ b/tests/rustdoc-gui/sidebar-mobile.goml
@@ -1,9 +1,9 @@
 // This test ensure that the sidebar isn't "hidden" on mobile but instead moved out of the viewport.
 // This is especially important for devices for "text-first" content (like for users with
 // sight issues).
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 // Switching to "mobile view" by reducing the width to 600px.
-size: (600, 600)
+set-window-size: (600, 600)
 assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 // Opening the sidebar menu.
 click: ".sidebar-menu-toggle"
@@ -59,7 +59,7 @@ define-function: (
     "check-colors",
     (theme, color, background),
     block {
-        local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}
+        set-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}
         reload:
 
         // Open the sidebar menu.
diff --git a/tests/rustdoc-gui/sidebar-source-code-display.goml b/tests/rustdoc-gui/sidebar-source-code-display.goml
index f3eb8ff76a3..f34e30b724d 100644
--- a/tests/rustdoc-gui/sidebar-source-code-display.goml
+++ b/tests/rustdoc-gui/sidebar-source-code-display.goml
@@ -1,6 +1,6 @@
 // This test ensures that the elements in the sidebar are displayed correctly.
 javascript: false
-goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 // Since the javascript is disabled, there shouldn't be a toggle.
 assert-false: "#src-sidebar-toggle"
 wait-for-css: (".sidebar", {"display": "none"})
@@ -22,7 +22,7 @@ wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"})
 wait-for-css: (".sidebar", {"width": "300px"})
 assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
 click: ".sidebar a.selected"
-goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 wait-for-css: (".sidebar", {"width": "300px"})
 assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
 
@@ -36,7 +36,7 @@ define-function: (
         background_toggle_hover,
     ),
     block {
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"})
         assert-css: (
@@ -148,7 +148,7 @@ call-function: ("check-colors", {
 })
 
 // Now checking on mobile devices.
-size: (500, 700)
+set-window-size: (500, 700)
 reload:
 // Waiting for the sidebar to be displayed...
 wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"})
@@ -184,13 +184,13 @@ wait-for-css: (".sidebar", {"left": "-1000px"})
 assert-window-property: {"pageYOffset": "2542"}
 
 // We now check that the scroll position is restored if the window is resized.
-size: (500, 700)
+set-window-size: (500, 700)
 click: "#src-sidebar-toggle"
 wait-for-css: ("#source-sidebar", {"visibility": "visible"})
 assert-window-property: {"pageYOffset": "0"}
-size: (900, 900)
+set-window-size: (900, 900)
 assert-window-property: {"pageYOffset": "2542"}
-size: (500, 700)
+set-window-size: (500, 700)
 click: "#src-sidebar-toggle"
 wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
 
@@ -203,11 +203,11 @@ click: "#src-sidebar-toggle"
 wait-for-css: ("#source-sidebar", {"visibility": "visible"})
 assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
 click: ".sidebar a.selected"
-goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
 assert-local-storage: {"rustdoc-source-sidebar-show": "false"}
 // Resize back to desktop size, to check that the sidebar doesn't spontaneously open.
-size: (1000, 1000)
+set-window-size: (1000, 1000)
 wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
 assert-local-storage: {"rustdoc-source-sidebar-show": "false"}
 click: "#src-sidebar-toggle"
diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml
index c8a29b58d34..96ea7202433 100644
--- a/tests/rustdoc-gui/sidebar-source-code.goml
+++ b/tests/rustdoc-gui/sidebar-source-code.goml
@@ -1,6 +1,6 @@
 // The goal of this test is to ensure that the sidebar is working as expected in the source
 // code pages.
-goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 show-text: true
 
 // First, check the sidebar colors.
@@ -8,7 +8,7 @@ define-function: (
     "check-colors",
     (theme, color, background_color),
     block {
-        local-storage: {
+        set-local-storage: {
             "rustdoc-theme": |theme|,
             "rustdoc-use-system-theme": "false",
         }
@@ -47,7 +47,7 @@ call-function: (
 )
 
 // Next, desktop mode layout.
-size: (1100, 800)
+set-window-size: (1100, 800)
 // We check that the sidebar isn't expanded and has the expected width.
 assert-css: ("nav.sidebar", {"width": "50px"})
 // We now click on the button to expand the sidebar.
@@ -62,7 +62,7 @@ wait-for: "html:not(.expanded)"
 assert: "nav.sidebar"
 
 // Checking that only the path to the current file is "open".
-goto: "file://" + |DOC_PATH| + "/src/lib2/another_folder/sub_mod/mod.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/lib2/another_folder/sub_mod/mod.rs.html"
 // First we expand the sidebar again.
 click: (10, 10)
 // We wait for the sidebar to be expanded.
@@ -76,7 +76,7 @@ assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']"
 assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 8)
 
 // We now switch to mobile mode.
-size: (600, 600)
+set-window-size: (600, 600)
 wait-for-css: (".source-sidebar-expanded nav.sidebar", {"left": "0px"})
 // We collapse the sidebar.
 click: (10, 10)
diff --git a/tests/rustdoc-gui/sidebar.goml b/tests/rustdoc-gui/sidebar.goml
index 473ab8fc960..3c1ed009a33 100644
--- a/tests/rustdoc-gui/sidebar.goml
+++ b/tests/rustdoc-gui/sidebar.goml
@@ -1,5 +1,5 @@
 // Checks multiple things on the sidebar display (width of its elements, colors, etc).
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
 show-text: true
 
@@ -8,7 +8,7 @@ define-function: (
     "check-colors",
     (theme, color, background_color),
     block {
-        local-storage: {
+        set-local-storage: {
             "rustdoc-theme": |theme|,
             "rustdoc-use-system-theme": "false",
         }
@@ -46,7 +46,7 @@ call-function: (
     }
 )
 
-local-storage: {"rustdoc-theme": "light"}
+set-local-storage: {"rustdoc-theme": "light"}
 // We reload the page so the local storage settings are being used.
 reload:
 
@@ -86,13 +86,13 @@ click: ".sidebar h2.location a"
 assert-property: ("html", {"scrollTop": "0"})
 
 // We now go back to the crate page to click on the "lib2" crate link.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
 assert-css: (".sidebar-elems ul.crate > li:first-child > a", {"color": "rgb(53, 109, 164)"})
 click: ".sidebar-elems ul.crate > li:first-child > a"
 
 // PAGE: lib2/index.html
-goto: "file://" + |DOC_PATH| + "/lib2/index.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
 assert-text: (".sidebar > .location", "Crate lib2")
 // We check that we have the crates list and that the "current" on is now "lib2".
@@ -115,13 +115,13 @@ assert-text: (".sidebar .sidebar-elems h2", "In lib2")
 // We check that we don't have the crate list.
 assert-false: ".sidebar-elems > .crate"
 
-goto: "./module/index.html"
+go-to: "./module/index.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
 assert-text: (".sidebar > .location", "Module module")
 // We check that we don't have the crate list.
 assert-false: ".sidebar-elems > .crate"
 
-goto: "./sub_module/sub_sub_module/index.html"
+go-to: "./sub_module/sub_sub_module/index.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
 assert-text: (".sidebar > .location", "Module sub_sub_module")
 // We check that we don't have the crate list.
@@ -130,13 +130,13 @@ assert-text: (".sidebar-elems > section ul > li:nth-child(1)", "Functions")
 assert-text: ("#functions + .item-table .item-name > a", "foo")
 
 // Links to trait implementations in the sidebar should not wrap even if they are long.
-goto: "file://" + |DOC_PATH| + "/lib2/struct.HasALongTraitWithParams.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.HasALongTraitWithParams.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
 assert-property: (".sidebar-elems section .block li > a", {"offsetHeight": 29})
 
 // Test that clicking on of the "In <module>" headings in the sidebar links to the
 // appropriate anchor in index.html.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 assert-property: (".sidebar", {"clientWidth": "200"})
 click: "//ul[@class='block mod']/preceding-sibling::h3/a"
 // PAGE: index.html
@@ -151,12 +151,12 @@ assert-text: ("#toggle-all-docs", "[−]")
 assert-property: (".sidebar", {"clientWidth": "200"})
 
 // Checks that all.html and index.html have their sidebar link in the same place.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 store-property: (index_sidebar_width, ".sidebar .location a", "clientWidth")
 store-property: (index_sidebar_height, ".sidebar .location a", "clientHeight")
 store-property: (index_sidebar_x, ".sidebar .location a", "offsetTop")
 store-property: (index_sidebar_y, ".sidebar .location a", "offsetLeft")
-goto: "file://" + |DOC_PATH| + "/test_docs/all.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/all.html"
 assert-property: (".sidebar .location a", {
     "clientWidth": |index_sidebar_width|,
     "clientHeight": |index_sidebar_height|,
diff --git a/tests/rustdoc-gui/source-anchor-scroll.goml b/tests/rustdoc-gui/source-anchor-scroll.goml
index ddfe0c3d1ab..3d88d5619b1 100644
--- a/tests/rustdoc-gui/source-anchor-scroll.goml
+++ b/tests/rustdoc-gui/source-anchor-scroll.goml
@@ -1,9 +1,9 @@
 // We check that when the anchor changes and is output of the displayed content,
 // the page is scrolled to it.
-goto: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html"
 
 // We reduce the window size to make it easier to make an element "out of the page".
-size: (600, 800)
+set-window-size: (600, 800)
 // We check that the scroll is at the top first.
 assert-property: ("html", {"scrollTop": "0"})
 
diff --git a/tests/rustdoc-gui/source-code-page-code-scroll.goml b/tests/rustdoc-gui/source-code-page-code-scroll.goml
index 42f1da749e9..35f338ea328 100644
--- a/tests/rustdoc-gui/source-code-page-code-scroll.goml
+++ b/tests/rustdoc-gui/source-code-page-code-scroll.goml
@@ -1,6 +1,6 @@
 // Checks that the scrollbar is visible on the page rather than the code block.
-goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
-size: (800, 1000)
+go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+set-window-size: (800, 1000)
 // "scrollWidth" should be superior than "clientWidth".
 assert-property: ("body", {"scrollWidth": 1047, "clientWidth": 800})
 
diff --git a/tests/rustdoc-gui/source-code-page.goml b/tests/rustdoc-gui/source-code-page.goml
index ea6ff12328c..1ac403308eb 100644
--- a/tests/rustdoc-gui/source-code-page.goml
+++ b/tests/rustdoc-gui/source-code-page.goml
@@ -1,5 +1,5 @@
 // Checks that the interactions with the source code pages are working as expected.
-goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 show-text: true
 // Check that we can click on the line number.
 click: ".src-line-numbers > a:nth-child(4)" // This is the anchor for line 4.
@@ -12,7 +12,7 @@ reload:
 assert-attribute: ("//*[@id='4']", {"class": "line-highlighted"})
 assert-css: ("//*[@id='4']", {"border-right-width": "0px"})
 // We now check that the good anchors are highlighted
-goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#4-6"
+go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#4-6"
 assert-attribute-false: (".src-line-numbers > a:nth-child(3)", {"class": "line-highlighted"})
 assert-attribute: (".src-line-numbers > a:nth-child(4)", {"class": "line-highlighted"})
 assert-attribute: (".src-line-numbers > a:nth-child(5)", {"class": "line-highlighted"})
@@ -23,7 +23,7 @@ define-function: (
     "check-colors",
     (theme, color, background_color, highlight_color, highlight_background_color),
     block {
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         assert-css: (
             ".src-line-numbers > a:not(.line-highlighted)",
@@ -87,7 +87,7 @@ assert-css: (".src-line-numbers", {"text-align": "right"})
 
 // Now let's check that clicking on something else than the line number doesn't
 // do anything (and certainly not add a `#NaN` to the URL!).
-goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+go-to: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
 // We use this assert-position to know where we will click.
 assert-position: ("//*[@id='1']", {"x": 88, "y": 112})
 // We click on the left of the "1" anchor but still in the "src-line-number" `<pre>`.
@@ -175,7 +175,7 @@ assert-property: ("#main-content", {"offsetTop": 90})
 // 28 = 90 - 34 - 28
 
 // Now do the same check on moderately-sized, tablet mobile.
-size: (700, 700)
+set-window-size: (700, 700)
 assert-css: ("nav.sub", {"flex-direction": "row"})
 assert-property: ("nav.sub form", {"offsetTop": 21, "offsetHeight": 34})
 assert-property: ("#main-content", {"offsetTop": 76})
@@ -198,7 +198,7 @@ call-function: ("check-sidebar-dir-entry", {
 })
 
 // Tiny, phone mobile gets a different display where the logo is stacked on top.
-size: (450, 700)
+set-window-size: (450, 700)
 assert-css: ("nav.sub", {"flex-direction": "column"})
 
 // Check the sidebar directory entries have a marker and spacing (phone).
diff --git a/tests/rustdoc-gui/src-font-size.goml b/tests/rustdoc-gui/src-font-size.goml
index bab66dae70c..790aeba529c 100644
--- a/tests/rustdoc-gui/src-font-size.goml
+++ b/tests/rustdoc-gui/src-font-size.goml
@@ -1,7 +1,7 @@
 // This test ensures that the "[src]" have the same font size as their headers
 // to avoid having some weird height difference in the background when the element
 // is selected.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 show-text: true
 // Check the impl headers.
 assert-css: (".impl .srclink", {"font-size": "16px", "font-weight": 400}, ALL)
diff --git a/tests/rustdoc-gui/stab-badge.goml b/tests/rustdoc-gui/stab-badge.goml
index 50ba1ba62db..e2340418871 100644
--- a/tests/rustdoc-gui/stab-badge.goml
+++ b/tests/rustdoc-gui/stab-badge.goml
@@ -1,12 +1,12 @@
 // All stability badges should have rounded corners and colored backgrounds.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 show-text: true
 define-function: (
     "check-badge",
     (theme, background, color),
     block {
-        local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}
-        goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+        set-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}
+        go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
         assert: ".docblock .stab"
         assert: ".item-table .stab"
         assert-css: (".stab", {
@@ -14,7 +14,7 @@ define-function: (
             "color": |color|,
             "background-color": |background|,
         })
-        goto: "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"
+        go-to: "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"
         assert: (".item-info .stab")
         assert-css: (".stab", {
             "border-radius": "3px",
diff --git a/tests/rustdoc-gui/struct-fields.goml b/tests/rustdoc-gui/struct-fields.goml
index fa3e16cb81e..da0467de13a 100644
--- a/tests/rustdoc-gui/struct-fields.goml
+++ b/tests/rustdoc-gui/struct-fields.goml
@@ -1,5 +1,5 @@
 // This test ensures that each field is on its own line (In other words, they have display: block).
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.StructWithPublicUndocumentedFields.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.StructWithPublicUndocumentedFields.html"
 
 store-property: (first_top, "//*[@id='structfield.first']", "offsetTop")
 assert-property-false: ("//*[@id='structfield.second']", { "offsetTop": |first_top| })
diff --git a/tests/rustdoc-gui/target.goml b/tests/rustdoc-gui/target.goml
index ca393ee5891..0c514fc6864 100644
--- a/tests/rustdoc-gui/target.goml
+++ b/tests/rustdoc-gui/target.goml
@@ -1,5 +1,5 @@
 // Check that the targetted element has the expected styles.
-goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html#method.a_method"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html#method.a_method"
 show-text: true
 
 // Confirming that the method is the target.
@@ -9,7 +9,7 @@ define-function: (
     "check-style",
     (theme, background, border),
     block {
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         reload:
         assert-css: ("#method\.a_method:target", {
             "background-color": |background|,
diff --git a/tests/rustdoc-gui/theme-change.goml b/tests/rustdoc-gui/theme-change.goml
index 31c9d99aa83..ae694721389 100644
--- a/tests/rustdoc-gui/theme-change.goml
+++ b/tests/rustdoc-gui/theme-change.goml
@@ -1,6 +1,6 @@
 // Ensures that the theme change is working as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
+set-local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
 reload:
 
 store-value: (background_light, "rgb(255, 255, 255)")
@@ -22,11 +22,11 @@ click: "#theme-dark"
 wait-for-css: ("body", { "background-color": |background_dark| })
 assert-local-storage: { "rustdoc-theme": "dark" }
 
-local-storage: {
+set-local-storage: {
     "rustdoc-preferred-light-theme": "light",
     "rustdoc-preferred-dark-theme": "light",
 }
-goto: "file://" + |DOC_PATH| + "/settings.html"
+go-to: "file://" + |DOC_PATH| + "/settings.html"
 
 wait-for: "#settings"
 click: "#theme-light"
diff --git a/tests/rustdoc-gui/theme-defaults.goml b/tests/rustdoc-gui/theme-defaults.goml
index d5ed536b1a9..2cc5d716cfe 100644
--- a/tests/rustdoc-gui/theme-defaults.goml
+++ b/tests/rustdoc-gui/theme-defaults.goml
@@ -1,5 +1,5 @@
 // Ensure that the theme picker always starts with the actual defaults.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 click: "#settings-menu"
 wait-for: "#theme-system-preference"
 assert: "#theme-system-preference:checked"
@@ -9,13 +9,13 @@ assert-false: "#preferred-dark-theme-ayu:checked"
 
 // Test legacy migration from old theme setup without system-preference matching.
 // See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
-local-storage: {
+set-local-storage: {
     "rustdoc-preferred-light-theme": null,
     "rustdoc-preferred-dark-theme": null,
     "rustdoc-use-system-theme": null,
     "rustdoc-theme": "ayu"
 }
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 click: "#settings-menu"
 wait-for: "#theme-system-preference"
 assert: "#theme-system-preference:checked"
diff --git a/tests/rustdoc-gui/theme-in-history.goml b/tests/rustdoc-gui/theme-in-history.goml
index 10508e86a36..8fcd0ecd309 100644
--- a/tests/rustdoc-gui/theme-in-history.goml
+++ b/tests/rustdoc-gui/theme-in-history.goml
@@ -1,7 +1,7 @@
 // Ensures that the theme is working when going back in history.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 // Set the theme to dark.
-local-storage: {
+set-local-storage: {
     "rustdoc-theme": "dark",
     "rustdoc-use-system-theme": "false",
 }
@@ -11,7 +11,7 @@ assert-css: ("body", { "background-color": "rgb(53, 53, 53)" })
 assert-local-storage: { "rustdoc-theme": "dark" }
 
 // Now we go to the settings page.
-goto: "file://" + |DOC_PATH| + "/settings.html"
+go-to: "file://" + |DOC_PATH| + "/settings.html"
 wait-for: "#settings"
 // We change the theme to "light".
 click: "#theme-light"
diff --git a/tests/rustdoc-gui/toggle-click-deadspace.goml b/tests/rustdoc-gui/toggle-click-deadspace.goml
index ac346f25b88..f115f63ab6b 100644
--- a/tests/rustdoc-gui/toggle-click-deadspace.goml
+++ b/tests/rustdoc-gui/toggle-click-deadspace.goml
@@ -1,6 +1,6 @@
 // This test ensures that clicking on a method summary, but not on the "[-]",
 // doesn't toggle the <details>.
-goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
 assert-attribute: (".impl-items .toggle", {"open": ""})
 click: "h4.code-header" // This is the position of "pub" in "pub fn a_method"
 assert-attribute: (".impl-items .toggle", {"open": ""})
diff --git a/tests/rustdoc-gui/toggle-docs-mobile.goml b/tests/rustdoc-gui/toggle-docs-mobile.goml
index 6ce24a81bb3..b69aa6e30ca 100644
--- a/tests/rustdoc-gui/toggle-docs-mobile.goml
+++ b/tests/rustdoc-gui/toggle-docs-mobile.goml
@@ -1,7 +1,7 @@
 // Checks that the documentation toggles on mobile have the correct position, style and work
 // as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-size: (433, 600)
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+set-window-size: (433, 600)
 assert-attribute: (".top-doc", {"open": ""})
 click: (4, 270) // This is the position of the top doc comment toggle
 assert-attribute-false: (".top-doc", {"open": ""})
@@ -22,7 +22,7 @@ assert-position: (
 )
 
 // Now we do the same but with a little bigger width
-size: (600, 600)
+set-window-size: (600, 600)
 assert-attribute: (".top-doc", {"open": ""})
 click: (4, 270) // New Y position since all search elements are back on one line.
 assert-attribute-false: (".top-doc", {"open": ""})
diff --git a/tests/rustdoc-gui/toggle-docs.goml b/tests/rustdoc-gui/toggle-docs.goml
index c9d236e9bba..9ea6d9b18f4 100644
--- a/tests/rustdoc-gui/toggle-docs.goml
+++ b/tests/rustdoc-gui/toggle-docs.goml
@@ -1,5 +1,5 @@
 // Checks that the documentation toggles have the correct position, style and work as expected.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 assert-attribute: ("#main-content > details.top-doc", {"open": ""})
 assert-text: ("#toggle-all-docs", "[−]")
 click: "#toggle-all-docs"
@@ -17,7 +17,7 @@ wait-for-attribute: ("#main-content > details.top-doc", {"open": ""})
 assert-text: ("#toggle-all-docs", "[−]")
 
 // Check that it works on non-module pages as well.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 // We first check that everything is visible.
 assert-text: ("#toggle-all-docs", "[−]")
 assert-attribute: ("#implementations-list details.toggle", {"open": ""}, ALL)
@@ -52,7 +52,7 @@ define-function: (
     (theme, filter),
     block {
         // Setting the theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
         reload:
 
diff --git a/tests/rustdoc-gui/toggle-implementors.goml b/tests/rustdoc-gui/toggle-implementors.goml
index 8ff5b91af0d..c4056275d3e 100644
--- a/tests/rustdoc-gui/toggle-implementors.goml
+++ b/tests/rustdoc-gui/toggle-implementors.goml
@@ -1,4 +1,4 @@
 // This test ensures that the implementors toggle are not open by default.
-goto: "file://" + |DOC_PATH| + "/implementors/trait.Whatever.html"
+go-to: "file://" + |DOC_PATH| + "/implementors/trait.Whatever.html"
 
 assert-attribute-false: ("#implementors-list > details", {"open": ""}, ALL)
diff --git a/tests/rustdoc-gui/toggled-open-implementations.goml b/tests/rustdoc-gui/toggled-open-implementations.goml
index 000293b555f..238205dd4df 100644
--- a/tests/rustdoc-gui/toggled-open-implementations.goml
+++ b/tests/rustdoc-gui/toggled-open-implementations.goml
@@ -1,5 +1,5 @@
 // This tests that the "implementations" section on struct/enum pages
 // has all the implementations toggled open by default, so users can
 // find method names in those implementations with Ctrl-F.
-goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
 assert-attribute: (".toggle.implementors-toggle", {"open": ""})
diff --git a/tests/rustdoc-gui/trait-sidebar-item-order.goml b/tests/rustdoc-gui/trait-sidebar-item-order.goml
index e5d023544d6..9330ef040ec 100644
--- a/tests/rustdoc-gui/trait-sidebar-item-order.goml
+++ b/tests/rustdoc-gui/trait-sidebar-item-order.goml
@@ -4,7 +4,7 @@
 // doesn't exist.
 fail-on-request-error: false
 
-goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
 assert-text: (".sidebar-elems section .block li:nth-of-type(1) > a", "another")
 assert-text: (".sidebar-elems section .block li:nth-of-type(2) > a", "func1")
 assert-text: (".sidebar-elems section .block li:nth-of-type(3) > a", "func2")
diff --git a/tests/rustdoc-gui/type-declation-overflow.goml b/tests/rustdoc-gui/type-declation-overflow.goml
index 708e9dca0ee..e8e42e4004b 100644
--- a/tests/rustdoc-gui/type-declation-overflow.goml
+++ b/tests/rustdoc-gui/type-declation-overflow.goml
@@ -6,20 +6,20 @@
 // doesn't exist.
 fail-on-request-error: false
 
-goto: "file://" + |DOC_PATH| + "/lib2/long_trait/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/long_trait/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.html"
 // We set a fixed size so there is no chance of "random" resize.
-size: (1100, 800)
+set-window-size: (1100, 800)
 // Logically, the <body> scroll width should be the width of the window.
 assert-property: ("body", {"scrollWidth": "1100"})
 // However, since there is overflow in the type declaration, its scroll width is bigger.
 assert-property: ("pre.item-decl", {"scrollWidth": "1324"})
 
 // In the table-ish view on the module index, the name should not be wrapped more than necessary.
-goto: "file://" + |DOC_PATH| + "/lib2/too_long/index.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/too_long/index.html"
 assert-property: (".item-table .struct", {"offsetWidth": "684"})
 
 // We now make the same check on type declaration...
-goto: "file://" + |DOC_PATH| + "/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html"
 assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
 assert-property: ("#main-content", {"scrollWidth": "840"})
@@ -28,7 +28,7 @@ assert-property: ("pre.item-decl", {"scrollWidth": "1103"})
 
 // ... and constant.
 // On a sidenote, it also checks that the (very) long title isn't changing the docblock width.
-goto: "file://" + |DOC_PATH| + "/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html"
 assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
 assert-property: ("#main-content", {"scrollWidth": "840"})
@@ -36,8 +36,8 @@ assert-property: ("#main-content", {"scrollWidth": "840"})
 assert-property: ("pre.item-decl", {"scrollWidth": "950"})
 
 // On mobile:
-size: (600, 600)
-goto: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
+set-window-size: (600, 600)
+go-to: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
 // It shouldn't have an overflow in the topbar either.
 store-property: (scrollWidth, ".mobile-topbar h2", "scrollWidth")
 assert-property: (".mobile-topbar h2", {"clientWidth": |scrollWidth|})
@@ -45,24 +45,24 @@ assert-css: (".mobile-topbar h2", {"overflow-x": "hidden"})
 
 // Check wrapping for top main-heading h1 and out-of-band.
 // On desktop, they wrap when too big.
-size: (1100, 800)
-goto: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
+set-window-size: (1100, 800)
+go-to: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
 compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y"))
-goto: "file://" + |DOC_PATH| + "/lib2/index.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html"
 compare-elements-position: (".main-heading h1", ".main-heading .out-of-band", ("y"))
 // make sure there is a gap between them
 compare-elements-position-near-false: (".main-heading h1", ".main-heading .out-of-band", {"x": 550})
 
 // On mobile, they always wrap.
-size: (600, 600)
-goto: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
+set-window-size: (600, 600)
+go-to: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
 compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y"))
-goto: "file://" + |DOC_PATH| + "/lib2/index.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/index.html"
 compare-elements-position-false: (".main-heading h1", ".main-heading .out-of-band", ("y"))
 
 // Now we will check that the scrolling is working.
 // First on an item with "hidden methods".
-goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.Iterator.html"
 
 click: ".item-decl .type-contents-toggle"
 assert-property: ("pre.item-decl", {"scrollLeft": 0})
@@ -70,7 +70,7 @@ scroll-to: "//*[@class='rust item-decl']//details/a[text()='String']"
 assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
 
 // Then on an item without "hidden methods".
-goto: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.TraitWithLongItemsName.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/scroll_traits/trait.TraitWithLongItemsName.html"
 assert-property: ("pre.item-decl", {"scrollLeft": 0})
 scroll-to: "//*[@class='rust item-decl']//code/a[text()='String']"
 assert-property-false: ("pre.item-decl", {"scrollLeft": 0})
diff --git a/tests/rustdoc-gui/unsafe-fn.goml b/tests/rustdoc-gui/unsafe-fn.goml
index 9d2577178c0..51007b653d9 100644
--- a/tests/rustdoc-gui/unsafe-fn.goml
+++ b/tests/rustdoc-gui/unsafe-fn.goml
@@ -1,5 +1,5 @@
 // Check position and color of the `<sup>` for unsafe elements.
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 // If the text isn't displayed, the browser doesn't compute color style correctly...
 show-text: true
 
@@ -16,7 +16,7 @@ define-function: (
     (theme, color),
     block {
         // Set the theme.
-        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
         // We reload the page so the local storage settings are being used.
         reload:
         assert-css: (".item-name sup", {"color": |color|})
diff --git a/tests/rustdoc-gui/where-whitespace.goml b/tests/rustdoc-gui/where-whitespace.goml
index 41596a9bccc..69e6c3356a4 100644
--- a/tests/rustdoc-gui/where-whitespace.goml
+++ b/tests/rustdoc-gui/where-whitespace.goml
@@ -1,5 +1,5 @@
 // This test ensures that the where conditions are correctly displayed.
-goto: "file://" + |DOC_PATH| + "/lib2/trait.Whitespace.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/trait.Whitespace.html"
 show-text: true
 // First, we check in the trait definition if the where clause is "on its own" (not on the same
 // line than "pub trait Whitespace<Idx>").
@@ -7,9 +7,9 @@ compare-elements-position-false: (".item-decl code", ".where.fmt-newline", ("y")
 // And that the code following it isn't on the same line either.
 compare-elements-position-false: (".item-decl .fn", ".where.fmt-newline", ("y"))
 
-goto: "file://" + |DOC_PATH| + "/lib2/struct.WhereWhitespace.html"
+go-to: "file://" + |DOC_PATH| + "/lib2/struct.WhereWhitespace.html"
 // We make the screen a bit wider to ensure that the trait impl is on one line.
-size: (915, 915)
+set-window-size: (915, 915)
 
 compare-elements-position-false: ("#method\.new .fn", "#method\.new .where.fmt-newline", ("y"))
 // We ensure that both the trait name and the struct name are on the same line in
diff --git a/tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs b/tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs
new file mode 100644
index 00000000000..6c48f5aa01f
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/auxiliary/inner-crate-enum.rs
@@ -0,0 +1,3 @@
+pub enum O {
+    L = -1,
+}
diff --git a/tests/rustdoc-ui/intra-doc/inline-external-enum.rs b/tests/rustdoc-ui/intra-doc/inline-external-enum.rs
new file mode 100644
index 00000000000..363dd7f64c2
--- /dev/null
+++ b/tests/rustdoc-ui/intra-doc/inline-external-enum.rs
@@ -0,0 +1,8 @@
+// check-pass
+// aux-build: inner-crate-enum.rs
+// compile-flags:-Z unstable-options --output-format json
+
+#[doc(inline)]
+pub extern crate inner_crate_enum;
+
+fn main() {}
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 61724c11745..6cc7bab3726 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -518,7 +518,7 @@ struct BoolField {
     #[help]
     foo: bool,
     #[help(no_crate_help)]
-    //~^ ERROR the `#[help(...)]` attribute can only be applied to fields of type `Span`, `bool` or `()`
+    //~^ ERROR the `#[help(...)]` attribute can only be applied to fields of type
     // only allow plain 'bool' fields
     bar: Option<bool>,
 }
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index cd14c7496b3..a2f3bb5277b 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -323,7 +323,7 @@ error: invalid applicability
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
    |                                                                     ^^^^^^^^
 
-error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `bool` or `()`
+error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()`
   --> $DIR/diagnostic-derive.rs:520:5
    |
 LL |     #[help(no_crate_help)]
diff --git a/tests/ui/argument-suggestions/issue-109831.rs b/tests/ui/argument-suggestions/issue-109831.rs
new file mode 100644
index 00000000000..2e8ae40f630
--- /dev/null
+++ b/tests/ui/argument-suggestions/issue-109831.rs
@@ -0,0 +1,9 @@
+struct A;
+struct B;
+
+fn f(b1: B, b2: B, a2: C) {} //~ ERROR E0412
+
+fn main() {
+    f(A, A, B, C); //~ ERROR E0425
+    //~^ ERROR E0061
+}
diff --git a/tests/ui/argument-suggestions/issue-109831.stderr b/tests/ui/argument-suggestions/issue-109831.stderr
new file mode 100644
index 00000000000..7b9a3c9ef2c
--- /dev/null
+++ b/tests/ui/argument-suggestions/issue-109831.stderr
@@ -0,0 +1,51 @@
+error[E0412]: cannot find type `C` in this scope
+  --> $DIR/issue-109831.rs:4:24
+   |
+LL | struct A;
+   | --------- similarly named struct `A` defined here
+...
+LL | fn f(b1: B, b2: B, a2: C) {}
+   |                        ^
+   |
+help: a struct with a similar name exists
+   |
+LL | fn f(b1: B, b2: B, a2: A) {}
+   |                        ~
+help: you might be missing a type parameter
+   |
+LL | fn f<C>(b1: B, b2: B, a2: C) {}
+   |     +++
+
+error[E0425]: cannot find value `C` in this scope
+  --> $DIR/issue-109831.rs:7:16
+   |
+LL | struct A;
+   | --------- similarly named unit struct `A` defined here
+...
+LL |     f(A, A, B, C);
+   |                ^ help: a unit struct with a similar name exists: `A`
+
+error[E0061]: this function takes 3 arguments but 4 arguments were supplied
+  --> $DIR/issue-109831.rs:7:5
+   |
+LL |     f(A, A, B, C);
+   |     ^ -  -     - unexpected argument
+   |       |  |
+   |       |  expected `B`, found `A`
+   |       expected `B`, found `A`
+   |
+note: function defined here
+  --> $DIR/issue-109831.rs:4:4
+   |
+LL | fn f(b1: B, b2: B, a2: C) {}
+   |    ^ -----  -----  -----
+help: remove the extra argument
+   |
+LL -     f(A, A, B, C);
+LL +     f(/* B */, /* B */, B);
+   |
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0061, E0412, E0425.
+For more information about an error, try `rustc --explain E0061`.
diff --git a/tests/ui/associated-type-bounds/issue-104916.rs b/tests/ui/associated-type-bounds/issue-104916.rs
new file mode 100644
index 00000000000..3361fa011ed
--- /dev/null
+++ b/tests/ui/associated-type-bounds/issue-104916.rs
@@ -0,0 +1,14 @@
+#![feature(associated_type_bounds)]
+
+trait B {
+    type AssocType;
+}
+
+fn f()
+where
+    dyn for<'j> B<AssocType: 'j>:,
+    //~^ ERROR: associated type bounds are only allowed in where clauses and function signatures
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/issue-104916.stderr b/tests/ui/associated-type-bounds/issue-104916.stderr
new file mode 100644
index 00000000000..35435962ffe
--- /dev/null
+++ b/tests/ui/associated-type-bounds/issue-104916.stderr
@@ -0,0 +1,8 @@
+error: associated type bounds are only allowed in where clauses and function signatures, not in bounds
+  --> $DIR/issue-104916.rs:9:19
+   |
+LL |     dyn for<'j> B<AssocType: 'j>:,
+   |                   ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.rs b/tests/ui/associated-types/associated-types-in-ambiguous-context.rs
index 51b53908f98..5d6b1b59181 100644
--- a/tests/ui/associated-types/associated-types-in-ambiguous-context.rs
+++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.rs
@@ -1,3 +1,5 @@
+// normalize-stderr-test: "and \d+ other candidates" -> "and N other candidates"
+
 trait Get {
     type Value;
     fn get(&self) -> <Self as Get>::Value;
diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
index 00856b55df5..1ff6fd4b821 100644
--- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
+++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr
@@ -1,5 +1,5 @@
 error[E0223]: ambiguous associated type
-  --> $DIR/associated-types-in-ambiguous-context.rs:6:36
+  --> $DIR/associated-types-in-ambiguous-context.rs:8:36
    |
 LL | fn get<T:Get,U:Get>(x: T, y: U) -> Get::Value {}
    |                                    ^^^^^^^^^^
@@ -10,30 +10,37 @@ LL | fn get<T:Get,U:Get>(x: T, y: U) -> <Example as Get>::Value {}
    |                                    ~~~~~~~~~~~~~~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
-  --> $DIR/associated-types-in-ambiguous-context.rs:20:17
+  --> $DIR/associated-types-in-ambiguous-context.rs:22:17
    |
 LL | trait Foo where Foo::Assoc: Bar {
    |                 ^^^^^^^^^^ help: use the fully-qualified path: `<Self as Foo>::Assoc`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/associated-types-in-ambiguous-context.rs:25:10
+  --> $DIR/associated-types-in-ambiguous-context.rs:27:10
    |
 LL | type X = std::ops::Deref::Target;
    |          ^^^^^^^^^^^^^^^^^^^^^^^
    |
-help: if there were a type named `Example` that implemented `Deref`, you could use the fully-qualified path
+help: use the fully-qualified path
    |
-LL | type X = <Example as Deref>::Target;
+LL | type X = <CString as Deref>::Target;
    |          ~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | type X = <IoSlice<'_> as Deref>::Target;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | type X = <IoSliceMut<'_> as Deref>::Target;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | type X = <OsString as Deref>::Target;
+   |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+     and N other candidates
 
 error[E0223]: ambiguous associated type
-  --> $DIR/associated-types-in-ambiguous-context.rs:11:23
+  --> $DIR/associated-types-in-ambiguous-context.rs:13:23
    |
 LL |     fn grab(&self) -> Grab::Value;
    |                       ^^^^^^^^^^^ help: use the fully-qualified path: `<Self as Grab>::Value`
 
 error[E0223]: ambiguous associated type
-  --> $DIR/associated-types-in-ambiguous-context.rs:14:22
+  --> $DIR/associated-types-in-ambiguous-context.rs:16:22
    |
 LL |     fn get(&self) -> Get::Value;
    |                      ^^^^^^^^^^
diff --git a/tests/ui/unique/expr-block-generic-unique1.rs b/tests/ui/box/unit/expr-block-generic-unique1.rs
index 14603a2c71f..14603a2c71f 100644
--- a/tests/ui/unique/expr-block-generic-unique1.rs
+++ b/tests/ui/box/unit/expr-block-generic-unique1.rs
diff --git a/tests/ui/unique/expr-block-generic-unique2.rs b/tests/ui/box/unit/expr-block-generic-unique2.rs
index 7879c144b10..7879c144b10 100644
--- a/tests/ui/unique/expr-block-generic-unique2.rs
+++ b/tests/ui/box/unit/expr-block-generic-unique2.rs
diff --git a/tests/ui/unique/expr-if-unique.rs b/tests/ui/box/unit/expr-if-unique.rs
index 86232683549..86232683549 100644
--- a/tests/ui/unique/expr-if-unique.rs
+++ b/tests/ui/box/unit/expr-if-unique.rs
diff --git a/tests/ui/unique/unique-assign-copy.rs b/tests/ui/box/unit/unique-assign-copy.rs
index b742973ce32..b742973ce32 100644
--- a/tests/ui/unique/unique-assign-copy.rs
+++ b/tests/ui/box/unit/unique-assign-copy.rs
diff --git a/tests/ui/unique/unique-assign-drop.rs b/tests/ui/box/unit/unique-assign-drop.rs
index e7685b589ca..e7685b589ca 100644
--- a/tests/ui/unique/unique-assign-drop.rs
+++ b/tests/ui/box/unit/unique-assign-drop.rs
diff --git a/tests/ui/unique/unique-assign-generic.rs b/tests/ui/box/unit/unique-assign-generic.rs
index d4932d8333a..d4932d8333a 100644
--- a/tests/ui/unique/unique-assign-generic.rs
+++ b/tests/ui/box/unit/unique-assign-generic.rs
diff --git a/tests/ui/unique/unique-assign.rs b/tests/ui/box/unit/unique-assign.rs
index d598744f145..d598744f145 100644
--- a/tests/ui/unique/unique-assign.rs
+++ b/tests/ui/box/unit/unique-assign.rs
diff --git a/tests/ui/unique/unique-autoderef-field.rs b/tests/ui/box/unit/unique-autoderef-field.rs
index 64147e11f1c..64147e11f1c 100644
--- a/tests/ui/unique/unique-autoderef-field.rs
+++ b/tests/ui/box/unit/unique-autoderef-field.rs
diff --git a/tests/ui/unique/unique-autoderef-index.rs b/tests/ui/box/unit/unique-autoderef-index.rs
index ea6598a7f6b..ea6598a7f6b 100644
--- a/tests/ui/unique/unique-autoderef-index.rs
+++ b/tests/ui/box/unit/unique-autoderef-index.rs
diff --git a/tests/ui/unique/unique-cmp.rs b/tests/ui/box/unit/unique-cmp.rs
index ee05dd5a31d..ee05dd5a31d 100644
--- a/tests/ui/unique/unique-cmp.rs
+++ b/tests/ui/box/unit/unique-cmp.rs
diff --git a/tests/ui/unique/unique-containing-tag.rs b/tests/ui/box/unit/unique-containing-tag.rs
index 6c31ae99b8e..6c31ae99b8e 100644
--- a/tests/ui/unique/unique-containing-tag.rs
+++ b/tests/ui/box/unit/unique-containing-tag.rs
diff --git a/tests/ui/unique/unique-create.rs b/tests/ui/box/unit/unique-create.rs
index c566e79620a..c566e79620a 100644
--- a/tests/ui/unique/unique-create.rs
+++ b/tests/ui/box/unit/unique-create.rs
diff --git a/tests/ui/unique/unique-decl-init-copy.rs b/tests/ui/box/unit/unique-decl-init-copy.rs
index 5b9576fcc7a..5b9576fcc7a 100644
--- a/tests/ui/unique/unique-decl-init-copy.rs
+++ b/tests/ui/box/unit/unique-decl-init-copy.rs
diff --git a/tests/ui/unique/unique-decl-init.rs b/tests/ui/box/unit/unique-decl-init.rs
index 1d70860c7ce..1d70860c7ce 100644
--- a/tests/ui/unique/unique-decl-init.rs
+++ b/tests/ui/box/unit/unique-decl-init.rs
diff --git a/tests/ui/unique/unique-decl-move.rs b/tests/ui/box/unit/unique-decl-move.rs
index 21187510ff0..21187510ff0 100644
--- a/tests/ui/unique/unique-decl-move.rs
+++ b/tests/ui/box/unit/unique-decl-move.rs
diff --git a/tests/ui/unique/unique-decl.rs b/tests/ui/box/unit/unique-decl.rs
index 84a1b2a5b83..84a1b2a5b83 100644
--- a/tests/ui/unique/unique-decl.rs
+++ b/tests/ui/box/unit/unique-decl.rs
diff --git a/tests/ui/unique/unique-deref.rs b/tests/ui/box/unit/unique-deref.rs
index 33a1e9932b5..33a1e9932b5 100644
--- a/tests/ui/unique/unique-deref.rs
+++ b/tests/ui/box/unit/unique-deref.rs
diff --git a/tests/ui/unique/unique-destructure.rs b/tests/ui/box/unit/unique-destructure.rs
index 7207ac96295..7207ac96295 100644
--- a/tests/ui/unique/unique-destructure.rs
+++ b/tests/ui/box/unit/unique-destructure.rs
diff --git a/tests/ui/unique/unique-drop-complex.rs b/tests/ui/box/unit/unique-drop-complex.rs
index 2324f1e1a65..2324f1e1a65 100644
--- a/tests/ui/unique/unique-drop-complex.rs
+++ b/tests/ui/box/unit/unique-drop-complex.rs
diff --git a/tests/ui/unique/unique-ffi-symbols.rs b/tests/ui/box/unit/unique-ffi-symbols.rs
index 77b5ead2633..77b5ead2633 100644
--- a/tests/ui/unique/unique-ffi-symbols.rs
+++ b/tests/ui/box/unit/unique-ffi-symbols.rs
diff --git a/tests/ui/unique/unique-fn-arg-move.rs b/tests/ui/box/unit/unique-fn-arg-move.rs
index 6d42df218fb..6d42df218fb 100644
--- a/tests/ui/unique/unique-fn-arg-move.rs
+++ b/tests/ui/box/unit/unique-fn-arg-move.rs
diff --git a/tests/ui/unique/unique-fn-arg-mut.rs b/tests/ui/box/unit/unique-fn-arg-mut.rs
index 01510200b11..01510200b11 100644
--- a/tests/ui/unique/unique-fn-arg-mut.rs
+++ b/tests/ui/box/unit/unique-fn-arg-mut.rs
diff --git a/tests/ui/unique/unique-fn-arg.rs b/tests/ui/box/unit/unique-fn-arg.rs
index b4f3bc4b294..b4f3bc4b294 100644
--- a/tests/ui/unique/unique-fn-arg.rs
+++ b/tests/ui/box/unit/unique-fn-arg.rs
diff --git a/tests/ui/unique/unique-fn-ret.rs b/tests/ui/box/unit/unique-fn-ret.rs
index 773a9bce1ad..773a9bce1ad 100644
--- a/tests/ui/unique/unique-fn-ret.rs
+++ b/tests/ui/box/unit/unique-fn-ret.rs
diff --git a/tests/ui/unique/unique-generic-assign.rs b/tests/ui/box/unit/unique-generic-assign.rs
index 9c4405aa8ac..9c4405aa8ac 100644
--- a/tests/ui/unique/unique-generic-assign.rs
+++ b/tests/ui/box/unit/unique-generic-assign.rs
diff --git a/tests/ui/unique/unique-in-tag.rs b/tests/ui/box/unit/unique-in-tag.rs
index 6daa06fb12d..6daa06fb12d 100644
--- a/tests/ui/unique/unique-in-tag.rs
+++ b/tests/ui/box/unit/unique-in-tag.rs
diff --git a/tests/ui/unique/unique-in-vec-copy.rs b/tests/ui/box/unit/unique-in-vec-copy.rs
index ce52d15ef1a..ce52d15ef1a 100644
--- a/tests/ui/unique/unique-in-vec-copy.rs
+++ b/tests/ui/box/unit/unique-in-vec-copy.rs
diff --git a/tests/ui/unique/unique-in-vec.rs b/tests/ui/box/unit/unique-in-vec.rs
index 1e8d05e3d26..1e8d05e3d26 100644
--- a/tests/ui/unique/unique-in-vec.rs
+++ b/tests/ui/box/unit/unique-in-vec.rs
diff --git a/tests/ui/unique/unique-init.rs b/tests/ui/box/unit/unique-init.rs
index d19605046e1..d19605046e1 100644
--- a/tests/ui/unique/unique-init.rs
+++ b/tests/ui/box/unit/unique-init.rs
diff --git a/tests/ui/unique/unique-kinds.rs b/tests/ui/box/unit/unique-kinds.rs
index f02d0b50764..f02d0b50764 100644
--- a/tests/ui/unique/unique-kinds.rs
+++ b/tests/ui/box/unit/unique-kinds.rs
diff --git a/tests/ui/unique/unique-log.rs b/tests/ui/box/unit/unique-log.rs
index 0715d16628f..0715d16628f 100644
--- a/tests/ui/unique/unique-log.rs
+++ b/tests/ui/box/unit/unique-log.rs
diff --git a/tests/ui/unique/unique-match-discrim.rs b/tests/ui/box/unit/unique-match-discrim.rs
index 6e6d7432277..6e6d7432277 100644
--- a/tests/ui/unique/unique-match-discrim.rs
+++ b/tests/ui/box/unit/unique-match-discrim.rs
diff --git a/tests/ui/unique/unique-move-drop.rs b/tests/ui/box/unit/unique-move-drop.rs
index c0f5d8f9053..c0f5d8f9053 100644
--- a/tests/ui/unique/unique-move-drop.rs
+++ b/tests/ui/box/unit/unique-move-drop.rs
diff --git a/tests/ui/unique/unique-move-temp.rs b/tests/ui/box/unit/unique-move-temp.rs
index 103af8e1f1e..103af8e1f1e 100644
--- a/tests/ui/unique/unique-move-temp.rs
+++ b/tests/ui/box/unit/unique-move-temp.rs
diff --git a/tests/ui/unique/unique-move.rs b/tests/ui/box/unit/unique-move.rs
index 40a2718e4e5..40a2718e4e5 100644
--- a/tests/ui/unique/unique-move.rs
+++ b/tests/ui/box/unit/unique-move.rs
diff --git a/tests/ui/unique/unique-mutable.rs b/tests/ui/box/unit/unique-mutable.rs
index 0367c08099a..0367c08099a 100644
--- a/tests/ui/unique/unique-mutable.rs
+++ b/tests/ui/box/unit/unique-mutable.rs
diff --git a/tests/ui/unique/unique-object-move.rs b/tests/ui/box/unit/unique-object-move.rs
index bb35a9b2d73..bb35a9b2d73 100644
--- a/tests/ui/unique/unique-object-move.rs
+++ b/tests/ui/box/unit/unique-object-move.rs
diff --git a/tests/ui/unique/unique-object-noncopyable.rs b/tests/ui/box/unit/unique-object-noncopyable.rs
index 2c40dfc7a4b..2c40dfc7a4b 100644
--- a/tests/ui/unique/unique-object-noncopyable.rs
+++ b/tests/ui/box/unit/unique-object-noncopyable.rs
diff --git a/tests/ui/unique/unique-object-noncopyable.stderr b/tests/ui/box/unit/unique-object-noncopyable.stderr
index db42ed9baf1..db42ed9baf1 100644
--- a/tests/ui/unique/unique-object-noncopyable.stderr
+++ b/tests/ui/box/unit/unique-object-noncopyable.stderr
diff --git a/tests/ui/unique/unique-pat-2.rs b/tests/ui/box/unit/unique-pat-2.rs
index 9c73fd2204c..9c73fd2204c 100644
--- a/tests/ui/unique/unique-pat-2.rs
+++ b/tests/ui/box/unit/unique-pat-2.rs
diff --git a/tests/ui/unique/unique-pat-3.rs b/tests/ui/box/unit/unique-pat-3.rs
index 2e81f898d0c..2e81f898d0c 100644
--- a/tests/ui/unique/unique-pat-3.rs
+++ b/tests/ui/box/unit/unique-pat-3.rs
diff --git a/tests/ui/unique/unique-pat.rs b/tests/ui/box/unit/unique-pat.rs
index c2474d0e772..c2474d0e772 100644
--- a/tests/ui/unique/unique-pat.rs
+++ b/tests/ui/box/unit/unique-pat.rs
diff --git a/tests/ui/unique/unique-pinned-nocopy.rs b/tests/ui/box/unit/unique-pinned-nocopy.rs
index 8edaeef51e0..8edaeef51e0 100644
--- a/tests/ui/unique/unique-pinned-nocopy.rs
+++ b/tests/ui/box/unit/unique-pinned-nocopy.rs
diff --git a/tests/ui/unique/unique-pinned-nocopy.stderr b/tests/ui/box/unit/unique-pinned-nocopy.stderr
index de6611324ca..de6611324ca 100644
--- a/tests/ui/unique/unique-pinned-nocopy.stderr
+++ b/tests/ui/box/unit/unique-pinned-nocopy.stderr
diff --git a/tests/ui/unique/unique-rec.rs b/tests/ui/box/unit/unique-rec.rs
index 9f8ad9bb050..9f8ad9bb050 100644
--- a/tests/ui/unique/unique-rec.rs
+++ b/tests/ui/box/unit/unique-rec.rs
diff --git a/tests/ui/unique/unique-send-2.rs b/tests/ui/box/unit/unique-send-2.rs
index 23ddd2cdca2..23ddd2cdca2 100644
--- a/tests/ui/unique/unique-send-2.rs
+++ b/tests/ui/box/unit/unique-send-2.rs
diff --git a/tests/ui/unique/unique-send.rs b/tests/ui/box/unit/unique-send.rs
index 431cc2be5d2..431cc2be5d2 100644
--- a/tests/ui/unique/unique-send.rs
+++ b/tests/ui/box/unit/unique-send.rs
diff --git a/tests/ui/unique/unique-swap.rs b/tests/ui/box/unit/unique-swap.rs
index 4f33ff9a8a3..4f33ff9a8a3 100644
--- a/tests/ui/unique/unique-swap.rs
+++ b/tests/ui/box/unit/unique-swap.rs
diff --git a/tests/ui/unique/unwind-unique.rs b/tests/ui/box/unit/unwind-unique.rs
index 50ecf751a86..50ecf751a86 100644
--- a/tests/ui/unique/unwind-unique.rs
+++ b/tests/ui/box/unit/unwind-unique.rs
diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr
index 9864aa385f9..5ca4d3b3de7 100644
--- a/tests/ui/check-cfg/compact-values.stderr
+++ b/tests/ui/check-cfg/compact-values.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition value
 LL | #[cfg(target(os = "linux", arch = "X"))]
    |                            ^^^^^^^^^^
    |
-   = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64
+   = note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, loongarch64, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/error-codes/E0449.stderr b/tests/ui/error-codes/E0449.stderr
index 8221a5e0ad6..cf41bcce8c2 100644
--- a/tests/ui/error-codes/E0449.stderr
+++ b/tests/ui/error-codes/E0449.stderr
@@ -1,22 +1,26 @@
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/E0449.rs:7:1
    |
 LL | pub impl Bar {}
-   | ^^^ `pub` not permitted here because it's implied
+   | ^^^
    |
    = note: place qualifiers on individual impl items instead
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/E0449.rs:9:1
    |
 LL | pub impl Foo for Bar {
-   | ^^^ `pub` not permitted here because it's implied
+   | ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/E0449.rs:10:5
    |
 LL |     pub fn foo() {}
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/extenv/extenv-no-args.rs b/tests/ui/extenv/extenv-no-args.rs
index 9f221ed10d7..2ff6d242b27 100644
--- a/tests/ui/extenv/extenv-no-args.rs
+++ b/tests/ui/extenv/extenv-no-args.rs
@@ -1 +1 @@
-fn main() { env!(); } //~ ERROR: env! takes 1 or 2 arguments
+fn main() { env!(); } //~ ERROR: `env!()` takes 1 or 2 arguments
diff --git a/tests/ui/extenv/extenv-no-args.stderr b/tests/ui/extenv/extenv-no-args.stderr
index 318ed635be0..70b85932c23 100644
--- a/tests/ui/extenv/extenv-no-args.stderr
+++ b/tests/ui/extenv/extenv-no-args.stderr
@@ -1,4 +1,4 @@
-error: env! takes 1 or 2 arguments
+error: `env!()` takes 1 or 2 arguments
   --> $DIR/extenv-no-args.rs:1:13
    |
 LL | fn main() { env!(); }
diff --git a/tests/ui/extenv/extenv-too-many-args.rs b/tests/ui/extenv/extenv-too-many-args.rs
index 1adbee583db..ffad1c51303 100644
--- a/tests/ui/extenv/extenv-too-many-args.rs
+++ b/tests/ui/extenv/extenv-too-many-args.rs
@@ -1 +1 @@
-fn main() { env!("one", "two", "three"); } //~ ERROR: env! takes 1 or 2 arguments
+fn main() { env!("one", "two", "three"); } //~ ERROR: `env!()` takes 1 or 2 arguments
diff --git a/tests/ui/extenv/extenv-too-many-args.stderr b/tests/ui/extenv/extenv-too-many-args.stderr
index 54150a3328f..47cf810b70d 100644
--- a/tests/ui/extenv/extenv-too-many-args.stderr
+++ b/tests/ui/extenv/extenv-too-many-args.stderr
@@ -1,4 +1,4 @@
-error: env! takes 1 or 2 arguments
+error: `env!()` takes 1 or 2 arguments
   --> $DIR/extenv-too-many-args.rs:1:13
    |
 LL | fn main() { env!("one", "two", "three"); }
diff --git a/tests/ui/extenv/issue-55897.stderr b/tests/ui/extenv/issue-55897.stderr
index 5752a965e35..401db827813 100644
--- a/tests/ui/extenv/issue-55897.stderr
+++ b/tests/ui/extenv/issue-55897.stderr
@@ -4,7 +4,7 @@ error: environment variable `NON_EXISTENT` not defined at compile time
 LL |     include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
    |                      ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: Use `std::env::var("NON_EXISTENT")` to read the variable at run time
+   = help: use `std::env::var("NON_EXISTENT")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: suffixes on string literals are invalid
diff --git a/tests/ui/issues/issue-28433.rs b/tests/ui/issues/issue-28433.rs
index 8d05c32d5de..2298ad240d5 100644
--- a/tests/ui/issues/issue-28433.rs
+++ b/tests/ui/issues/issue-28433.rs
@@ -1,9 +1,9 @@
 enum Bird {
     pub Duck,
-    //~^ ERROR unnecessary visibility qualifier
+    //~^ ERROR visibility qualifiers are not permitted here
     Goose,
     pub(crate) Dove
-    //~^ ERROR unnecessary visibility qualifier
+    //~^ ERROR visibility qualifiers are not permitted here
 }
 
 
diff --git a/tests/ui/issues/issue-28433.stderr b/tests/ui/issues/issue-28433.stderr
index 9f5f6333602..5fb8a89621c 100644
--- a/tests/ui/issues/issue-28433.stderr
+++ b/tests/ui/issues/issue-28433.stderr
@@ -1,14 +1,18 @@
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/issue-28433.rs:2:5
    |
 LL |     pub Duck,
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: enum variants and their fields always share the visibility of the enum they are in
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/issue-28433.rs:5:5
    |
 LL |     pub(crate) Dove
    |     ^^^^^^^^^^
+   |
+   = note: enum variants and their fields always share the visibility of the enum they are in
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/issues/issue-50403.rs b/tests/ui/issues/issue-50403.rs
index 012057fc280..ab22aff26d9 100644
--- a/tests/ui/issues/issue-50403.rs
+++ b/tests/ui/issues/issue-50403.rs
@@ -1,5 +1,5 @@
 #![feature(concat_idents)]
 
 fn main() {
-    let x = concat_idents!(); //~ ERROR concat_idents! takes 1 or more arguments
+    let x = concat_idents!(); //~ ERROR `concat_idents!()` takes 1 or more arguments
 }
diff --git a/tests/ui/issues/issue-50403.stderr b/tests/ui/issues/issue-50403.stderr
index a3a2ed044db..d50befa5e32 100644
--- a/tests/ui/issues/issue-50403.stderr
+++ b/tests/ui/issues/issue-50403.stderr
@@ -1,4 +1,4 @@
-error: concat_idents! takes 1 or more arguments
+error: `concat_idents!()` takes 1 or more arguments
   --> $DIR/issue-50403.rs:4:13
    |
 LL |     let x = concat_idents!();
diff --git a/tests/ui/macros/concat-bytes-error.stderr b/tests/ui/macros/concat-bytes-error.stderr
index d6cd1a3d178..3f2c64922e3 100644
--- a/tests/ui/macros/concat-bytes-error.stderr
+++ b/tests/ui/macros/concat-bytes-error.stderr
@@ -4,7 +4,7 @@ error: expected a byte literal
 LL |     concat_bytes!(pie);
    |                   ^^^
    |
-   = note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`
+   = note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
 
 error: expected a byte literal
   --> $DIR/concat-bytes-error.rs:5:19
@@ -12,7 +12,7 @@ error: expected a byte literal
 LL |     concat_bytes!(pie, pie);
    |                   ^^^  ^^^
    |
-   = note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`
+   = note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
 
 error: cannot concatenate string literals
   --> $DIR/concat-bytes-error.rs:6:19
@@ -98,7 +98,7 @@ error: expected a byte literal
 LL |         -33,
    |         ^^^
    |
-   = note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`
+   = note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
 
 error: cannot concatenate doubly nested array
   --> $DIR/concat-bytes-error.rs:35:9
@@ -151,7 +151,7 @@ error: expected a byte literal
 LL |     concat_bytes!([pie; 2]);
    |                    ^^^
    |
-   = note: only byte literals (like `b"foo"`, `b's'`, and `[3, 4, 5]`) can be passed to `concat_bytes!()`
+   = note: only byte literals (like `b"foo"`, `b's'` and `[3, 4, 5]`) can be passed to `concat_bytes!()`
 
 error: cannot concatenate float literals
   --> $DIR/concat-bytes-error.rs:46:20
diff --git a/tests/ui/macros/macro-path-prelude-fail-4.stderr b/tests/ui/macros/macro-path-prelude-fail-4.stderr
index dfd6818b678..81c6722b56a 100644
--- a/tests/ui/macros/macro-path-prelude-fail-4.stderr
+++ b/tests/ui/macros/macro-path-prelude-fail-4.stderr
@@ -3,6 +3,14 @@ error: expected derive macro, found built-in attribute `inline`
    |
 LL | #[derive(inline)]
    |          ^^^^^^ not a derive macro
+   |
+help: remove from the surrounding `derive()`
+  --> $DIR/macro-path-prelude-fail-4.rs:1:10
+   |
+LL | #[derive(inline)]
+   |          ^^^^^^
+   = help: add as non-Derive macro
+           `#[inline]`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/macros/macro-path-prelude-fail-5.rs b/tests/ui/macros/macro-path-prelude-fail-5.rs
new file mode 100644
index 00000000000..b82b6bc7878
--- /dev/null
+++ b/tests/ui/macros/macro-path-prelude-fail-5.rs
@@ -0,0 +1,10 @@
+#[derive(Clone, Debug)] // OK
+struct S;
+
+#[derive(Debug, inline)] //~ ERROR expected derive macro, found built-in attribute `inline`
+struct T;
+
+#[derive(inline, Debug)] //~ ERROR expected derive macro, found built-in attribute `inline`
+struct U;
+
+fn main() {}
diff --git a/tests/ui/macros/macro-path-prelude-fail-5.stderr b/tests/ui/macros/macro-path-prelude-fail-5.stderr
new file mode 100644
index 00000000000..105c59db674
--- /dev/null
+++ b/tests/ui/macros/macro-path-prelude-fail-5.stderr
@@ -0,0 +1,30 @@
+error: expected derive macro, found built-in attribute `inline`
+  --> $DIR/macro-path-prelude-fail-5.rs:4:17
+   |
+LL | #[derive(Debug, inline)]
+   |                 ^^^^^^ not a derive macro
+   |
+help: remove from the surrounding `derive()`
+  --> $DIR/macro-path-prelude-fail-5.rs:4:17
+   |
+LL | #[derive(Debug, inline)]
+   |                 ^^^^^^
+   = help: add as non-Derive macro
+           `#[inline]`
+
+error: expected derive macro, found built-in attribute `inline`
+  --> $DIR/macro-path-prelude-fail-5.rs:7:10
+   |
+LL | #[derive(inline, Debug)]
+   |          ^^^^^^ not a derive macro
+   |
+help: remove from the surrounding `derive()`
+  --> $DIR/macro-path-prelude-fail-5.rs:7:10
+   |
+LL | #[derive(inline, Debug)]
+   |          ^^^^^^
+   = help: add as non-Derive macro
+           `#[inline]`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr
index 93fbc9c8a44..ca373ea6cd9 100644
--- a/tests/ui/macros/macros-nonfatal-errors.stderr
+++ b/tests/ui/macros/macros-nonfatal-errors.stderr
@@ -3,36 +3,48 @@ error: the `#[default]` attribute may only be used on unit enum variants
    |
 LL |     #[default]
    |     ^^^^^^^^^^
+   |
+   = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
   --> $DIR/macros-nonfatal-errors.rs:18:36
    |
 LL | struct DefaultInnerAttrTupleStruct(#[default] ());
    |                                    ^^^^^^^^^^
+   |
+   = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
   --> $DIR/macros-nonfatal-errors.rs:22:1
    |
 LL | #[default]
    | ^^^^^^^^^^
+   |
+   = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
   --> $DIR/macros-nonfatal-errors.rs:26:1
    |
 LL | #[default]
    | ^^^^^^^^^^
+   |
+   = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
   --> $DIR/macros-nonfatal-errors.rs:36:11
    |
 LL |     Foo = #[default] 0,
    |           ^^^^^^^^^^
+   |
+   = help: consider a manual implementation of `Default`
 
 error: the `#[default]` attribute may only be used on unit enum variants
   --> $DIR/macros-nonfatal-errors.rs:37:14
    |
 LL |     Bar([u8; #[default] 1]),
    |              ^^^^^^^^^^
+   |
+   = help: consider a manual implementation of `Default`
 
 error: no default declared
   --> $DIR/macros-nonfatal-errors.rs:42:10
@@ -132,7 +144,7 @@ error: asm template must be a string literal
 LL |     asm!(invalid);
    |          ^^^^^^^
 
-error: concat_idents! requires ident args
+error: `concat_idents!()` requires ident args
   --> $DIR/macros-nonfatal-errors.rs:101:5
    |
 LL |     concat_idents!("not", "idents");
@@ -150,7 +162,7 @@ error: expected string literal
 LL |     env!(invalid);
    |          ^^^^^^^
 
-error: env! takes 1 or 2 arguments
+error: `env!()` takes 1 or 2 arguments
   --> $DIR/macros-nonfatal-errors.rs:105:5
    |
 LL |     env!(foo, abr, baz);
@@ -162,7 +174,7 @@ error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at co
 LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: Use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time
+   = help: use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: format argument must be a string literal
diff --git a/tests/ui/parser/assoc-static-semantic-fail.rs b/tests/ui/parser/assoc-static-semantic-fail.rs
index a8759d2090d..403160f1253 100644
--- a/tests/ui/parser/assoc-static-semantic-fail.rs
+++ b/tests/ui/parser/assoc-static-semantic-fail.rs
@@ -31,7 +31,7 @@ trait T {
     //~| ERROR a static item cannot be `default`
     pub(crate) default static TD: u8;
     //~^ ERROR associated `static` items are not allowed
-    //~| ERROR unnecessary visibility qualifier
+    //~| ERROR visibility qualifiers are not permitted here
     //~| ERROR a static item cannot be `default`
 }
 
@@ -47,6 +47,6 @@ impl T for S {
     pub default static TD: u8;
     //~^ ERROR associated `static` items are not allowed
     //~| ERROR associated constant in `impl` without body
-    //~| ERROR unnecessary visibility qualifier
+    //~| ERROR visibility qualifiers are not permitted here
     //~| ERROR a static item cannot be `default`
 }
diff --git a/tests/ui/parser/assoc-static-semantic-fail.stderr b/tests/ui/parser/assoc-static-semantic-fail.stderr
index 8a74f49b95c..8178bd22373 100644
--- a/tests/ui/parser/assoc-static-semantic-fail.stderr
+++ b/tests/ui/parser/assoc-static-semantic-fail.stderr
@@ -134,11 +134,13 @@ LL |     pub(crate) default static ID: u8;
    |                                     |
    |                                     help: provide a definition for the constant: `= <expr>;`
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/assoc-static-semantic-fail.rs:32:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^
+   |
+   = note: trait items always share the visibility of their trait
 
 error: associated constant in `impl` without body
   --> $DIR/assoc-static-semantic-fail.rs:41:5
@@ -156,11 +158,13 @@ LL |     pub default static TD: u8;
    |                              |
    |                              help: provide a definition for the constant: `= <expr>;`
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/assoc-static-semantic-fail.rs:47:5
    |
 LL |     pub default static TD: u8;
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/assoc-static-semantic-fail.rs:3:12
diff --git a/tests/ui/parser/default.rs b/tests/ui/parser/default.rs
index 52338c1f13a..d1058ceb2a1 100644
--- a/tests/ui/parser/default.rs
+++ b/tests/ui/parser/default.rs
@@ -14,7 +14,7 @@ impl Foo for u8 {
 }
 
 impl Foo for u16 {
-    pub default fn foo<T: Default>() -> T { //~ ERROR unnecessary visibility qualifier
+    pub default fn foo<T: Default>() -> T { //~ ERROR visibility qualifiers are not permitted here
         T::default()
     }
 }
diff --git a/tests/ui/parser/default.stderr b/tests/ui/parser/default.stderr
index 37aa48ccf52..e6330f368d9 100644
--- a/tests/ui/parser/default.stderr
+++ b/tests/ui/parser/default.stderr
@@ -17,11 +17,13 @@ LL |     default pub fn foo<T: Default>() -> T { T::default() }
 LL | }
    | - item list ends here
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/default.rs:17:5
    |
 LL |     pub default fn foo<T: Default>() -> T {
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/default.rs:3:12
diff --git a/tests/ui/parser/trait-pub-assoc-const.rs b/tests/ui/parser/trait-pub-assoc-const.rs
index 219ffa309c2..7953e12ecdb 100644
--- a/tests/ui/parser/trait-pub-assoc-const.rs
+++ b/tests/ui/parser/trait-pub-assoc-const.rs
@@ -1,6 +1,6 @@
 trait Foo {
     pub const Foo: u32;
-    //~^ ERROR unnecessary visibility qualifier
+    //~^ ERROR visibility qualifiers are not permitted here
 }
 
 fn main() {}
diff --git a/tests/ui/parser/trait-pub-assoc-const.stderr b/tests/ui/parser/trait-pub-assoc-const.stderr
index efd09a0364e..c14a2f2eea5 100644
--- a/tests/ui/parser/trait-pub-assoc-const.stderr
+++ b/tests/ui/parser/trait-pub-assoc-const.stderr
@@ -1,8 +1,10 @@
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/trait-pub-assoc-const.rs:2:5
    |
 LL |     pub const Foo: u32;
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
 error: aborting due to previous error
 
diff --git a/tests/ui/parser/trait-pub-assoc-ty.rs b/tests/ui/parser/trait-pub-assoc-ty.rs
index a78dfbdcdda..5d9434edc10 100644
--- a/tests/ui/parser/trait-pub-assoc-ty.rs
+++ b/tests/ui/parser/trait-pub-assoc-ty.rs
@@ -1,6 +1,6 @@
 trait Foo {
     pub type Foo;
-    //~^ ERROR unnecessary visibility qualifier
+    //~^ ERROR visibility qualifiers are not permitted here
 }
 
 fn main() {}
diff --git a/tests/ui/parser/trait-pub-assoc-ty.stderr b/tests/ui/parser/trait-pub-assoc-ty.stderr
index e76373f5c5f..7f6e7350ca7 100644
--- a/tests/ui/parser/trait-pub-assoc-ty.stderr
+++ b/tests/ui/parser/trait-pub-assoc-ty.stderr
@@ -1,8 +1,10 @@
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/trait-pub-assoc-ty.rs:2:5
    |
 LL |     pub type Foo;
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
 error: aborting due to previous error
 
diff --git a/tests/ui/parser/trait-pub-method.rs b/tests/ui/parser/trait-pub-method.rs
index 1f6ee028a17..c8f33e782e2 100644
--- a/tests/ui/parser/trait-pub-method.rs
+++ b/tests/ui/parser/trait-pub-method.rs
@@ -1,6 +1,6 @@
 trait Foo {
     pub fn foo();
-    //~^ ERROR unnecessary visibility qualifier
+    //~^ ERROR visibility qualifiers are not permitted here
 }
 
 fn main() {}
diff --git a/tests/ui/parser/trait-pub-method.stderr b/tests/ui/parser/trait-pub-method.stderr
index 0e3fe027cb5..2bf1d468a85 100644
--- a/tests/ui/parser/trait-pub-method.stderr
+++ b/tests/ui/parser/trait-pub-method.stderr
@@ -1,8 +1,10 @@
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/trait-pub-method.rs:2:5
    |
 LL |     pub fn foo();
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
 error: aborting due to previous error
 
diff --git a/tests/ui/privacy/issue-29161.rs b/tests/ui/privacy/issue-29161.rs
index d80405aa856..5c926dee05b 100644
--- a/tests/ui/privacy/issue-29161.rs
+++ b/tests/ui/privacy/issue-29161.rs
@@ -2,7 +2,7 @@ mod a {
     struct A;
 
     impl Default for A {
-        pub fn default() -> A { //~ ERROR unnecessary visibility qualifier
+        pub fn default() -> A { //~ ERROR visibility qualifiers are not permitted here
             A
         }
     }
diff --git a/tests/ui/privacy/issue-29161.stderr b/tests/ui/privacy/issue-29161.stderr
index 7ce95e4b0df..1a6c80499a1 100644
--- a/tests/ui/privacy/issue-29161.stderr
+++ b/tests/ui/privacy/issue-29161.stderr
@@ -1,8 +1,10 @@
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/issue-29161.rs:5:9
    |
 LL |         pub fn default() -> A {
-   |         ^^^ `pub` not permitted here because it's implied
+   |         ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
 error[E0603]: struct `A` is private
   --> $DIR/issue-29161.rs:13:8
diff --git a/tests/ui/privacy/priv-in-bad-locations.rs b/tests/ui/privacy/priv-in-bad-locations.rs
index 76af8c6cde8..32c5b801fda 100644
--- a/tests/ui/privacy/priv-in-bad-locations.rs
+++ b/tests/ui/privacy/priv-in-bad-locations.rs
@@ -1,4 +1,4 @@
-pub extern "C" { //~ ERROR unnecessary visibility qualifier
+pub extern "C" { //~ ERROR visibility qualifiers are not permitted here
     pub fn bar();
 }
 
@@ -8,10 +8,10 @@ trait A {
 
 struct B;
 
-pub impl B {} //~ ERROR unnecessary visibility qualifier
+pub impl B {} //~ ERROR visibility qualifiers are not permitted here
 
-pub impl A for B { //~ ERROR unnecessary visibility qualifier
-    pub fn foo(&self) {} //~ ERROR unnecessary visibility qualifier
+pub impl A for B { //~ ERROR visibility qualifiers are not permitted here
+    pub fn foo(&self) {} //~ ERROR visibility qualifiers are not permitted here
 }
 
 pub fn main() {}
diff --git a/tests/ui/privacy/priv-in-bad-locations.stderr b/tests/ui/privacy/priv-in-bad-locations.stderr
index 75bd2fe47b7..70dab5bfe13 100644
--- a/tests/ui/privacy/priv-in-bad-locations.stderr
+++ b/tests/ui/privacy/priv-in-bad-locations.stderr
@@ -1,30 +1,34 @@
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/priv-in-bad-locations.rs:1:1
    |
 LL | pub extern "C" {
-   | ^^^ `pub` not permitted here because it's implied
+   | ^^^
    |
    = note: place qualifiers on individual foreign items instead
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/priv-in-bad-locations.rs:11:1
    |
 LL | pub impl B {}
-   | ^^^ `pub` not permitted here because it's implied
+   | ^^^
    |
    = note: place qualifiers on individual impl items instead
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/priv-in-bad-locations.rs:13:1
    |
 LL | pub impl A for B {
-   | ^^^ `pub` not permitted here because it's implied
+   | ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/priv-in-bad-locations.rs:14:5
    |
 LL |     pub fn foo(&self) {}
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/privacy/privacy-sanity.rs b/tests/ui/privacy/privacy-sanity.rs
index 8bbf1ab5d1f..6622089dda6 100644
--- a/tests/ui/privacy/privacy-sanity.rs
+++ b/tests/ui/privacy/privacy-sanity.rs
@@ -10,17 +10,17 @@ pub struct S {
 }
 struct Ts(pub u8);
 
-pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
-    pub fn f() {} //~ ERROR unnecessary visibility qualifier
-    pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
-    pub type T = u8; //~ ERROR unnecessary visibility qualifier
+pub impl Tr for S {  //~ ERROR visibility qualifiers are not permitted here
+    pub fn f() {} //~ ERROR visibility qualifiers are not permitted here
+    pub const C: u8 = 0; //~ ERROR visibility qualifiers are not permitted here
+    pub type T = u8; //~ ERROR visibility qualifiers are not permitted here
 }
-pub impl S { //~ ERROR unnecessary visibility qualifier
+pub impl S { //~ ERROR visibility qualifiers are not permitted here
     pub fn f() {}
     pub const C: u8 = 0;
     // pub type T = u8;
 }
-pub extern "C" { //~ ERROR unnecessary visibility qualifier
+pub extern "C" { //~ ERROR visibility qualifiers are not permitted here
     pub fn f();
     pub static St: u8;
 }
@@ -36,17 +36,17 @@ const MAIN: u8 = {
     }
     struct Ts(pub u8);
 
-    pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
-        pub fn f() {} //~ ERROR unnecessary visibility qualifier
-        pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
-        pub type T = u8; //~ ERROR unnecessary visibility qualifier
+    pub impl Tr for S {  //~ ERROR visibility qualifiers are not permitted here
+        pub fn f() {} //~ ERROR visibility qualifiers are not permitted here
+        pub const C: u8 = 0; //~ ERROR visibility qualifiers are not permitted here
+        pub type T = u8; //~ ERROR visibility qualifiers are not permitted here
     }
-    pub impl S { //~ ERROR unnecessary visibility qualifier
+    pub impl S { //~ ERROR visibility qualifiers are not permitted here
         pub fn f() {}
         pub const C: u8 = 0;
         // pub type T = u8;
     }
-    pub extern "C" { //~ ERROR unnecessary visibility qualifier
+    pub extern "C" { //~ ERROR visibility qualifiers are not permitted here
         pub fn f();
         pub static St: u8;
     }
@@ -65,17 +65,17 @@ fn main() {
     }
     struct Ts(pub u8);
 
-    pub impl Tr for S {  //~ ERROR unnecessary visibility qualifier
-        pub fn f() {} //~ ERROR unnecessary visibility qualifier
-        pub const C: u8 = 0; //~ ERROR unnecessary visibility qualifier
-        pub type T = u8; //~ ERROR unnecessary visibility qualifier
+    pub impl Tr for S {  //~ ERROR visibility qualifiers are not permitted here
+        pub fn f() {} //~ ERROR visibility qualifiers are not permitted here
+        pub const C: u8 = 0; //~ ERROR visibility qualifiers are not permitted here
+        pub type T = u8; //~ ERROR visibility qualifiers are not permitted here
     }
-    pub impl S { //~ ERROR unnecessary visibility qualifier
+    pub impl S { //~ ERROR visibility qualifiers are not permitted here
         pub fn f() {}
         pub const C: u8 = 0;
         // pub type T = u8;
     }
-    pub extern "C" { //~ ERROR unnecessary visibility qualifier
+    pub extern "C" { //~ ERROR visibility qualifiers are not permitted here
         pub fn f();
         pub static St: u8;
     }
diff --git a/tests/ui/privacy/privacy-sanity.stderr b/tests/ui/privacy/privacy-sanity.stderr
index c92553fd1a1..a537f8c1901 100644
--- a/tests/ui/privacy/privacy-sanity.stderr
+++ b/tests/ui/privacy/privacy-sanity.stderr
@@ -1,120 +1,144 @@
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:13:1
    |
 LL | pub impl Tr for S {
-   | ^^^ `pub` not permitted here because it's implied
+   | ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:14:5
    |
 LL |     pub fn f() {}
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:15:5
    |
 LL |     pub const C: u8 = 0;
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:16:5
    |
 LL |     pub type T = u8;
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:18:1
    |
 LL | pub impl S {
-   | ^^^ `pub` not permitted here because it's implied
+   | ^^^
    |
    = note: place qualifiers on individual impl items instead
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:23:1
    |
 LL | pub extern "C" {
-   | ^^^ `pub` not permitted here because it's implied
+   | ^^^
    |
    = note: place qualifiers on individual foreign items instead
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:39:5
    |
 LL |     pub impl Tr for S {
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:40:9
    |
 LL |         pub fn f() {}
-   |         ^^^ `pub` not permitted here because it's implied
+   |         ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:41:9
    |
 LL |         pub const C: u8 = 0;
-   |         ^^^ `pub` not permitted here because it's implied
+   |         ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:42:9
    |
 LL |         pub type T = u8;
-   |         ^^^ `pub` not permitted here because it's implied
+   |         ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:44:5
    |
 LL |     pub impl S {
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
    |
    = note: place qualifiers on individual impl items instead
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:49:5
    |
 LL |     pub extern "C" {
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
    |
    = note: place qualifiers on individual foreign items instead
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:68:5
    |
 LL |     pub impl Tr for S {
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:69:9
    |
 LL |         pub fn f() {}
-   |         ^^^ `pub` not permitted here because it's implied
+   |         ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:70:9
    |
 LL |         pub const C: u8 = 0;
-   |         ^^^ `pub` not permitted here because it's implied
+   |         ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:71:9
    |
 LL |         pub type T = u8;
-   |         ^^^ `pub` not permitted here because it's implied
+   |         ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:73:5
    |
 LL |     pub impl S {
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
    |
    = note: place qualifiers on individual impl items instead
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/privacy-sanity.rs:78:5
    |
 LL |     pub extern "C" {
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
    |
    = note: place qualifiers on individual foreign items instead
 
diff --git a/tests/ui/privacy/useless-pub.rs b/tests/ui/privacy/useless-pub.rs
index fde7cd5d89d..e4b671142f9 100644
--- a/tests/ui/privacy/useless-pub.rs
+++ b/tests/ui/privacy/useless-pub.rs
@@ -5,12 +5,12 @@ pub trait E {
 }
 
 impl E for A {
-    pub fn foo(&self) {} //~ ERROR: unnecessary visibility qualifier
+    pub fn foo(&self) {} //~ ERROR: visibility qualifiers are not permitted here
 }
 
 enum Foo {
-    V1 { pub f: i32 }, //~ ERROR unnecessary visibility qualifier
-    V2(pub i32), //~ ERROR unnecessary visibility qualifier
+    V1 { pub f: i32 }, //~ ERROR visibility qualifiers are not permitted here
+    V2(pub i32), //~ ERROR visibility qualifiers are not permitted here
 }
 
 fn main() {}
diff --git a/tests/ui/privacy/useless-pub.stderr b/tests/ui/privacy/useless-pub.stderr
index 14c4983ae29..73497e3fed5 100644
--- a/tests/ui/privacy/useless-pub.stderr
+++ b/tests/ui/privacy/useless-pub.stderr
@@ -1,20 +1,26 @@
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/useless-pub.rs:8:5
    |
 LL |     pub fn foo(&self) {}
-   |     ^^^ `pub` not permitted here because it's implied
+   |     ^^^
+   |
+   = note: trait items always share the visibility of their trait
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/useless-pub.rs:12:10
    |
 LL |     V1 { pub f: i32 },
-   |          ^^^ `pub` not permitted here because it's implied
+   |          ^^^
+   |
+   = note: enum variants and their fields always share the visibility of the enum they are in
 
-error[E0449]: unnecessary visibility qualifier
+error[E0449]: visibility qualifiers are not permitted here
   --> $DIR/useless-pub.rs:13:8
    |
 LL |     V2(pub i32),
-   |        ^^^ `pub` not permitted here because it's implied
+   |        ^^^
+   |
+   = note: enum variants and their fields always share the visibility of the enum they are in
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/proc-macro/macro-namespace-reserved-2.stderr b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr
index 633a6c6a0d3..b9effe7cf21 100644
--- a/tests/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/tests/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -57,6 +57,14 @@ error: expected derive macro, found attribute macro `my_macro_attr`
    |
 LL | #[derive(my_macro_attr)]
    |          ^^^^^^^^^^^^^ not a derive macro
+   |
+help: remove from the surrounding `derive()`
+  --> $DIR/macro-namespace-reserved-2.rs:53:10
+   |
+LL | #[derive(my_macro_attr)]
+   |          ^^^^^^^^^^^^^
+   = help: add as non-Derive macro
+           `#[my_macro_attr]`
 
 error: can't use a procedural macro from the same crate that defines it
   --> $DIR/macro-namespace-reserved-2.rs:56:10
@@ -87,6 +95,14 @@ error: expected derive macro, found macro `crate::my_macro`
    |
 LL | #[derive(crate::my_macro)]
    |          ^^^^^^^^^^^^^^^ not a derive macro
+   |
+help: remove from the surrounding `derive()`
+  --> $DIR/macro-namespace-reserved-2.rs:50:10
+   |
+LL | #[derive(crate::my_macro)]
+   |          ^^^^^^^^^^^^^^^
+   = help: add as non-Derive macro
+           `#[crate::my_macro]`
 
 error: cannot find macro `my_macro_attr` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:28:5
diff --git a/tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr b/tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr
index 6d0f826e621..06696b548d4 100644
--- a/tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr
+++ b/tests/ui/tool-attributes/tool-attributes-misplaced-2.stderr
@@ -3,6 +3,14 @@ error: expected derive macro, found tool attribute `rustfmt::skip`
    |
 LL | #[derive(rustfmt::skip)]
    |          ^^^^^^^^^^^^^ not a derive macro
+   |
+help: remove from the surrounding `derive()`
+  --> $DIR/tool-attributes-misplaced-2.rs:1:10
+   |
+LL | #[derive(rustfmt::skip)]
+   |          ^^^^^^^^^^^^^
+   = help: add as non-Derive macro
+           `#[rustfmt::skip]`
 
 error: expected macro, found tool attribute `rustfmt::skip`
   --> $DIR/tool-attributes-misplaced-2.rs:5:5
diff --git a/tests/ui/traits/new-solver/int-var-is-send.rs b/tests/ui/traits/new-solver/int-var-is-send.rs
new file mode 100644
index 00000000000..083aa90e1f6
--- /dev/null
+++ b/tests/ui/traits/new-solver/int-var-is-send.rs
@@ -0,0 +1,8 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+fn needs_send(_: impl Send) {}
+
+fn main() {
+    needs_send(1);
+}
diff --git a/tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr b/tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr
new file mode 100644
index 00000000000..a3ab7836c19
--- /dev/null
+++ b/tests/ui/traits/new-solver/stall-num-var-auto-trait.fallback.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/stall-num-var-auto-trait.rs:18:15
+   |
+LL |     needs_foo(x);
+   |     --------- ^ the trait `Foo` is not implemented for `i32`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `needs_foo`
+  --> $DIR/stall-num-var-auto-trait.rs:14:22
+   |
+LL | fn needs_foo(x: impl Foo) {}
+   |                      ^^^ required by this bound in `needs_foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/new-solver/stall-num-var-auto-trait.rs b/tests/ui/traits/new-solver/stall-num-var-auto-trait.rs
new file mode 100644
index 00000000000..0539c3a4292
--- /dev/null
+++ b/tests/ui/traits/new-solver/stall-num-var-auto-trait.rs
@@ -0,0 +1,25 @@
+// compile-flags: -Ztrait-solver=next
+// revisions: fallback constrain
+//[constrain] check-pass
+
+// Tests that we stall the `{integer}: Foo` obligation until after we
+// constrain the int type (or fallback occurs).
+
+#![feature(negative_impls, auto_traits)]
+
+auto trait Foo {}
+
+impl !Foo for i32 {}
+
+fn needs_foo(x: impl Foo) {}
+
+fn main() {
+    let mut x = 0;
+    needs_foo(x);
+    //[fallback]~^ ERROR the trait bound `i32: Foo` is not satisfied
+
+    #[cfg(constrain)]
+    {
+        x = 1u64;
+    }
+}
diff --git a/tests/ui/transmutability/primitives/bool.stderr b/tests/ui/transmutability/primitives/bool.current.stderr
index 22decf15e54..999302224ee 100644
--- a/tests/ui/transmutability/primitives/bool.stderr
+++ b/tests/ui/transmutability/primitives/bool.current.stderr
@@ -1,12 +1,12 @@
 error[E0277]: `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
-  --> $DIR/bool.rs:22:35
+  --> $DIR/bool.rs:24:35
    |
 LL |     assert::is_transmutable::<u8, bool>();
    |                                   ^^^^ `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `bool`
 note: required by a bound in `is_transmutable`
-  --> $DIR/bool.rs:12:14
+  --> $DIR/bool.rs:14:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
diff --git a/tests/ui/transmutability/primitives/bool.next.stderr b/tests/ui/transmutability/primitives/bool.next.stderr
new file mode 100644
index 00000000000..999302224ee
--- /dev/null
+++ b/tests/ui/transmutability/primitives/bool.next.stderr
@@ -0,0 +1,19 @@
+error[E0277]: `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
+  --> $DIR/bool.rs:24:35
+   |
+LL |     assert::is_transmutable::<u8, bool>();
+   |                                   ^^^^ `u8` cannot be safely transmuted into `bool` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: true, validity: false }>` is not implemented for `bool`
+note: required by a bound in `is_transmutable`
+  --> $DIR/bool.rs:14:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context, { Assume::SAFETY }>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/transmutability/primitives/bool.rs b/tests/ui/transmutability/primitives/bool.rs
index eebb74fff47..de77cfc78aa 100644
--- a/tests/ui/transmutability/primitives/bool.rs
+++ b/tests/ui/transmutability/primitives/bool.rs
@@ -1,8 +1,10 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
 #![crate_type = "lib"]
 #![feature(transmutability)]
 #![allow(dead_code)]
 #![allow(incomplete_features)]
-
 mod assert {
     use std::mem::{Assume, BikeshedIntrinsicFrom};
     pub struct Context;
diff --git a/tests/ui/transmutability/primitives/numbers.stderr b/tests/ui/transmutability/primitives/numbers.current.stderr
index c04a0e82aa2..bbf1f166999 100644
--- a/tests/ui/transmutability/primitives/numbers.stderr
+++ b/tests/ui/transmutability/primitives/numbers.current.stderr
@@ -1,12 +1,12 @@
 error[E0277]: `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:62:40
+  --> $DIR/numbers.rs:65:40
    |
 LL |     assert::is_transmutable::<   i8,   i16>();
    |                                        ^^^ `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -15,14 +15,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:63:40
+  --> $DIR/numbers.rs:66:40
    |
 LL |     assert::is_transmutable::<   i8,   u16>();
    |                                        ^^^ `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -31,14 +31,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:64:40
+  --> $DIR/numbers.rs:67:40
    |
 LL |     assert::is_transmutable::<   i8,   i32>();
    |                                        ^^^ `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -47,14 +47,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:65:40
+  --> $DIR/numbers.rs:68:40
    |
 LL |     assert::is_transmutable::<   i8,   f32>();
    |                                        ^^^ `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -63,14 +63,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:66:40
+  --> $DIR/numbers.rs:69:40
    |
 LL |     assert::is_transmutable::<   i8,   u32>();
    |                                        ^^^ `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -79,14 +79,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:67:40
+  --> $DIR/numbers.rs:70:40
    |
 LL |     assert::is_transmutable::<   i8,   u64>();
    |                                        ^^^ `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -95,14 +95,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:68:40
+  --> $DIR/numbers.rs:71:40
    |
 LL |     assert::is_transmutable::<   i8,   i64>();
    |                                        ^^^ `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -111,14 +111,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:69:40
+  --> $DIR/numbers.rs:72:40
    |
 LL |     assert::is_transmutable::<   i8,   f64>();
    |                                        ^^^ `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -127,14 +127,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:70:39
+  --> $DIR/numbers.rs:73:39
    |
 LL |     assert::is_transmutable::<   i8,  u128>();
    |                                       ^^^^ `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -143,14 +143,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:71:39
+  --> $DIR/numbers.rs:74:39
    |
 LL |     assert::is_transmutable::<   i8,  i128>();
    |                                       ^^^^ `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -159,14 +159,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:73:40
+  --> $DIR/numbers.rs:76:40
    |
 LL |     assert::is_transmutable::<   u8,   i16>();
    |                                        ^^^ `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -175,14 +175,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:74:40
+  --> $DIR/numbers.rs:77:40
    |
 LL |     assert::is_transmutable::<   u8,   u16>();
    |                                        ^^^ `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -191,14 +191,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:75:40
+  --> $DIR/numbers.rs:78:40
    |
 LL |     assert::is_transmutable::<   u8,   i32>();
    |                                        ^^^ `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -207,14 +207,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:76:40
+  --> $DIR/numbers.rs:79:40
    |
 LL |     assert::is_transmutable::<   u8,   f32>();
    |                                        ^^^ `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -223,14 +223,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:77:40
+  --> $DIR/numbers.rs:80:40
    |
 LL |     assert::is_transmutable::<   u8,   u32>();
    |                                        ^^^ `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -239,14 +239,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:78:40
+  --> $DIR/numbers.rs:81:40
    |
 LL |     assert::is_transmutable::<   u8,   u64>();
    |                                        ^^^ `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -255,14 +255,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:79:40
+  --> $DIR/numbers.rs:82:40
    |
 LL |     assert::is_transmutable::<   u8,   i64>();
    |                                        ^^^ `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -271,14 +271,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:80:40
+  --> $DIR/numbers.rs:83:40
    |
 LL |     assert::is_transmutable::<   u8,   f64>();
    |                                        ^^^ `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -287,14 +287,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:81:39
+  --> $DIR/numbers.rs:84:39
    |
 LL |     assert::is_transmutable::<   u8,  u128>();
    |                                       ^^^^ `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -303,14 +303,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:82:39
+  --> $DIR/numbers.rs:85:39
    |
 LL |     assert::is_transmutable::<   u8,  i128>();
    |                                       ^^^^ `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -319,14 +319,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:84:40
+  --> $DIR/numbers.rs:87:40
    |
 LL |     assert::is_transmutable::<  i16,   i32>();
    |                                        ^^^ `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -335,14 +335,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:85:40
+  --> $DIR/numbers.rs:88:40
    |
 LL |     assert::is_transmutable::<  i16,   f32>();
    |                                        ^^^ `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -351,14 +351,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:86:40
+  --> $DIR/numbers.rs:89:40
    |
 LL |     assert::is_transmutable::<  i16,   u32>();
    |                                        ^^^ `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -367,14 +367,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:87:40
+  --> $DIR/numbers.rs:90:40
    |
 LL |     assert::is_transmutable::<  i16,   u64>();
    |                                        ^^^ `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -383,14 +383,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:88:40
+  --> $DIR/numbers.rs:91:40
    |
 LL |     assert::is_transmutable::<  i16,   i64>();
    |                                        ^^^ `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -399,14 +399,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:89:40
+  --> $DIR/numbers.rs:92:40
    |
 LL |     assert::is_transmutable::<  i16,   f64>();
    |                                        ^^^ `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -415,14 +415,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:90:39
+  --> $DIR/numbers.rs:93:39
    |
 LL |     assert::is_transmutable::<  i16,  u128>();
    |                                       ^^^^ `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -431,14 +431,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:91:39
+  --> $DIR/numbers.rs:94:39
    |
 LL |     assert::is_transmutable::<  i16,  i128>();
    |                                       ^^^^ `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -447,14 +447,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:93:40
+  --> $DIR/numbers.rs:96:40
    |
 LL |     assert::is_transmutable::<  u16,   i32>();
    |                                        ^^^ `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -463,14 +463,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:94:40
+  --> $DIR/numbers.rs:97:40
    |
 LL |     assert::is_transmutable::<  u16,   f32>();
    |                                        ^^^ `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -479,14 +479,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:95:40
+  --> $DIR/numbers.rs:98:40
    |
 LL |     assert::is_transmutable::<  u16,   u32>();
    |                                        ^^^ `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -495,14 +495,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:96:40
+  --> $DIR/numbers.rs:99:40
    |
 LL |     assert::is_transmutable::<  u16,   u64>();
    |                                        ^^^ `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -511,14 +511,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:97:40
+  --> $DIR/numbers.rs:100:40
    |
 LL |     assert::is_transmutable::<  u16,   i64>();
    |                                        ^^^ `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -527,14 +527,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:98:40
+  --> $DIR/numbers.rs:101:40
    |
 LL |     assert::is_transmutable::<  u16,   f64>();
    |                                        ^^^ `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -543,14 +543,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:99:39
+  --> $DIR/numbers.rs:102:39
    |
 LL |     assert::is_transmutable::<  u16,  u128>();
    |                                       ^^^^ `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -559,14 +559,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:100:39
+  --> $DIR/numbers.rs:103:39
    |
 LL |     assert::is_transmutable::<  u16,  i128>();
    |                                       ^^^^ `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -575,14 +575,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:102:40
+  --> $DIR/numbers.rs:105:40
    |
 LL |     assert::is_transmutable::<  i32,   u64>();
    |                                        ^^^ `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -591,14 +591,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:103:40
+  --> $DIR/numbers.rs:106:40
    |
 LL |     assert::is_transmutable::<  i32,   i64>();
    |                                        ^^^ `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -607,14 +607,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:104:40
+  --> $DIR/numbers.rs:107:40
    |
 LL |     assert::is_transmutable::<  i32,   f64>();
    |                                        ^^^ `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -623,14 +623,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:105:39
+  --> $DIR/numbers.rs:108:39
    |
 LL |     assert::is_transmutable::<  i32,  u128>();
    |                                       ^^^^ `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -639,14 +639,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:106:39
+  --> $DIR/numbers.rs:109:39
    |
 LL |     assert::is_transmutable::<  i32,  i128>();
    |                                       ^^^^ `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -655,14 +655,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:108:40
+  --> $DIR/numbers.rs:111:40
    |
 LL |     assert::is_transmutable::<  f32,   u64>();
    |                                        ^^^ `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -671,14 +671,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:109:40
+  --> $DIR/numbers.rs:112:40
    |
 LL |     assert::is_transmutable::<  f32,   i64>();
    |                                        ^^^ `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -687,14 +687,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:110:40
+  --> $DIR/numbers.rs:113:40
    |
 LL |     assert::is_transmutable::<  f32,   f64>();
    |                                        ^^^ `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -703,14 +703,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:111:39
+  --> $DIR/numbers.rs:114:39
    |
 LL |     assert::is_transmutable::<  f32,  u128>();
    |                                       ^^^^ `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -719,14 +719,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:112:39
+  --> $DIR/numbers.rs:115:39
    |
 LL |     assert::is_transmutable::<  f32,  i128>();
    |                                       ^^^^ `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -735,14 +735,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:114:40
+  --> $DIR/numbers.rs:117:40
    |
 LL |     assert::is_transmutable::<  u32,   u64>();
    |                                        ^^^ `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -751,14 +751,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:115:40
+  --> $DIR/numbers.rs:118:40
    |
 LL |     assert::is_transmutable::<  u32,   i64>();
    |                                        ^^^ `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -767,14 +767,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:116:40
+  --> $DIR/numbers.rs:119:40
    |
 LL |     assert::is_transmutable::<  u32,   f64>();
    |                                        ^^^ `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -783,14 +783,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:117:39
+  --> $DIR/numbers.rs:120:39
    |
 LL |     assert::is_transmutable::<  u32,  u128>();
    |                                       ^^^^ `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -799,14 +799,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:118:39
+  --> $DIR/numbers.rs:121:39
    |
 LL |     assert::is_transmutable::<  u32,  i128>();
    |                                       ^^^^ `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -815,14 +815,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:120:39
+  --> $DIR/numbers.rs:123:39
    |
 LL |     assert::is_transmutable::<  u64,  u128>();
    |                                       ^^^^ `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -831,14 +831,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:121:39
+  --> $DIR/numbers.rs:124:39
    |
 LL |     assert::is_transmutable::<  u64,  i128>();
    |                                       ^^^^ `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -847,14 +847,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:123:39
+  --> $DIR/numbers.rs:126:39
    |
 LL |     assert::is_transmutable::<  i64,  u128>();
    |                                       ^^^^ `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -863,14 +863,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:124:39
+  --> $DIR/numbers.rs:127:39
    |
 LL |     assert::is_transmutable::<  i64,  i128>();
    |                                       ^^^^ `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -879,14 +879,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:126:39
+  --> $DIR/numbers.rs:129:39
    |
 LL |     assert::is_transmutable::<  f64,  u128>();
    |                                       ^^^^ `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -895,14 +895,14 @@ LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
-  --> $DIR/numbers.rs:127:39
+  --> $DIR/numbers.rs:130:39
    |
 LL |     assert::is_transmutable::<  f64,  i128>();
    |                                       ^^^^ `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:12:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
diff --git a/tests/ui/transmutability/primitives/numbers.next.stderr b/tests/ui/transmutability/primitives/numbers.next.stderr
new file mode 100644
index 00000000000..bbf1f166999
--- /dev/null
+++ b/tests/ui/transmutability/primitives/numbers.next.stderr
@@ -0,0 +1,915 @@
+error[E0277]: `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:65:40
+   |
+LL |     assert::is_transmutable::<   i8,   i16>();
+   |                                        ^^^ `i8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:66:40
+   |
+LL |     assert::is_transmutable::<   i8,   u16>();
+   |                                        ^^^ `i8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:67:40
+   |
+LL |     assert::is_transmutable::<   i8,   i32>();
+   |                                        ^^^ `i8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:68:40
+   |
+LL |     assert::is_transmutable::<   i8,   f32>();
+   |                                        ^^^ `i8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:69:40
+   |
+LL |     assert::is_transmutable::<   i8,   u32>();
+   |                                        ^^^ `i8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:70:40
+   |
+LL |     assert::is_transmutable::<   i8,   u64>();
+   |                                        ^^^ `i8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:71:40
+   |
+LL |     assert::is_transmutable::<   i8,   i64>();
+   |                                        ^^^ `i8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:72:40
+   |
+LL |     assert::is_transmutable::<   i8,   f64>();
+   |                                        ^^^ `i8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:73:39
+   |
+LL |     assert::is_transmutable::<   i8,  u128>();
+   |                                       ^^^^ `i8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:74:39
+   |
+LL |     assert::is_transmutable::<   i8,  i128>();
+   |                                       ^^^^ `i8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:76:40
+   |
+LL |     assert::is_transmutable::<   u8,   i16>();
+   |                                        ^^^ `u8` cannot be safely transmuted into `i16` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i16`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:77:40
+   |
+LL |     assert::is_transmutable::<   u8,   u16>();
+   |                                        ^^^ `u8` cannot be safely transmuted into `u16` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u16`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:78:40
+   |
+LL |     assert::is_transmutable::<   u8,   i32>();
+   |                                        ^^^ `u8` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:79:40
+   |
+LL |     assert::is_transmutable::<   u8,   f32>();
+   |                                        ^^^ `u8` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:80:40
+   |
+LL |     assert::is_transmutable::<   u8,   u32>();
+   |                                        ^^^ `u8` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:81:40
+   |
+LL |     assert::is_transmutable::<   u8,   u64>();
+   |                                        ^^^ `u8` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:82:40
+   |
+LL |     assert::is_transmutable::<   u8,   i64>();
+   |                                        ^^^ `u8` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:83:40
+   |
+LL |     assert::is_transmutable::<   u8,   f64>();
+   |                                        ^^^ `u8` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:84:39
+   |
+LL |     assert::is_transmutable::<   u8,  u128>();
+   |                                       ^^^^ `u8` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:85:39
+   |
+LL |     assert::is_transmutable::<   u8,  i128>();
+   |                                       ^^^^ `u8` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u8, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:87:40
+   |
+LL |     assert::is_transmutable::<  i16,   i32>();
+   |                                        ^^^ `i16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:88:40
+   |
+LL |     assert::is_transmutable::<  i16,   f32>();
+   |                                        ^^^ `i16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:89:40
+   |
+LL |     assert::is_transmutable::<  i16,   u32>();
+   |                                        ^^^ `i16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:90:40
+   |
+LL |     assert::is_transmutable::<  i16,   u64>();
+   |                                        ^^^ `i16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:91:40
+   |
+LL |     assert::is_transmutable::<  i16,   i64>();
+   |                                        ^^^ `i16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:92:40
+   |
+LL |     assert::is_transmutable::<  i16,   f64>();
+   |                                        ^^^ `i16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:93:39
+   |
+LL |     assert::is_transmutable::<  i16,  u128>();
+   |                                       ^^^^ `i16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:94:39
+   |
+LL |     assert::is_transmutable::<  i16,  i128>();
+   |                                       ^^^^ `i16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:96:40
+   |
+LL |     assert::is_transmutable::<  u16,   i32>();
+   |                                        ^^^ `u16` cannot be safely transmuted into `i32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:97:40
+   |
+LL |     assert::is_transmutable::<  u16,   f32>();
+   |                                        ^^^ `u16` cannot be safely transmuted into `f32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:98:40
+   |
+LL |     assert::is_transmutable::<  u16,   u32>();
+   |                                        ^^^ `u16` cannot be safely transmuted into `u32` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u32`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:99:40
+   |
+LL |     assert::is_transmutable::<  u16,   u64>();
+   |                                        ^^^ `u16` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:100:40
+   |
+LL |     assert::is_transmutable::<  u16,   i64>();
+   |                                        ^^^ `u16` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:101:40
+   |
+LL |     assert::is_transmutable::<  u16,   f64>();
+   |                                        ^^^ `u16` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:102:39
+   |
+LL |     assert::is_transmutable::<  u16,  u128>();
+   |                                       ^^^^ `u16` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:103:39
+   |
+LL |     assert::is_transmutable::<  u16,  i128>();
+   |                                       ^^^^ `u16` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u16, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:105:40
+   |
+LL |     assert::is_transmutable::<  i32,   u64>();
+   |                                        ^^^ `i32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:106:40
+   |
+LL |     assert::is_transmutable::<  i32,   i64>();
+   |                                        ^^^ `i32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:107:40
+   |
+LL |     assert::is_transmutable::<  i32,   f64>();
+   |                                        ^^^ `i32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:108:39
+   |
+LL |     assert::is_transmutable::<  i32,  u128>();
+   |                                       ^^^^ `i32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:109:39
+   |
+LL |     assert::is_transmutable::<  i32,  i128>();
+   |                                       ^^^^ `i32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:111:40
+   |
+LL |     assert::is_transmutable::<  f32,   u64>();
+   |                                        ^^^ `f32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:112:40
+   |
+LL |     assert::is_transmutable::<  f32,   i64>();
+   |                                        ^^^ `f32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:113:40
+   |
+LL |     assert::is_transmutable::<  f32,   f64>();
+   |                                        ^^^ `f32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:114:39
+   |
+LL |     assert::is_transmutable::<  f32,  u128>();
+   |                                       ^^^^ `f32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:115:39
+   |
+LL |     assert::is_transmutable::<  f32,  i128>();
+   |                                       ^^^^ `f32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<f32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:117:40
+   |
+LL |     assert::is_transmutable::<  u32,   u64>();
+   |                                        ^^^ `u32` cannot be safely transmuted into `u64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:118:40
+   |
+LL |     assert::is_transmutable::<  u32,   i64>();
+   |                                        ^^^ `u32` cannot be safely transmuted into `i64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:119:40
+   |
+LL |     assert::is_transmutable::<  u32,   f64>();
+   |                                        ^^^ `u32` cannot be safely transmuted into `f64` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `f64`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:120:39
+   |
+LL |     assert::is_transmutable::<  u32,  u128>();
+   |                                       ^^^^ `u32` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:121:39
+   |
+LL |     assert::is_transmutable::<  u32,  i128>();
+   |                                       ^^^^ `u32` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u32, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:123:39
+   |
+LL |     assert::is_transmutable::<  u64,  u128>();
+   |                                       ^^^^ `u64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:124:39
+   |
+LL |     assert::is_transmutable::<  u64,  i128>();
+   |                                       ^^^^ `u64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<u64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:126:39
+   |
+LL |     assert::is_transmutable::<  i64,  u128>();
+   |                                       ^^^^ `i64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:127:39
+   |
+LL |     assert::is_transmutable::<  i64,  i128>();
+   |                                       ^^^^ `i64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<i64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:129:39
+   |
+LL |     assert::is_transmutable::<  f64,  u128>();
+   |                                       ^^^^ `f64` cannot be safely transmuted into `u128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `u128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error[E0277]: `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+  --> $DIR/numbers.rs:130:39
+   |
+LL |     assert::is_transmutable::<  f64,  i128>();
+   |                                       ^^^^ `f64` cannot be safely transmuted into `i128` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<f64, assert::Context, Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `i128`
+note: required by a bound in `is_transmutable`
+  --> $DIR/numbers.rs:15:14
+   |
+LL |     pub fn is_transmutable<Src, Dst>()
+   |            --------------- required by a bound in this function
+LL |     where
+LL |         Dst: BikeshedIntrinsicFrom<Src, Context>
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
+
+error: aborting due to 57 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/transmutability/primitives/numbers.rs b/tests/ui/transmutability/primitives/numbers.rs
index 0df43d2045f..e980e91ed06 100644
--- a/tests/ui/transmutability/primitives/numbers.rs
+++ b/tests/ui/transmutability/primitives/numbers.rs
@@ -1,3 +1,6 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
 #![crate_type = "lib"]
 #![feature(transmutability)]
 #![allow(dead_code)]
diff --git a/tests/ui/transmutability/primitives/unit.stderr b/tests/ui/transmutability/primitives/unit.current.stderr
index 988cd33b3bf..c20355e16f5 100644
--- a/tests/ui/transmutability/primitives/unit.stderr
+++ b/tests/ui/transmutability/primitives/unit.current.stderr
@@ -1,12 +1,12 @@
 error[E0277]: `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`.
-  --> $DIR/unit.rs:28:35
+  --> $DIR/unit.rs:31:35
    |
 LL |     assert::is_transmutable::<(), u8, Context>();
    |                                   ^^ `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<(), should_have_correct_size::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u8`
 note: required by a bound in `is_transmutable`
-  --> $DIR/unit.rs:12:14
+  --> $DIR/unit.rs:15:14
    |
 LL |       pub fn is_transmutable<Src, Dst, Context>()
    |              --------------- required by a bound in this function
diff --git a/tests/ui/transmutability/primitives/unit.next.stderr b/tests/ui/transmutability/primitives/unit.next.stderr
new file mode 100644
index 00000000000..c20355e16f5
--- /dev/null
+++ b/tests/ui/transmutability/primitives/unit.next.stderr
@@ -0,0 +1,25 @@
+error[E0277]: `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`.
+  --> $DIR/unit.rs:31:35
+   |
+LL |     assert::is_transmutable::<(), u8, Context>();
+   |                                   ^^ `()` cannot be safely transmuted into `u8` in the defining scope of `should_have_correct_size::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<(), should_have_correct_size::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `u8`
+note: required by a bound in `is_transmutable`
+  --> $DIR/unit.rs:15:14
+   |
+LL |       pub fn is_transmutable<Src, Dst, Context>()
+   |              --------------- required by a bound in this function
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume::ALIGNMENT
+LL | |                 .and(Assume::LIFETIMES)
+LL | |                 .and(Assume::SAFETY)
+LL | |                 .and(Assume::VALIDITY)
+LL | |         }>
+   | |__________^ required by this bound in `is_transmutable`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/transmutability/primitives/unit.rs b/tests/ui/transmutability/primitives/unit.rs
index 1975a61de98..12eac175106 100644
--- a/tests/ui/transmutability/primitives/unit.rs
+++ b/tests/ui/transmutability/primitives/unit.rs
@@ -1,3 +1,6 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
 //! The unit type, `()`, should be one byte.
 
 #![crate_type = "lib"]
diff --git a/tests/ui/transmutability/references.stderr b/tests/ui/transmutability/references.current.stderr
index eb3bd03fd31..39d42cc4fa6 100644
--- a/tests/ui/transmutability/references.stderr
+++ b/tests/ui/transmutability/references.current.stderr
@@ -1,12 +1,12 @@
 error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
-  --> $DIR/references.rs:26:52
+  --> $DIR/references.rs:29:52
    |
 LL |     assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
    |                                                    ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `&'static Unit`
 note: required by a bound in `is_maybe_transmutable`
-  --> $DIR/references.rs:13:14
+  --> $DIR/references.rs:16:14
    |
 LL |       pub fn is_maybe_transmutable<Src, Dst>()
    |              --------------------- required by a bound in this function
diff --git a/tests/ui/transmutability/references.next.stderr b/tests/ui/transmutability/references.next.stderr
new file mode 100644
index 00000000000..39d42cc4fa6
--- /dev/null
+++ b/tests/ui/transmutability/references.next.stderr
@@ -0,0 +1,26 @@
+error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
+  --> $DIR/references.rs:29:52
+   |
+LL |     assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
+   |                                                    ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
+   |
+   = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `&'static Unit`
+note: required by a bound in `is_maybe_transmutable`
+  --> $DIR/references.rs:16:14
+   |
+LL |       pub fn is_maybe_transmutable<Src, Dst>()
+   |              --------------------- required by a bound in this function
+LL |       where
+LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
+   |  ______________^
+LL | |             Assume {
+LL | |                 alignment: true,
+LL | |                 lifetimes: true,
+...  |
+LL | |             }
+LL | |         }>
+   | |__________^ required by this bound in `is_maybe_transmutable`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/transmutability/references.rs b/tests/ui/transmutability/references.rs
index af3ff0ec1d2..8c2b25ebba1 100644
--- a/tests/ui/transmutability/references.rs
+++ b/tests/ui/transmutability/references.rs
@@ -1,3 +1,6 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+
 //! Transmutations involving references are not yet supported.
 
 #![crate_type = "lib"]