about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-13 06:29:38 +0000
committerbors <bors@rust-lang.org>2024-01-13 06:29:38 +0000
commit12c0f090af379f2a6334cc35100cb6ee3f13f0ef (patch)
treeab6ca2c31a68888b7c34f3b091e899054f3a56aa
parent67659fb7952bad8c5d54955f69d289f03763e0b1 (diff)
parent9b46f3bb6499c263c9c81e7cea4815396bbbce14 (diff)
downloadrust-12c0f090af379f2a6334cc35100cb6ee3f13f0ef.tar.gz
rust-12c0f090af379f2a6334cc35100cb6ee3f13f0ef.zip
Auto merge of #3265 - rust-lang:rustup-2024-01-13, r=saethlin
Automatic Rustup
-rw-r--r--Cargo.lock23
-rw-r--r--Cargo.toml2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs19
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs46
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs22
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs3
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs13
-rw-r--r--compiler/rustc_errors/Cargo.toml2
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs13
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs15
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs30
-rw-r--r--compiler/rustc_errors/src/lib.rs122
-rw-r--r--compiler/rustc_errors/src/markdown/tests/term.rs5
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_fluent_macro/Cargo.toml2
-rw-r--r--compiler/rustc_fluent_macro/src/fluent.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/object_safety.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs6
-rw-r--r--compiler/rustc_interface/src/interface.rs11
-rw-r--r--compiler/rustc_lint/messages.ftl10
-rw-r--r--compiler/rustc_lint/src/context.rs24
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs12
-rw-r--r--compiler/rustc_lint/src/levels.rs9
-rw-r--r--compiler/rustc_lint/src/lints.rs3
-rw-r--r--compiler/rustc_lint/src/unused.rs34
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp9
-rw-r--r--compiler/rustc_macros/src/serialize.rs30
-rw-r--r--compiler/rustc_middle/src/arena.rs1
-rw-r--r--compiler/rustc_middle/src/middle/exported_symbols.rs5
-rw-r--r--compiler/rustc_middle/src/query/mod.rs3
-rw-r--r--compiler/rustc_middle/src/query/on_disk_cache.rs9
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect.rs1
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs3
-rw-r--r--compiler/rustc_middle/src/traits/specialization_graph.rs14
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs4
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs4
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs23
-rw-r--r--compiler/rustc_monomorphize/messages.ftl3
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs6
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs5
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs32
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs24
-rw-r--r--compiler/rustc_parse/src/lexer/unicode_chars.rs2
-rw-r--r--compiler/rustc_parse/src/lib.rs76
-rw-r--r--compiler/rustc_passes/messages.ftl5
-rw-r--r--compiler/rustc_passes/src/errors.rs6
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs6
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs6
-rw-r--r--compiler/rustc_pattern_analysis/src/lints.rs107
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs182
-rw-r--r--compiler/rustc_serialize/src/serialize.rs33
-rw-r--r--compiler/rustc_session/src/config.rs14
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_span/src/edit_distance.rs28
-rw-r--r--compiler/rustc_span/src/lib.rs23
-rw-r--r--compiler/rustc_target/src/spec/mod.rs17
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml1
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs1
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/build.rs5
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalize.rs41
-rw-r--r--compiler/rustc_trait_selection/src/solve/search_graph.rs368
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs68
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_normalize.rs3
-rw-r--r--compiler/stable_mir/src/mir/body.rs33
-rw-r--r--compiler/stable_mir/src/mir/visit.rs24
-rw-r--r--library/alloc/src/raw_vec.rs1
-rw-r--r--library/alloc/tests/autotraits.rs7
-rw-r--r--library/alloc/tests/vec.rs10
-rw-r--r--library/core/benches/num/int_pow/mod.rs99
-rw-r--r--library/core/benches/num/mod.rs1
-rw-r--r--library/core/src/intrinsics.rs10
-rw-r--r--library/core/src/num/nonzero.rs22
-rw-r--r--library/core/tests/array.rs2
-rw-r--r--library/core/tests/cell.rs16
-rw-r--r--library/core/tests/error.rs2
-rw-r--r--library/core/tests/fmt/mod.rs8
-rw-r--r--library/core/tests/hash/mod.rs6
-rw-r--r--library/core/tests/iter/adapters/chain.rs15
-rw-r--r--library/core/tests/iter/adapters/flatten.rs2
-rw-r--r--library/core/tests/iter/adapters/step_by.rs22
-rw-r--r--library/core/tests/iter/adapters/take.rs5
-rw-r--r--library/core/tests/iter/adapters/zip.rs2
-rw-r--r--library/core/tests/iter/traits/iterator.rs10
-rw-r--r--library/core/tests/net/ip_addr.rs6
-rw-r--r--library/core/tests/option.rs42
-rw-r--r--library/core/tests/ptr.rs24
-rw-r--r--library/core/tests/time.rs24
-rw-r--r--library/std/src/num.rs3
-rw-r--r--library/std/src/num/benches.rs9
-rw-r--r--library/std/tests/process_spawning.rs2
-rw-r--r--library/test/src/lib.rs22
-rw-r--r--rustfmt.toml2
-rw-r--r--src/bootstrap/Cargo.lock277
-rw-r--r--src/bootstrap/Cargo.toml34
-rw-r--r--src/bootstrap/src/core/config/config.rs1
-rw-r--r--src/bootstrap/src/tests/config.rs9
-rw-r--r--src/bootstrap/src/tests/helpers.rs2
-rwxr-xr-xsrc/ci/scripts/dump-environment.sh16
-rw-r--r--src/doc/unstable-book/src/compiler-flags/env-set.md (renamed from src/doc/unstable-book/src/compiler-flags/env.md)14
-rw-r--r--src/etc/completions/x.py.sh6
-rw-r--r--src/librustdoc/clean/render_macro_matchers.rs4
-rw-r--r--src/librustdoc/doctest.rs8
m---------src/llvm-project0
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/.github/workflows/clippy.yml2
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml10
-rw-r--r--src/tools/clippy/.github/workflows/clippy_dev.yml2
-rw-r--r--src/tools/clippy/.github/workflows/deploy.yml4
-rw-r--r--src/tools/clippy/.github/workflows/remark.yml2
-rw-r--r--src/tools/clippy/CHANGELOG.md7
-rw-r--r--src/tools/clippy/COPYRIGHT2
-rw-r--r--src/tools/clippy/LICENSE-APACHE2
-rw-r--r--src/tools/clippy/LICENSE-MIT2
-rw-r--r--src/tools/clippy/README.md4
-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/continuous_integration/github_actions.md2
-rw-r--r--src/tools/clippy/book/src/continuous_integration/gitlab.md16
-rw-r--r--src/tools/clippy/book/src/development/macro_expansions.md2
-rw-r--r--src/tools/clippy/book/src/development/type_checking.md4
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md10
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs7
-rw-r--r--src/tools/clippy/clippy_config/src/metadata.rs3
-rw-r--r--src/tools/clippy/clippy_config/src/msrvs.rs2
-rw-r--r--src/tools/clippy/clippy_config/src/types.rs6
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs141
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_with_brackets.rs (renamed from src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs)56
-rw-r--r--src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/item_name_repetitions.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_filter.rs206
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs59
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs142
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs115
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_cloned.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_split.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/useless_asref.rs123
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/utils.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/mutex_atomic.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/identity_op.rs208
-rw-r--r--src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs83
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/serde_api.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs102
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs53
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unconditional_recursion.rs413
-rw-r--r--src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/vec.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs13
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs6
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/rustc_tools_util/README.md2
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_underscore_fields/all_pub_fields/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_underscore_fields/exported/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr60
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.exported.stderr12
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs66
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr2
-rw-r--r--src/tools/clippy/tests/ui/as_conversions.rs2
-rw-r--r--src/tools/clippy/tests/ui/cast.rs49
-rw-r--r--src/tools/clippy/tests/ui/cast.stderr74
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-8821.fixed10
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-8821.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-8821.stderr11
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed4
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs2
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr26
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed36
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs34
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr44
-rw-r--r--src/tools/clippy/tests/ui/eager_transmute.fixed35
-rw-r--r--src/tools/clippy/tests/ui/eager_transmute.rs35
-rw-r--r--src/tools/clippy/tests/ui/eager_transmute.stderr117
-rw-r--r--src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.fixed27
-rw-r--r--src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.rs27
-rw-r--r--src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.stderr36
-rw-r--r--src/tools/clippy/tests/ui/identity_op.fixed94
-rw-r--r--src/tools/clippy/tests/ui/identity_op.rs94
-rw-r--r--src/tools/clippy/tests/ui/identity_op.stderr154
-rw-r--r--src/tools/clippy/tests/ui/if_then_some_else_none.rs5
-rw-r--r--src/tools/clippy/tests/ui/into_iter_without_iter.rs39
-rw-r--r--src/tools/clippy/tests/ui/into_iter_without_iter.stderr38
-rw-r--r--src/tools/clippy/tests/ui/iter_filter_is_ok.fixed193
-rw-r--r--src/tools/clippy/tests/ui/iter_filter_is_ok.rs193
-rw-r--r--src/tools/clippy/tests/ui/iter_filter_is_ok.stderr74
-rw-r--r--src/tools/clippy/tests/ui/iter_filter_is_some.fixed231
-rw-r--r--src/tools/clippy/tests/ui/iter_filter_is_some.rs231
-rw-r--r--src/tools/clippy/tests/ui/iter_filter_is_some.stderr62
-rw-r--r--src/tools/clippy/tests/ui/iter_without_into_iter.rs31
-rw-r--r--src/tools/clippy/tests/ui/iter_without_into_iter.stderr40
-rw-r--r--src/tools/clippy/tests/ui/let_unit.fixed50
-rw-r--r--src/tools/clippy/tests/ui/let_unit.rs48
-rw-r--r--src/tools/clippy/tests/ui/let_unit.stderr56
-rw-r--r--src/tools/clippy/tests/ui/manual_is_variant_and.fixed51
-rw-r--r--src/tools/clippy/tests/ui/manual_is_variant_and.rs57
-rw-r--r--src/tools/clippy/tests/ui/manual_is_variant_and.stderr82
-rw-r--r--src/tools/clippy/tests/ui/map_clone.fixed24
-rw-r--r--src/tools/clippy/tests/ui/map_clone.rs24
-rw-r--r--src/tools/clippy/tests/ui/map_clone.stderr44
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.fixed6
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.rs6
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.stderr10
-rw-r--r--src/tools/clippy/tests/ui/mutex_atomic.rs19
-rw-r--r--src/tools/clippy/tests/ui/mutex_atomic.stderr30
-rw-r--r--src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed4
-rw-r--r--src/tools/clippy/tests/ui/non_octal_unix_permissions.rs4
-rw-r--r--src/tools/clippy/tests/ui/non_octal_unix_permissions.stderr2
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_cloned.fixed21
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_cloned.rs21
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_cloned.stderr37
-rw-r--r--src/tools/clippy/tests/ui/redundant_as_str.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_as_str.rs2
-rw-r--r--src/tools/clippy/tests/ui/regex.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.fixed2
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.rs2
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.stderr26
-rw-r--r--src/tools/clippy/tests/ui/str_split.fixed145
-rw-r--r--src/tools/clippy/tests/ui/str_split.rs145
-rw-r--r--src/tools/clippy/tests/ui/str_split.stderr65
-rw-r--r--src/tools/clippy/tests/ui/struct_fields.rs24
-rw-r--r--src/tools/clippy/tests/ui/struct_fields.stderr28
-rw-r--r--src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed30
-rw-r--r--src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs30
-rw-r--r--src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr29
-rw-r--r--src/tools/clippy/tests/ui/unconditional_recursion.rs108
-rw-r--r--src/tools/clippy/tests/ui/unconditional_recursion.stderr95
-rw-r--r--src/tools/clippy/tests/ui/unknown_clippy_lints.fixed6
-rw-r--r--src/tools/clippy/tests/ui/unknown_clippy_lints.rs4
-rw-r--r--src/tools/clippy/tests/ui/unknown_clippy_lints.stderr20
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed13
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs13
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr126
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_safety_comment.rs21
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed18
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs18
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr24
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.fixed14
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.rs14
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.stderr42
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.fixed4
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.rs4
-rw-r--r--src/tools/clippy/tests/ui/vec.fixed7
-rw-r--r--src/tools/clippy/tests/ui/vec.rs7
-rw-r--r--src/tools/clippy/triagebot.toml1
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/bin/miri.rs1
-rw-r--r--src/tools/rustfmt/src/parse/parser.rs4
-rw-r--r--src/tools/rustfmt/src/parse/session.rs8
-rw-r--r--src/tools/tidy/src/deps.rs2
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/codegen/issues/issue-119422.rs83
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff1
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff1
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff1
-rw-r--r--tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff1
-rw-r--r--tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-abort.diff12
-rw-r--r--tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff12
-rw-r--r--tests/mir-opt/simplify_match.main.GVN.panic-abort.diff10
-rw-r--r--tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff10
-rw-r--r--tests/run-make/libtest-padding/Makefile14
-rw-r--r--tests/run-make/libtest-padding/bench.stdout9
-rw-r--r--tests/run-make/libtest-padding/test.stdout9
-rw-r--r--tests/run-make/libtest-padding/tests.rs18
-rw-r--r--tests/run-make/no-builtins-lto/Makefile18
-rw-r--r--tests/run-make/no-builtins-lto/filecheck.lto.txt17
-rw-r--r--tests/run-make/no-builtins-lto/foo.rs33
-rw-r--r--tests/run-make/no-builtins-lto/main.rs28
-rw-r--r--tests/run-make/no-builtins-lto/no_builtins.rs13
-rw-r--r--tests/run-make/no-builtins-symbols/Makefile7
-rw-r--r--tests/run-make/no-builtins-symbols/main.rs1
-rw-r--r--tests/run-make/wasm-spurious-import/Makefile (renamed from tests/run-make/wasm-builtins-import/Makefile)0
-rw-r--r--tests/run-make/wasm-spurious-import/main.rs (renamed from tests/run-make/wasm-builtins-import/main.rs)5
-rw-r--r--tests/run-make/wasm-spurious-import/verify.js (renamed from tests/run-make/wasm-builtins-import/verify.js)0
-rw-r--r--tests/rustdoc-ui/ice-bug-report-url.stderr2
-rw-r--r--tests/rustdoc-ui/unable-fulfill-trait.rs1
-rw-r--r--tests/rustdoc-ui/unable-fulfill-trait.stderr23
-rw-r--r--tests/ui/associated-inherent-types/issue-109071.no_gate.stderr2
-rw-r--r--tests/ui/associated-inherent-types/issue-109071.rs4
-rw-r--r--tests/ui/associated-inherent-types/issue-109071.with_gate.stderr23
-rw-r--r--tests/ui/associated-types/issue-23595-1.rs3
-rw-r--r--tests/ui/associated-types/issue-23595-1.stderr24
-rw-r--r--tests/ui/check-cfg/compact-values.stderr1
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr1
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.feature.stderr1
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.full.stderr1
-rw-r--r--tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr1
-rw-r--r--tests/ui/check-cfg/exhaustive-values.without_names.stderr1
-rw-r--r--tests/ui/check-cfg/no-expected-values.empty.stderr1
-rw-r--r--tests/ui/check-cfg/no-expected-values.mixed.stderr1
-rw-r--r--tests/ui/check-cfg/no-expected-values.simple.stderr1
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr26
-rw-r--r--tests/ui/const-generics/issues/issue-71381.full.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-71381.min.stderr20
-rw-r--r--tests/ui/const-generics/issues/issue-71381.rs6
-rw-r--r--tests/ui/const-generics/issues/issue-71611.min.stderr10
-rw-r--r--tests/ui/const-generics/issues/issue-71611.rs3
-rw-r--r--tests/ui/consts/const-err-enum-discriminant.rs (renamed from tests/ui/consts/const-err4.rs)1
-rw-r--r--tests/ui/consts/const-err-enum-discriminant.stderr (renamed from tests/ui/consts/const-err4.32bit.stderr)2
-rw-r--r--tests/ui/consts/const-err4.64bit.stderr9
-rw-r--r--tests/ui/consts/const-eval/const-eval-query-stack.stderr2
-rw-r--r--tests/ui/coroutine/clone-rpit.next.stderr52
-rw-r--r--tests/ui/coroutine/clone-rpit.rs3
-rw-r--r--tests/ui/derives/issue-97343.rs1
-rw-r--r--tests/ui/derives/issue-97343.stderr14
-rw-r--r--tests/ui/error-codes/E0227.rs4
-rw-r--r--tests/ui/error-codes/E0227.stderr22
-rw-r--r--tests/ui/extenv/extenv-env-overload.rs2
-rw-r--r--tests/ui/extenv/extenv-env.rs2
-rw-r--r--tests/ui/extenv/extenv-not-env.rs2
-rw-r--r--tests/ui/extern-flag/empty-extern-arg.stderr6
-rw-r--r--tests/ui/feature-gates/env-flag.rs2
-rw-r--r--tests/ui/feature-gates/env-flag.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-71176.rs3
-rw-r--r--tests/ui/generic-associated-types/issue-71176.stderr55
-rw-r--r--tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs16
-rw-r--r--tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr119
-rw-r--r--tests/ui/hygiene/panic-location.run.stderr2
-rw-r--r--tests/ui/impl-trait/eagerly-reveal-in-local-body.rs13
-rw-r--r--tests/ui/impl-trait/issues/issue-86800.stderr2
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr2
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr2
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.rs4
-rw-r--r--tests/ui/issues/issue-3214.rs1
-rw-r--r--tests/ui/issues/issue-3214.stderr10
-rw-r--r--tests/ui/lang-items/required-lang-item.rs7
-rw-r--r--tests/ui/lang-items/required-lang-item.stderr6
-rw-r--r--tests/ui/layout/issue-84108.rs2
-rw-r--r--tests/ui/layout/issue-84108.stderr24
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.rs1
-rw-r--r--tests/ui/lifetimes/unusual-rib-combinations.stderr11
-rw-r--r--tests/ui/lint/unused/issue-117142-invalid-remove-parens.rs19
-rw-r--r--tests/ui/no_std/no-std-no-start-binary.rs13
-rw-r--r--tests/ui/no_std/no-std-no-start-binary.stderr6
-rw-r--r--tests/ui/no_std/no-std-unwind-binary.rs15
-rw-r--r--tests/ui/no_std/no-std-unwind-binary.stderr7
-rw-r--r--tests/ui/panic-handler/weak-lang-item.rs2
-rw-r--r--tests/ui/panic-handler/weak-lang-item.stderr6
-rw-r--r--tests/ui/panics/default-backtrace-ice.stderr2
-rw-r--r--tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs1
-rw-r--r--tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr17
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/issue-117648-overlapping_range_endpoints-false-positive.rs9
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs11
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr24
-rw-r--r--tests/ui/proc-macro/env.rs2
-rw-r--r--tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs1
-rw-r--r--tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr8
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs9
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr41
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs3
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr16
-rw-r--r--tests/ui/traits/next-solver/alias-bound-unsound.rs6
-rw-r--r--tests/ui/traits/next-solver/alias-bound-unsound.stderr3
-rw-r--r--tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs39
-rw-r--r--tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr16
-rw-r--r--tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs32
-rw-r--r--tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr16
-rw-r--r--tests/ui/traits/next-solver/cycles/provisional-cache-impacts-behavior.rs70
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs6
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr21
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs6
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr21
-rw-r--r--tests/ui/treat-err-as-bug/eagerly-emit.rs11
-rw-r--r--tests/ui/treat-err-as-bug/eagerly-emit.stderr28
-rw-r--r--tests/ui/treat-err-as-bug/err.stderr2
401 files changed, 7533 insertions, 2393 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 75c7de4f405..440def72768 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -120,6 +120,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "annotate-snippets"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a433302f833baa830c0092100c481c7ea768c5981a3c36f549517a502f246dd"
+dependencies = [
+ "anstyle",
+ "unicode-width",
+]
+
+[[package]]
 name = "ansi_term"
 version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3771,7 +3781,7 @@ dependencies = [
 name = "rustc_errors"
 version = "0.0.0"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.10.1",
  "derive_setters",
  "rustc_ast",
  "rustc_ast_pretty",
@@ -3831,7 +3841,7 @@ dependencies = [
 name = "rustc_fluent_macro"
 version = "0.0.0"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.10.1",
  "fluent-bundle",
  "fluent-syntax",
  "proc-macro2",
@@ -4564,6 +4574,7 @@ checksum = "8ba09476327c4b70ccefb6180f046ef588c26a24cf5d269a9feba316eb4f029f"
 name = "rustc_trait_selection"
 version = "0.0.0"
 dependencies = [
+ "bitflags 2.4.1",
  "itertools",
  "rustc_ast",
  "rustc_attr",
@@ -4738,7 +4749,7 @@ dependencies = [
 name = "rustfmt-nightly"
 version = "1.7.0"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.9.1",
  "anyhow",
  "bytecount",
  "cargo_metadata 0.15.4",
@@ -5728,7 +5739,7 @@ version = "0.21.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "aaf4bf7c184b8dfc7a4d3b90df789b1eb992ee42811cd115f32a7a1eb781058d"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.9.1",
  "anyhow",
  "bstr",
  "cargo-platform",
@@ -5859,9 +5870,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.10"
+version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
diff --git a/Cargo.toml b/Cargo.toml
index 03915078838..2ea16c22666 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -64,7 +64,7 @@ exclude = [
 ]
 
 [profile.release.package.compiler_builtins]
-# The compiler-builtins crate cannot reference libcore, and it's own CI will
+# The compiler-builtins crate cannot reference libcore, and its own CI will
 # verify that this is the case. This requires, however, that the crate is built
 # without overflow checks and debug assertions. Forcefully disable debug
 # assertions and overflow checks here which should ensure that even if these
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 495b255583c..0457b4e6ddc 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -2399,10 +2399,10 @@ mod error {
         /// and we want only the best of those errors.
         ///
         /// The `report_use_of_moved_or_uninitialized` function checks this map and replaces the
-        /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of the
-        /// `Place` of the previous most diagnostic. This happens instead of buffering the error. Once
-        /// all move errors have been reported, any diagnostics in this map are added to the buffer
-        /// to be emitted.
+        /// diagnostic (if there is one) if the `Place` of the error being reported is a prefix of
+        /// the `Place` of the previous most diagnostic. This happens instead of buffering the
+        /// error. Once all move errors have been reported, any diagnostics in this map are added
+        /// to the buffer to be emitted.
         ///
         /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary
         /// when errors in the map are being re-added to the error buffer so that errors with the
@@ -2410,7 +2410,8 @@ mod error {
         buffered_move_errors:
             BTreeMap<Vec<MoveOutIndex>, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx>)>,
         buffered_mut_errors: FxIndexMap<Span, (DiagnosticBuilder<'tcx>, usize)>,
-        /// Diagnostics to be reported buffer.
+        /// Buffer of diagnostics to be reported. Uses `Diagnostic` rather than `DiagnosticBuilder`
+        /// because it has a mixture of error diagnostics and non-error diagnostics.
         buffered: Vec<Diagnostic>,
         /// Set to Some if we emit an error during borrowck
         tainted_by_errors: Option<ErrorGuaranteed>,
@@ -2434,11 +2435,11 @@ mod error {
                     "diagnostic buffered but not emitted",
                 ))
             }
-            t.buffer(&mut self.buffered);
+            self.buffered.push(t.into_diagnostic());
         }
 
         pub fn buffer_non_error_diag(&mut self, t: DiagnosticBuilder<'_, ()>) {
-            t.buffer(&mut self.buffered);
+            self.buffered.push(t.into_diagnostic());
         }
 
         pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) {
@@ -2486,13 +2487,13 @@ mod error {
             // Buffer any move errors that we collected and de-duplicated.
             for (_, (_, diag)) in std::mem::take(&mut self.errors.buffered_move_errors) {
                 // We have already set tainted for this error, so just buffer it.
-                diag.buffer(&mut self.errors.buffered);
+                self.errors.buffered.push(diag.into_diagnostic());
             }
             for (_, (mut diag, count)) in std::mem::take(&mut self.errors.buffered_mut_errors) {
                 if count > 10 {
                     diag.note(format!("...and {} other attempted mutable borrows", count - 10));
                 }
-                diag.buffer(&mut self.errors.buffered);
+                self.errors.buffered.push(diag.into_diagnostic());
             }
 
             if !self.errors.buffered.is_empty() {
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index 4b3eaf78557..a0fd0e3f9be 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -18,7 +18,7 @@ fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Option<Symbol> {
     if let Some(value) = cx.sess.opts.logical_env.get(var) {
         return Some(Symbol::intern(value));
     }
-    // If the environment variable was not defined with the `--env` option, we try to retrieve it
+    // If the environment variable was not defined with the `--env-set` option, we try to retrieve it
     // from rustc's environment.
     env::var(var).ok().as_deref().map(Symbol::intern)
 }
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index e9e8ade09b7..42bd8687042 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -60,7 +60,7 @@ fn prepare_lto(
     };
 
     let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
-        if info.level.is_below_threshold(export_threshold) || info.used || info.used_compiler {
+        if info.level.is_below_threshold(export_threshold) || info.used {
             Some(CString::new(name.as_str()).unwrap())
         } else {
             None
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index a912ef9e755..27cb0366f17 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -569,6 +569,7 @@ pub(crate) unsafe fn llvm_optimize(
         unroll_loops,
         config.vectorize_slp,
         config.vectorize_loop,
+        config.no_builtins,
         config.emit_lifetime_markers,
         sanitizer_options.as_ref(),
         pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
@@ -677,6 +678,7 @@ pub(crate) unsafe fn codegen(
         unsafe fn with_codegen<'ll, F, R>(
             tm: &'ll llvm::TargetMachine,
             llmod: &'ll llvm::Module,
+            no_builtins: bool,
             f: F,
         ) -> R
         where
@@ -684,7 +686,7 @@ pub(crate) unsafe fn codegen(
         {
             let cpm = llvm::LLVMCreatePassManager();
             llvm::LLVMAddAnalysisPasses(tm, cpm);
-            llvm::LLVMRustAddLibraryInfo(cpm, llmod);
+            llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
             f(cpm)
         }
 
@@ -785,7 +787,7 @@ pub(crate) unsafe fn codegen(
             } else {
                 llmod
             };
-            with_codegen(tm, llmod, |cpm| {
+            with_codegen(tm, llmod, config.no_builtins, |cpm| {
                 write_output_file(
                     dcx,
                     tm,
@@ -820,7 +822,7 @@ pub(crate) unsafe fn codegen(
                     (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
                 };
 
-                with_codegen(tm, llmod, |cpm| {
+                with_codegen(tm, llmod, config.no_builtins, |cpm| {
                     write_output_file(
                         dcx,
                         tm,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index aefca6b34f5..ee73c6b4756 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2173,8 +2173,13 @@ extern "C" {
         ArgsCstrBuff: *const c_char,
         ArgsCstrBuffLen: usize,
     ) -> *mut TargetMachine;
+
     pub fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
-    pub fn LLVMRustAddLibraryInfo<'a>(PM: &PassManager<'a>, M: &'a Module);
+    pub fn LLVMRustAddLibraryInfo<'a>(
+        PM: &PassManager<'a>,
+        M: &'a Module,
+        DisableSimplifyLibCalls: bool,
+    );
     pub fn LLVMRustWriteOutputFile<'a>(
         T: &'a TargetMachine,
         PM: &PassManager<'a>,
@@ -2196,6 +2201,7 @@ extern "C" {
         UnrollLoops: bool,
         SLPVectorize: bool,
         LoopVectorize: bool,
+        DisableSimplifyLibCalls: bool,
         EmitLifetimeMarkers: bool,
         SanitizerOptions: Option<&SanitizerOptions>,
         PGOGenPath: *const c_char,
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 70fda982b01..ace356ab153 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -270,14 +270,8 @@ pub fn each_linked_rlib(
 
     for &cnum in crates {
         match fmts.get(cnum.as_usize() - 1) {
-            Some(&Linkage::NotLinked | &Linkage::Dynamic) => continue,
-            Some(&Linkage::IncludedFromDylib) => {
-                // We always link crate `compiler_builtins` statically. When enabling LTO, we include it as well.
-                if info.compiler_builtins != Some(cnum) {
-                    continue;
-                }
-            }
-            Some(&Linkage::Static) => {}
+            Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue,
+            Some(_) => {}
             None => return Err(errors::LinkRlibError::MissingFormat),
         }
         let crate_name = info.crate_name[&cnum];
@@ -526,7 +520,8 @@ fn link_staticlib<'a>(
         &codegen_results.crate_info,
         Some(CrateType::Staticlib),
         &mut |cnum, path| {
-            let lto = are_upstream_rust_objects_already_included(sess);
+            let lto = are_upstream_rust_objects_already_included(sess)
+                && !ignored_for_lto(sess, &codegen_results.crate_info, cnum);
 
             let native_libs = codegen_results.crate_info.native_libraries[&cnum].iter();
             let relevant = native_libs.clone().filter(|lib| relevant_lib(sess, lib));
@@ -1277,6 +1272,24 @@ fn link_sanitizer_runtime(
     }
 }
 
+/// Returns a boolean indicating whether the specified crate should be ignored
+/// during LTO.
+///
+/// Crates ignored during LTO are not lumped together in the "massive object
+/// file" that we create and are linked in their normal rlib states. See
+/// comments below for what crates do not participate in LTO.
+///
+/// It's unusual for a crate to not participate in LTO. Typically only
+/// compiler-specific and unstable crates have a reason to not participate in
+/// LTO.
+pub fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum) -> bool {
+    // If our target enables builtin function lowering in LLVM then the
+    // crates providing these functions don't participate in LTO (e.g.
+    // no_builtins or compiler builtins crates).
+    !sess.target.no_builtins
+        && (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
+}
+
 /// This functions tries to determine the appropriate linker (and corresponding LinkerFlavor) to use
 pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
     fn infer_from(
@@ -2742,6 +2755,10 @@ fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf {
 // symbols). We must continue to include the rest of the rlib, however, as
 // it may contain static native libraries which must be linked in.
 //
+// (*) Crates marked with `#![no_builtins]` don't participate in LTO and
+// their bytecode wasn't included. The object files in those libraries must
+// still be passed to the linker.
+//
 // Note, however, that if we're not doing LTO we can just pass the rlib
 // blindly to the linker (fast) because it's fine if it's not actually
 // included as we're at the end of the dependency chain.
@@ -2767,7 +2784,9 @@ fn add_static_crate<'a>(
         cmd.link_rlib(&rlib_path);
     };
 
-    if !are_upstream_rust_objects_already_included(sess) {
+    if !are_upstream_rust_objects_already_included(sess)
+        || ignored_for_lto(sess, &codegen_results.crate_info, cnum)
+    {
         link_upstream(cratepath);
         return;
     }
@@ -2781,6 +2800,8 @@ fn add_static_crate<'a>(
         let canonical_name = name.replace('-', "_");
         let upstream_rust_objects_already_included =
             are_upstream_rust_objects_already_included(sess);
+        let is_builtins =
+            sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum);
 
         let mut archive = archive_builder_builder.new_archive_builder(sess);
         if let Err(error) = archive.add_archive(
@@ -2797,8 +2818,9 @@ fn add_static_crate<'a>(
 
                 // If we're performing LTO and this is a rust-generated object
                 // file, then we don't need the object file as it's part of the
-                // LTO module.
-                if upstream_rust_objects_already_included && is_rust_object {
+                // LTO module. Note that `#![no_builtins]` is excluded from LTO,
+                // though, so we let that object file slide.
+                if upstream_rust_objects_already_included && is_rust_object && is_builtins {
                     return true;
                 }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 94841ab7b33..cae7c40c5ad 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -54,8 +54,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
     // export level, however, as they're just implementation details.
     // Down below we'll hardwire all of the symbols to the `Rust` export
     // level instead.
-    let is_compiler_builtins = tcx.is_compiler_builtins(LOCAL_CRATE);
-    let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) || is_compiler_builtins;
+    let special_runtime_crate =
+        tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE);
 
     let mut reachable_non_generics: DefIdMap<_> = tcx
         .reachable_set(())
@@ -105,14 +105,8 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
             }
         })
         .map(|def_id| {
-            let codegen_attrs = tcx.codegen_fn_attrs(def_id.to_def_id());
             // We won't link right if this symbol is stripped during LTO.
             let name = tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())).name;
-            // We have to preserve the symbols of the built-in functions during LTO.
-            let is_builtin_fn = is_compiler_builtins
-                && symbol_export_level(tcx, def_id.to_def_id())
-                    .is_below_threshold(SymbolExportLevel::C)
-                && codegen_attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE);
             let used = name == "rust_eh_personality";
 
             let export_level = if special_runtime_crate {
@@ -120,6 +114,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
             } else {
                 symbol_export_level(tcx, def_id.to_def_id())
             };
+            let codegen_attrs = tcx.codegen_fn_attrs(def_id.to_def_id());
             debug!(
                 "EXPORTED SYMBOL (local): {} ({:?})",
                 tcx.symbol_name(Instance::mono(tcx, def_id.to_def_id())),
@@ -139,7 +134,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
                 used: codegen_attrs.flags.contains(CodegenFnAttrFlags::USED)
                     || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
                     || used,
-                used_compiler: is_builtin_fn,
             };
             (def_id.to_def_id(), info)
         })
@@ -152,7 +146,6 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> DefIdMap<S
                 level: SymbolExportLevel::C,
                 kind: SymbolExportKind::Data,
                 used: false,
-                used_compiler: false,
             },
         );
     }
@@ -201,7 +194,6 @@ fn exported_symbols_provider_local(
                         level: info.level,
                         kind: SymbolExportKind::Text,
                         used: info.used,
-                        used_compiler: false,
                     },
                 )
             })
@@ -218,7 +210,6 @@ fn exported_symbols_provider_local(
                 level: SymbolExportLevel::C,
                 kind: SymbolExportKind::Text,
                 used: false,
-                used_compiler: false,
             },
         ));
     }
@@ -238,7 +229,6 @@ fn exported_symbols_provider_local(
                     level: SymbolExportLevel::Rust,
                     kind: SymbolExportKind::Text,
                     used: false,
-                    used_compiler: false,
                 },
             ));
         }
@@ -251,7 +241,6 @@ fn exported_symbols_provider_local(
                 level: SymbolExportLevel::Rust,
                 kind: SymbolExportKind::Data,
                 used: false,
-                used_compiler: false,
             },
         ))
     }
@@ -271,7 +260,6 @@ fn exported_symbols_provider_local(
                     level: SymbolExportLevel::C,
                     kind: SymbolExportKind::Data,
                     used: false,
-                    used_compiler: false,
                 },
             )
         }));
@@ -297,7 +285,6 @@ fn exported_symbols_provider_local(
                     level: SymbolExportLevel::C,
                     kind: SymbolExportKind::Data,
                     used: false,
-                    used_compiler: false,
                 },
             )
         }));
@@ -315,7 +302,6 @@ fn exported_symbols_provider_local(
                 level: SymbolExportLevel::C,
                 kind: SymbolExportKind::Data,
                 used: true,
-                used_compiler: false,
             },
         ));
     }
@@ -356,7 +342,6 @@ fn exported_symbols_provider_local(
                                 level: SymbolExportLevel::Rust,
                                 kind: SymbolExportKind::Text,
                                 used: false,
-                                used_compiler: false,
                             },
                         ));
                     }
@@ -373,7 +358,6 @@ fn exported_symbols_provider_local(
                             level: SymbolExportLevel::Rust,
                             kind: SymbolExportKind::Text,
                             used: false,
-                            used_compiler: false,
                         },
                     ));
                 }
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 8e835039970..af1c6594446 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -148,12 +148,23 @@ impl ModuleConfig {
 
         let emit_obj = if !should_emit_obj {
             EmitObj::None
-        } else if sess.target.obj_is_bitcode || sess.opts.cg.linker_plugin_lto.enabled() {
+        } else if sess.target.obj_is_bitcode
+            || (sess.opts.cg.linker_plugin_lto.enabled() && !no_builtins)
+        {
             // This case is selected if the target uses objects as bitcode, or
             // if linker plugin LTO is enabled. In the linker plugin LTO case
             // the assumption is that the final link-step will read the bitcode
             // and convert it to object code. This may be done by either the
             // native linker or rustc itself.
+            //
+            // Note, however, that the linker-plugin-lto requested here is
+            // explicitly ignored for `#![no_builtins]` crates. These crates are
+            // specifically ignored by rustc's LTO passes and wouldn't work if
+            // loaded into the linker. These crates define symbols that LLVM
+            // lowers intrinsics to, and these symbol dependencies aren't known
+            // until after codegen. As a result any crate marked
+            // `#![no_builtins]` is assumed to not participate in LTO and
+            // instead goes on to generate object code.
             EmitObj::Bitcode
         } else if need_bitcode_in_object(tcx) {
             EmitObj::ObjectCode(BitcodeSection::Full)
@@ -1023,6 +1034,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
 
     let mut each_linked_rlib_for_lto = Vec::new();
     drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| {
+        if link::ignored_for_lto(sess, crate_info, cnum) {
+            return;
+        }
         each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
     }));
 
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 9d1729c4b54..0ad4af968db 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -859,6 +859,7 @@ impl CrateInfo {
             local_crate_name,
             compiler_builtins,
             profiler_runtime: None,
+            is_no_builtins: Default::default(),
             native_libraries: Default::default(),
             used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(),
             crate_name: Default::default(),
@@ -885,6 +886,9 @@ impl CrateInfo {
             if tcx.is_profiler_runtime(cnum) {
                 info.profiler_runtime = Some(cnum);
             }
+            if tcx.is_no_builtins(cnum) {
+                info.is_no_builtins.insert(cnum);
+            }
         }
 
         // Handle circular dependencies in the standard library.
@@ -892,7 +896,9 @@ impl CrateInfo {
         // If global LTO is enabled then almost everything (*) is glued into a single object file,
         // so this logic is not necessary and can cause issues on some targets (due to weak lang
         // item symbols being "privatized" to that object file), so we disable it.
-        // (*) Native libs are not glued, and we assume that they cannot define weak lang items.
+        // (*) Native libs, and `#[compiler_builtins]` and `#[no_builtins]` crates are not glued,
+        // and we assume that they cannot define weak lang items. This is not currently enforced
+        // by the compiler, but that's ok because all this stuff is unstable anyway.
         let target = &tcx.sess.target;
         if !are_upstream_rust_objects_already_included(tcx.sess) {
             let missing_weak_lang_items: FxHashSet<Symbol> = info
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 0d88df63280..99280fdba7c 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -25,7 +25,7 @@ extern crate tracing;
 extern crate rustc_middle;
 
 use rustc_ast as ast;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def_id::CrateNum;
 use rustc_middle::dep_graph::WorkProduct;
@@ -158,6 +158,7 @@ pub struct CrateInfo {
     pub local_crate_name: Symbol,
     pub compiler_builtins: Option<CrateNum>,
     pub profiler_runtime: Option<CrateNum>,
+    pub is_no_builtins: FxHashSet<CrateNum>,
     pub native_libraries: FxHashMap<CrateNum, Vec<NativeLib>>,
     pub crate_name: FxHashMap<CrateNum, Symbol>,
     pub used_libraries: Vec<NativeLib>,
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 738c532964a..ae9595d7e64 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -1,6 +1,6 @@
 //! The `Visitor` responsible for actually checking a `mir::Body` for invalid operations.
 
-use rustc_errors::{Diagnostic, ErrorGuaranteed};
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::BitSet;
@@ -214,7 +214,7 @@ pub struct Checker<'mir, 'tcx> {
     local_has_storage_dead: Option<BitSet<Local>>,
 
     error_emitted: Option<ErrorGuaranteed>,
-    secondary_errors: Vec<Diagnostic>,
+    secondary_errors: Vec<DiagnosticBuilder<'tcx>>,
 }
 
 impl<'mir, 'tcx> Deref for Checker<'mir, 'tcx> {
@@ -272,14 +272,17 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
         }
 
         // If we got through const-checking without emitting any "primary" errors, emit any
-        // "secondary" errors if they occurred.
+        // "secondary" errors if they occurred. Otherwise, cancel the "secondary" errors.
         let secondary_errors = mem::take(&mut self.secondary_errors);
         if self.error_emitted.is_none() {
             for error in secondary_errors {
-                self.tcx.dcx().emit_diagnostic(error);
+                error.emit();
             }
         } else {
             assert!(self.tcx.dcx().has_errors().is_some());
+            for error in secondary_errors {
+                error.cancel();
+            }
         }
     }
 
@@ -347,7 +350,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
                 self.error_emitted = Some(reported);
             }
 
-            ops::DiagnosticImportance::Secondary => err.buffer(&mut self.secondary_errors),
+            ops::DiagnosticImportance::Secondary => self.secondary_errors.push(err),
         }
     }
 
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index fc3ff835a81..0c1fcecb571 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
-annotate-snippets = "0.9"
+annotate-snippets = "0.10"
 derive_setters = "0.1.6"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index 97f2efa7874..648c9118400 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -12,8 +12,7 @@ use crate::{
     CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
     LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
 };
-use annotate_snippets::display_list::{DisplayList, FormatOptions};
-use annotate_snippets::snippet::*;
+use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
 use rustc_data_structures::sync::Lrc;
 use rustc_error_messages::FluentArgs;
 use rustc_span::source_map::SourceMap;
@@ -86,7 +85,7 @@ fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
 /// Maps `Diagnostic::Level` to `snippet::AnnotationType`
 fn annotation_type_for_level(level: Level) -> AnnotationType {
     match level {
-        Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error => AnnotationType::Error,
+        Level::Bug | Level::DelayedBug(_) | Level::Fatal | Level::Error => AnnotationType::Error,
         Level::ForceWarning(_) | Level::Warning => AnnotationType::Warning,
         Level::Note | Level::OnceNote => AnnotationType::Note,
         Level::Help | Level::OnceHelp => AnnotationType::Help,
@@ -190,11 +189,6 @@ impl AnnotateSnippetEmitter {
                     annotation_type: annotation_type_for_level(*level),
                 }),
                 footer: vec![],
-                opt: FormatOptions {
-                    color: true,
-                    anonymized_line_numbers: self.ui_testing,
-                    margin: None,
-                },
                 slices: annotated_files
                     .iter()
                     .map(|(file_name, source, line_index, annotations)| {
@@ -222,7 +216,8 @@ impl AnnotateSnippetEmitter {
             // FIXME(#59346): Figure out if we can _always_ print to stderr or not.
             // `emitter.rs` has the `Destination` enum that lists various possible output
             // destinations.
-            eprintln!("{}", DisplayList::from(snippet))
+            let renderer = Renderer::plain().anonymized_line_numbers(self.ui_testing);
+            eprintln!("{}", renderer.render(snippet))
         }
         // FIXME(#59346): Is it ok to return None if there's no source_map?
     }
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index d8d6922a1bc..786aced5b4f 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1,7 +1,7 @@
 use crate::snippet::Style;
 use crate::{
-    CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, MultiSpan,
-    SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
+    CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level,
+    MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_error_messages::fluent_value_from_str_list_sep_by_and;
@@ -243,12 +243,15 @@ impl Diagnostic {
 
     pub fn is_error(&self) -> bool {
         match self.level {
-            Level::Bug | Level::DelayedBug | Level::Fatal | Level::Error | Level::FailureNote => {
-                true
-            }
+            Level::Bug
+            | Level::DelayedBug(DelayedBugKind::Normal)
+            | Level::Fatal
+            | Level::Error
+            | Level::FailureNote => true,
 
             Level::ForceWarning(_)
             | Level::Warning
+            | Level::DelayedBug(DelayedBugKind::GoodPath)
             | Level::Note
             | Level::OnceNote
             | Level::Help
@@ -318,7 +321,7 @@ impl Diagnostic {
             "downgrade_to_delayed_bug: cannot downgrade {:?} to DelayedBug: not an error",
             self.level
         );
-        self.level = Level::DelayedBug;
+        self.level = Level::DelayedBug(DelayedBugKind::Normal);
     }
 
     /// Appends a labeled span to the diagnostic.
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index a02909f29c4..bd7c58d904e 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -255,35 +255,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
     /// Stashes diagnostic for possible later improvement in a different,
     /// later stage of the compiler. The diagnostic can be accessed with
     /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`].
-    ///
-    /// As with `buffer`, this is unless the dcx has disabled such buffering.
     pub fn stash(self, span: Span, key: StashKey) {
-        if let Some((diag, dcx)) = self.into_diagnostic() {
-            dcx.stash_diagnostic(span, key, diag);
-        }
-    }
-
-    /// Converts the builder to a `Diagnostic` for later emission,
-    /// unless dcx has disabled such buffering.
-    fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> {
-        if self.dcx.inner.lock().flags.treat_err_as_bug.is_some() {
-            self.emit();
-            return None;
-        }
-
-        let diag = self.take_diag();
-
-        // Logging here is useful to help track down where in logs an error was
-        // actually emitted.
-        debug!("buffer: diag={:?}", diag);
-
-        Some((diag, self.dcx))
+        self.dcx.stash_diagnostic(span, key, self.into_diagnostic());
     }
 
-    /// Buffers the diagnostic for later emission,
-    /// unless dcx has disabled such buffering.
-    pub fn buffer(self, buffered_diagnostics: &mut Vec<Diagnostic>) {
-        buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag));
+    /// Converts the builder to a `Diagnostic` for later emission.
+    pub fn into_diagnostic(mut self) -> Diagnostic {
+        self.take_diag()
     }
 
     /// Delay emission of this diagnostic as a bug.
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 8fb539fc358..8c2752af659 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -519,6 +519,12 @@ fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) {
 pub static TRACK_DIAGNOSTIC: AtomicRef<fn(Diagnostic, &mut dyn FnMut(Diagnostic))> =
     AtomicRef::new(&(default_track_diagnostic as _));
 
+#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)]
+pub enum DelayedBugKind {
+    Normal,
+    GoodPath,
+}
+
 #[derive(Copy, Clone, Default)]
 pub struct DiagCtxtFlags {
     /// If false, warning-level lints are suppressed.
@@ -527,6 +533,9 @@ pub struct DiagCtxtFlags {
     /// If Some, the Nth error-level diagnostic is upgraded to bug-level.
     /// (rustc: see `-Z treat-err-as-bug`)
     pub treat_err_as_bug: Option<NonZeroUsize>,
+    /// Eagerly emit delayed bugs as errors, so that the compiler debugger may
+    /// see all of the errors being emitted at once.
+    pub eagerly_emit_delayed_bugs: bool,
     /// Show macro backtraces.
     /// (rustc: see `-Z macro-backtrace`)
     pub macro_backtrace: bool,
@@ -541,8 +550,7 @@ impl Drop for DiagCtxtInner {
         self.emit_stashed_diagnostics();
 
         if !self.has_errors() {
-            let bugs = std::mem::replace(&mut self.span_delayed_bugs, Vec::new());
-            self.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued");
+            self.flush_delayed(DelayedBugKind::Normal)
         }
 
         // FIXME(eddyb) this explains what `good_path_delayed_bugs` are!
@@ -551,11 +559,7 @@ impl Drop for DiagCtxtInner {
         // lints can be `#[allow]`'d, potentially leading to this triggering.
         // Also, "good path" should be replaced with a better naming.
         if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
-            let bugs = std::mem::replace(&mut self.good_path_delayed_bugs, Vec::new());
-            self.flush_delayed(
-                bugs,
-                "no warnings or errors encountered even though `good_path_delayed_bugs` issued",
-            );
+            self.flush_delayed(DelayedBugKind::GoodPath);
         }
 
         if self.check_unstable_expect_diagnostics {
@@ -865,7 +869,8 @@ impl DiagCtxt {
         if treat_next_err_as_bug {
             self.bug(msg);
         }
-        DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).emit()
+        DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
+            .emit()
     }
 
     /// Like `delayed_bug`, but takes an additional span.
@@ -882,16 +887,15 @@ impl DiagCtxt {
         if treat_next_err_as_bug {
             self.span_bug(sp, msg);
         }
-        DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug, msg).with_span(sp).emit()
+        DiagnosticBuilder::<ErrorGuaranteed>::new(self, DelayedBug(DelayedBugKind::Normal), msg)
+            .with_span(sp)
+            .emit()
     }
 
     // FIXME(eddyb) note the comment inside `impl Drop for DiagCtxtInner`, that's
     // where the explanation of what "good path" is (also, it should be renamed).
     pub fn good_path_delayed_bug(&self, msg: impl Into<DiagnosticMessage>) {
-        let mut inner = self.inner.borrow_mut();
-        let diagnostic = Diagnostic::new(DelayedBug, msg);
-        let backtrace = std::backtrace::Backtrace::capture();
-        inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace));
+        DiagnosticBuilder::<()>::new(self, DelayedBug(DelayedBugKind::GoodPath), msg).emit()
     }
 
     #[track_caller]
@@ -981,6 +985,10 @@ impl DiagCtxt {
 
         inner.emit_stashed_diagnostics();
 
+        if inner.treat_err_as_bug() {
+            return;
+        }
+
         let warnings = match inner.deduplicated_warn_count {
             0 => Cow::from(""),
             1 => Cow::from("1 warning emitted"),
@@ -991,9 +999,6 @@ impl DiagCtxt {
             1 => Cow::from("aborting due to 1 previous error"),
             count => Cow::from(format!("aborting due to {count} previous errors")),
         };
-        if inner.treat_err_as_bug() {
-            return;
-        }
 
         match (errors.len(), warnings.len()) {
             (0, 0) => return,
@@ -1168,7 +1173,8 @@ impl DiagCtxt {
         let mut inner = self.inner.borrow_mut();
 
         if loud && lint_level.is_error() {
-            inner.bump_err_count();
+            inner.err_count += 1;
+            inner.panic_if_treat_err_as_bug();
         }
 
         inner.emitter.emit_unused_externs(lint_level, unused_externs)
@@ -1216,9 +1222,7 @@ impl DiagCtxt {
     }
 
     pub fn flush_delayed(&self) {
-        let mut inner = self.inner.borrow_mut();
-        let bugs = std::mem::replace(&mut inner.span_delayed_bugs, Vec::new());
-        inner.flush_delayed(bugs, "no errors encountered even though `span_delayed_bug` issued");
+        self.inner.borrow_mut().flush_delayed(DelayedBugKind::Normal);
     }
 }
 
@@ -1255,7 +1259,7 @@ impl DiagCtxtInner {
     }
 
     fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option<ErrorGuaranteed> {
-        if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() {
+        if matches!(diagnostic.level, Error | Fatal) && self.treat_next_err_as_bug() {
             diagnostic.level = Bug;
         }
 
@@ -1268,17 +1272,30 @@ impl DiagCtxtInner {
             return None;
         }
 
-        if diagnostic.level == DelayedBug {
-            // FIXME(eddyb) this should check for `has_errors` and stop pushing
-            // once *any* errors were emitted (and truncate `span_delayed_bugs`
-            // when an error is first emitted, also), but maybe there's a case
-            // in which that's not sound? otherwise this is really inefficient.
-            let backtrace = std::backtrace::Backtrace::capture();
-            self.span_delayed_bugs
-                .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
+        // FIXME(eddyb) this should check for `has_errors` and stop pushing
+        // once *any* errors were emitted (and truncate `span_delayed_bugs`
+        // when an error is first emitted, also), but maybe there's a case
+        // in which that's not sound? otherwise this is really inefficient.
+        match diagnostic.level {
+            DelayedBug(_) if self.flags.eagerly_emit_delayed_bugs => {
+                diagnostic.level = Error;
+            }
+            DelayedBug(DelayedBugKind::Normal) => {
+                let backtrace = std::backtrace::Backtrace::capture();
+                self.span_delayed_bugs
+                    .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
 
-            #[allow(deprecated)]
-            return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
+                #[allow(deprecated)]
+                return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
+            }
+            DelayedBug(DelayedBugKind::GoodPath) => {
+                let backtrace = std::backtrace::Backtrace::capture();
+                self.good_path_delayed_bugs
+                    .push(DelayedDiagnostic::with_backtrace(diagnostic.clone(), backtrace));
+
+                return None;
+            }
+            _ => {}
         }
 
         if diagnostic.has_future_breakage() {
@@ -1353,10 +1370,11 @@ impl DiagCtxtInner {
             }
             if diagnostic.is_error() {
                 if diagnostic.is_lint {
-                    self.bump_lint_err_count();
+                    self.lint_err_count += 1;
                 } else {
-                    self.bump_err_count();
+                    self.err_count += 1;
                 }
+                self.panic_if_treat_err_as_bug();
 
                 #[allow(deprecated)]
                 {
@@ -1393,11 +1411,18 @@ impl DiagCtxtInner {
         self.emit_diagnostic(Diagnostic::new(FailureNote, msg));
     }
 
-    fn flush_delayed(
-        &mut self,
-        bugs: Vec<DelayedDiagnostic>,
-        explanation: impl Into<DiagnosticMessage> + Copy,
-    ) {
+    fn flush_delayed(&mut self, kind: DelayedBugKind) {
+        let (bugs, explanation) = match kind {
+            DelayedBugKind::Normal => (
+                std::mem::take(&mut self.span_delayed_bugs),
+                "no errors encountered even though `span_delayed_bug` issued",
+            ),
+            DelayedBugKind::GoodPath => (
+                std::mem::take(&mut self.good_path_delayed_bugs),
+                "no warnings or errors encountered even though `good_path_delayed_bugs` issued",
+            ),
+        };
+
         if bugs.is_empty() {
             return;
         }
@@ -1430,7 +1455,7 @@ impl DiagCtxtInner {
                 if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
 
             // "Undelay" the `DelayedBug`s (into plain `Bug`s).
-            if bug.level != DelayedBug {
+            if !matches!(bug.level, DelayedBug(_)) {
                 // NOTE(eddyb) not panicking here because we're already producing
                 // an ICE, and the more information the merrier.
                 bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
@@ -1447,16 +1472,6 @@ impl DiagCtxtInner {
         panic::panic_any(DelayedBugPanic);
     }
 
-    fn bump_lint_err_count(&mut self) {
-        self.lint_err_count += 1;
-        self.panic_if_treat_err_as_bug();
-    }
-
-    fn bump_err_count(&mut self) {
-        self.err_count += 1;
-        self.panic_if_treat_err_as_bug();
-    }
-
     fn panic_if_treat_err_as_bug(&self) {
         if self.treat_err_as_bug() {
             match (
@@ -1528,8 +1543,9 @@ pub enum Level {
     /// silently dropped. I.e. "expect other errors are emitted" semantics. Useful on code paths
     /// that should only be reached when compiling erroneous code.
     ///
-    /// Its `EmissionGuarantee` is `ErrorGuaranteed`.
-    DelayedBug,
+    /// Its `EmissionGuarantee` is `ErrorGuaranteed` for `Normal` delayed bugs, and `()` for
+    /// `GoodPath` delayed bugs.
+    DelayedBug(DelayedBugKind),
 
     /// An error that causes an immediate abort. Used for things like configuration errors,
     /// internal overflows, some file operation errors.
@@ -1604,7 +1620,7 @@ impl Level {
     fn color(self) -> ColorSpec {
         let mut spec = ColorSpec::new();
         match self {
-            Bug | DelayedBug | Fatal | Error => {
+            Bug | DelayedBug(_) | Fatal | Error => {
                 spec.set_fg(Some(Color::Red)).set_intense(true);
             }
             ForceWarning(_) | Warning => {
@@ -1624,7 +1640,7 @@ impl Level {
 
     pub fn to_str(self) -> &'static str {
         match self {
-            Bug | DelayedBug => "error: internal compiler error",
+            Bug | DelayedBug(_) => "error: internal compiler error",
             Fatal | Error => "error",
             ForceWarning(_) | Warning => "warning",
             Note | OnceNote => "note",
diff --git a/compiler/rustc_errors/src/markdown/tests/term.rs b/compiler/rustc_errors/src/markdown/tests/term.rs
index a0d956bf0cd..bab47dcc175 100644
--- a/compiler/rustc_errors/src/markdown/tests/term.rs
+++ b/compiler/rustc_errors/src/markdown/tests/term.rs
@@ -5,7 +5,8 @@ use termcolor::{BufferWriter, ColorChoice};
 use super::*;
 
 const INPUT: &str = include_str!("input.md");
-const OUTPUT_PATH: &[&str] = &[env!("CARGO_MANIFEST_DIR"), "src","markdown","tests","output.stdout"];
+const OUTPUT_PATH: &[&str] =
+    &[env!("CARGO_MANIFEST_DIR"), "src", "markdown", "tests", "output.stdout"];
 
 const TEST_WIDTH: usize = 80;
 
@@ -34,7 +35,7 @@ quis dolor non venenatis. Aliquam ut. ";
 fn test_wrapping_write() {
     WIDTH.with(|w| w.set(TEST_WIDTH));
     let mut buf = BufWriter::new(Vec::new());
-    let txt = TXT.replace("-\n","-").replace("_\n","_").replace('\n', " ").replace("    ", "");
+    let txt = TXT.replace("-\n", "-").replace("_\n", "_").replace('\n', " ").replace("    ", "");
     write_wrapping(&mut buf, &txt, 0, None).unwrap();
     write_wrapping(&mut buf, &txt, 4, None).unwrap();
     write_wrapping(
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index aa0db9891a5..6e3996b4509 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -77,7 +77,7 @@ declare_features! (
     /// Allows empty structs and enum variants with braces.
     (accepted, braced_empty_structs, "1.8.0", Some(29720)),
     /// Allows `c"foo"` literals.
-    (accepted, c_str_literals, "1.76.0", Some(105723)),
+    (accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723)),
     /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
     (accepted, cfg_attr_multi, "1.33.0", Some(54881)),
     /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 59ea828440f..2f2b551e6ec 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -450,7 +450,7 @@ declare_features! (
     (unstable, doc_masked, "1.21.0", Some(44027)),
     /// Allows `dyn* Trait` objects.
     (incomplete, dyn_star, "1.65.0", Some(102425)),
-    // Uses generic effect parameters for ~const bounds
+    /// Uses generic effect parameters for ~const bounds
     (unstable, effects, "1.72.0", Some(102090)),
     /// Allows `X..Y` patterns.
     (unstable, exclusive_range_pattern, "1.11.0", Some(37854)),
diff --git a/compiler/rustc_fluent_macro/Cargo.toml b/compiler/rustc_fluent_macro/Cargo.toml
index 872dd29a7a8..c5a53ae8313 100644
--- a/compiler/rustc_fluent_macro/Cargo.toml
+++ b/compiler/rustc_fluent_macro/Cargo.toml
@@ -8,7 +8,7 @@ proc-macro = true
 
 [dependencies]
 # tidy-alphabetical-start
-annotate-snippets = "0.9"
+annotate-snippets = "0.10"
 fluent-bundle = "0.15.2"
 fluent-syntax = "0.11"
 proc-macro2 = "1"
diff --git a/compiler/rustc_fluent_macro/src/fluent.rs b/compiler/rustc_fluent_macro/src/fluent.rs
index 3b1b63455ed..520a64aaf5e 100644
--- a/compiler/rustc_fluent_macro/src/fluent.rs
+++ b/compiler/rustc_fluent_macro/src/fluent.rs
@@ -1,7 +1,4 @@
-use annotate_snippets::{
-    display_list::DisplayList,
-    snippet::{Annotation, AnnotationType, Slice, Snippet, SourceAnnotation},
-};
+use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
 use fluent_bundle::{FluentBundle, FluentError, FluentResource};
 use fluent_syntax::{
     ast::{
@@ -179,10 +176,9 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
                             range: (pos.start, pos.end - 1),
                         }],
                     }],
-                    opt: Default::default(),
                 };
-                let dl = DisplayList::from(snippet);
-                eprintln!("{dl}\n");
+                let renderer = Renderer::plain();
+                eprintln!("{}\n", renderer.render(snippet));
             }
 
             return failed(&crate_name);
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index 1f88aaa6a4b..2ad96a24891 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -300,13 +300,15 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
             .expect("missing associated item");
 
         if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {
-            tcx.dcx()
+            let reported = tcx
+                .dcx()
                 .struct_span_err(
                     binding.span,
                     format!("{} `{}` is private", assoc_item.kind, binding.item_name),
                 )
                 .with_span_label(binding.span, format!("private {}", assoc_item.kind))
                 .emit();
+            self.set_tainted_by_errors(reported);
         }
         tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None);
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index fc2ed104b3d..7b23b74f829 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -354,7 +354,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         );
         err.span_label(name.span, format!("multiple `{name}` found"));
         self.note_ambiguous_inherent_assoc_type(&mut err, candidates, span);
-        err.emit()
+        let reported = err.emit();
+        self.set_tainted_by_errors(reported);
+        reported
     }
 
     // FIXME(fmease): Heavily adapted from `rustc_hir_typeck::method::suggest`. Deduplicate.
@@ -843,7 +845,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
-        err.emit();
+        self.set_tainted_by_errors(err.emit());
     }
 }
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 1f47564649e..2886ec21320 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -390,6 +390,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             infer_args,
         );
 
+        if let Err(err) = &arg_count.correct
+            && let Some(reported) = err.reported
+        {
+            self.set_tainted_by_errors(reported);
+        }
+
         // Skip processing if type has no generic parameters.
         // Traits always have `Self` as a generic parameter, which means they will not return early
         // here and so associated type bindings will be handled regardless of whether there are any
@@ -568,6 +574,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 span,
                 modifier: constness.as_str(),
             });
+            self.set_tainted_by_errors(e);
             arg_count.correct =
                 Err(GenericArgCountMismatch { reported: Some(e), invalid_args: vec![] });
         }
@@ -966,7 +973,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 }
             }
         }
-        err.emit()
+        let reported = err.emit();
+        self.set_tainted_by_errors(reported);
+        reported
     }
 
     // Search for a bound on a type parameter which includes the associated item
@@ -1043,6 +1052,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 span,
                 binding,
             );
+            self.set_tainted_by_errors(reported);
             return Err(reported);
         };
         debug!(?bound);
@@ -1120,6 +1130,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 ));
             }
             let reported = err.emit();
+            self.set_tainted_by_errors(reported);
             if !where_bounds.is_empty() {
                 return Err(reported);
             }
@@ -1374,6 +1385,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         assoc_ident.name,
                     )
                 };
+                self.set_tainted_by_errors(reported);
                 return Err(reported);
             }
         };
@@ -1616,12 +1628,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             let kind = tcx.def_kind_descr(kind, item);
             let msg = format!("{kind} `{name}` is private");
             let def_span = tcx.def_span(item);
-            tcx.dcx()
+            let reported = tcx
+                .dcx()
                 .struct_span_err(span, msg)
                 .with_code(rustc_errors::error_code!(E0624))
                 .with_span_label(span, format!("private {kind}"))
                 .with_span_label(def_span, format!("{kind} defined here"))
                 .emit();
+            self.set_tainted_by_errors(reported);
         }
         tcx.check_stability(item, Some(block), span, None);
     }
@@ -1862,7 +1876,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 err.span_label(span, format!("not allowed on {what}"));
             }
             extend(&mut err);
-            err.emit();
+            self.set_tainted_by_errors(err.emit());
             emitted = true;
         }
 
@@ -2184,7 +2198,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     {
                         err.span_note(impl_.self_ty.span, "not a concrete type");
                     }
-                    Ty::new_error(tcx, err.emit())
+                    let reported = err.emit();
+                    self.set_tainted_by_errors(reported);
+                    Ty::new_error(tcx, reported)
                 } else {
                     ty
                 }
@@ -2586,7 +2602,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 );
             }
 
-            diag.emit();
+            self.set_tainted_by_errors(diag.emit());
         }
 
         // Find any late-bound regions declared in return type that do
@@ -2686,7 +2702,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 err.note("consider introducing a named lifetime parameter");
             }
 
-            err.emit();
+            self.set_tainted_by_errors(err.emit());
         }
     }
 
@@ -2725,7 +2741,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         // error.
         let r = derived_region_bounds[0];
         if derived_region_bounds[1..].iter().any(|r1| r != *r1) {
-            tcx.dcx().emit_err(AmbiguousLifetimeBound { span });
+            self.set_tainted_by_errors(tcx.dcx().emit_err(AmbiguousLifetimeBound { span }));
         }
         Some(r)
     }
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index ea2f5f50b5c..f77f250cd28 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -116,7 +116,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
              for more information on them, visit \
              <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
             );
-            err.emit();
+            self.set_tainted_by_errors(err.emit());
         }
 
         if regular_traits.is_empty() && auto_traits.is_empty() {
@@ -127,6 +127,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 .map(|trait_ref| tcx.def_span(trait_ref));
             let reported =
                 tcx.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span });
+            self.set_tainted_by_errors(reported);
             return Ty::new_error(tcx, reported);
         }
 
@@ -290,7 +291,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
                 if references_self {
                     let def_id = i.bottom().0.def_id();
-                    struct_span_code_err!(
+                    let reported = struct_span_code_err!(
                         tcx.dcx(),
                         i.bottom().1,
                         E0038,
@@ -303,6 +304,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             .error_msg(),
                     )
                     .emit();
+                    self.set_tainted_by_errors(reported);
                 }
 
                 ty::ExistentialTraitRef { def_id: trait_ref.def_id, args }
@@ -389,6 +391,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         } else {
                             err.emit()
                         };
+                        self.set_tainted_by_errors(e);
                         ty::Region::new_error(tcx, e)
                     })
                 }
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 5f599487912..556560945e9 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -74,7 +74,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
             // we have some type like `&<Ty as Trait>::Assoc`, since users of
             // autoderef expect this type to have been structurally normalized.
             if self.infcx.next_trait_solver()
-                && let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = ty.kind()
+                && let ty::Alias(..) = ty.kind()
             {
                 let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
                 self.state.obligations.extend(obligations);
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index c9f89a0c3ef..e557f36037b 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -35,6 +35,7 @@ use rustc_target::spec::abi;
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 use rustc_trait_selection::traits::ObligationCtxt;
+use std::cell::Cell;
 use std::iter;
 use std::ops::Bound;
 
@@ -119,6 +120,7 @@ pub fn provide(providers: &mut Providers) {
 pub struct ItemCtxt<'tcx> {
     tcx: TyCtxt<'tcx>,
     item_def_id: LocalDefId,
+    tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -343,7 +345,7 @@ fn bad_placeholder<'tcx>(
 
 impl<'tcx> ItemCtxt<'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
-        ItemCtxt { tcx, item_def_id }
+        ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
     }
 
     pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
@@ -357,6 +359,13 @@ impl<'tcx> ItemCtxt<'tcx> {
     pub fn node(&self) -> hir::Node<'tcx> {
         self.tcx.hir_node(self.hir_id())
     }
+
+    fn check_tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> {
+        match self.tainted_by_errors.get() {
+            Some(err) => Err(err),
+            None => Ok(()),
+        }
+    }
 }
 
 impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
@@ -492,8 +501,8 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
         ty.ty_adt_def()
     }
 
-    fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
-        // There's no obvious place to track this, so just let it go.
+    fn set_tainted_by_errors(&self, err: ErrorGuaranteed) {
+        self.tainted_by_errors.set(Some(err));
     }
 
     fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 3ceea3dc7ae..b936b0c0805 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -513,7 +513,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
             bug!("unexpected sort of node in type_of(): {:?}", x);
         }
     };
-    ty::EarlyBinder::bind(output)
+    if let Err(e) = icx.check_tainted_by_errors() {
+        ty::EarlyBinder::bind(Ty::new_error(tcx, e))
+    } else {
+        ty::EarlyBinder::bind(output)
+    }
 }
 
 pub(super) fn type_of_opaque(
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 7edb5912dd5..b6b33299315 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -802,7 +802,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .explicit_item_bounds(def_id)
                 .iter_instantiated_copied(self.tcx, args)
                 .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
-            ty::Error(_) => return None,
+            ty::Error(_) => return Some(ret_ty),
             _ => span_bug!(
                 closure_span,
                 "async fn coroutine return type not an inference variable: {ret_ty}"
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index c56a028321a..3430a5fb00d 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -498,14 +498,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                     // order when emitting them.
                     let err =
                         self.tcx().dcx().struct_span_err(span, format!("user args: {user_args:?}"));
-                    err.buffer(&mut errors_buffer);
+                    errors_buffer.push(err);
                 }
             }
 
             if !errors_buffer.is_empty() {
                 errors_buffer.sort_by_key(|diag| diag.span.primary_span());
-                for diag in errors_buffer {
-                    self.tcx().dcx().emit_diagnostic(diag);
+                for err in errors_buffer {
+                    err.emit();
                 }
             }
         }
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 6c000380e71..03335996c03 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -82,7 +82,7 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec<String>) -> Cfg {
                     Ok(..) => {}
                     Err(err) => err.cancel(),
                 },
-                Err(errs) => drop(errs),
+                Err(errs) => errs.into_iter().for_each(|err| err.cancel()),
             }
 
             // If the user tried to use a key="value" flag, but is missing the quotes, provide
@@ -129,9 +129,12 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
             error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`")
         };
 
-        let Ok(mut parser) = maybe_new_parser_from_source_str(&sess, filename, s.to_string())
-        else {
-            expected_error();
+        let mut parser = match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) {
+            Ok(parser) => parser,
+            Err(errs) => {
+                errs.into_iter().for_each(|err| err.cancel());
+                expected_error();
+            }
         };
 
         let meta_item = match parser.parse_meta_item() {
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 40e6b1b579f..b6fa2f1f221 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -532,8 +532,14 @@ lint_unknown_gated_lint =
 
 lint_unknown_lint =
     unknown lint: `{$name}`
-    .suggestion = did you mean
-    .help = did you mean: `{$replace}`
+    .suggestion = {$from_rustc ->
+        [true] a lint with a similar name exists in `rustc` lints
+        *[false] did you mean
+    }
+    .help = {$from_rustc ->
+        [true] a lint with a similar name exists in `rustc` lints: `{$replace}`
+        *[false] did you mean: `{$replace}`
+    }
 
 lint_unknown_tool_in_scoped_lint = unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`
     .help = add `#![register_tool({$tool_name})]` to the crate root
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index d0fd019a8b1..ffd8f1b3c79 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -33,7 +33,7 @@ use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, Ty
 use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId};
 use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
 use rustc_session::{LintStoreMarker, Session};
-use rustc_span::edit_distance::find_best_match_for_name;
+use rustc_span::edit_distance::find_best_match_for_names;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
 use rustc_target::abi;
@@ -117,7 +117,7 @@ struct LintGroup {
 pub enum CheckLintNameResult<'a> {
     Ok(&'a [LintId]),
     /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
-    NoLint(Option<Symbol>),
+    NoLint(Option<(Symbol, bool)>),
     /// The lint refers to a tool that has not been registered.
     NoTool,
     /// The lint has been renamed to a new name.
@@ -377,7 +377,7 @@ impl LintStore {
                         debug!("lints={:?}", self.by_name.keys().collect::<Vec<_>>());
                         let tool_prefix = format!("{tool_name}::");
                         return if self.by_name.keys().any(|lint| lint.starts_with(&tool_prefix)) {
-                            self.no_lint_suggestion(&complete_name)
+                            self.no_lint_suggestion(&complete_name, tool_name.as_str())
                         } else {
                             // 2. The tool isn't currently running, so no lints will be registered.
                             // To avoid giving a false positive, ignore all unknown lints.
@@ -419,13 +419,14 @@ impl LintStore {
         }
     }
 
-    fn no_lint_suggestion(&self, lint_name: &str) -> CheckLintNameResult<'_> {
+    fn no_lint_suggestion(&self, lint_name: &str, tool_name: &str) -> CheckLintNameResult<'_> {
         let name_lower = lint_name.to_lowercase();
 
         if lint_name.chars().any(char::is_uppercase) && self.find_lints(&name_lower).is_ok() {
             // First check if the lint name is (partly) in upper case instead of lower case...
-            return CheckLintNameResult::NoLint(Some(Symbol::intern(&name_lower)));
+            return CheckLintNameResult::NoLint(Some((Symbol::intern(&name_lower), false)));
         }
+
         // ...if not, search for lints with a similar name
         // Note: find_best_match_for_name depends on the sort order of its input vector.
         // To ensure deterministic output, sort elements of the lint_groups hash map.
@@ -441,7 +442,16 @@ impl LintStore {
         let groups = groups.iter().map(|k| Symbol::intern(k));
         let lints = self.lints.iter().map(|l| Symbol::intern(&l.name_lower()));
         let names: Vec<Symbol> = groups.chain(lints).collect();
-        let suggestion = find_best_match_for_name(&names, Symbol::intern(&name_lower), None);
+        let mut lookups = vec![Symbol::intern(&name_lower)];
+        if let Some(stripped) = name_lower.split("::").last() {
+            lookups.push(Symbol::intern(stripped));
+        }
+        let res = find_best_match_for_names(&names, &lookups, None);
+        let is_rustc = res.map_or_else(
+            || false,
+            |s| name_lower.contains("::") && !s.as_str().starts_with(tool_name),
+        );
+        let suggestion = res.map(|s| (s, is_rustc));
         CheckLintNameResult::NoLint(suggestion)
     }
 
@@ -454,7 +464,7 @@ impl LintStore {
         match self.by_name.get(&complete_name) {
             None => match self.lint_groups.get(&*complete_name) {
                 // Now we are sure, that this lint exists nowhere
-                None => self.no_lint_suggestion(lint_name),
+                None => self.no_lint_suggestion(lint_name, tool_name),
                 Some(LintGroup { lint_ids, depr, .. }) => {
                     // Reaching this would be weird, but let's cover this case anyway
                     if let Some(LintAlias { name, silent }) = depr {
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 75756c6946a..9e6a6f70eac 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -356,6 +356,12 @@ pub(super) fn builtin(
                 }
             }
 
+            // We don't want to suggest adding values to well known names
+            // since those are defined by rustc it-self. Users can still
+            // do it if they want, but should not encourage them.
+            let is_cfg_a_well_know_name =
+                sess.parse_sess.check_config.well_known_names.contains(&name);
+
             let inst = if let Some((value, _value_span)) = value {
                 let pre = if is_from_cargo { "\\" } else { "" };
                 format!("cfg({name}, values({pre}\"{value}{pre}\"))")
@@ -368,12 +374,14 @@ pub(super) fn builtin(
                     if let Some((value, _value_span)) = value {
                         db.help(format!("consider adding `{value}` as a feature in `Cargo.toml`"));
                     }
-                } else {
+                } else if !is_cfg_a_well_know_name {
                     db.help(format!("consider using a Cargo feature instead or adding `println!(\"cargo:rustc-check-cfg={inst}\");` to the top of a `build.rs`"));
                 }
                 db.note("see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration");
             } else {
-                db.help(format!("to expect this configuration use `--check-cfg={inst}`"));
+                if !is_cfg_a_well_know_name {
+                    db.help(format!("to expect this configuration use `--check-cfg={inst}`"));
+                }
                 db.note("see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration");
             }
         }
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 49821437b76..3c2d0c7b205 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -582,8 +582,9 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                 }
                 CheckLintNameResult::NoLint(suggestion) => {
                     let name = lint_name.clone();
-                    let suggestion =
-                        suggestion.map(|replace| UnknownLintSuggestion::WithoutSpan { replace });
+                    let suggestion = suggestion.map(|(replace, from_rustc)| {
+                        UnknownLintSuggestion::WithoutSpan { replace, from_rustc }
+                    });
                     let requested_level = RequestedLevel { level, lint_name };
                     let lint = UnknownLintFromCommandLine { name, suggestion, requested_level };
                     self.emit_lint(UNKNOWN_LINTS, lint);
@@ -990,8 +991,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                         } else {
                             name.to_string()
                         };
-                        let suggestion = suggestion.map(|replace| {
-                            UnknownLintSuggestion::WithSpan { suggestion: sp, replace }
+                        let suggestion = suggestion.map(|(replace, from_rustc)| {
+                            UnknownLintSuggestion::WithSpan { suggestion: sp, replace, from_rustc }
                         });
                         let lint = UnknownLint { name, suggestion };
                         self.emit_spanned_lint(UNKNOWN_LINTS, sp.into(), lint);
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index bc9a9d7b745..f370c4392b3 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1050,9 +1050,10 @@ pub enum UnknownLintSuggestion {
         #[primary_span]
         suggestion: Span,
         replace: Symbol,
+        from_rustc: bool,
     },
     #[help(lint_help)]
-    WithoutSpan { replace: Symbol },
+    WithoutSpan { replace: Symbol, from_rustc: bool },
 }
 
 #[derive(LintDiagnostic)]
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 0386f2ec56c..0f4528d1d5c 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1071,17 +1071,31 @@ impl UnusedParens {
             self.emit_unused_delims(cx, value.span, spans, "pattern", keep_space, false);
         }
     }
+
+    fn cast_followed_by_lt(&self, expr: &ast::Expr) -> Option<ast::NodeId> {
+        if let ExprKind::Binary(op, lhs, _rhs) = &expr.kind
+            && (op.node == ast::BinOpKind::Lt || op.node == ast::BinOpKind::Shl)
+        {
+            let mut cur = lhs;
+            while let ExprKind::Binary(_, _, rhs) = &cur.kind {
+                cur = rhs;
+            }
+
+            if let ExprKind::Cast(_, ty) = &cur.kind
+                && let ast::TyKind::Paren(_) = &ty.kind
+            {
+                return Some(ty.id);
+            }
+        }
+        None
+    }
 }
 
 impl EarlyLintPass for UnusedParens {
     #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
-        if let ExprKind::Binary(op, lhs, _rhs) = &e.kind
-            && (op.node == ast::BinOpKind::Lt || op.node == ast::BinOpKind::Shl)
-            && let ExprKind::Cast(_expr, ty) = &lhs.kind
-            && let ast::TyKind::Paren(_) = &ty.kind
-        {
-            self.parens_in_cast_in_lt.push(ty.id);
+        if let Some(ty_id) = self.cast_followed_by_lt(e) {
+            self.parens_in_cast_in_lt.push(ty_id);
         }
 
         match e.kind {
@@ -1133,17 +1147,13 @@ impl EarlyLintPass for UnusedParens {
     }
 
     fn check_expr_post(&mut self, _cx: &EarlyContext<'_>, e: &ast::Expr) {
-        if let ExprKind::Binary(op, lhs, _rhs) = &e.kind
-            && (op.node == ast::BinOpKind::Lt || op.node == ast::BinOpKind::Shl)
-            && let ExprKind::Cast(_expr, ty) = &lhs.kind
-            && let ast::TyKind::Paren(_) = &ty.kind
-        {
+        if let Some(ty_id) = self.cast_followed_by_lt(e) {
             let id = self
                 .parens_in_cast_in_lt
                 .pop()
                 .expect("check_expr and check_expr_post must balance");
             assert_eq!(
-                id, ty.id,
+                id, ty_id,
                 "check_expr, check_ty, and check_expr_post are called, in that order, by the visitor"
             );
         }
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 76eb6bfaef7..6114f7c8678 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -531,9 +531,12 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
 
 // Unfortunately, the LLVM C API doesn't provide a way to create the
 // TargetLibraryInfo pass, so we use this method to do so.
-extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M) {
+extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
+                                       bool DisableSimplifyLibCalls) {
   Triple TargetTriple(unwrap(M)->getTargetTriple());
   TargetLibraryInfoImpl TLII(TargetTriple);
+  if (DisableSimplifyLibCalls)
+    TLII.disableAllFunctions();
   unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
 }
 
@@ -700,7 +703,7 @@ LLVMRustOptimize(
     bool IsLinkerPluginLTO,
     bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers,
     bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize,
-    bool EmitLifetimeMarkers,
+    bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers,
     LLVMRustSanitizerOptions *SanitizerOptions,
     const char *PGOGenPath, const char *PGOUsePath,
     bool InstrumentCoverage, const char *InstrProfileOutput,
@@ -800,6 +803,8 @@ LLVMRustOptimize(
 
   Triple TargetTriple(TheModule->getTargetTriple());
   std::unique_ptr<TargetLibraryInfoImpl> TLII(new TargetLibraryInfoImpl(TargetTriple));
+  if (DisableSimplifyLibCalls)
+    TLII->disableAllFunctions();
   FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
 
   PB.registerModuleAnalyses(MAM);
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index 9ca7ce09ba6..98b53945b91 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -76,8 +76,17 @@ fn decodable_body(
                 ty_name,
                 variants.len()
             );
+            let tag = if variants.len() < u8::MAX as usize {
+                quote! {
+                    ::rustc_serialize::Decoder::read_u8(__decoder) as usize
+                }
+            } else {
+                quote! {
+                    ::rustc_serialize::Decoder::read_usize(__decoder)
+                }
+            };
             quote! {
-                match ::rustc_serialize::Decoder::read_usize(__decoder) {
+                match #tag {
                     #match_inner
                     n => panic!(#message, n),
                 }
@@ -206,11 +215,20 @@ fn encodable_body(
                     variant_idx += 1;
                     result
                 });
-                quote! {
-                    let disc = match *self {
-                        #encode_inner
-                    };
-                    ::rustc_serialize::Encoder::emit_usize(__encoder, disc);
+                if variant_idx < u8::MAX as usize {
+                    quote! {
+                        let disc = match *self {
+                            #encode_inner
+                        };
+                        ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
+                    }
+                } else {
+                    quote! {
+                        let disc = match *self {
+                            #encode_inner
+                        };
+                        ::rustc_serialize::Encoder::emit_usize(__encoder, disc);
+                    }
                 }
             };
 
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 0ab09dadf58..8a4fd01437f 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -113,6 +113,7 @@ macro_rules! arena_types {
             [] stripped_cfg_items: rustc_ast::expand::StrippedCfgItem,
             [] mod_child: rustc_middle::metadata::ModChild,
             [] features: rustc_feature::Features,
+            [decode] specialization_graph: rustc_middle::traits::specialization_graph::Graph,
         ]);
     )
 }
diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs
index 59ce0a14b2a..e30b6b203d7 100644
--- a/compiler/rustc_middle/src/middle/exported_symbols.rs
+++ b/compiler/rustc_middle/src/middle/exported_symbols.rs
@@ -35,12 +35,7 @@ pub enum SymbolExportKind {
 pub struct SymbolExportInfo {
     pub level: SymbolExportLevel,
     pub kind: SymbolExportKind,
-    /// Used to mark these symbols not to be internalized by LTO. These symbols
-    /// are also added to `symbols.o` to avoid circular dependencies when linking.
     pub used: bool,
-    /// Also used to mark these symbols not to be internalized by LTO. But will
-    /// not be added to `symbols.o`. Currently there are only builtin functions.
-    pub used_compiler: bool,
 }
 
 #[derive(Eq, PartialEq, Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 0e3b9984423..1dc77220881 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1294,8 +1294,7 @@ rustc_queries! {
         desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) }
     }
 
-    query specialization_graph_of(trait_id: DefId) -> &'tcx specialization_graph::Graph {
-        arena_cache
+    query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> {
         desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(trait_id) }
         cache_on_disk_if { true }
     }
diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs
index 31db4ba62fb..f4dfbe059eb 100644
--- a/compiler/rustc_middle/src/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/query/on_disk_cache.rs
@@ -786,6 +786,15 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsm
     }
 }
 
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
+    for &'tcx crate::traits::specialization_graph::Graph
+{
+    #[inline]
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
+        RefDecodable::decode(d)
+    }
+}
+
 macro_rules! impl_ref_decoder {
     (<$tcx:tt> $($ty:ty,)*) => {
         $(impl<'a, $tcx> Decodable<CacheDecoder<'a, $tcx>> for &$tcx [$ty] {
diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs
index 77d112d0afc..e94ad4aa539 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect.rs
@@ -73,6 +73,7 @@ pub struct CanonicalGoalEvaluation<'tcx> {
 pub enum CanonicalGoalEvaluationKind<'tcx> {
     Overflow,
     CycleInStack,
+    ProvisionalCacheHit,
     Evaluation { revisions: &'tcx [GoalEvaluationStep<'tcx>] },
 }
 impl Debug for GoalEvaluation<'_> {
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index 4e2207ed523..54db8dbd336 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -77,6 +77,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
             CanonicalGoalEvaluationKind::CycleInStack => {
                 writeln!(self.f, "CYCLE IN STACK: {:?}", eval.result)
             }
+            CanonicalGoalEvaluationKind::ProvisionalCacheHit => {
+                writeln!(self.f, "PROVISIONAL CACHE HIT: {:?}", eval.result)
+            }
             CanonicalGoalEvaluationKind::Evaluation { revisions } => {
                 for (n, step) in revisions.iter().enumerate() {
                     writeln!(self.f, "REVISION {n}")?;
diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs
index 898258445dc..ba29d4040a1 100644
--- a/compiler/rustc_middle/src/traits/specialization_graph.rs
+++ b/compiler/rustc_middle/src/traits/specialization_graph.rs
@@ -30,18 +30,16 @@ pub struct Graph {
 
     /// The "root" impls are found by looking up the trait's def_id.
     pub children: DefIdMap<Children>,
-
-    /// Whether an error was emitted while constructing the graph.
-    pub has_errored: Option<ErrorGuaranteed>,
 }
 
 impl Graph {
     pub fn new() -> Graph {
-        Graph { parent: Default::default(), children: Default::default(), has_errored: None }
+        Graph { parent: Default::default(), children: Default::default() }
     }
 
     /// The parent of a given impl, which is the `DefId` of the trait when the
     /// impl is a "specialization root".
+    #[track_caller]
     pub fn parent(&self, child: DefId) -> DefId {
         *self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {child:?}"))
     }
@@ -255,13 +253,9 @@ pub fn ancestors(
     trait_def_id: DefId,
     start_from_impl: DefId,
 ) -> Result<Ancestors<'_>, ErrorGuaranteed> {
-    let specialization_graph = tcx.specialization_graph_of(trait_def_id);
+    let specialization_graph = tcx.specialization_graph_of(trait_def_id)?;
 
-    if let Some(reported) = specialization_graph.has_errored {
-        Err(reported)
-    } else if let Err(reported) =
-        tcx.type_of(start_from_impl).instantiate_identity().error_reported()
-    {
+    if let Err(reported) = tcx.type_of(start_from_impl).instantiate_identity().error_reported() {
         Err(reported)
     } else {
         Ok(Ancestors {
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 6ed68f90eb3..b71919adc58 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -32,6 +32,7 @@ pub enum SimplifiedType {
     CoroutineWitness(DefId),
     Function(usize),
     Placeholder,
+    Error,
 }
 
 /// Generic parameters are pretty much just bound variables, e.g.
@@ -153,7 +154,8 @@ pub fn simplify_type<'tcx>(
             TreatParams::ForLookup | TreatParams::AsCandidateKey => None,
         },
         ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)),
-        ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None,
+        ty::Error(_) => Some(SimplifiedType::Error),
+        ty::Bound(..) | ty::Infer(_) => None,
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index bf9b244936f..227a0753d04 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -1,6 +1,5 @@
 use crate::traits::specialization_graph;
 use crate::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections};
-use crate::ty::visit::TypeVisitableExt;
 use crate::ty::{Ident, Ty, TyCtxt};
 use hir::def_id::LOCAL_CRATE;
 use rustc_hir as hir;
@@ -241,9 +240,6 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
         let impl_def_id = impl_def_id.to_def_id();
 
         let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();
-        if impl_self_ty.references_error() {
-            continue;
-        }
 
         if let Some(simplified_self_ty) =
             fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::AsCandidateKey)
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 43c5b3873b9..ce9043ec287 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -566,17 +566,28 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         body,
         &[
             &check_alignment::CheckAlignment,
-            &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
+            // Before inlining: trim down MIR with passes to reduce inlining work.
+
+            // Has to be done before inlining, otherwise actual call will be almost always inlined.
+            // Also simple, so can just do first
+            &lower_slice_len::LowerSliceLenCalls,
+            // Perform inlining, which may add a lot of code.
             &inline::Inline,
-            // Substitutions during inlining may introduce switch on enums with uninhabited branches.
+            // Code from other crates may have storage markers, so this needs to happen after inlining.
+            &remove_storage_markers::RemoveStorageMarkers,
+            // Inlining and substitution may introduce ZST and useless drops.
+            &remove_zsts::RemoveZsts,
+            &remove_unneeded_drops::RemoveUnneededDrops,
+            // Type substitution may create uninhabited enums.
             &uninhabited_enum_branching::UninhabitedEnumBranching,
             &unreachable_prop::UnreachablePropagation,
             &o1(simplify::SimplifyCfg::AfterUninhabitedEnumBranching),
-            &remove_storage_markers::RemoveStorageMarkers,
-            &remove_zsts::RemoveZsts,
-            &normalize_array_len::NormalizeArrayLen, // has to run after `slice::len` lowering
+            // Inlining may have introduced a lot of redundant code and a large move pattern.
+            // Now, we need to shrink the generated MIR.
+
+            // Has to run after `slice::len` lowering
+            &normalize_array_len::NormalizeArrayLen,
             &const_goto::ConstGoto,
-            &remove_unneeded_drops::RemoveUnneededDrops,
             &ref_prop::ReferencePropagation,
             &sroa::ScalarReplacementOfAggregates,
             &match_branches::MatchBranchSimplification,
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index e27875853df..94b553a07a7 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -20,6 +20,9 @@ monomorphize_recursion_limit =
     reached the recursion limit while instantiating `{$shrunk}`
     .note = `{$def_path_str}` defined here
 
+monomorphize_start_not_found = using `fn main` requires the standard library
+    .help = use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]`
+
 monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
 
 monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 44beafa0873..92f001cc321 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -194,7 +194,7 @@ use rustc_target::abi::Size;
 use std::path::PathBuf;
 
 use crate::errors::{
-    EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit,
+    self, EncounteredErrorWhileInstantiating, LargeAssignmentsLint, NoOptimizedMir, RecursionLimit,
     TypeLengthLimit,
 };
 
@@ -1272,7 +1272,9 @@ impl<'v> RootCollector<'_, 'v> {
             return;
         };
 
-        let start_def_id = self.tcx.require_lang_item(LangItem::Start, None);
+        let Some(start_def_id) = self.tcx.lang_items().start_fn() else {
+            self.tcx.dcx().emit_fatal(errors::StartNotFound);
+        };
         let main_ret_ty = self.tcx.fn_sig(main_def_id).no_bound_vars().unwrap().output();
 
         // Given that `main()` has no arguments,
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 2ca14673a58..bd89874b5cc 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -95,6 +95,11 @@ pub struct EncounteredErrorWhileInstantiating {
 }
 
 #[derive(Diagnostic)]
+#[diag(monomorphize_start_not_found)]
+#[help]
+pub struct StartNotFound;
+
+#[derive(Diagnostic)]
 #[diag(monomorphize_unknown_cgu_collection_mode)]
 pub struct UnknownCguCollectionMode<'a> {
     pub mode: &'a str,
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 7db9291921f..d7ecf577ed6 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -7,7 +7,7 @@ use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::unicode::contains_text_flow_control_chars;
-use rustc_errors::{error_code, Applicability, DiagCtxt, Diagnostic, StashKey};
+use rustc_errors::{error_code, Applicability, DiagCtxt, DiagnosticBuilder, StashKey};
 use rustc_lexer::unescape::{self, EscapeError, Mode};
 use rustc_lexer::{Base, DocStyle, RawStrError};
 use rustc_lexer::{Cursor, LiteralKind};
@@ -42,12 +42,12 @@ pub struct UnmatchedDelim {
     pub candidate_span: Option<Span>,
 }
 
-pub(crate) fn parse_token_trees<'a>(
-    sess: &'a ParseSess,
-    mut src: &'a str,
+pub(crate) fn parse_token_trees<'sess, 'src>(
+    sess: &'sess ParseSess,
+    mut src: &'src str,
     mut start_pos: BytePos,
     override_span: Option<Span>,
-) -> Result<TokenStream, Vec<Diagnostic>> {
+) -> Result<TokenStream, Vec<DiagnosticBuilder<'sess>>> {
     // Skip `#!`, if present.
     if let Some(shebang_len) = rustc_lexer::strip_shebang(src) {
         src = &src[shebang_len..];
@@ -76,13 +76,13 @@ pub(crate) fn parse_token_trees<'a>(
             let mut buffer = Vec::with_capacity(1);
             for unmatched in unmatched_delims {
                 if let Some(err) = make_unclosed_delims_error(unmatched, sess) {
-                    err.buffer(&mut buffer);
+                    buffer.push(err);
                 }
             }
             if let Err(errs) = res {
                 // Add unclosing delimiter or diff marker errors
                 for err in errs {
-                    err.buffer(&mut buffer);
+                    buffer.push(err);
                 }
             }
             Err(buffer)
@@ -90,16 +90,16 @@ pub(crate) fn parse_token_trees<'a>(
     }
 }
 
-struct StringReader<'a> {
-    sess: &'a ParseSess,
+struct StringReader<'sess, 'src> {
+    sess: &'sess ParseSess,
     /// Initial position, read-only.
     start_pos: BytePos,
     /// The absolute offset within the source_map of the current character.
     pos: BytePos,
     /// Source text to tokenize.
-    src: &'a str,
+    src: &'src str,
     /// Cursor for getting lexer tokens.
-    cursor: Cursor<'a>,
+    cursor: Cursor<'src>,
     override_span: Option<Span>,
     /// When a "unknown start of token: \u{a0}" has already been emitted earlier
     /// in this file, it's safe to treat further occurrences of the non-breaking
@@ -107,8 +107,8 @@ struct StringReader<'a> {
     nbsp_is_whitespace: bool,
 }
 
-impl<'a> StringReader<'a> {
-    pub fn dcx(&self) -> &'a DiagCtxt {
+impl<'sess, 'src> StringReader<'sess, 'src> {
+    pub fn dcx(&self) -> &'sess DiagCtxt {
         &self.sess.dcx
     }
 
@@ -526,7 +526,7 @@ impl<'a> StringReader<'a> {
 
     /// Slice of the source text from `start` up to but excluding `self.pos`,
     /// meaning the slice does not include the character `self.ch`.
-    fn str_from(&self, start: BytePos) -> &'a str {
+    fn str_from(&self, start: BytePos) -> &'src str {
         self.str_from_to(start, self.pos)
     }
 
@@ -537,12 +537,12 @@ impl<'a> StringReader<'a> {
     }
 
     /// Slice of the source text spanning from `start` up to but excluding `end`.
-    fn str_from_to(&self, start: BytePos, end: BytePos) -> &'a str {
+    fn str_from_to(&self, start: BytePos, end: BytePos) -> &'src str {
         &self.src[self.src_index(start)..self.src_index(end)]
     }
 
     /// Slice of the source text spanning from `start` until the end
-    fn str_from_to_end(&self, start: BytePos) -> &'a str {
+    fn str_from_to_end(&self, start: BytePos) -> &'src str {
         &self.src[self.src_index(start)..]
     }
 
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 64b3928689a..c9ff2d58e2c 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -8,18 +8,18 @@ use rustc_ast_pretty::pprust::token_to_string;
 use rustc_errors::{Applicability, PErr};
 use rustc_span::symbol::kw;
 
-pub(super) struct TokenTreesReader<'a> {
-    string_reader: StringReader<'a>,
+pub(super) struct TokenTreesReader<'sess, 'src> {
+    string_reader: StringReader<'sess, 'src>,
     /// The "next" token, which has been obtained from the `StringReader` but
     /// not yet handled by the `TokenTreesReader`.
     token: Token,
     diag_info: TokenTreeDiagInfo,
 }
 
-impl<'a> TokenTreesReader<'a> {
+impl<'sess, 'src> TokenTreesReader<'sess, 'src> {
     pub(super) fn parse_all_token_trees(
-        string_reader: StringReader<'a>,
-    ) -> (TokenStream, Result<(), Vec<PErr<'a>>>, Vec<UnmatchedDelim>) {
+        string_reader: StringReader<'sess, 'src>,
+    ) -> (TokenStream, Result<(), Vec<PErr<'sess>>>, Vec<UnmatchedDelim>) {
         let mut tt_reader = TokenTreesReader {
             string_reader,
             token: Token::dummy(),
@@ -35,7 +35,7 @@ impl<'a> TokenTreesReader<'a> {
     fn parse_token_trees(
         &mut self,
         is_delimited: bool,
-    ) -> (Spacing, TokenStream, Result<(), Vec<PErr<'a>>>) {
+    ) -> (Spacing, TokenStream, Result<(), Vec<PErr<'sess>>>) {
         // Move past the opening delimiter.
         let (_, open_spacing) = self.bump(false);
 
@@ -71,7 +71,7 @@ impl<'a> TokenTreesReader<'a> {
         }
     }
 
-    fn eof_err(&mut self) -> PErr<'a> {
+    fn eof_err(&mut self) -> PErr<'sess> {
         let msg = "this file contains an unclosed delimiter";
         let mut err = self.string_reader.sess.dcx.struct_span_err(self.token.span, msg);
         for &(_, sp) in &self.diag_info.open_braces {
@@ -99,7 +99,7 @@ impl<'a> TokenTreesReader<'a> {
     fn parse_token_tree_open_delim(
         &mut self,
         open_delim: Delimiter,
-    ) -> Result<TokenTree, Vec<PErr<'a>>> {
+    ) -> Result<TokenTree, Vec<PErr<'sess>>> {
         // The span for beginning of the delimited section
         let pre_span = self.token.span;
 
@@ -229,7 +229,11 @@ impl<'a> TokenTreesReader<'a> {
         (this_tok, this_spacing)
     }
 
-    fn unclosed_delim_err(&mut self, tts: TokenStream, mut errs: Vec<PErr<'a>>) -> Vec<PErr<'a>> {
+    fn unclosed_delim_err(
+        &mut self,
+        tts: TokenStream,
+        mut errs: Vec<PErr<'sess>>,
+    ) -> Vec<PErr<'sess>> {
         // If there are unclosed delims, see if there are diff markers and if so, point them
         // out instead of complaining about the unclosed delims.
         let mut parser = crate::stream_to_parser(self.string_reader.sess, tts, None);
@@ -285,7 +289,7 @@ impl<'a> TokenTreesReader<'a> {
         return errs;
     }
 
-    fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> {
+    fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'sess> {
         // An unexpected closing delimiter (i.e., there is no
         // matching opening delimiter).
         let token_str = token_to_string(&self.token);
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index dac7569e385..a136abaa28b 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -337,7 +337,7 @@ const ASCII_ARRAY: &[(&str, &str, Option<token::TokenKind>)] = &[
 ];
 
 pub(super) fn check_for_substitution(
-    reader: &StringReader<'_>,
+    reader: &StringReader<'_, '_>,
     pos: BytePos,
     ch: char,
     count: usize,
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index b93f08a21e3..c00e318f227 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -19,7 +19,7 @@ use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{AttrItem, Attribute, MetaItem};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Diagnostic, FatalError, Level, PResult};
+use rustc_errors::{DiagnosticBuilder, FatalError, PResult};
 use rustc_session::parse::ParseSess;
 use rustc_span::{FileName, SourceFile, Span};
 
@@ -45,14 +45,13 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 /// A variant of 'panictry!' that works on a `Vec<Diagnostic>` instead of a single
 /// `DiagnosticBuilder`.
 macro_rules! panictry_buffer {
-    ($handler:expr, $e:expr) => {{
-        use rustc_errors::FatalError;
+    ($e:expr) => {{
         use std::result::Result::{Err, Ok};
         match $e {
             Ok(e) => e,
             Err(errs) => {
                 for e in errs {
-                    $handler.emit_diagnostic(e);
+                    e.emit();
                 }
                 FatalError.raise()
             }
@@ -100,36 +99,41 @@ pub fn parse_stream_from_source_str(
 
 /// Creates a new parser from a source string.
 pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String) -> Parser<'_> {
-    panictry_buffer!(&sess.dcx, maybe_new_parser_from_source_str(sess, name, source))
+    panictry_buffer!(maybe_new_parser_from_source_str(sess, name, source))
 }
 
 /// Creates a new parser from a source string. Returns any buffered errors from lexing the initial
-/// token stream.
+/// token stream; these must be consumed via `emit`, `cancel`, etc., otherwise a panic will occur
+/// when they are dropped.
 pub fn maybe_new_parser_from_source_str(
     sess: &ParseSess,
     name: FileName,
     source: String,
-) -> Result<Parser<'_>, Vec<Diagnostic>> {
+) -> Result<Parser<'_>, Vec<DiagnosticBuilder<'_>>> {
     maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))
 }
 
-/// Creates a new parser, handling errors as appropriate if the file doesn't exist.
-/// If a span is given, that is used on an error as the source of the problem.
+/// Creates a new parser, aborting if the file doesn't exist. If a span is given, that is used on
+/// an error as the source of the problem.
 pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, sp: Option<Span>) -> Parser<'a> {
-    source_file_to_parser(sess, file_to_source_file(sess, path, sp))
-}
+    let source_file = sess.source_map().load_file(path).unwrap_or_else(|e| {
+        let msg = format!("couldn't read {}: {}", path.display(), e);
+        let mut err = sess.dcx.struct_fatal(msg);
+        if let Some(sp) = sp {
+            err.span(sp);
+        }
+        err.emit();
+    });
 
-/// Given a session and a `source_file`, returns a parser.
-fn source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Parser<'_> {
-    panictry_buffer!(&sess.dcx, maybe_source_file_to_parser(sess, source_file))
+    panictry_buffer!(maybe_source_file_to_parser(sess, source_file))
 }
 
-/// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing the
-/// initial token stream.
+/// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing
+/// the initial token stream.
 fn maybe_source_file_to_parser(
     sess: &ParseSess,
     source_file: Lrc<SourceFile>,
-) -> Result<Parser<'_>, Vec<Diagnostic>> {
+) -> Result<Parser<'_>, Vec<DiagnosticBuilder<'_>>> {
     let end_pos = source_file.end_position();
     let stream = maybe_file_to_stream(sess, source_file, None)?;
     let mut parser = stream_to_parser(sess, stream, None);
@@ -142,52 +146,22 @@ fn maybe_source_file_to_parser(
 
 // Base abstractions
 
-/// Given a session and a path and an optional span (for error reporting),
-/// add the path to the session's source_map and return the new source_file or
-/// error when a file can't be read.
-fn try_file_to_source_file(
-    sess: &ParseSess,
-    path: &Path,
-    spanopt: Option<Span>,
-) -> Result<Lrc<SourceFile>, Diagnostic> {
-    sess.source_map().load_file(path).map_err(|e| {
-        let msg = format!("couldn't read {}: {}", path.display(), e);
-        let mut diag = Diagnostic::new(Level::Fatal, msg);
-        if let Some(sp) = spanopt {
-            diag.span(sp);
-        }
-        diag
-    })
-}
-
-/// Given a session and a path and an optional span (for error reporting),
-/// adds the path to the session's `source_map` and returns the new `source_file`.
-fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>) -> Lrc<SourceFile> {
-    match try_file_to_source_file(sess, path, spanopt) {
-        Ok(source_file) => source_file,
-        Err(d) => {
-            sess.dcx.emit_diagnostic(d);
-            FatalError.raise();
-        }
-    }
-}
-
 /// Given a `source_file`, produces a sequence of token trees.
 pub fn source_file_to_stream(
     sess: &ParseSess,
     source_file: Lrc<SourceFile>,
     override_span: Option<Span>,
 ) -> TokenStream {
-    panictry_buffer!(&sess.dcx, maybe_file_to_stream(sess, source_file, override_span))
+    panictry_buffer!(maybe_file_to_stream(sess, source_file, override_span))
 }
 
 /// Given a source file, produces a sequence of token trees. Returns any buffered errors from
 /// parsing the token stream.
-pub fn maybe_file_to_stream(
-    sess: &ParseSess,
+fn maybe_file_to_stream<'sess>(
+    sess: &'sess ParseSess,
     source_file: Lrc<SourceFile>,
     override_span: Option<Span>,
-) -> Result<TokenStream, Vec<Diagnostic>> {
+) -> Result<TokenStream, Vec<DiagnosticBuilder<'sess>>> {
     let src = source_file.src.as_ref().unwrap_or_else(|| {
         sess.dcx.bug(format!(
             "cannot lex `source_file` without source: {}",
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index be50aad1303..d41cc724408 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -575,6 +575,11 @@ passes_outside_loop =
 
 passes_outside_loop_suggestion = consider labeling this block to be able to break within it
 
+passes_panic_unwind_without_std =
+    unwinding panics are not supported without std
+    .note = since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
+    .help = using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
+
 passes_params_not_allowed =
     referencing function parameters is not allowed in naked functions
     .help = follow the calling convention in asm block to use parameters
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index d934e959a41..cf3c7cc4ace 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -813,6 +813,12 @@ pub struct UnknownExternLangItem {
 pub struct MissingPanicHandler;
 
 #[derive(Diagnostic)]
+#[diag(passes_panic_unwind_without_std)]
+#[help]
+#[note]
+pub struct PanicUnwindWithoutStd;
+
+#[derive(Diagnostic)]
 #[diag(passes_missing_lang_item)]
 #[note]
 #[help]
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index db3d442676e..4eb0c6c275e 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -9,7 +9,9 @@ use rustc_middle::middle::lang_items::required;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::CrateType;
 
-use crate::errors::{MissingLangItem, MissingPanicHandler, UnknownExternLangItem};
+use crate::errors::{
+    MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd, UnknownExternLangItem,
+};
 
 /// Checks the crate for usage of weak lang items, returning a vector of all the
 /// language items required by this crate, but not defined yet.
@@ -76,6 +78,8 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) {
         if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() {
             if item == LangItem::PanicImpl {
                 tcx.dcx().emit_err(MissingPanicHandler);
+            } else if item == LangItem::EhPersonality {
+                tcx.dcx().emit_err(PanicUnwindWithoutStd);
             } else {
                 tcx.dcx().emit_err(MissingLangItem { name: item.name() });
             }
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index b52643adcc9..374914055d8 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -124,8 +124,10 @@ pub fn analyze_match<'p, 'tcx>(
 
     let pat_column = PatternColumn::new(arms);
 
-    // Lint on ranges that overlap on their endpoints, which is likely a mistake.
-    lint_overlapping_range_endpoints(cx, &pat_column)?;
+    // Lint ranges that overlap on their endpoints, which is likely a mistake.
+    if !report.overlapping_range_endpoints.is_empty() {
+        lint_overlapping_range_endpoints(cx, &report.overlapping_range_endpoints);
+    }
 
     // Run the non_exhaustive_omitted_patterns lint. Only run on refutable patterns to avoid hitting
     // `if let`s. Only run if the match is exhaustive otherwise the error is redundant.
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index 52c9af85006..cfe4ca3ce93 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -1,20 +1,14 @@
-use smallvec::SmallVec;
-
-use rustc_data_structures::captures::Captures;
-use rustc_middle::ty;
 use rustc_session::lint;
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
-use rustc_span::{ErrorGuaranteed, Span};
+use rustc_span::ErrorGuaranteed;
 
-use crate::constructor::{IntRange, MaybeInfiniteInt};
 use crate::errors::{
-    NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Overlap,
-    OverlappingRangeEndpoints, Uncovered,
+    self, NonExhaustiveOmittedPattern, NonExhaustiveOmittedPatternLintOnArm, Uncovered,
 };
 use crate::pat::PatOrWild;
 use crate::rustc::{
-    Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy, RustcMatchCheckCtxt,
-    SplitConstructorSet, WitnessPat,
+    self, Constructor, DeconstructedPat, MatchArm, MatchCtxt, PlaceCtxt, RevealedTy,
+    RustcMatchCheckCtxt, SplitConstructorSet, WitnessPat,
 };
 
 /// A column of patterns in the matrix, where a column is the intuitive notion of "subpatterns that
@@ -68,10 +62,6 @@ impl<'p, 'tcx> PatternColumn<'p, 'tcx> {
         Ok(ctors_for_ty.split(pcx, column_ctors))
     }
 
-    fn iter(&self) -> impl Iterator<Item = &'p DeconstructedPat<'p, 'tcx>> + Captures<'_> {
-        self.patterns.iter().copied()
-    }
-
     /// Does specialization: given a constructor, this takes the patterns from the column that match
     /// the constructor, and outputs their fields.
     /// This returns one column per field of the constructor. They usually all have the same length
@@ -207,78 +197,25 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
     Ok(())
 }
 
-/// Traverse the patterns to warn the user about ranges that overlap on their endpoints.
-#[instrument(level = "debug", skip(cx))]
 pub(crate) fn lint_overlapping_range_endpoints<'a, 'p, 'tcx>(
     cx: MatchCtxt<'a, 'p, 'tcx>,
-    column: &PatternColumn<'p, 'tcx>,
-) -> Result<(), ErrorGuaranteed> {
-    let Some(ty) = column.head_ty() else {
-        return Ok(());
-    };
-    let pcx = &PlaceCtxt::new_dummy(cx, ty);
-    let rcx: &RustcMatchCheckCtxt<'_, '_> = cx.tycx;
-
-    let set = column.analyze_ctors(pcx)?;
-
-    if matches!(ty.kind(), ty::Char | ty::Int(_) | ty::Uint(_)) {
-        let emit_lint = |overlap: &IntRange, this_span: Span, overlapped_spans: &[Span]| {
-            let overlap_as_pat = rcx.hoist_pat_range(overlap, ty);
-            let overlaps: Vec<_> = overlapped_spans
-                .iter()
-                .copied()
-                .map(|span| Overlap { range: overlap_as_pat.clone(), span })
-                .collect();
-            rcx.tcx.emit_spanned_lint(
-                lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
-                rcx.match_lint_level,
-                this_span,
-                OverlappingRangeEndpoints { overlap: overlaps, range: this_span },
-            );
-        };
-
-        // If two ranges overlapped, the split set will contain their intersection as a singleton.
-        let split_int_ranges = set.present.iter().filter_map(|c| c.as_int_range());
-        for overlap_range in split_int_ranges.clone() {
-            if overlap_range.is_singleton() {
-                let overlap: MaybeInfiniteInt = overlap_range.lo;
-                // Ranges that look like `lo..=overlap`.
-                let mut prefixes: SmallVec<[_; 1]> = Default::default();
-                // Ranges that look like `overlap..=hi`.
-                let mut suffixes: SmallVec<[_; 1]> = Default::default();
-                // Iterate on patterns that contained `overlap`.
-                for pat in column.iter() {
-                    let Constructor::IntRange(this_range) = pat.ctor() else { continue };
-                    let this_span = pat.data().unwrap().span;
-                    if this_range.is_singleton() {
-                        // Don't lint when one of the ranges is a singleton.
-                        continue;
-                    }
-                    if this_range.lo == overlap {
-                        // `this_range` looks like `overlap..=this_range.hi`; it overlaps with any
-                        // ranges that look like `lo..=overlap`.
-                        if !prefixes.is_empty() {
-                            emit_lint(overlap_range, this_span, &prefixes);
-                        }
-                        suffixes.push(this_span)
-                    } else if this_range.hi == overlap.plus_one() {
-                        // `this_range` looks like `this_range.lo..=overlap`; it overlaps with any
-                        // ranges that look like `overlap..=hi`.
-                        if !suffixes.is_empty() {
-                            emit_lint(overlap_range, this_span, &suffixes);
-                        }
-                        prefixes.push(this_span)
-                    }
-                }
-            }
-        }
-    } else {
-        // Recurse into the fields.
-        for ctor in set.present {
-            for col in column.specialize(pcx, &ctor) {
-                lint_overlapping_range_endpoints(cx, &col)?;
-            }
-        }
+    overlapping_range_endpoints: &[rustc::OverlappingRanges<'p, 'tcx>],
+) {
+    let rcx = cx.tycx;
+    for overlap in overlapping_range_endpoints {
+        let overlap_as_pat = rcx.hoist_pat_range(&overlap.overlaps_on, overlap.pat.ty());
+        let overlaps: Vec<_> = overlap
+            .overlaps_with
+            .iter()
+            .map(|pat| pat.data().unwrap().span)
+            .map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
+            .collect();
+        let pat_span = overlap.pat.data().unwrap().span;
+        rcx.tcx.emit_spanned_lint(
+            lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
+            rcx.match_lint_level,
+            pat_span,
+            errors::OverlappingRangeEndpoints { overlap: overlaps, range: pat_span },
+        );
     }
-    Ok(())
 }
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index a8d1bece613..a17cd2c81b9 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -34,6 +34,8 @@ pub type DeconstructedPat<'p, 'tcx> =
     crate::pat::DeconstructedPat<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type MatchArm<'p, 'tcx> = crate::MatchArm<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub type MatchCtxt<'a, 'p, 'tcx> = crate::MatchCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>;
+pub type OverlappingRanges<'p, 'tcx> =
+    crate::usefulness::OverlappingRanges<'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub(crate) type PlaceCtxt<'a, 'p, 'tcx> =
     crate::usefulness::PlaceCtxt<'a, 'p, RustcMatchCheckCtxt<'p, 'tcx>>;
 pub(crate) type SplitConstructorSet<'p, 'tcx> =
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index b4935d280e6..85b6a6a3b6c 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -712,10 +712,11 @@
 //! I (Nadrieril) prefer to put new tests in `ui/pattern/usefulness` unless there's a specific
 //! reason not to, for example if they crucially depend on a particular feature like `or_patterns`.
 
+use rustc_index::bit_set::BitSet;
 use smallvec::{smallvec, SmallVec};
 use std::fmt;
 
-use crate::constructor::{Constructor, ConstructorSet};
+use crate::constructor::{Constructor, ConstructorSet, IntRange};
 use crate::pat::{DeconstructedPat, PatOrWild, WitnessPat};
 use crate::{Captures, MatchArm, MatchCtxt, TypeCx};
 
@@ -911,6 +912,11 @@ struct MatrixRow<'p, Cx: TypeCx> {
     /// [`compute_exhaustiveness_and_usefulness`] if the arm is found to be useful.
     /// This is reset to `false` when specializing.
     useful: bool,
+    /// Tracks which rows above this one have an intersection with this one, i.e. such that there is
+    /// a value that matches both rows.
+    /// Note: Because of relevancy we may miss some intersections. The intersections we do find are
+    /// correct.
+    intersects: BitSet<usize>,
 }
 
 impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> {
@@ -938,6 +944,7 @@ impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> {
             parent_row: self.parent_row,
             is_under_guard: self.is_under_guard,
             useful: false,
+            intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`.
         })
     }
 
@@ -955,6 +962,7 @@ impl<'p, Cx: TypeCx> MatrixRow<'p, Cx> {
             parent_row,
             is_under_guard: self.is_under_guard,
             useful: false,
+            intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`.
         }
     }
 }
@@ -993,13 +1001,15 @@ struct Matrix<'p, Cx: TypeCx> {
 impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
     /// Pushes a new row to the matrix. If the row starts with an or-pattern, this recursively
     /// expands it. Internal method, prefer [`Matrix::new`].
-    fn expand_and_push(&mut self, row: MatrixRow<'p, Cx>) {
+    fn expand_and_push(&mut self, mut row: MatrixRow<'p, Cx>) {
         if !row.is_empty() && row.head().is_or_pat() {
             // Expand nested or-patterns.
-            for new_row in row.expand_or_pat() {
+            for mut new_row in row.expand_or_pat() {
+                new_row.intersects = BitSet::new_empty(self.rows.len());
                 self.rows.push(new_row);
             }
         } else {
+            row.intersects = BitSet::new_empty(self.rows.len());
             self.rows.push(row);
         }
     }
@@ -1019,9 +1029,10 @@ impl<'p, Cx: TypeCx> Matrix<'p, Cx> {
         for (row_id, arm) in arms.iter().enumerate() {
             let v = MatrixRow {
                 pats: PatStack::from_pattern(arm.pat),
-                parent_row: row_id, // dummy, we won't read it
+                parent_row: row_id, // dummy, we don't read it
                 is_under_guard: arm.has_guard,
                 useful: false,
+                intersects: BitSet::new_empty(0), // Initialized in `Matrix::expand_and_push`.
             };
             matrix.expand_and_push(v);
         }
@@ -1317,6 +1328,83 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
     }
 }
 
+/// Collect ranges that overlap like `lo..=overlap`/`overlap..=hi`. Must be called during
+/// exhaustiveness checking, if we find a singleton range after constructor splitting. This reuses
+/// row intersection information to only detect ranges that truly overlap.
+///
+/// If two ranges overlapped, the split set will contain their intersection as a singleton.
+/// Specialization will then select rows that match the overlap, and exhaustiveness will compute
+/// which rows have an intersection that includes the overlap. That gives us all the info we need to
+/// compute overlapping ranges without false positives.
+///
+/// We can however get false negatives because exhaustiveness does not explore all cases. See the
+/// section on relevancy at the top of the file.
+fn collect_overlapping_range_endpoints<'p, Cx: TypeCx>(
+    overlap_range: IntRange,
+    matrix: &Matrix<'p, Cx>,
+    specialized_matrix: &Matrix<'p, Cx>,
+    overlapping_range_endpoints: &mut Vec<OverlappingRanges<'p, Cx>>,
+) {
+    let overlap = overlap_range.lo;
+    // Ranges that look like `lo..=overlap`.
+    let mut prefixes: SmallVec<[_; 1]> = Default::default();
+    // Ranges that look like `overlap..=hi`.
+    let mut suffixes: SmallVec<[_; 1]> = Default::default();
+    // Iterate on patterns that contained `overlap`. We iterate on `specialized_matrix` which
+    // contains only rows that matched the current `ctor` as well as accurate intersection
+    // information. It doesn't contain the column that contains the range; that can be found in
+    // `matrix`.
+    for (child_row_id, child_row) in specialized_matrix.rows().enumerate() {
+        let PatOrWild::Pat(pat) = matrix.rows[child_row.parent_row].head() else { continue };
+        let Constructor::IntRange(this_range) = pat.ctor() else { continue };
+        // Don't lint when one of the ranges is a singleton.
+        if this_range.is_singleton() {
+            continue;
+        }
+        if this_range.lo == overlap {
+            // `this_range` looks like `overlap..=this_range.hi`; it overlaps with any
+            // ranges that look like `lo..=overlap`.
+            if !prefixes.is_empty() {
+                let overlaps_with: Vec<_> = prefixes
+                    .iter()
+                    .filter(|&&(other_child_row_id, _)| {
+                        child_row.intersects.contains(other_child_row_id)
+                    })
+                    .map(|&(_, pat)| pat)
+                    .collect();
+                if !overlaps_with.is_empty() {
+                    overlapping_range_endpoints.push(OverlappingRanges {
+                        pat,
+                        overlaps_on: overlap_range,
+                        overlaps_with,
+                    });
+                }
+            }
+            suffixes.push((child_row_id, pat))
+        } else if this_range.hi == overlap.plus_one() {
+            // `this_range` looks like `this_range.lo..=overlap`; it overlaps with any
+            // ranges that look like `overlap..=hi`.
+            if !suffixes.is_empty() {
+                let overlaps_with: Vec<_> = suffixes
+                    .iter()
+                    .filter(|&&(other_child_row_id, _)| {
+                        child_row.intersects.contains(other_child_row_id)
+                    })
+                    .map(|&(_, pat)| pat)
+                    .collect();
+                if !overlaps_with.is_empty() {
+                    overlapping_range_endpoints.push(OverlappingRanges {
+                        pat,
+                        overlaps_on: overlap_range,
+                        overlaps_with,
+                    });
+                }
+            }
+            prefixes.push((child_row_id, pat))
+        }
+    }
+}
+
 /// The core of the algorithm.
 ///
 /// This recursively computes witnesses of the non-exhaustiveness of `matrix` (if any). Also tracks
@@ -1335,6 +1423,7 @@ impl<Cx: TypeCx> WitnessMatrix<Cx> {
 fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
     mcx: MatchCtxt<'a, 'p, Cx>,
     matrix: &mut Matrix<'p, Cx>,
+    overlapping_range_endpoints: &mut Vec<OverlappingRanges<'p, Cx>>,
     is_top_level: bool,
 ) -> Result<WitnessMatrix<Cx>, Cx::Error> {
     debug_assert!(matrix.rows().all(|r| r.len() == matrix.column_count()));
@@ -1349,21 +1438,19 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
     let Some(ty) = matrix.head_ty() else {
         // The base case: there are no columns in the matrix. We are morally pattern-matching on ().
         // A row is useful iff it has no (unguarded) rows above it.
-        for row in matrix.rows_mut() {
-            // All rows are useful until they're not.
-            row.useful = true;
-            // When there's an unguarded row, the match is exhaustive and any subsequent row is not
-            // useful.
-            if !row.is_under_guard {
-                return Ok(WitnessMatrix::empty());
-            }
+        let mut useful = true; // Whether the next row is useful.
+        for (i, row) in matrix.rows_mut().enumerate() {
+            row.useful = useful;
+            row.intersects.insert_range(0..i);
+            // The next rows stays useful if this one is under a guard.
+            useful &= row.is_under_guard;
         }
-        // No (unguarded) rows, so the match is not exhaustive. We return a new witness unless
-        // irrelevant.
-        return if matrix.wildcard_row_is_relevant {
+        return if useful && matrix.wildcard_row_is_relevant {
+            // The wildcard row is useful; the match is non-exhaustive.
             Ok(WitnessMatrix::unit_witness())
         } else {
-            // We choose to not report anything here; see at the top for details.
+            // Either the match is exhaustive, or we choose not to report anything because of
+            // relevancy. See at the top for details.
             Ok(WitnessMatrix::empty())
         };
     };
@@ -1416,7 +1503,12 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
         let ctor_is_relevant = matches!(ctor, Constructor::Missing) || missing_ctors.is_empty();
         let mut spec_matrix = matrix.specialize_constructor(pcx, &ctor, ctor_is_relevant);
         let mut witnesses = ensure_sufficient_stack(|| {
-            compute_exhaustiveness_and_usefulness(mcx, &mut spec_matrix, false)
+            compute_exhaustiveness_and_usefulness(
+                mcx,
+                &mut spec_matrix,
+                overlapping_range_endpoints,
+                false,
+            )
         })?;
 
         // Transform witnesses for `spec_matrix` into witnesses for `matrix`.
@@ -1424,10 +1516,34 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
         // Accumulate the found witnesses.
         ret.extend(witnesses);
 
-        // A parent row is useful if any of its children is.
         for child_row in spec_matrix.rows() {
-            let parent_row = &mut matrix.rows[child_row.parent_row];
-            parent_row.useful = parent_row.useful || child_row.useful;
+            let parent_row_id = child_row.parent_row;
+            let parent_row = &mut matrix.rows[parent_row_id];
+            // A parent row is useful if any of its children is.
+            parent_row.useful |= child_row.useful;
+            for child_intersection in child_row.intersects.iter() {
+                // Convert the intersecting ids into ids for the parent matrix.
+                let parent_intersection = spec_matrix.rows[child_intersection].parent_row;
+                // Note: self-intersection can happen with or-patterns.
+                if parent_intersection != parent_row_id {
+                    parent_row.intersects.insert(parent_intersection);
+                }
+            }
+        }
+
+        // Detect ranges that overlap on their endpoints.
+        if let Constructor::IntRange(overlap_range) = ctor {
+            if overlap_range.is_singleton()
+                && spec_matrix.rows.len() >= 2
+                && spec_matrix.rows.iter().any(|row| !row.intersects.is_empty())
+            {
+                collect_overlapping_range_endpoints(
+                    overlap_range,
+                    matrix,
+                    &spec_matrix,
+                    overlapping_range_endpoints,
+                );
+            }
         }
     }
 
@@ -1453,6 +1569,15 @@ pub enum Usefulness<'p, Cx: TypeCx> {
     Redundant,
 }
 
+/// Indicates that the range `pat` overlapped with all the ranges in `overlaps_with`, where the
+/// range they overlapped over is `overlaps_on`. We only detect singleton overlaps.
+#[derive(Clone, Debug)]
+pub struct OverlappingRanges<'p, Cx: TypeCx> {
+    pub pat: &'p DeconstructedPat<'p, Cx>,
+    pub overlaps_on: IntRange,
+    pub overlaps_with: Vec<&'p DeconstructedPat<'p, Cx>>,
+}
+
 /// The output of checking a match for exhaustiveness and arm usefulness.
 pub struct UsefulnessReport<'p, Cx: TypeCx> {
     /// For each arm of the input, whether that arm is useful after the arms above it.
@@ -1460,6 +1585,7 @@ pub struct UsefulnessReport<'p, Cx: TypeCx> {
     /// If the match is exhaustive, this is empty. If not, this contains witnesses for the lack of
     /// exhaustiveness.
     pub non_exhaustiveness_witnesses: Vec<WitnessPat<Cx>>,
+    pub overlapping_range_endpoints: Vec<OverlappingRanges<'p, Cx>>,
 }
 
 /// Computes whether a match is exhaustive and which of its arms are useful.
@@ -1470,9 +1596,14 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>(
     scrut_ty: Cx::Ty,
     scrut_validity: ValidityConstraint,
 ) -> Result<UsefulnessReport<'p, Cx>, Cx::Error> {
+    let mut overlapping_range_endpoints = Vec::new();
     let mut matrix = Matrix::new(arms, scrut_ty, scrut_validity);
-    let non_exhaustiveness_witnesses =
-        compute_exhaustiveness_and_usefulness(cx, &mut matrix, true)?;
+    let non_exhaustiveness_witnesses = compute_exhaustiveness_and_usefulness(
+        cx,
+        &mut matrix,
+        &mut overlapping_range_endpoints,
+        true,
+    )?;
 
     let non_exhaustiveness_witnesses: Vec<_> = non_exhaustiveness_witnesses.single_column();
     let arm_usefulness: Vec<_> = arms
@@ -1489,5 +1620,10 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>(
             (arm, usefulness)
         })
         .collect();
-    Ok(UsefulnessReport { arm_usefulness, non_exhaustiveness_witnesses })
+
+    Ok(UsefulnessReport {
+        arm_usefulness,
+        non_exhaustiveness_witnesses,
+        overlapping_range_endpoints,
+    })
 }
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index 63bd3457eb9..287e317b10f 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -70,14 +70,6 @@ pub trait Encoder {
     }
 
     fn emit_raw_bytes(&mut self, s: &[u8]);
-
-    fn emit_enum_variant<F>(&mut self, v_id: usize, f: F)
-    where
-        F: FnOnce(&mut Self),
-    {
-        self.emit_usize(v_id);
-        f(self);
-    }
 }
 
 // Note: all the methods in this trait are infallible, which may be surprising.
@@ -132,10 +124,6 @@ pub trait Decoder {
 
     fn read_raw_bytes(&mut self, len: usize) -> &[u8];
 
-    // Although there is an `emit_enum_variant` method in `Encoder`, the code
-    // patterns in decoding are different enough to encoding that there is no
-    // need for a corresponding `read_enum_variant` method here.
-
     fn peek_byte(&self) -> u8;
     fn position(&self) -> usize;
 }
@@ -372,15 +360,18 @@ impl<'a, D: Decoder> Decodable<D> for Cow<'a, str> {
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for Option<T> {
     fn encode(&self, s: &mut S) {
         match *self {
-            None => s.emit_enum_variant(0, |_| {}),
-            Some(ref v) => s.emit_enum_variant(1, |s| v.encode(s)),
+            None => s.emit_u8(0),
+            Some(ref v) => {
+                s.emit_u8(1);
+                v.encode(s);
+            }
         }
     }
 }
 
 impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> {
     fn decode(d: &mut D) -> Option<T> {
-        match d.read_usize() {
+        match d.read_u8() {
             0 => None,
             1 => Some(Decodable::decode(d)),
             _ => panic!("Encountered invalid discriminant while decoding `Option`."),
@@ -391,15 +382,21 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Option<T> {
 impl<S: Encoder, T1: Encodable<S>, T2: Encodable<S>> Encodable<S> for Result<T1, T2> {
     fn encode(&self, s: &mut S) {
         match *self {
-            Ok(ref v) => s.emit_enum_variant(0, |s| v.encode(s)),
-            Err(ref v) => s.emit_enum_variant(1, |s| v.encode(s)),
+            Ok(ref v) => {
+                s.emit_u8(0);
+                v.encode(s);
+            }
+            Err(ref v) => {
+                s.emit_u8(1);
+                v.encode(s);
+            }
         }
     }
 }
 
 impl<D: Decoder, T1: Decodable<D>, T2: Decodable<D>> Decodable<D> for Result<T1, T2> {
     fn decode(d: &mut D) -> Result<T1, T2> {
-        match d.read_usize() {
+        match d.read_u8() {
             0 => Ok(T1::decode(d)),
             1 => Err(T2::decode(d)),
             _ => panic!("Encountered invalid discriminant while decoding `Result`."),
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 61796d7a6ca..fe1166457ba 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -1146,6 +1146,7 @@ impl UnstableOptions {
         DiagCtxtFlags {
             can_emit_warnings,
             treat_err_as_bug: self.treat_err_as_bug,
+            eagerly_emit_delayed_bugs: self.eagerly_emit_delayed_bugs,
             macro_backtrace: self.macro_backtrace,
             deduplicate_diagnostics: self.deduplicate_diagnostics,
             track_diagnostics: self.track_diagnostics,
@@ -1379,6 +1380,8 @@ pub struct CheckCfg {
     pub exhaustive_values: bool,
     /// All the expected values for a config name
     pub expecteds: FxHashMap<Symbol, ExpectedValues<Symbol>>,
+    /// Well known names (only used for diagnostics purposes)
+    pub well_known_names: FxHashSet<Symbol>,
 }
 
 pub enum ExpectedValues<T> {
@@ -1431,9 +1434,10 @@ impl CheckCfg {
         };
 
         macro_rules! ins {
-            ($name:expr, $values:expr) => {
+            ($name:expr, $values:expr) => {{
+                self.well_known_names.insert($name);
                 self.expecteds.entry($name).or_insert_with($values)
-            };
+            }};
         }
 
         // Symbols are inserted in alphabetical order as much as possible.
@@ -1823,7 +1827,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
             "Remap source names in all output (compiler messages and output files)",
             "FROM=TO",
         ),
-        opt::multi("", "env", "Inject an environment variable", "VAR=VALUE"),
+        opt::multi("", "env-set", "Inject an environment variable", "VAR=VALUE"),
     ]);
     opts
 }
@@ -2599,11 +2603,11 @@ fn parse_logical_env(
 ) -> FxIndexMap<String, String> {
     let mut vars = FxIndexMap::default();
 
-    for arg in matches.opt_strs("env") {
+    for arg in matches.opt_strs("env-set") {
         if let Some((name, val)) = arg.split_once('=') {
             vars.insert(name.to_string(), val.to_string());
         } else {
-            early_dcx.early_fatal(format!("`--env`: specify value for variable `{arg}`"));
+            early_dcx.early_fatal(format!("`--env-set`: specify value for variable `{arg}`"));
         }
     }
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index c97b18ebd66..2d91a3fbd91 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1583,6 +1583,9 @@ options! {
         "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
     dylib_lto: bool = (false, parse_bool, [UNTRACKED],
         "enables LTO for dylib crate type"),
+    eagerly_emit_delayed_bugs: bool = (false, parse_bool, [UNTRACKED],
+        "emit delayed bugs eagerly as errors instead of stashing them and emitting \
+        them only if an error has not been emitted"),
     ehcont_guard: bool = (false, parse_bool, [TRACKED],
         "generate Windows EHCont Guard tables"),
     emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_span/src/edit_distance.rs b/compiler/rustc_span/src/edit_distance.rs
index 14cb1d6d362..87a0ccbb1a5 100644
--- a/compiler/rustc_span/src/edit_distance.rs
+++ b/compiler/rustc_span/src/edit_distance.rs
@@ -170,6 +170,34 @@ pub fn find_best_match_for_name(
     find_best_match_for_name_impl(false, candidates, lookup, dist)
 }
 
+/// Find the best match for multiple words
+///
+/// This function is intended for use when the desired match would never be
+/// returned due to a substring in `lookup` which is superfluous.
+///
+/// For example, when looking for the closest lint name to `clippy:missing_docs`,
+/// we would find `clippy::erasing_op`, despite `missing_docs` existing and being a better suggestion.
+/// `missing_docs` would have a larger edit distance because it does not contain the `clippy` tool prefix.
+/// In order to find `missing_docs`, this function takes multiple lookup strings, computes the best match
+/// for each and returns the match which had the lowest edit distance. In our example, `clippy:missing_docs` and
+/// `missing_docs` would be `lookups`, enabling `missing_docs` to be the best match, as desired.
+pub fn find_best_match_for_names(
+    candidates: &[Symbol],
+    lookups: &[Symbol],
+    dist: Option<usize>,
+) -> Option<Symbol> {
+    lookups
+        .iter()
+        .map(|s| (s, find_best_match_for_name_impl(false, candidates, *s, dist)))
+        .filter_map(|(s, r)| r.map(|r| (s, r)))
+        .min_by(|(s1, r1), (s2, r2)| {
+            let d1 = edit_distance(s1.as_str(), r1.as_str(), usize::MAX).unwrap();
+            let d2 = edit_distance(s2.as_str(), r2.as_str(), usize::MAX).unwrap();
+            d1.cmp(&d2)
+        })
+        .map(|(_, r)| r)
+}
+
 #[cold]
 fn find_best_match_for_name_impl(
     use_substring_score: bool,
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 4235293823c..65702f76fda 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -203,18 +203,19 @@ impl Hash for RealFileName {
 impl<S: Encoder> Encodable<S> for RealFileName {
     fn encode(&self, encoder: &mut S) {
         match *self {
-            RealFileName::LocalPath(ref local_path) => encoder.emit_enum_variant(0, |encoder| {
+            RealFileName::LocalPath(ref local_path) => {
+                encoder.emit_u8(0);
                 local_path.encode(encoder);
-            }),
-
-            RealFileName::Remapped { ref local_path, ref virtual_name } => encoder
-                .emit_enum_variant(1, |encoder| {
-                    // For privacy and build reproducibility, we must not embed host-dependant path
-                    // in artifacts if they have been remapped by --remap-path-prefix
-                    assert!(local_path.is_none());
-                    local_path.encode(encoder);
-                    virtual_name.encode(encoder);
-                }),
+            }
+
+            RealFileName::Remapped { ref local_path, ref virtual_name } => {
+                encoder.emit_u8(1);
+                // For privacy and build reproducibility, we must not embed host-dependant path
+                // in artifacts if they have been remapped by --remap-path-prefix
+                assert!(local_path.is_none());
+                local_path.encode(encoder);
+                virtual_name.encode(encoder);
+            }
         }
     }
 }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 8e26327196a..da8706ea715 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -3396,19 +3396,22 @@ impl Hash for TargetTriple {
 impl<S: Encoder> Encodable<S> for TargetTriple {
     fn encode(&self, s: &mut S) {
         match self {
-            TargetTriple::TargetTriple(triple) => s.emit_enum_variant(0, |s| s.emit_str(triple)),
-            TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => s
-                .emit_enum_variant(1, |s| {
-                    s.emit_str(triple);
-                    s.emit_str(contents)
-                }),
+            TargetTriple::TargetTriple(triple) => {
+                s.emit_u8(0);
+                s.emit_str(triple);
+            }
+            TargetTriple::TargetJson { path_for_rustdoc: _, triple, contents } => {
+                s.emit_u8(1);
+                s.emit_str(triple);
+                s.emit_str(contents);
+            }
         }
     }
 }
 
 impl<D: Decoder> Decodable<D> for TargetTriple {
     fn decode(d: &mut D) -> Self {
-        match d.read_usize() {
+        match d.read_u8() {
             0 => TargetTriple::TargetTriple(d.read_str().to_owned()),
             1 => TargetTriple::TargetJson {
                 path_for_rustdoc: PathBuf::new(),
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index 1883099d345..00ce9fbe758 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+bitflags = "2.4.1"
 itertools = "0.11.0"
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index de2577cca49..552c28c0586 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -19,6 +19,7 @@
 #![feature(control_flow_enum)]
 #![feature(extract_if)]
 #![feature(let_chains)]
+#![feature(option_take_if)]
 #![feature(if_let_guard)]
 #![feature(never_type)]
 #![feature(type_alias_impl_trait)]
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 6db53d6ddc4..f33d0f397ce 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -171,7 +171,8 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         let mut candidates = vec![];
         let last_eval_step = match self.evaluation.evaluation.kind {
             inspect::CanonicalGoalEvaluationKind::Overflow
-            | inspect::CanonicalGoalEvaluationKind::CycleInStack => {
+            | inspect::CanonicalGoalEvaluationKind::CycleInStack
+            | inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit => {
                 warn!("unexpected root evaluation: {:?}", self.evaluation);
                 return vec![];
             }
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/build.rs b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
index d8caef5b03f..b587a93b24c 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/build.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/build.rs
@@ -118,6 +118,7 @@ pub(in crate::solve) enum WipGoalEvaluationKind<'tcx> {
 pub(in crate::solve) enum WipCanonicalGoalEvaluationKind<'tcx> {
     Overflow,
     CycleInStack,
+    ProvisionalCacheHit,
     Interned { revisions: &'tcx [inspect::GoalEvaluationStep<'tcx>] },
 }
 
@@ -126,6 +127,7 @@ impl std::fmt::Debug for WipCanonicalGoalEvaluationKind<'_> {
         match self {
             Self::Overflow => write!(f, "Overflow"),
             Self::CycleInStack => write!(f, "CycleInStack"),
+            Self::ProvisionalCacheHit => write!(f, "ProvisionalCacheHit"),
             Self::Interned { revisions: _ } => f.debug_struct("Interned").finish_non_exhaustive(),
         }
     }
@@ -151,6 +153,9 @@ impl<'tcx> WipCanonicalGoalEvaluation<'tcx> {
             WipCanonicalGoalEvaluationKind::CycleInStack => {
                 inspect::CanonicalGoalEvaluationKind::CycleInStack
             }
+            WipCanonicalGoalEvaluationKind::ProvisionalCacheHit => {
+                inspect::CanonicalGoalEvaluationKind::ProvisionalCacheHit
+            }
             WipCanonicalGoalEvaluationKind::Interned { revisions } => {
                 inspect::CanonicalGoalEvaluationKind::Evaluation { revisions }
             }
diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs
index 55b79e6fc39..d87cc89954a 100644
--- a/compiler/rustc_trait_selection/src/solve/normalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalize.rs
@@ -8,7 +8,7 @@ use rustc_infer::infer::InferCtxt;
 use rustc_infer::traits::TraitEngineExt;
 use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
-use rustc_middle::traits::{ObligationCause, Reveal};
+use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
 use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
@@ -52,14 +52,16 @@ struct NormalizationFolder<'me, 'tcx> {
 impl<'tcx> NormalizationFolder<'_, 'tcx> {
     fn normalize_alias_ty(
         &mut self,
-        alias: AliasTy<'tcx>,
+        alias_ty: Ty<'tcx>,
     ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
+        assert!(matches!(alias_ty.kind(), ty::Alias(..)));
+
         let infcx = self.at.infcx;
         let tcx = infcx.tcx;
         let recursion_limit = tcx.recursion_limit();
         if !recursion_limit.value_within_limit(self.depth) {
             self.at.infcx.err_ctxt().report_overflow_error(
-                &alias.to_ty(tcx),
+                &alias_ty,
                 self.at.cause.span,
                 true,
                 |_| {},
@@ -76,7 +78,11 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
             tcx,
             self.at.cause.clone(),
             self.at.param_env,
-            ty::NormalizesTo { alias, term: new_infer_ty.into() },
+            ty::PredicateKind::AliasRelate(
+                alias_ty.into(),
+                new_infer_ty.into(),
+                ty::AliasRelationDirection::Equate,
+            ),
         );
 
         // Do not emit an error if normalization is known to fail but instead
@@ -90,9 +96,12 @@ impl<'tcx> NormalizationFolder<'_, 'tcx> {
                 return Err(errors);
             }
             let ty = infcx.resolve_vars_if_possible(new_infer_ty);
-            ty.try_fold_with(self)?
+
+            // Alias is guaranteed to be fully structurally resolved,
+            // so we can super fold here.
+            ty.try_super_fold_with(self)?
         } else {
-            alias.to_ty(tcx).try_super_fold_with(self)?
+            alias_ty.try_super_fold_with(self)?
         };
 
         self.depth -= 1;
@@ -170,24 +179,18 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
     }
 
     fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
-        let reveal = self.at.param_env.reveal();
         let infcx = self.at.infcx;
         debug_assert_eq!(ty, infcx.shallow_resolve(ty));
-        if !needs_normalization(&ty, reveal) {
+        if !ty.has_projections() {
             return Ok(ty);
         }
 
-        // We don't normalize opaque types unless we have
-        // `Reveal::All`, even if we're in the defining scope.
-        let data = match *ty.kind() {
-            ty::Alias(kind, alias_ty) if kind != ty::Opaque || reveal == Reveal::All => alias_ty,
-            _ => return ty.try_super_fold_with(self),
-        };
+        let ty::Alias(..) = *ty.kind() else { return ty.try_super_fold_with(self) };
 
-        if data.has_escaping_bound_vars() {
-            let (data, mapped_regions, mapped_types, mapped_consts) =
-                BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
-            let result = ensure_sufficient_stack(|| self.normalize_alias_ty(data))?;
+        if ty.has_escaping_bound_vars() {
+            let (ty, mapped_regions, mapped_types, mapped_consts) =
+                BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty);
+            let result = ensure_sufficient_stack(|| self.normalize_alias_ty(ty))?;
             Ok(PlaceholderReplacer::replace_placeholders(
                 infcx,
                 mapped_regions,
@@ -197,7 +200,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
                 result,
             ))
         } else {
-            ensure_sufficient_stack(|| self.normalize_alias_ty(data))
+            ensure_sufficient_stack(|| self.normalize_alias_ty(ty))
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/search_graph.rs b/compiler/rustc_trait_selection/src/solve/search_graph.rs
index 2a161c2d956..bede94a2e43 100644
--- a/compiler/rustc_trait_selection/src/solve/search_graph.rs
+++ b/compiler/rustc_trait_selection/src/solve/search_graph.rs
@@ -11,37 +11,90 @@ use rustc_middle::traits::solve::{CanonicalInput, Certainty, EvaluationCache, Qu
 use rustc_middle::ty;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Limit;
-use std::collections::hash_map::Entry;
+use std::mem;
 
 rustc_index::newtype_index! {
     #[orderable]
     pub struct StackDepth {}
 }
 
+bitflags::bitflags! {
+    /// Whether and how this goal has been used as the root of a
+    /// cycle. We track the kind of cycle as we're otherwise forced
+    /// to always rerun at least once.
+    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+    struct HasBeenUsed: u8 {
+        const INDUCTIVE_CYCLE = 1 << 0;
+        const COINDUCTIVE_CYCLE = 1 << 1;
+    }
+}
+
 #[derive(Debug)]
 struct StackEntry<'tcx> {
     input: CanonicalInput<'tcx>,
+
     available_depth: Limit,
-    // The maximum depth reached by this stack entry, only up-to date
-    // for the top of the stack and lazily updated for the rest.
+
+    /// The maximum depth reached by this stack entry, only up-to date
+    /// for the top of the stack and lazily updated for the rest.
     reached_depth: StackDepth,
-    // In case of a cycle, the depth of the root.
-    cycle_root_depth: StackDepth,
+
+    /// Whether this entry is a non-root cycle participant.
+    ///
+    /// We must not move the result of non-root cycle participants to the
+    /// global cache. See [SearchGraph::cycle_participants] for more details.
+    /// We store the highest stack depth of a head of a cycle this goal is involved
+    /// in. This necessary to soundly cache its provisional result.
+    non_root_cycle_participant: Option<StackDepth>,
 
     encountered_overflow: bool,
-    has_been_used: bool,
+
+    has_been_used: HasBeenUsed,
     /// Starts out as `None` and gets set when rerunning this
     /// goal in case we encounter a cycle.
     provisional_result: Option<QueryResult<'tcx>>,
+}
 
-    /// We put only the root goal of a coinductive cycle into the global cache.
+/// The provisional result for a goal which is not on the stack.
+struct DetachedEntry<'tcx> {
+    /// The head of the smallest non-trivial cycle involving this entry.
     ///
-    /// If we were to use that result when later trying to prove another cycle
-    /// participant, we can end up with unstable query results.
-    ///
-    /// See tests/ui/next-solver/coinduction/incompleteness-unstable-result.rs for
-    /// an example of where this is needed.
-    cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
+    /// Given the following rules, when proving `A` the head for
+    /// the provisional entry of `C` would be `B`.
+    /// ```plain
+    /// A :- B
+    /// B :- C
+    /// C :- A + B + C
+    /// ```
+    head: StackDepth,
+    result: QueryResult<'tcx>,
+}
+
+/// Stores the stack depth of a currently evaluated goal *and* already
+/// computed results for goals which depend on other goals still on the stack.
+///
+/// The provisional result may depend on whether the stack above it is inductive
+/// or coinductive. Because of this, we store separate provisional results for
+/// each case. If an provisional entry is not applicable, it may be the case
+/// that we already have provisional result while computing a goal. In this case
+/// we prefer the provisional result to potentially avoid fixpoint iterations.
+/// See tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs for an example.
+///
+/// The provisional cache can theoretically result in changes to the observable behavior,
+/// see tests/ui/traits/next-solver/cycles/provisional-cache-impacts-behavior.rs.
+#[derive(Default)]
+struct ProvisionalCacheEntry<'tcx> {
+    stack_depth: Option<StackDepth>,
+    with_inductive_stack: Option<DetachedEntry<'tcx>>,
+    with_coinductive_stack: Option<DetachedEntry<'tcx>>,
+}
+
+impl<'tcx> ProvisionalCacheEntry<'tcx> {
+    fn is_empty(&self) -> bool {
+        self.stack_depth.is_none()
+            && self.with_inductive_stack.is_none()
+            && self.with_coinductive_stack.is_none()
+    }
 }
 
 pub(super) struct SearchGraph<'tcx> {
@@ -51,7 +104,15 @@ pub(super) struct SearchGraph<'tcx> {
     ///
     /// An element is *deeper* in the stack if its index is *lower*.
     stack: IndexVec<StackDepth, StackEntry<'tcx>>,
-    stack_entries: FxHashMap<CanonicalInput<'tcx>, StackDepth>,
+    provisional_cache: FxHashMap<CanonicalInput<'tcx>, ProvisionalCacheEntry<'tcx>>,
+    /// We put only the root goal of a coinductive cycle into the global cache.
+    ///
+    /// If we were to use that result when later trying to prove another cycle
+    /// participant, we can end up with unstable query results.
+    ///
+    /// See tests/ui/next-solver/coinduction/incompleteness-unstable-result.rs for
+    /// an example of where this is needed.
+    cycle_participants: FxHashSet<CanonicalInput<'tcx>>,
 }
 
 impl<'tcx> SearchGraph<'tcx> {
@@ -60,7 +121,8 @@ impl<'tcx> SearchGraph<'tcx> {
             mode,
             local_overflow_limit: tcx.recursion_limit().0.checked_ilog2().unwrap_or(0) as usize,
             stack: Default::default(),
-            stack_entries: Default::default(),
+            provisional_cache: Default::default(),
+            cycle_participants: Default::default(),
         }
     }
 
@@ -89,7 +151,6 @@ impl<'tcx> SearchGraph<'tcx> {
     /// would cause us to not track overflow and recursion depth correctly.
     fn pop_stack(&mut self) -> StackEntry<'tcx> {
         let elem = self.stack.pop().unwrap();
-        assert!(self.stack_entries.remove(&elem.input).is_some());
         if let Some(last) = self.stack.raw.last_mut() {
             last.reached_depth = last.reached_depth.max(elem.reached_depth);
             last.encountered_overflow |= elem.encountered_overflow;
@@ -109,7 +170,13 @@ impl<'tcx> SearchGraph<'tcx> {
     }
 
     pub(super) fn is_empty(&self) -> bool {
-        self.stack.is_empty()
+        if self.stack.is_empty() {
+            debug_assert!(self.provisional_cache.is_empty());
+            debug_assert!(self.cycle_participants.is_empty());
+            true
+        } else {
+            false
+        }
     }
 
     pub(super) fn current_goal_is_normalizes_to(&self) -> bool {
@@ -146,6 +213,52 @@ impl<'tcx> SearchGraph<'tcx> {
         }
     }
 
+    fn stack_coinductive_from(
+        tcx: TyCtxt<'tcx>,
+        stack: &IndexVec<StackDepth, StackEntry<'tcx>>,
+        head: StackDepth,
+    ) -> bool {
+        stack.raw[head.index()..]
+            .iter()
+            .all(|entry| entry.input.value.goal.predicate.is_coinductive(tcx))
+    }
+
+    // When encountering a solver cycle, the result of the current goal
+    // depends on goals lower on the stack.
+    //
+    // We have to therefore be careful when caching goals. Only the final result
+    // of the cycle root, i.e. the lowest goal on the stack involved in this cycle,
+    // is moved to the global cache while all others are stored in a provisional cache.
+    //
+    // We update both the head of this cycle to rerun its evaluation until
+    // we reach a fixpoint and all other cycle participants to make sure that
+    // their result does not get moved to the global cache.
+    fn tag_cycle_participants(
+        stack: &mut IndexVec<StackDepth, StackEntry<'tcx>>,
+        cycle_participants: &mut FxHashSet<CanonicalInput<'tcx>>,
+        usage_kind: HasBeenUsed,
+        head: StackDepth,
+    ) {
+        stack[head].has_been_used |= usage_kind;
+        debug_assert!(!stack[head].has_been_used.is_empty());
+        for entry in &mut stack.raw[head.index() + 1..] {
+            entry.non_root_cycle_participant = entry.non_root_cycle_participant.max(Some(head));
+            cycle_participants.insert(entry.input);
+        }
+    }
+
+    fn clear_dependent_provisional_results(
+        provisional_cache: &mut FxHashMap<CanonicalInput<'tcx>, ProvisionalCacheEntry<'tcx>>,
+        head: StackDepth,
+    ) {
+        #[allow(rustc::potential_query_instability)]
+        provisional_cache.retain(|_, entry| {
+            entry.with_coinductive_stack.take_if(|p| p.head == head);
+            entry.with_inductive_stack.take_if(|p| p.head == head);
+            !entry.is_empty()
+        });
+    }
+
     /// Probably the most involved method of the whole solver.
     ///
     /// Given some goal which is proven via the `prove_goal` closure, this
@@ -200,82 +313,79 @@ impl<'tcx> SearchGraph<'tcx> {
             return result;
         }
 
-        // Check whether we're in a cycle.
-        match self.stack_entries.entry(input) {
-            // No entry, we push this goal on the stack and try to prove it.
-            Entry::Vacant(v) => {
-                let depth = self.stack.next_index();
-                let entry = StackEntry {
-                    input,
-                    available_depth,
-                    reached_depth: depth,
-                    cycle_root_depth: depth,
-                    encountered_overflow: false,
-                    has_been_used: false,
-                    provisional_result: None,
-                    cycle_participants: Default::default(),
-                };
-                assert_eq!(self.stack.push(entry), depth);
-                v.insert(depth);
-            }
-            // We have a nested goal which relies on a goal `root` deeper in the stack.
+        // Check whether the goal is in the provisional cache.
+        // The provisional result may rely on the path to its cycle roots,
+        // so we have to check the path of the current goal matches that of
+        // the cache entry.
+        let cache_entry = self.provisional_cache.entry(input).or_default();
+        if let Some(entry) = cache_entry
+            .with_coinductive_stack
+            .as_ref()
+            .filter(|p| Self::stack_coinductive_from(tcx, &self.stack, p.head))
+            .or_else(|| {
+                cache_entry
+                    .with_inductive_stack
+                    .as_ref()
+                    .filter(|p| !Self::stack_coinductive_from(tcx, &self.stack, p.head))
+            })
+        {
+            // We have a nested goal which is already in the provisional cache, use
+            // its result. We do not provide any usage kind as that should have been
+            // already set correctly while computing the cache entry.
+            inspect
+                .goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::ProvisionalCacheHit);
+            Self::tag_cycle_participants(
+                &mut self.stack,
+                &mut self.cycle_participants,
+                HasBeenUsed::empty(),
+                entry.head,
+            );
+            return entry.result;
+        } else if let Some(stack_depth) = cache_entry.stack_depth {
+            debug!("encountered cycle with depth {stack_depth:?}");
+            // We have a nested goal which directly relies on a goal deeper in the stack.
             //
-            // We first store that we may have to reprove `root` in case the provisional
-            // response is not equal to the final response. We also update the depth of all
-            // goals which recursively depend on our current goal to depend on `root`
-            // instead.
+            // We start by tagging all cycle participants, as that's necessary for caching.
             //
-            // Finally we can return either the provisional response for that goal if we have a
-            // coinductive cycle or an ambiguous result if the cycle is inductive.
-            Entry::Occupied(entry) => {
-                inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CycleInStack);
-
-                let stack_depth = *entry.get();
-                debug!("encountered cycle with depth {stack_depth:?}");
-                // We start by updating the root depth of all cycle participants, and
-                // add all cycle participants to the root.
-                let root_depth = self.stack[stack_depth].cycle_root_depth;
-                let (prev, participants) = self.stack.raw.split_at_mut(stack_depth.as_usize() + 1);
-                let root = &mut prev[root_depth.as_usize()];
-                for entry in participants {
-                    debug_assert!(entry.cycle_root_depth >= root_depth);
-                    entry.cycle_root_depth = root_depth;
-                    root.cycle_participants.insert(entry.input);
-                    // FIXME(@lcnr): I believe that this line is needed as we could
-                    // otherwise access a cache entry for the root of a cycle while
-                    // computing the result for a cycle participant. This can result
-                    // in unstable results due to incompleteness.
-                    //
-                    // However, a test for this would be an even more complex version of
-                    // tests/ui/traits/next-solver/coinduction/incompleteness-unstable-result.rs.
-                    // I did not bother to write such a test and we have no regression test
-                    // for this. It would be good to have such a test :)
-                    #[allow(rustc::potential_query_instability)]
-                    root.cycle_participants.extend(entry.cycle_participants.drain());
-                }
+            // Finally we can return either the provisional response or the initial response
+            // in case we're in the first fixpoint iteration for this goal.
+            inspect.goal_evaluation_kind(inspect::WipCanonicalGoalEvaluationKind::CycleInStack);
+            let is_coinductive_cycle = Self::stack_coinductive_from(tcx, &self.stack, stack_depth);
+            let usage_kind = if is_coinductive_cycle {
+                HasBeenUsed::COINDUCTIVE_CYCLE
+            } else {
+                HasBeenUsed::INDUCTIVE_CYCLE
+            };
+            Self::tag_cycle_participants(
+                &mut self.stack,
+                &mut self.cycle_participants,
+                usage_kind,
+                stack_depth,
+            );
 
-                // If we're in a cycle, we have to retry proving the cycle head
-                // until we reach a fixpoint. It is not enough to simply retry the
-                // `root` goal of this cycle.
-                //
-                // See tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs
-                // for an example.
-                self.stack[stack_depth].has_been_used = true;
-                return if let Some(result) = self.stack[stack_depth].provisional_result {
-                    result
-                } else {
-                    // If we don't have a provisional result yet we're in the first iteration,
-                    // so we start with no constraints.
-                    let is_coinductive = self.stack.raw[stack_depth.index()..]
-                        .iter()
-                        .all(|entry| entry.input.value.goal.predicate.is_coinductive(tcx));
-                    if is_coinductive {
-                        Self::response_no_constraints(tcx, input, Certainty::Yes)
-                    } else {
-                        Self::response_no_constraints(tcx, input, Certainty::OVERFLOW)
-                    }
-                };
-            }
+            // Return the provisional result or, if we're in the first iteration,
+            // start with no constraints.
+            return if let Some(result) = self.stack[stack_depth].provisional_result {
+                result
+            } else if is_coinductive_cycle {
+                Self::response_no_constraints(tcx, input, Certainty::Yes)
+            } else {
+                Self::response_no_constraints(tcx, input, Certainty::OVERFLOW)
+            };
+        } else {
+            // No entry, we push this goal on the stack and try to prove it.
+            let depth = self.stack.next_index();
+            let entry = StackEntry {
+                input,
+                available_depth,
+                reached_depth: depth,
+                non_root_cycle_participant: None,
+                encountered_overflow: false,
+                has_been_used: HasBeenUsed::empty(),
+                provisional_result: None,
+            };
+            assert_eq!(self.stack.push(entry), depth);
+            cache_entry.stack_depth = Some(depth);
         }
 
         // This is for global caching, so we properly track query dependencies.
@@ -290,29 +400,58 @@ impl<'tcx> SearchGraph<'tcx> {
                 // point we are done.
                 for _ in 0..self.local_overflow_limit() {
                     let result = prove_goal(self, inspect);
-
-                    // Check whether the current goal is the root of a cycle and whether
-                    // we have to rerun because its provisional result differed from the
-                    // final result.
                     let stack_entry = self.pop_stack();
                     debug_assert_eq!(stack_entry.input, input);
-                    if stack_entry.has_been_used
-                        && stack_entry.provisional_result.map_or(true, |r| r != result)
-                    {
-                        // If so, update its provisional result and reevaluate it.
+
+                    // If the current goal is not the root of a cycle, we are done.
+                    if stack_entry.has_been_used.is_empty() {
+                        return (stack_entry, result);
+                    }
+
+                    // If it is a cycle head, we have to keep trying to prove it until
+                    // we reach a fixpoint. We need to do so for all cycle heads,
+                    // not only for the root.
+                    //
+                    // See tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs
+                    // for an example.
+
+                    // Start by clearing all provisional cache entries which depend on this
+                    // the current goal.
+                    Self::clear_dependent_provisional_results(
+                        &mut self.provisional_cache,
+                        self.stack.next_index(),
+                    );
+
+                    // Check whether we reached a fixpoint, either because the final result
+                    // is equal to the provisional result of the previous iteration, or because
+                    // this was only the root of either coinductive or inductive cycles, and the
+                    // final result is equal to the initial response for that case.
+                    let reached_fixpoint = if let Some(r) = stack_entry.provisional_result {
+                        r == result
+                    } else if stack_entry.has_been_used == HasBeenUsed::COINDUCTIVE_CYCLE {
+                        Self::response_no_constraints(tcx, input, Certainty::Yes) == result
+                    } else if stack_entry.has_been_used == HasBeenUsed::INDUCTIVE_CYCLE {
+                        Self::response_no_constraints(tcx, input, Certainty::OVERFLOW) == result
+                    } else {
+                        false
+                    };
+
+                    // If we did not reach a fixpoint, update the provisional result and reevaluate.
+                    if reached_fixpoint {
+                        return (stack_entry, result);
+                    } else {
                         let depth = self.stack.push(StackEntry {
-                            has_been_used: false,
+                            has_been_used: HasBeenUsed::empty(),
                             provisional_result: Some(result),
                             ..stack_entry
                         });
-                        assert_eq!(self.stack_entries.insert(input, depth), None);
-                    } else {
-                        return (stack_entry, result);
+                        debug_assert_eq!(self.provisional_cache[&input].stack_depth, Some(depth));
                     }
                 }
 
                 debug!("canonical cycle overflow");
                 let current_entry = self.pop_stack();
+                debug_assert!(current_entry.has_been_used.is_empty());
                 let result = Self::response_no_constraints(tcx, input, Certainty::OVERFLOW);
                 (current_entry, result)
             });
@@ -322,26 +461,35 @@ impl<'tcx> SearchGraph<'tcx> {
         // We're now done with this goal. In case this goal is involved in a larger cycle
         // do not remove it from the provisional cache and update its provisional result.
         // We only add the root of cycles to the global cache.
-        //
-        // It is not possible for any nested goal to depend on something deeper on the
-        // stack, as this would have also updated the depth of the current goal.
-        if final_entry.cycle_root_depth == self.stack.next_index() {
+        if let Some(head) = final_entry.non_root_cycle_participant {
+            let coinductive_stack = Self::stack_coinductive_from(tcx, &self.stack, head);
+
+            let entry = self.provisional_cache.get_mut(&input).unwrap();
+            entry.stack_depth = None;
+            if coinductive_stack {
+                entry.with_coinductive_stack = Some(DetachedEntry { head, result });
+            } else {
+                entry.with_inductive_stack = Some(DetachedEntry { head, result });
+            }
+        } else {
+            self.provisional_cache.remove(&input);
+            let reached_depth = final_entry.reached_depth.as_usize() - self.stack.len();
+            let cycle_participants = mem::take(&mut self.cycle_participants);
             // When encountering a cycle, both inductive and coinductive, we only
             // move the root into the global cache. We also store all other cycle
             // participants involved.
             //
-            // We disable the global cache entry of the root goal if a cycle
+            // We must not use the global cache entry of a root goal if a cycle
             // participant is on the stack. This is necessary to prevent unstable
-            // results. See the comment of `StackEntry::cycle_participants` for
+            // results. See the comment of `SearchGraph::cycle_participants` for
             // more details.
-            let reached_depth = final_entry.reached_depth.as_usize() - self.stack.len();
             self.global_cache(tcx).insert(
                 tcx,
                 input,
                 proof_tree,
                 reached_depth,
                 final_entry.encountered_overflow,
-                final_entry.cycle_participants,
+                cycle_participants,
                 dep_node,
                 result,
             )
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 10329c623b3..200d022c80c 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -26,7 +26,7 @@ use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
 use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
 use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
 
 use super::util;
 use super::SelectionContext;
@@ -258,7 +258,7 @@ fn fulfill_implication<'tcx>(
 pub(super) fn specialization_graph_provider(
     tcx: TyCtxt<'_>,
     trait_id: DefId,
-) -> specialization_graph::Graph {
+) -> Result<&'_ specialization_graph::Graph, ErrorGuaranteed> {
     let mut sg = specialization_graph::Graph::new();
     let overlap_mode = specialization_graph::OverlapMode::get(tcx, trait_id);
 
@@ -271,6 +271,8 @@ pub(super) fn specialization_graph_provider(
     trait_impls
         .sort_unstable_by_key(|def_id| (-(def_id.krate.as_u32() as i64), def_id.index.index()));
 
+    let mut errored = Ok(());
+
     for impl_def_id in trait_impls {
         if let Some(impl_def_id) = impl_def_id.as_local() {
             // This is where impl overlap checking happens:
@@ -283,15 +285,21 @@ pub(super) fn specialization_graph_provider(
             };
 
             if let Some(overlap) = overlap {
-                report_overlap_conflict(tcx, overlap, impl_def_id, used_to_be_allowed, &mut sg);
+                errored = errored.and(report_overlap_conflict(
+                    tcx,
+                    overlap,
+                    impl_def_id,
+                    used_to_be_allowed,
+                ));
             }
         } else {
             let parent = tcx.impl_parent(impl_def_id).unwrap_or(trait_id);
             sg.record_impl_from_cstore(tcx, parent, impl_def_id)
         }
     }
+    errored?;
 
-    sg
+    Ok(tcx.arena.alloc(sg))
 }
 
 // This function is only used when
@@ -304,36 +312,31 @@ fn report_overlap_conflict<'tcx>(
     overlap: OverlapError<'tcx>,
     impl_def_id: LocalDefId,
     used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
-    sg: &mut specialization_graph::Graph,
-) {
+) -> Result<(), ErrorGuaranteed> {
     let impl_polarity = tcx.impl_polarity(impl_def_id.to_def_id());
     let other_polarity = tcx.impl_polarity(overlap.with_impl);
     match (impl_polarity, other_polarity) {
         (ty::ImplPolarity::Negative, ty::ImplPolarity::Positive) => {
-            report_negative_positive_conflict(
+            Err(report_negative_positive_conflict(
                 tcx,
                 &overlap,
                 impl_def_id,
                 impl_def_id.to_def_id(),
                 overlap.with_impl,
-                sg,
-            );
+            ))
         }
 
         (ty::ImplPolarity::Positive, ty::ImplPolarity::Negative) => {
-            report_negative_positive_conflict(
+            Err(report_negative_positive_conflict(
                 tcx,
                 &overlap,
                 impl_def_id,
                 overlap.with_impl,
                 impl_def_id.to_def_id(),
-                sg,
-            );
+            ))
         }
 
-        _ => {
-            report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed, sg);
-        }
+        _ => report_conflicting_impls(tcx, overlap, impl_def_id, used_to_be_allowed),
     }
 }
 
@@ -343,16 +346,16 @@ fn report_negative_positive_conflict<'tcx>(
     local_impl_def_id: LocalDefId,
     negative_impl_def_id: DefId,
     positive_impl_def_id: DefId,
-    sg: &mut specialization_graph::Graph,
-) {
-    let err = tcx.dcx().create_err(NegativePositiveConflict {
-        impl_span: tcx.def_span(local_impl_def_id),
-        trait_desc: overlap.trait_ref,
-        self_ty: overlap.self_ty,
-        negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
-        positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
-    });
-    sg.has_errored = Some(err.emit());
+) -> ErrorGuaranteed {
+    tcx.dcx()
+        .create_err(NegativePositiveConflict {
+            impl_span: tcx.def_span(local_impl_def_id),
+            trait_desc: overlap.trait_ref,
+            self_ty: overlap.self_ty,
+            negative_impl_span: tcx.span_of_impl(negative_impl_def_id),
+            positive_impl_span: tcx.span_of_impl(positive_impl_def_id),
+        })
+        .emit()
 }
 
 fn report_conflicting_impls<'tcx>(
@@ -360,8 +363,7 @@ fn report_conflicting_impls<'tcx>(
     overlap: OverlapError<'tcx>,
     impl_def_id: LocalDefId,
     used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
-    sg: &mut specialization_graph::Graph,
-) {
+) -> Result<(), ErrorGuaranteed> {
     let impl_span = tcx.def_span(impl_def_id);
 
     // Work to be done after we've built the DiagnosticBuilder. We have to define it
@@ -429,14 +431,11 @@ fn report_conflicting_impls<'tcx>(
                 let mut err = tcx.dcx().struct_span_err(impl_span, msg);
                 err.code(error_code!(E0119));
                 decorate(tcx, &overlap, impl_span, &mut err);
-                Some(err.emit())
+                err.emit()
             } else {
-                Some(
-                    tcx.dcx()
-                        .span_delayed_bug(impl_span, "impl should have failed the orphan check"),
-                )
+                tcx.dcx().span_delayed_bug(impl_span, "impl should have failed the orphan check")
             };
-            sg.has_errored = reported;
+            Err(reported)
         }
         Some(kind) => {
             let lint = match kind {
@@ -452,8 +451,9 @@ fn report_conflicting_impls<'tcx>(
                     decorate(tcx, &overlap, impl_span, err);
                 },
             );
+            Ok(())
         }
-    };
+    }
 }
 
 /// Recovers the "impl X for Y" signature from `impl_def_id` and returns it as a
diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
index e0f9fdc3827..ed5d01d7048 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs
@@ -22,8 +22,7 @@ impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> {
         assert!(!ty.is_ty_var(), "should have resolved vars before calling");
 
         if self.infcx.next_trait_solver() {
-            // FIXME(-Znext-solver): Should we resolve opaques here?
-            let ty::Alias(ty::Projection | ty::Inherent | ty::Weak, _) = *ty.kind() else {
+            let ty::Alias(..) = *ty.kind() else {
                 return Ok(ty);
             };
 
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 72227a04bf1..38877f7a77f 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -963,7 +963,7 @@ pub enum PointerCoercion {
     /// Go from a safe fn pointer to an unsafe fn pointer.
     UnsafeFnPointer,
 
-    /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
+    /// Go from a non-capturing closure to a fn pointer or an unsafe fn pointer.
     /// It cannot convert a closure that requires unsafe.
     ClosureFnPointer(Safety),
 
@@ -1037,21 +1037,24 @@ impl Place {
     /// locals from the function body where this place originates from.
     pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
         let start_ty = locals[self.local].ty;
-        self.projection.iter().fold(Ok(start_ty), |place_ty, elem| {
-            let ty = place_ty?;
-            match elem {
-                ProjectionElem::Deref => Self::deref_ty(ty),
-                ProjectionElem::Field(_idx, fty) => Ok(*fty),
-                ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => {
-                    Self::index_ty(ty)
-                }
-                ProjectionElem::Subslice { from, to, from_end } => {
-                    Self::subslice_ty(ty, from, to, from_end)
-                }
-                ProjectionElem::Downcast(_) => Ok(ty),
-                ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty),
+        self.projection.iter().fold(Ok(start_ty), |place_ty, elem| elem.ty(place_ty?))
+    }
+}
+
+impl ProjectionElem {
+    /// Get the expected type after applying this projection to a given place type.
+    pub fn ty(&self, place_ty: Ty) -> Result<Ty, Error> {
+        let ty = place_ty;
+        match &self {
+            ProjectionElem::Deref => Self::deref_ty(ty),
+            ProjectionElem::Field(_idx, fty) => Ok(*fty),
+            ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => Self::index_ty(ty),
+            ProjectionElem::Subslice { from, to, from_end } => {
+                Self::subslice_ty(ty, from, to, from_end)
             }
-        })
+            ProjectionElem::Downcast(_) => Ok(ty),
+            ProjectionElem::OpaqueCast(ty) | ProjectionElem::Subtype(ty) => Ok(*ty),
+        }
     }
 
     fn index_ty(ty: Ty) -> Result<Ty, Error> {
diff --git a/compiler/stable_mir/src/mir/visit.rs b/compiler/stable_mir/src/mir/visit.rs
index ab57ff0f8f5..24296e9e877 100644
--- a/compiler/stable_mir/src/mir/visit.rs
+++ b/compiler/stable_mir/src/mir/visit.rs
@@ -37,7 +37,7 @@
 
 use crate::mir::*;
 use crate::ty::{Const, GenericArgs, Region, Ty};
-use crate::{Opaque, Span};
+use crate::{Error, Opaque, Span};
 
 pub trait MirVisitor {
     fn visit_body(&mut self, body: &Body) {
@@ -76,12 +76,14 @@ pub trait MirVisitor {
         self.super_place(place, ptx, location)
     }
 
-    fn visit_projection_elem(
+    fn visit_projection_elem<'a>(
         &mut self,
+        place_ref: PlaceRef<'a>,
         elem: &ProjectionElem,
         ptx: PlaceContext,
         location: Location,
     ) {
+        let _ = place_ref;
         self.super_projection_elem(elem, ptx, location);
     }
 
@@ -284,8 +286,9 @@ pub trait MirVisitor {
         let _ = ptx;
         self.visit_local(&place.local, ptx, location);
 
-        for elem in &place.projection {
-            self.visit_projection_elem(elem, ptx, location);
+        for (idx, elem) in place.projection.iter().enumerate() {
+            let place_ref = PlaceRef { local: place.local, projection: &place.projection[..idx] };
+            self.visit_projection_elem(place_ref, elem, ptx, location);
         }
     }
 
@@ -453,6 +456,19 @@ impl Location {
     }
 }
 
+/// Reference to a place used to represent a partial projection.
+pub struct PlaceRef<'a> {
+    pub local: Local,
+    pub projection: &'a [ProjectionElem],
+}
+
+impl<'a> PlaceRef<'a> {
+    /// Get the type of this place.
+    pub fn ty(&self, locals: &[LocalDecl]) -> Result<Ty, Error> {
+        self.projection.iter().fold(Ok(locals[self.local].ty), |place_ty, elem| elem.ty(place_ty?))
+    }
+}
+
 /// Information about a place's usage.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct PlaceContext {
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index 74fa30456eb..45e82240164 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -552,7 +552,6 @@ fn handle_reserve(result: Result<(), TryReserveError>) {
 // `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add
 // an extra guard for this in case we're running on a platform which can use
 // all 4GB in user-space, e.g., PAE or x32.
-
 #[inline]
 fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
     if usize::BITS < 64 && alloc_size > isize::MAX as usize {
diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs
index ba5e28f7293..6b82deeac8a 100644
--- a/library/alloc/tests/autotraits.rs
+++ b/library/alloc/tests/autotraits.rs
@@ -55,12 +55,7 @@ fn test_btree_map() {
 
     require_send_sync(async {
         let _v = None::<
-            alloc::collections::btree_map::ExtractIf<
-                '_,
-                &u32,
-                &u32,
-                fn(&&u32, &mut &u32) -> bool,
-            >,
+            alloc::collections::btree_map::ExtractIf<'_, &u32, &u32, fn(&&u32, &mut &u32) -> bool>,
         >;
         async {}.await;
     });
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 9ec6f6ae1ac..0f5e0d99eca 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1,7 +1,7 @@
 use core::alloc::{Allocator, Layout};
-use core::{assert_eq, assert_ne};
 use core::num::NonZeroUsize;
 use core::ptr::NonNull;
+use core::{assert_eq, assert_ne};
 use std::alloc::System;
 use std::assert_matches::assert_matches;
 use std::borrow::Cow;
@@ -1212,7 +1212,7 @@ fn test_in_place_specialization_step_up_down() {
     assert_eq!(sink.len(), 2);
 
     let mut src: Vec<[u8; 3]> = Vec::with_capacity(17);
-    src.resize( 8, [0; 3]);
+    src.resize(8, [0; 3]);
     let iter = src.into_iter().map(|[a, b, _]| [a, b]);
     assert_in_place_trait(&iter);
     let sink: Vec<[u8; 2]> = iter.collect();
@@ -1221,11 +1221,7 @@ fn test_in_place_specialization_step_up_down() {
 
     let src = vec![[0u8; 4]; 256];
     let srcptr = src.as_ptr();
-    let iter = src
-        .into_iter()
-        .flat_map(|a| {
-            a.into_iter().map(|b| b.wrapping_add(1))
-        });
+    let iter = src.into_iter().flat_map(|a| a.into_iter().map(|b| b.wrapping_add(1)));
     assert_in_place_trait(&iter);
     let sink = iter.collect::<Vec<_>>();
     assert_eq!(srcptr as *const u8, sink.as_ptr());
diff --git a/library/core/benches/num/int_pow/mod.rs b/library/core/benches/num/int_pow/mod.rs
new file mode 100644
index 00000000000..063d722bdd1
--- /dev/null
+++ b/library/core/benches/num/int_pow/mod.rs
@@ -0,0 +1,99 @@
+use rand::Rng;
+use test::{black_box, Bencher};
+
+const ITERATIONS: usize = 128; // Uses an ITERATIONS * 20 Byte stack allocation
+type IntType = i128; // Hardest native type to multiply
+const EXPONENT_MAX: u32 = 31;
+const MAX_BASE: IntType = 17; // +-17 ** 31 <= IntType::MAX
+
+macro_rules! pow_bench_template {
+    ($name:ident, $inner_macro:ident, $base_macro:ident) => {
+        #[bench]
+        fn $name(bench: &mut Bencher) {
+            // Frequent black_box calls can add latency and prevent optimizations, so for
+            // variable parameters we premake an array and pass the
+            // reference through black_box outside of the loop.
+            let mut rng = crate::bench_rng();
+            let base_array: [IntType; ITERATIONS] =
+                core::array::from_fn(|_| rng.gen_range((-MAX_BASE..=MAX_BASE)));
+            let exp_array: [u32; ITERATIONS] =
+                core::array::from_fn(|_| rng.gen_range((0..=EXPONENT_MAX)));
+
+            bench.iter(|| {
+                #[allow(unused, unused_mut)]
+                let mut base_iter = black_box(&base_array).into_iter();
+                let mut exp_iter = black_box(&exp_array).into_iter();
+
+                (0..ITERATIONS).fold((0 as IntType, false), |acc, _| {
+                    // Sometimes constants don't propogate all the way to the
+                    // inside of the loop, so we call a custom expression every cycle
+                    // rather than iter::repeat(CONST)
+                    let base: IntType = $base_macro!(base_iter);
+                    let exp: u32 = *exp_iter.next().unwrap();
+
+                    let r: (IntType, bool) = $inner_macro!(base, exp);
+                    (acc.0 ^ r.0, acc.1 ^ r.1)
+                })
+            });
+        }
+    };
+}
+
+// This may panic if it overflows.
+macro_rules! inner_pow {
+    ($base:ident, $exp:ident) => {
+        ($base.pow($exp), false)
+    };
+}
+
+macro_rules! inner_wrapping {
+    ($base:ident, $exp:ident) => {
+        ($base.wrapping_pow($exp), false)
+    };
+}
+
+macro_rules! inner_overflowing {
+    ($base:ident, $exp:ident) => {
+        $base.overflowing_pow($exp)
+    };
+}
+
+// This will panic if it overflows.
+macro_rules! inner_checked_unwrapped {
+    ($base:ident, $exp:ident) => {
+        ($base.checked_pow($exp).unwrap(), false)
+    };
+}
+
+macro_rules! inner_saturating {
+    ($base:ident, $exp:ident) => {
+        ($base.saturating_pow($exp), false)
+    };
+}
+
+macro_rules! make_const_base {
+    ($name:ident, $x:literal) => {
+        macro_rules! $name {
+            ($iter:ident) => {
+                $x
+            };
+        }
+    };
+}
+
+make_const_base!(const_base_m7, -7);
+make_const_base!(const_base_m8, -8);
+
+macro_rules! variable_base {
+    ($iter:ident) => {
+        *$iter.next().unwrap()
+    };
+}
+
+pow_bench_template!(pow_variable, inner_pow, variable_base);
+pow_bench_template!(wrapping_pow_variable, inner_wrapping, variable_base);
+pow_bench_template!(overflowing_pow_variable, inner_overflowing, variable_base);
+pow_bench_template!(checked_pow_variable, inner_checked_unwrapped, variable_base);
+pow_bench_template!(saturating_pow_variable, inner_saturating, variable_base);
+pow_bench_template!(pow_m7, inner_pow, const_base_m7);
+pow_bench_template!(pow_m8, inner_pow, const_base_m8);
diff --git a/library/core/benches/num/mod.rs b/library/core/benches/num/mod.rs
index b97014d9bf9..4922ee150d9 100644
--- a/library/core/benches/num/mod.rs
+++ b/library/core/benches/num/mod.rs
@@ -1,6 +1,7 @@
 mod dec2flt;
 mod flt2dec;
 mod int_log;
+mod int_pow;
 
 use std::str::FromStr;
 use test::{black_box, Bencher};
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 3df3e8ea05c..5d917dc6fbb 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1787,8 +1787,9 @@ extern "rust-intrinsic" {
     /// so this rounds half-way cases to the number with an even least significant digit.
     ///
     /// May raise an inexact floating-point exception if the argument is not an integer.
-    /// However, Rust assumes floating-point exceptions cannot be observed, so this is not something that
-    /// can actually be used from Rust code.
+    /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
+    /// cannot actually be utilized from Rust code.
+    /// In other words, this intrinsic is equivalent in behavior to `nearbyintf32` and `roundevenf32`.
     ///
     /// The stabilized version of this intrinsic is
     /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
@@ -1798,8 +1799,9 @@ extern "rust-intrinsic" {
     /// so this rounds half-way cases to the number with an even least significant digit.
     ///
     /// May raise an inexact floating-point exception if the argument is not an integer.
-    /// However, Rust assumes floating-point exceptions cannot be observed, so this is not something that
-    /// can actually be used from Rust code.
+    /// However, Rust assumes floating-point exceptions cannot be observed, so these exceptions
+    /// cannot actually be utilized from Rust code.
+    /// In other words, this intrinsic is equivalent in behavior to `nearbyintf64` and `roundevenf64`.
     ///
     /// The stabilized version of this intrinsic is
     /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index f5ecf501ce9..2df38ab5848 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -104,6 +104,18 @@ macro_rules! nonzero_integers {
                 #[inline]
                 #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")]
                 pub const fn get(self) -> $Int {
+                    // FIXME: Remove this after LLVM supports `!range` metadata for function
+                    // arguments https://github.com/llvm/llvm-project/issues/76628
+                    //
+                    // Rustc can set range metadata only if it loads `self` from
+                    // memory somewhere. If the value of `self` was from by-value argument
+                    // of some not-inlined function, LLVM don't have range metadata
+                    // to understand that the value cannot be zero.
+
+                    // SAFETY: It is an invariant of this type.
+                    unsafe {
+                        intrinsics::assume(self.0 != 0);
+                    }
                     self.0
                 }
 
@@ -114,7 +126,9 @@ macro_rules! nonzero_integers {
                 #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")]
                 #[inline]
                 fn from(nonzero: $Ty) -> Self {
-                    nonzero.0
+                    // Call nonzero to keep information range information
+                    // from get method.
+                    nonzero.get()
                 }
             }
 
@@ -233,7 +247,7 @@ macro_rules! nonzero_leading_trailing_zeros {
                 #[inline]
                 pub const fn leading_zeros(self) -> u32 {
                     // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`.
-                    unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 }
+                    unsafe { intrinsics::ctlz_nonzero(self.get() as $Uint) as u32 }
                 }
 
                 /// Returns the number of trailing zeros in the binary representation
@@ -257,7 +271,7 @@ macro_rules! nonzero_leading_trailing_zeros {
                 #[inline]
                 pub const fn trailing_zeros(self) -> u32 {
                     // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`.
-                    unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 }
+                    unsafe { intrinsics::cttz_nonzero(self.get() as $Uint) as u32 }
                 }
 
             }
@@ -515,7 +529,7 @@ macro_rules! nonzero_unsigned_operations {
                               without modifying the original"]
                 #[inline]
                 pub const fn ilog10(self) -> u32 {
-                    super::int_log10::$Int(self.0)
+                    super::int_log10::$Int(self.get())
                 }
 
                 /// Calculates the middle point of `self` and `rhs`.
diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
index b1c1456ade1..ed52de3cbec 100644
--- a/library/core/tests/array.rs
+++ b/library/core/tests/array.rs
@@ -1,6 +1,6 @@
-use core::{array, assert_eq};
 use core::num::NonZeroUsize;
 use core::sync::atomic::{AtomicUsize, Ordering};
+use core::{array, assert_eq};
 
 #[test]
 fn array_from_ref() {
diff --git a/library/core/tests/cell.rs b/library/core/tests/cell.rs
index 71b8eb29600..d6a401c2b4d 100644
--- a/library/core/tests/cell.rs
+++ b/library/core/tests/cell.rs
@@ -466,14 +466,14 @@ fn const_cells() {
     const CELL: Cell<i32> = Cell::new(3);
     const _: i32 = CELL.into_inner();
 
-/* FIXME(#110395)
-    const UNSAFE_CELL_FROM: UnsafeCell<i32> = UnsafeCell::from(3);
-    const _: i32 = UNSAFE_CELL.into_inner();
+    /* FIXME(#110395)
+        const UNSAFE_CELL_FROM: UnsafeCell<i32> = UnsafeCell::from(3);
+        const _: i32 = UNSAFE_CELL.into_inner();
 
-    const REF_CELL_FROM: RefCell<i32> = RefCell::from(3);
-    const _: i32 = REF_CELL.into_inner();
+        const REF_CELL_FROM: RefCell<i32> = RefCell::from(3);
+        const _: i32 = REF_CELL.into_inner();
 
-    const CELL_FROM: Cell<i32> = Cell::from(3);
-    const _: i32 = CELL.into_inner();
-*/
+        const CELL_FROM: Cell<i32> = Cell::from(3);
+        const _: i32 = CELL.into_inner();
+    */
 }
diff --git a/library/core/tests/error.rs b/library/core/tests/error.rs
index cb7cb5441d1..5e20c34ca6c 100644
--- a/library/core/tests/error.rs
+++ b/library/core/tests/error.rs
@@ -1,4 +1,4 @@
-use core::error::{request_value, request_ref, Request};
+use core::error::{request_ref, request_value, Request};
 
 // Test the `Request` API.
 #[derive(Debug)]
diff --git a/library/core/tests/fmt/mod.rs b/library/core/tests/fmt/mod.rs
index c1c80c46c78..704d2461399 100644
--- a/library/core/tests/fmt/mod.rs
+++ b/library/core/tests/fmt/mod.rs
@@ -22,11 +22,11 @@ fn test_pointer_formats_data_pointer() {
 #[test]
 fn test_estimated_capacity() {
     assert_eq!(format_args!("").estimated_capacity(), 0);
-    assert_eq!(format_args!("{}", {""}).estimated_capacity(), 0);
+    assert_eq!(format_args!("{}", { "" }).estimated_capacity(), 0);
     assert_eq!(format_args!("Hello").estimated_capacity(), 5);
-    assert_eq!(format_args!("Hello, {}!", {""}).estimated_capacity(), 16);
-    assert_eq!(format_args!("{}, hello!", {"World"}).estimated_capacity(), 0);
-    assert_eq!(format_args!("{}. 16-bytes piece", {"World"}).estimated_capacity(), 32);
+    assert_eq!(format_args!("Hello, {}!", { "" }).estimated_capacity(), 16);
+    assert_eq!(format_args!("{}, hello!", { "World" }).estimated_capacity(), 0);
+    assert_eq!(format_args!("{}. 16-bytes piece", { "World" }).estimated_capacity(), 32);
 }
 
 #[test]
diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs
index addc255de4a..3b9351457a9 100644
--- a/library/core/tests/hash/mod.rs
+++ b/library/core/tests/hash/mod.rs
@@ -35,7 +35,8 @@ impl Hasher for MyHasher {
 #[test]
 fn test_writer_hasher() {
     // FIXME(#110395)
-    /* const */ fn hash<T: Hash>(t: &T) -> u64 {
+    /* const */
+    fn hash<T: Hash>(t: &T) -> u64 {
         let mut s = MyHasher { hash: 0 };
         t.hash(&mut s);
         s.finish()
@@ -140,7 +141,8 @@ impl Hash for Custom {
 #[test]
 fn test_custom_state() {
     // FIXME(#110395)
-    /* const */ fn hash<T: Hash>(t: &T) -> u64 {
+    /* const */
+    fn hash<T: Hash>(t: &T) -> u64 {
         let mut c = CustomHasher { output: 0 };
         t.hash(&mut c);
         c.finish()
diff --git a/library/core/tests/iter/adapters/chain.rs b/library/core/tests/iter/adapters/chain.rs
index 175a1b638e1..ad78a85a88d 100644
--- a/library/core/tests/iter/adapters/chain.rs
+++ b/library/core/tests/iter/adapters/chain.rs
@@ -42,7 +42,10 @@ fn test_iterator_chain_advance_by() {
             let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
             assert_eq!(iter.advance_by(xs.len() + i), Ok(()));
             assert_eq!(iter.next(), Some(&ys[i]));
-            assert_eq!(iter.advance_by(100), Err(NonZeroUsize::new(100 - (ys.len() - i - 1)).unwrap()));
+            assert_eq!(
+                iter.advance_by(100),
+                Err(NonZeroUsize::new(100 - (ys.len() - i - 1)).unwrap())
+            );
             assert_eq!(iter.advance_by(0), Ok(()));
         }
 
@@ -71,7 +74,10 @@ fn test_iterator_chain_advance_back_by() {
             let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
             assert_eq!(iter.advance_back_by(i), Ok(()));
             assert_eq!(iter.next_back(), Some(&ys[ys.len() - i - 1]));
-            assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (len - i - 1)).unwrap()));
+            assert_eq!(
+                iter.advance_back_by(100),
+                Err(NonZeroUsize::new(100 - (len - i - 1)).unwrap())
+            );
             assert_eq!(iter.advance_back_by(0), Ok(()));
         }
 
@@ -79,7 +85,10 @@ fn test_iterator_chain_advance_back_by() {
             let mut iter = Unfuse::new(xs).chain(Unfuse::new(ys));
             assert_eq!(iter.advance_back_by(ys.len() + i), Ok(()));
             assert_eq!(iter.next_back(), Some(&xs[xs.len() - i - 1]));
-            assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (xs.len() - i - 1)).unwrap()));
+            assert_eq!(
+                iter.advance_back_by(100),
+                Err(NonZeroUsize::new(100 - (xs.len() - i - 1)).unwrap())
+            );
             assert_eq!(iter.advance_back_by(0), Ok(()));
         }
 
diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs
index 91809c9e5fd..f429d90cd7d 100644
--- a/library/core/tests/iter/adapters/flatten.rs
+++ b/library/core/tests/iter/adapters/flatten.rs
@@ -1,5 +1,5 @@
-use core::assert_eq;
 use super::*;
+use core::assert_eq;
 use core::iter::*;
 use core::num::NonZeroUsize;
 
diff --git a/library/core/tests/iter/adapters/step_by.rs b/library/core/tests/iter/adapters/step_by.rs
index 4c5b1dd9a6b..70c9906163a 100644
--- a/library/core/tests/iter/adapters/step_by.rs
+++ b/library/core/tests/iter/adapters/step_by.rs
@@ -245,7 +245,6 @@ fn test_step_by_skip() {
     assert_eq!((200..=255u8).step_by(10).nth(3), Some(230));
 }
 
-
 struct DeOpt<I: Iterator>(I);
 
 impl<I: Iterator> Iterator for DeOpt<I> {
@@ -265,17 +264,15 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for DeOpt<I> {
 #[test]
 fn test_step_by_fold_range_specialization() {
     macro_rules! t {
-        ($range:expr, $var: ident, $body:tt) => {
-            {
-                // run the same tests for the non-optimized version
-                let mut $var = DeOpt($range);
-                $body
-            }
-            {
-                let mut $var = $range;
-                $body
-            }
+        ($range:expr, $var: ident, $body:tt) => {{
+            // run the same tests for the non-optimized version
+            let mut $var = DeOpt($range);
+            $body
         }
+        {
+            let mut $var = $range;
+            $body
+        }};
     }
 
     t!((1usize..5).step_by(1), r, {
@@ -288,13 +285,12 @@ fn test_step_by_fold_range_specialization() {
         assert_eq!(r.sum::<usize>(), 2);
     });
 
-
     t!((0usize..5).step_by(2), r, {
         assert_eq!(r.next(), Some(0));
         assert_eq!(r.sum::<usize>(), 6);
     });
 
-    t!((usize::MAX - 6 .. usize::MAX).step_by(5), r, {
+    t!((usize::MAX - 6..usize::MAX).step_by(5), r, {
         assert_eq!(r.next(), Some(usize::MAX - 6));
         assert_eq!(r.sum::<usize>(), usize::MAX - 1);
     });
diff --git a/library/core/tests/iter/adapters/take.rs b/library/core/tests/iter/adapters/take.rs
index 3cad47c06de..ff6e362b065 100644
--- a/library/core/tests/iter/adapters/take.rs
+++ b/library/core/tests/iter/adapters/take.rs
@@ -93,7 +93,10 @@ fn test_take_advance_by() {
     assert_eq!((0..2).take(1).advance_back_by(10), Err(NonZeroUsize::new(9).unwrap()));
     assert_eq!((0..0).take(1).advance_back_by(1), Err(NonZeroUsize::new(1).unwrap()));
     assert_eq!((0..0).take(1).advance_back_by(0), Ok(()));
-    assert_eq!((0..usize::MAX).take(100).advance_back_by(usize::MAX), Err(NonZeroUsize::new(usize::MAX - 100).unwrap()));
+    assert_eq!(
+        (0..usize::MAX).take(100).advance_back_by(usize::MAX),
+        Err(NonZeroUsize::new(usize::MAX - 100).unwrap())
+    );
 }
 
 #[test]
diff --git a/library/core/tests/iter/adapters/zip.rs b/library/core/tests/iter/adapters/zip.rs
index c3508be8598..ba54de5822b 100644
--- a/library/core/tests/iter/adapters/zip.rs
+++ b/library/core/tests/iter/adapters/zip.rs
@@ -184,7 +184,7 @@ fn test_zip_nested_sideffectful() {
         let it = xs.iter_mut().map(|x| *x = 1).enumerate().zip(&ys);
         it.count();
     }
-    let length_aware =  &xs == &[1, 1, 1, 1, 0, 0];
+    let length_aware = &xs == &[1, 1, 1, 1, 0, 0];
     let probe_first = &xs == &[1, 1, 1, 1, 1, 0];
 
     // either implementation is valid according to zip documentation
diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs
index 995bbf0e261..9c1dce7b66d 100644
--- a/library/core/tests/iter/traits/iterator.rs
+++ b/library/core/tests/iter/traits/iterator.rs
@@ -168,7 +168,10 @@ fn test_iterator_advance_back_by() {
         let mut iter = v.iter();
         assert_eq!(iter.advance_back_by(i), Ok(()));
         assert_eq!(iter.next_back().unwrap(), &v[v.len() - 1 - i]);
-        assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap()));
+        assert_eq!(
+            iter.advance_back_by(100),
+            Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap())
+        );
     }
 
     assert_eq!(v.iter().advance_back_by(v.len()), Ok(()));
@@ -183,7 +186,10 @@ fn test_iterator_rev_advance_back_by() {
         let mut iter = v.iter().rev();
         assert_eq!(iter.advance_back_by(i), Ok(()));
         assert_eq!(iter.next_back().unwrap(), &v[i]);
-        assert_eq!(iter.advance_back_by(100), Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap()));
+        assert_eq!(
+            iter.advance_back_by(100),
+            Err(NonZeroUsize::new(100 - (v.len() - 1 - i)).unwrap())
+        );
     }
 
     assert_eq!(v.iter().rev().advance_back_by(v.len()), Ok(()));
diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs
index 7f7802c221a..3d13bffba92 100644
--- a/library/core/tests/net/ip_addr.rs
+++ b/library/core/tests/net/ip_addr.rs
@@ -664,7 +664,11 @@ fn ipv6_properties() {
         &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         global | unicast_global
     );
-    check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
+    check!(
+        "2001:30::",
+        &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
     check!("2001:40::", &[0x20, 1, 0, 0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
 
     check!(
diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs
index 00a308b29d2..b1b9492f182 100644
--- a/library/core/tests/option.rs
+++ b/library/core/tests/option.rs
@@ -178,19 +178,19 @@ fn test_or_else() {
     assert_eq!(x.or_else(two), Some(2));
     assert_eq!(x.or_else(none), None);
 
-/* FIXME(#110395)
-    const FOO: Option<isize> = Some(1);
-    const A: Option<isize> = FOO.or_else(two);
-    const B: Option<isize> = FOO.or_else(none);
-    assert_eq!(A, Some(1));
-    assert_eq!(B, Some(1));
-
-    const BAR: Option<isize> = None;
-    const C: Option<isize> = BAR.or_else(two);
-    const D: Option<isize> = BAR.or_else(none);
-    assert_eq!(C, Some(2));
-    assert_eq!(D, None);
-*/
+    /* FIXME(#110395)
+        const FOO: Option<isize> = Some(1);
+        const A: Option<isize> = FOO.or_else(two);
+        const B: Option<isize> = FOO.or_else(none);
+        assert_eq!(A, Some(1));
+        assert_eq!(B, Some(1));
+
+        const BAR: Option<isize> = None;
+        const C: Option<isize> = BAR.or_else(two);
+        const D: Option<isize> = BAR.or_else(none);
+        assert_eq!(C, Some(2));
+        assert_eq!(D, None);
+    */
 }
 
 #[test]
@@ -486,15 +486,15 @@ const fn option_const_mut() {
             None => unreachable!(),
         }
     }
-/* FIXME(const-hack)
-    {
-        let as_mut: Option<&mut usize> = Option::from(&mut option);
-        match as_mut {
-            Some(v) => *v = 42,
-            None => unreachable!(),
+    /* FIXME(const-hack)
+        {
+            let as_mut: Option<&mut usize> = Option::from(&mut option);
+            match as_mut {
+                Some(v) => *v = 42,
+                None => unreachable!(),
+            }
         }
-    }
-*/
+    */
 }
 
 #[test]
diff --git a/library/core/tests/ptr.rs b/library/core/tests/ptr.rs
index 238f29c5980..b68f2a50b32 100644
--- a/library/core/tests/ptr.rs
+++ b/library/core/tests/ptr.rs
@@ -478,7 +478,11 @@ fn align_offset_various_strides() {
                 x |= test_stride::<A9>(ptr::invalid::<A9>(ptr), align);
 
                 #[repr(packed)]
-                struct A10(#[allow(dead_code)] u32, #[allow(dead_code)] u32, #[allow(dead_code)] u16);
+                struct A10(
+                    #[allow(dead_code)] u32,
+                    #[allow(dead_code)] u32,
+                    #[allow(dead_code)] u16,
+                );
                 x |= test_stride::<A10>(ptr::invalid::<A10>(ptr), align);
 
                 x |= test_stride::<u32>(ptr::invalid::<u32>(ptr), align);
@@ -532,7 +536,11 @@ fn align_offset_various_strides_const() {
                     test_stride::<A6>(ptr::invalid::<A6>(ptr), ptr, align);
 
                     #[repr(packed)]
-                    struct A7(#[allow(dead_code)] u32, #[allow(dead_code)] u16, #[allow(dead_code)] u8);
+                    struct A7(
+                        #[allow(dead_code)] u32,
+                        #[allow(dead_code)] u16,
+                        #[allow(dead_code)] u8,
+                    );
                     test_stride::<A7>(ptr::invalid::<A7>(ptr), ptr, align);
 
                     #[repr(packed)]
@@ -540,11 +548,19 @@ fn align_offset_various_strides_const() {
                     test_stride::<A8>(ptr::invalid::<A8>(ptr), ptr, align);
 
                     #[repr(packed)]
-                    struct A9(#[allow(dead_code)] u32, #[allow(dead_code)] u32, #[allow(dead_code)] u8);
+                    struct A9(
+                        #[allow(dead_code)] u32,
+                        #[allow(dead_code)] u32,
+                        #[allow(dead_code)] u8,
+                    );
                     test_stride::<A9>(ptr::invalid::<A9>(ptr), ptr, align);
 
                     #[repr(packed)]
-                    struct A10(#[allow(dead_code)] u32, #[allow(dead_code)] u32, #[allow(dead_code)] u16);
+                    struct A10(
+                        #[allow(dead_code)] u32,
+                        #[allow(dead_code)] u32,
+                        #[allow(dead_code)] u16,
+                    );
                     test_stride::<A10>(ptr::invalid::<A10>(ptr), ptr, align);
 
                     test_stride::<u32>(ptr::invalid::<u32>(ptr), ptr, align);
diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs
index 24ab4be9d8c..23f07bf84b3 100644
--- a/library/core/tests/time.rs
+++ b/library/core/tests/time.rs
@@ -479,22 +479,22 @@ fn duration_const() {
     const CHECKED_MUL: Option<Duration> = Duration::SECOND.checked_mul(1);
     assert_eq!(CHECKED_MUL, Some(Duration::SECOND));
 
-/*  FIXME(#110395)
-    const MUL_F32: Duration = Duration::SECOND.mul_f32(1.0);
-    assert_eq!(MUL_F32, Duration::SECOND);
+    /*  FIXME(#110395)
+        const MUL_F32: Duration = Duration::SECOND.mul_f32(1.0);
+        assert_eq!(MUL_F32, Duration::SECOND);
 
-    const MUL_F64: Duration = Duration::SECOND.mul_f64(1.0);
-    assert_eq!(MUL_F64, Duration::SECOND);
+        const MUL_F64: Duration = Duration::SECOND.mul_f64(1.0);
+        assert_eq!(MUL_F64, Duration::SECOND);
 
-    const CHECKED_DIV: Option<Duration> = Duration::SECOND.checked_div(1);
-    assert_eq!(CHECKED_DIV, Some(Duration::SECOND));
+        const CHECKED_DIV: Option<Duration> = Duration::SECOND.checked_div(1);
+        assert_eq!(CHECKED_DIV, Some(Duration::SECOND));
 
-    const DIV_F32: Duration = Duration::SECOND.div_f32(1.0);
-    assert_eq!(DIV_F32, Duration::SECOND);
+        const DIV_F32: Duration = Duration::SECOND.div_f32(1.0);
+        assert_eq!(DIV_F32, Duration::SECOND);
 
-    const DIV_F64: Duration = Duration::SECOND.div_f64(1.0);
-    assert_eq!(DIV_F64, Duration::SECOND);
-*/
+        const DIV_F64: Duration = Duration::SECOND.div_f64(1.0);
+        assert_eq!(DIV_F64, Duration::SECOND);
+    */
 
     const DIV_DURATION_F32: f32 = Duration::SECOND.div_duration_f32(Duration::SECOND);
     assert_eq!(DIV_DURATION_F32, 1.0);
diff --git a/library/std/src/num.rs b/library/std/src/num.rs
index 3cd5fa458e0..55f6ddcf77f 100644
--- a/library/std/src/num.rs
+++ b/library/std/src/num.rs
@@ -9,9 +9,6 @@
 #[cfg(test)]
 mod tests;
 
-#[cfg(test)]
-mod benches;
-
 #[stable(feature = "saturating_int_impl", since = "1.74.0")]
 pub use core::num::Saturating;
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/num/benches.rs b/library/std/src/num/benches.rs
deleted file mode 100644
index 233ea0506c0..00000000000
--- a/library/std/src/num/benches.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use test::Bencher;
-
-#[bench]
-fn bench_pow_function(b: &mut Bencher) {
-    let v = (0..1024).collect::<Vec<u32>>();
-    b.iter(|| {
-        v.iter().fold(0u32, |old, new| old.pow(*new as u32));
-    });
-}
diff --git a/library/std/tests/process_spawning.rs b/library/std/tests/process_spawning.rs
index 46dc9ff00bd..59f67f9901f 100644
--- a/library/std/tests/process_spawning.rs
+++ b/library/std/tests/process_spawning.rs
@@ -1,4 +1,4 @@
-#![cfg(not(target_env="sgx"))]
+#![cfg(not(target_env = "sgx"))]
 
 use std::env;
 use std::fs;
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 2fa5a8e5e38..2e93796d981 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -298,24 +298,18 @@ where
 
     let mut filtered = FilteredTests { tests: Vec::new(), benches: Vec::new(), next_id: 0 };
 
-    for test in filter_tests(opts, tests) {
+    let mut filtered_tests = filter_tests(opts, tests);
+    if !opts.bench_benchmarks {
+        filtered_tests = convert_benchmarks_to_tests(filtered_tests);
+    }
+
+    for test in filtered_tests {
         let mut desc = test.desc;
         desc.name = desc.name.with_padding(test.testfn.padding());
 
         match test.testfn {
-            DynBenchFn(benchfn) => {
-                if opts.bench_benchmarks {
-                    filtered.add_bench(desc, DynBenchFn(benchfn));
-                } else {
-                    filtered.add_test(desc, DynBenchAsTestFn(benchfn));
-                }
-            }
-            StaticBenchFn(benchfn) => {
-                if opts.bench_benchmarks {
-                    filtered.add_bench(desc, StaticBenchFn(benchfn));
-                } else {
-                    filtered.add_test(desc, StaticBenchAsTestFn(benchfn));
-                }
+            DynBenchFn(_) | StaticBenchFn(_) => {
+                filtered.add_bench(desc, test.testfn);
             }
             testfn => {
                 filtered.add_test(desc, testfn);
diff --git a/rustfmt.toml b/rustfmt.toml
index e292a310742..e6cc298ec44 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -13,7 +13,7 @@ ignore = [
 
     # tests for now are not formatted, as they are sometimes pretty-printing constrained
     # (and generally rustfmt can move around comments in UI-testing incompatible ways)
-    "tests",
+    "/tests/",
 
     # do not format submodules
     # FIXME: sync submodule list with tidy/bootstrap/etc
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 95553e7ea02..e2c90cc8c84 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -4,18 +4,18 @@ version = 3
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.18"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "anstyle"
-version = "1.0.0"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
 
 [[package]]
 name = "autocfg"
@@ -37,9 +37,9 @@ checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
 
 [[package]]
 name = "block-buffer"
-version = "0.10.2"
+version = "0.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
 dependencies = [
  "generic-array",
 ]
@@ -79,13 +79,13 @@ dependencies = [
 
 [[package]]
 name = "bstr"
-version = "0.2.17"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
+checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
 dependencies = [
- "lazy_static",
  "memchr",
  "regex-automata",
+ "serde",
 ]
 
 [[package]]
@@ -110,9 +110,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "clap"
-version = "4.4.7"
+version = "4.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
+checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -120,9 +120,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.4.7"
+version = "4.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
+checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
 dependencies = [
  "anstyle",
  "clap_lex",
@@ -130,9 +130,9 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.4.3"
+version = "4.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3ae8ba90b9d8b007efe66e55e48fb936272f5ca00349b5b0e89877520d35ea7"
+checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd"
 dependencies = [
  "clap",
 ]
@@ -166,24 +166,24 @@ dependencies = [
 
 [[package]]
 name = "core-foundation-sys"
-version = "0.8.3"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.5"
+version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
 dependencies = [
  "libc",
 ]
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.8.2"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
+checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
 dependencies = [
  "cfg-if",
  "crossbeam-epoch",
@@ -192,31 +192,29 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.9.13"
+version = "0.9.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
+checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d"
 dependencies = [
  "autocfg",
  "cfg-if",
  "crossbeam-utils",
- "memoffset",
- "scopeguard",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.14"
+version = "0.8.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
+checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c"
 dependencies = [
  "cfg-if",
 ]
 
 [[package]]
 name = "crypto-common"
-version = "0.1.3"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
 dependencies = [
  "generic-array",
  "typenum",
@@ -224,15 +222,15 @@ dependencies = [
 
 [[package]]
 name = "diff"
-version = "0.1.12"
+version = "0.1.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
+checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
 
 [[package]]
 name = "digest"
-version = "0.10.3"
+version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
 dependencies = [
  "block-buffer",
  "crypto-common",
@@ -240,9 +238,9 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.6.1"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
+checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
 
 [[package]]
 name = "errno"
@@ -267,27 +265,21 @@ dependencies = [
 
 [[package]]
 name = "filetime"
-version = "0.2.16"
+version = "0.2.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c"
+checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
- "winapi",
+ "windows-sys",
 ]
 
 [[package]]
-name = "fnv"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
-
-[[package]]
 name = "generic-array"
-version = "0.14.5"
+version = "0.14.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
 dependencies = [
  "typenum",
  "version_check",
@@ -295,15 +287,15 @@ dependencies = [
 
 [[package]]
 name = "globset"
-version = "0.4.8"
+version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd"
+checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
 dependencies = [
  "aho-corasick",
  "bstr",
- "fnv",
  "log",
- "regex",
+ "regex-automata",
+ "regex-syntax",
 ]
 
 [[package]]
@@ -314,36 +306,34 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
 name = "home"
-version = "0.5.4"
+version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408"
+checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
 dependencies = [
- "winapi",
+ "windows-sys",
 ]
 
 [[package]]
 name = "ignore"
-version = "0.4.18"
+version = "0.4.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d"
+checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060"
 dependencies = [
- "crossbeam-utils",
+ "crossbeam-deque",
  "globset",
- "lazy_static",
  "log",
  "memchr",
- "regex",
+ "regex-automata",
  "same-file",
- "thread_local",
  "walkdir",
  "winapi-util",
 ]
 
 [[package]]
 name = "itoa"
-version = "1.0.2"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
 
 [[package]]
 name = "junction"
@@ -356,16 +346,10 @@ dependencies = [
 ]
 
 [[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
 name = "libc"
-version = "0.2.150"
+version = "0.2.151"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
+checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
 
 [[package]]
 name = "linux-raw-sys"
@@ -375,18 +359,15 @@ checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
 
 [[package]]
 name = "log"
-version = "0.4.17"
+version = "0.4.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
-dependencies = [
- "cfg-if",
-]
+checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
 
 [[package]]
 name = "lzma-sys"
-version = "0.1.17"
+version = "0.1.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdb4b7c3eddad11d3af9e86c487607d2d2442d185d848575365c4856ba96d619"
+checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
 dependencies = [
  "cc",
  "libc",
@@ -395,33 +376,24 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.5.0"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
-
-[[package]]
-name = "memoffset"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
-dependencies = [
- "autocfg",
-]
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
 
 [[package]]
 name = "ntapi"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc"
+checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
 dependencies = [
  "winapi",
 ]
 
 [[package]]
 name = "object"
-version = "0.32.0"
+version = "0.32.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
 dependencies = [
  "memchr",
 ]
@@ -434,9 +406,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
 name = "opener"
-version = "0.5.0"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952"
+checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005"
 dependencies = [
  "bstr",
  "winapi",
@@ -444,9 +416,9 @@ dependencies = [
 
 [[package]]
 name = "pkg-config"
-version = "0.3.25"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
+checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
 
 [[package]]
 name = "pretty_assertions"
@@ -460,18 +432,18 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.60"
+version = "1.0.76"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
+checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.26"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
 dependencies = [
  "proc-macro2",
 ]
@@ -498,18 +470,18 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.13"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
 dependencies = [
  "bitflags 1.3.2",
 ]
 
 [[package]]
-name = "regex"
-version = "1.5.6"
+name = "regex-automata"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -517,16 +489,10 @@ dependencies = [
 ]
 
 [[package]]
-name = "regex-automata"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
-
-[[package]]
 name = "regex-syntax"
-version = "0.6.26"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
 
 [[package]]
 name = "rustix"
@@ -543,9 +509,9 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.10"
+version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
 
 [[package]]
 name = "same-file"
@@ -558,27 +524,30 @@ dependencies = [
 
 [[package]]
 name = "scopeguard"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "semver"
-version = "1.0.17"
+version = "1.0.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
 
 [[package]]
 name = "serde"
-version = "1.0.160"
+version = "1.0.195"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
+checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
+dependencies = [
+ "serde_derive",
+]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.160"
+version = "1.0.195"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
+checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -587,9 +556,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.81"
+version = "1.0.111"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
+checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
 dependencies = [
  "itoa",
  "ryu",
@@ -598,9 +567,9 @@ dependencies = [
 
 [[package]]
 name = "sha2"
-version = "0.10.2"
+version = "0.10.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
 dependencies = [
  "cfg-if",
  "cpufeatures",
@@ -609,9 +578,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.8"
+version = "2.0.48"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -620,9 +589,9 @@ dependencies = [
 
 [[package]]
 name = "sysinfo"
-version = "0.30.3"
+version = "0.30.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba2dbd2894d23b2d78dae768d85e323b557ac3ac71a5d917a31536d8f77ebada"
+checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2"
 dependencies = [
  "cfg-if",
  "core-foundation-sys",
@@ -635,9 +604,9 @@ dependencies = [
 
 [[package]]
 name = "tar"
-version = "0.4.38"
+version = "0.4.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6"
+checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
 dependencies = [
  "filetime",
  "libc",
@@ -646,42 +615,33 @@ dependencies = [
 
 [[package]]
 name = "termcolor"
-version = "1.2.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
+checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
 dependencies = [
  "winapi-util",
 ]
 
 [[package]]
-name = "thread_local"
-version = "1.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
-dependencies = [
- "once_cell",
-]
-
-[[package]]
 name = "toml"
-version = "0.5.9"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "typenum"
-version = "1.15.0"
+version = "1.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.0"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
 [[package]]
 name = "version_check"
@@ -691,12 +651,11 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "walkdir"
-version = "2.3.2"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
 dependencies = [
  "same-file",
- "winapi",
  "winapi-util",
 ]
 
@@ -718,9 +677,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
 [[package]]
 name = "winapi-util"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
 dependencies = [
  "winapi",
 ]
@@ -818,18 +777,20 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
 
 [[package]]
 name = "xattr"
-version = "0.2.3"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc"
+checksum = "914566e6413e7fa959cc394fb30e563ba80f3541fbd40816d4c05a0fc3f2a0f1"
 dependencies = [
  "libc",
+ "linux-raw-sys",
+ "rustix",
 ]
 
 [[package]]
 name = "xz2"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c179869f34fc7c01830d3ce7ea2086bc3a07e0d35289b667d0a8bf910258926c"
+checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
 dependencies = [
  "lzma-sys",
 ]
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 8e09f216d74..b232885c590 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -33,30 +33,34 @@ path = "src/bin/sccache-plus-cl.rs"
 test = false
 
 [dependencies]
+# Most of the time updating these dependencies requires modifications
+# to the bootstrap codebase; otherwise, some targets will fail. That's
+# why these dependencies are explicitly pinned.
+cc = "=1.0.73"
+cmake = "=0.1.48"
+
 build_helper = { path = "../tools/build_helper" }
-cc = "1.0.69"
-clap = { version = "4.4.7", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
-clap_complete = "4.4.3"
-cmake = "0.1.38"
+clap = { version = "4.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
+clap_complete = "4.4"
 fd-lock = "4.0"
 filetime = "0.2"
-home = "0.5.4"
-ignore = "0.4.10"
-libc = "0.2.150"
-object = { version = "0.32.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
-once_cell = "1.7.2"
+home = "0.5"
+ignore = "0.4"
+libc = "0.2"
+object = { version = "0.32", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
+once_cell = "1.19"
 opener = "0.5"
-semver = "1.0.17"
-serde = "1.0.137"
+semver = "1.0"
+serde = "1.0"
 # Directly use serde_derive rather than through the derive feature of serde to allow building both
 # in parallel and to allow serde_json and toml to start building as soon as serde has been built.
-serde_derive = "1.0.137"
-serde_json = "1.0.2"
+serde_derive = "1.0"
+serde_json = "1.0"
 sha2 = "0.10"
 tar = "0.4"
-termcolor = "1.2.0"
+termcolor = "1.4"
 toml = "0.5"
-walkdir = "2"
+walkdir = "2.4"
 xz2 = "0.1"
 
 # Dependencies needed by the build-metrics feature
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 85132e405b4..fcdd742e69c 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -1776,7 +1776,6 @@ impl Config {
                 check_ci_llvm!(static_libstdcpp);
                 check_ci_llvm!(targets);
                 check_ci_llvm!(experimental_targets);
-                check_ci_llvm!(link_jobs);
                 check_ci_llvm!(clang_cl);
                 check_ci_llvm!(version_suffix);
                 check_ci_llvm!(cflags);
diff --git a/src/bootstrap/src/tests/config.rs b/src/bootstrap/src/tests/config.rs
index 6f432343882..c65067f8e8f 100644
--- a/src/bootstrap/src/tests/config.rs
+++ b/src/bootstrap/src/tests/config.rs
@@ -32,9 +32,12 @@ fn download_ci_llvm() {
     assert_eq!(parse_llvm("rust.channel = \"dev\""), if_unchanged);
     assert!(!parse_llvm("rust.channel = \"stable\""));
     assert_eq!(parse_llvm("build.build = \"x86_64-unknown-linux-gnu\""), if_unchanged);
-    assert_eq!(parse_llvm(
-        "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-unchanged\""
-    ), if_unchanged);
+    assert_eq!(
+        parse_llvm(
+            "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-unchanged\""
+        ),
+        if_unchanged
+    );
     assert!(!parse_llvm(
         "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-unchanged\""
     ));
diff --git a/src/bootstrap/src/tests/helpers.rs b/src/bootstrap/src/tests/helpers.rs
index 163594dbb2f..2d626fad417 100644
--- a/src/bootstrap/src/tests/helpers.rs
+++ b/src/bootstrap/src/tests/helpers.rs
@@ -1,4 +1,4 @@
-use crate::utils::helpers::{extract_beta_rev, hex_encode, make, check_cfg_arg};
+use crate::utils::helpers::{check_cfg_arg, extract_beta_rev, hex_encode, make};
 use std::path::PathBuf;
 
 #[test]
diff --git a/src/ci/scripts/dump-environment.sh b/src/ci/scripts/dump-environment.sh
index c6774b52ab9..812690181e9 100755
--- a/src/ci/scripts/dump-environment.sh
+++ b/src/ci/scripts/dump-environment.sh
@@ -1,6 +1,8 @@
 #!/bin/bash
 # This script dumps information about the build environment to stdout.
 
+source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
+
 set -euo pipefail
 IFS=$'\n\t'
 
@@ -17,3 +19,17 @@ set +o pipefail
 du . | sort -nr | head -n100
 set -o pipefail
 echo
+
+if isMacOS
+then
+    # Debugging information that might be helpful for diagnosing macOS
+    # performance issues.
+    # SIP
+    csrutil status
+    # Gatekeeper
+    spctl --status
+    # Authorization policy
+    DevToolsSecurity -status
+    # Spotlight status
+    mdutil -avs
+fi
diff --git a/src/doc/unstable-book/src/compiler-flags/env.md b/src/doc/unstable-book/src/compiler-flags/env-set.md
index ac6d7474a9b..e5d7206c3a3 100644
--- a/src/doc/unstable-book/src/compiler-flags/env.md
+++ b/src/doc/unstable-book/src/compiler-flags/env-set.md
@@ -1,4 +1,4 @@
-# `env`
+# `env-set`
 
 The tracking issue for this feature is: [#118372](https://github.com/rust-lang/rust/issues/118372).
 
@@ -11,11 +11,11 @@ from the `proc_macro` crate.
 This information will be stored in the dep-info files. For more information about
 dep-info files, take a look [here](https://doc.rust-lang.org/cargo/guide/build-cache.html#dep-info-files).
 
-When retrieving an environment variable value, the one specified by `--env` will take
+When retrieving an environment variable value, the one specified by `--env-set` will take
 precedence. For example, if you want have `PATH=a` in your environment and pass:
 
 ```bash
-rustc --env PATH=env
+rustc --env-set PATH=env
 ```
 
 Then you will have:
@@ -24,17 +24,17 @@ Then you will have:
 assert_eq!(env!("PATH"), "env");
 ```
 
-It will trigger a new compilation if any of the `--env` argument value is different.
+It will trigger a new compilation if any of the `--env-set` argument value is different.
 So if you first passed:
 
 ```bash
---env A=B --env X=12
+--env-set A=B --env X=12
 ```
 
 and then on next compilation:
 
 ```bash
---env A=B
+--env-set A=B
 ```
 
 `X` value is different (not set) so the code will be re-compiled.
@@ -42,4 +42,4 @@ and then on next compilation:
 Please note that on Windows, environment variables are case insensitive but case
 preserving whereas `rustc`'s environment variables are case sensitive. For example,
 having `Path` in your environment (case insensitive) is different than using
-`rustc --env Path=...` (case sensitive).
+`rustc --env-set Path=...` (case sensitive).
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
index 8ffd8f67df2..e1436dcde67 100644
--- a/src/etc/completions/x.py.sh
+++ b/src/etc/completions/x.py.sh
@@ -1761,4 +1761,8 @@ _x.py() {
     esac
 }
 
-complete -F _x.py -o nosort -o bashdefault -o default x.py
+if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then
+    complete -F _x.py -o nosort -o bashdefault -o default x.py
+else
+    complete -F _x.py -o bashdefault -o default x.py
+fi
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index 605f9e496c7..b736f4a7956 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -69,8 +69,8 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option<String
     let mut parser =
         match rustc_parse::maybe_new_parser_from_source_str(&sess, file_name, snippet.clone()) {
             Ok(parser) => parser,
-            Err(diagnostics) => {
-                drop(diagnostics);
+            Err(errs) => {
+                errs.into_iter().for_each(|err| err.cancel());
                 return None;
             }
         };
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 9a900625268..82746a7ab03 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -589,7 +589,7 @@ pub(crate) fn make_test(
             let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source) {
                 Ok(p) => p,
                 Err(errs) => {
-                    drop(errs);
+                    errs.into_iter().for_each(|err| err.cancel());
                     return (found_main, found_extern_crate, found_macro);
                 }
             };
@@ -759,8 +759,10 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
             let mut parser =
                 match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) {
                     Ok(p) => p,
-                    Err(_) => {
-                        // If there is an unclosed delimiter, an error will be returned by the tokentrees.
+                    Err(errs) => {
+                        errs.into_iter().for_each(|err| err.cancel());
+                        // If there is an unclosed delimiter, an error will be returned by the
+                        // tokentrees.
                         return false;
                     }
                 };
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 606bc11367b475542bd6228163424ca43b4dbdb
+Subproject 700fbf978e6c5bb297d12963206f7487722de48
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 3e428a38a34e820a461d2cc082e726d3bda71bc
+Subproject 84976cd699f4aea56cb3a90ce3eedeed9e20d5a
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index 99d80bec025..5ba960db66d 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -38,7 +38,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: Install toolchain
       run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 73c25550742..012797e5ca7 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -26,7 +26,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
       with:
         ref: ${{ github.ref }}
 
@@ -72,7 +72,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: Install i686 dependencies
       if: matrix.host == 'i686-unknown-linux-gnu'
@@ -151,7 +151,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -175,7 +175,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: Install toolchain
       run: rustup show active-toolchain
@@ -231,7 +231,7 @@ jobs:
         github_token: "${{ secrets.github_token }}"
 
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: Install toolchain
       run: rustup show active-toolchain
diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml
index 0f0e3f2db92..37f18a4c087 100644
--- a/src/tools/clippy/.github/workflows/clippy_dev.yml
+++ b/src/tools/clippy/.github/workflows/clippy_dev.yml
@@ -24,7 +24,7 @@ jobs:
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     # Run
     - name: Build
diff --git a/src/tools/clippy/.github/workflows/deploy.yml b/src/tools/clippy/.github/workflows/deploy.yml
index 999ee7acfe7..94f494b65c4 100644
--- a/src/tools/clippy/.github/workflows/deploy.yml
+++ b/src/tools/clippy/.github/workflows/deploy.yml
@@ -21,10 +21,10 @@ jobs:
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
       with:
         ref: ${{ env.TARGET_BRANCH }}
         path: 'out'
diff --git a/src/tools/clippy/.github/workflows/remark.yml b/src/tools/clippy/.github/workflows/remark.yml
index 30bd476332f..05e1b3b9202 100644
--- a/src/tools/clippy/.github/workflows/remark.yml
+++ b/src/tools/clippy/.github/workflows/remark.yml
@@ -16,7 +16,7 @@ jobs:
     steps:
     # Setup
     - name: Checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: Setup Node.js
       uses: actions/setup-node@v3
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index f82421a687b..4d32bbec914 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -5105,6 +5105,7 @@ Released 2018-09-13
 [`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
 [`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
 [`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
+[`empty_enum_variants_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum_variants_with_brackets
 [`empty_line_after_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments
 [`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr
 [`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop
@@ -5294,6 +5295,7 @@ Released 2018-09-13
 [`manual_is_ascii_check`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_ascii_check
 [`manual_is_finite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_finite
 [`manual_is_infinite`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_infinite
+[`manual_is_variant_and`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_is_variant_and
 [`manual_let_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else
 [`manual_main_separator_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_main_separator_str
 [`manual_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_map
@@ -5440,6 +5442,7 @@ Released 2018-09-13
 [`only_used_in_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#only_used_in_recursion
 [`op_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#op_ref
 [`option_and_then_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_and_then_some
+[`option_as_ref_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_cloned
 [`option_as_ref_deref`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_as_ref_deref
 [`option_env_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_env_unwrap
 [`option_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#option_expect_used
@@ -5483,6 +5486,7 @@ Released 2018-09-13
 [`ptr_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_eq
 [`ptr_offset_with_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#ptr_offset_with_cast
 [`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names
+[`pub_underscore_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields
 [`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use
 [`pub_with_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_with_shorthand
 [`pub_without_shorthand`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_without_shorthand
@@ -5580,6 +5584,7 @@ Released 2018-09-13
 [`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
 [`std_instead_of_alloc`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_alloc
 [`std_instead_of_core`]: https://rust-lang.github.io/rust-clippy/master/index.html#std_instead_of_core
+[`str_split_at_newline`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_split_at_newline
 [`str_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#str_to_string
 [`string_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add
 [`string_add_assign`]: https://rust-lang.github.io/rust-clippy/master/index.html#string_add_assign
@@ -5612,6 +5617,7 @@ Released 2018-09-13
 [`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr
 [`test_attr_in_doctest`]: https://rust-lang.github.io/rust-clippy/master/index.html#test_attr_in_doctest
 [`tests_outside_test_module`]: https://rust-lang.github.io/rust-clippy/master/index.html#tests_outside_test_module
+[`thread_local_initializer_can_be_made_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#thread_local_initializer_can_be_made_const
 [`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
@@ -5810,4 +5816,5 @@ Released 2018-09-13
 [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles
 [`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow
 [`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items
+[`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior
 <!-- end autogenerated links to configuration documentation -->
diff --git a/src/tools/clippy/COPYRIGHT b/src/tools/clippy/COPYRIGHT
index 82703b18fd7..219693d63d9 100644
--- a/src/tools/clippy/COPYRIGHT
+++ b/src/tools/clippy/COPYRIGHT
@@ -1,6 +1,6 @@
 // REUSE-IgnoreStart
 
-Copyright 2014-2022 The Rust Project Developers
+Copyright 2014-2024 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
diff --git a/src/tools/clippy/LICENSE-APACHE b/src/tools/clippy/LICENSE-APACHE
index 0d62c37278e..506582c31d6 100644
--- a/src/tools/clippy/LICENSE-APACHE
+++ b/src/tools/clippy/LICENSE-APACHE
@@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work.
    same "printed page" as the copyright notice for easier
    identification within third-party archives.
 
-Copyright 2014-2022 The Rust Project Developers
+Copyright 2014-2024 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
diff --git a/src/tools/clippy/LICENSE-MIT b/src/tools/clippy/LICENSE-MIT
index b724b24aa83..6d8ee9afb61 100644
--- a/src/tools/clippy/LICENSE-MIT
+++ b/src/tools/clippy/LICENSE-MIT
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2014-2022 The Rust Project Developers
+Copyright (c) 2014-2024 The Rust Project Developers
 
 Permission is hereby granted, free of charge, to any
 person obtaining a copy of this software and associated
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index 5d490645d89..fa18447090c 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -5,7 +5,7 @@
 
 A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
 
-[There are over 650 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
 
 Lints are divided into categories, each with a default [lint level](https://doc.rust-lang.org/rustc/lints/levels.html).
 You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the lint level by category.
@@ -278,7 +278,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT
 
 <!-- REUSE-IgnoreStart -->
 
-Copyright 2014-2023 The Rust Project Developers
+Copyright 2014-2024 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license
diff --git a/src/tools/clippy/book/src/README.md b/src/tools/clippy/book/src/README.md
index 486ea3df704..e7972b0db19 100644
--- a/src/tools/clippy/book/src/README.md
+++ b/src/tools/clippy/book/src/README.md
@@ -6,7 +6,7 @@
 A collection of lints to catch common mistakes and improve your
 [Rust](https://github.com/rust-lang/rust) code.
 
-[There are over 650 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are over 700 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
 
 Lints are divided into categories, each with a default [lint
 level](https://doc.rust-lang.org/rustc/lints/levels.html). You can choose how
diff --git a/src/tools/clippy/book/src/SUMMARY.md b/src/tools/clippy/book/src/SUMMARY.md
index b02457307d7..a048fbbd8ac 100644
--- a/src/tools/clippy/book/src/SUMMARY.md
+++ b/src/tools/clippy/book/src/SUMMARY.md
@@ -9,6 +9,7 @@
 - [Clippy's Lints](lints.md)
 - [Continuous Integration](continuous_integration/README.md)
     - [GitHub Actions](continuous_integration/github_actions.md)
+    - [GitLab CI](continuous_integration/gitlab.md)
     - [Travis CI](continuous_integration/travis.md)
 - [Development](development/README.md)
     - [Basics](development/basics.md)
diff --git a/src/tools/clippy/book/src/continuous_integration/github_actions.md b/src/tools/clippy/book/src/continuous_integration/github_actions.md
index 339287a7dd9..b588c8f0f02 100644
--- a/src/tools/clippy/book/src/continuous_integration/github_actions.md
+++ b/src/tools/clippy/book/src/continuous_integration/github_actions.md
@@ -15,7 +15,7 @@ jobs:
   clippy_check:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Run Clippy
         run: cargo clippy --all-targets --all-features
 ```
diff --git a/src/tools/clippy/book/src/continuous_integration/gitlab.md b/src/tools/clippy/book/src/continuous_integration/gitlab.md
new file mode 100644
index 00000000000..bb3ef246c2f
--- /dev/null
+++ b/src/tools/clippy/book/src/continuous_integration/gitlab.md
@@ -0,0 +1,16 @@
+# GitLab CI
+
+You can add Clippy to GitLab CI by using the latest stable [rust docker image](https://hub.docker.com/_/rust),
+as it is shown in the `.gitlab-ci.yml` CI configuration file below,
+
+```yml
+# Make sure CI fails on all warnings, including Clippy lints
+variables:
+  RUSTFLAGS: "-Dwarnings"
+
+clippy_check:
+  image: rust:latest
+  script:
+    - rustup component add clippy
+    - cargo clippy --all-targets --all-features
+```
diff --git a/src/tools/clippy/book/src/development/macro_expansions.md b/src/tools/clippy/book/src/development/macro_expansions.md
index c5eb000272d..aecca9ef72e 100644
--- a/src/tools/clippy/book/src/development/macro_expansions.md
+++ b/src/tools/clippy/book/src/development/macro_expansions.md
@@ -102,7 +102,7 @@ let x: Option<u32> = Some(42);
 m!(x, x.unwrap());
 ```
 
-If the `m!(x, x.unwrapp());` line is expanded, we would get two expanded
+If the `m!(x, x.unwrap());` line is expanded, we would get two expanded
 expressions:
 
 - `x.is_some()` (from the `$a.is_some()` line in the `m` macro)
diff --git a/src/tools/clippy/book/src/development/type_checking.md b/src/tools/clippy/book/src/development/type_checking.md
index a8c9660da4c..dc29ab5d08d 100644
--- a/src/tools/clippy/book/src/development/type_checking.md
+++ b/src/tools/clippy/book/src/development/type_checking.md
@@ -133,7 +133,7 @@ in this chapter:
 - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
 - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
 
-[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html#variant.Adt
+[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html#variant.Adt
 [AdtDef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html
 [expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty
 [node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type
@@ -144,7 +144,7 @@ in this chapter:
 [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/typeck_results/struct.TypeckResults.html#method.pat_ty
 [Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
-[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/sty/enum.TyKind.html
+[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html
 [TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html
 [middle_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.Ty.html
 [hir_ty]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_hir/struct.Ty.html
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 7c9a8eb1bfb..3b62ae0524a 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -805,3 +805,13 @@ for _ in &mut *rmvec {}
 * [`missing_errors_doc`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc)
 
 
+## `pub-underscore-fields-behavior`
+
+
+**Default Value:** `"PublicallyExported"`
+
+---
+**Affected lints:**
+* [`pub_underscore_fields`](https://rust-lang.github.io/rust-clippy/master/index.html#pub_underscore_fields)
+
+
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index a4f368397ce..5477d9b83a7 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -1,5 +1,5 @@
 use crate::msrvs::Msrv;
-use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, Rename};
+use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
 use crate::ClippyConfiguration;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_session::Session;
@@ -547,6 +547,11 @@ define_Conf! {
     ///
     /// Whether to also run the listed lints on private items.
     (check_private_items: bool = false),
+    /// Lint: PUB_UNDERSCORE_FIELDS
+    ///
+    /// Lint "public" fields in a struct that are prefixed with an underscore based on their
+    /// exported visibility, or whether they are marked as "pub".
+    (pub_underscore_fields_behavior: PubUnderscoreFieldsBehaviour = PubUnderscoreFieldsBehaviour::PublicallyExported),
 }
 
 /// Search for the configuration file.
diff --git a/src/tools/clippy/clippy_config/src/metadata.rs b/src/tools/clippy/clippy_config/src/metadata.rs
index 2451fbc91e8..3ba2796e18d 100644
--- a/src/tools/clippy/clippy_config/src/metadata.rs
+++ b/src/tools/clippy/clippy_config/src/metadata.rs
@@ -96,6 +96,9 @@ fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
         doc_comment.make_ascii_lowercase();
         let lints: Vec<String> = doc_comment
             .split_off(DOC_START.len())
+            .lines()
+            .next()
+            .unwrap()
             .split(", ")
             .map(str::to_string)
             .collect();
diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs
index dae9f09ec00..72d5b9aff28 100644
--- a/src/tools/clippy/clippy_config/src/msrvs.rs
+++ b/src/tools/clippy/clippy_config/src/msrvs.rs
@@ -17,7 +17,7 @@ macro_rules! msrv_aliases {
 // names may refer to stabilized feature flags or library items
 msrv_aliases! {
     1,71,0 { TUPLE_ARRAY_CONVERSIONS, BUILD_HASHER_HASH_ONE }
-    1,70,0 { OPTION_IS_SOME_AND, BINARY_HEAP_RETAIN }
+    1,70,0 { OPTION_RESULT_IS_VARIANT_AND, BINARY_HEAP_RETAIN }
     1,68,0 { PATH_MAIN_SEPARATOR_STR }
     1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS }
     1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs
index df48cc3f5e3..baee09629ac 100644
--- a/src/tools/clippy/clippy_config/src/types.rs
+++ b/src/tools/clippy/clippy_config/src/types.rs
@@ -126,3 +126,9 @@ unimplemented_serialize! {
     Rename,
     MacroMatcher,
 }
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
+pub enum PubUnderscoreFieldsBehaviour {
+    PublicallyExported,
+    AllPubFields,
+}
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index 31a42734c13..5d9cde06cd8 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -67,7 +67,7 @@ pub fn create(
     if pass == "early" {
         println!(
             "\n\
-            NOTE: Use a late pass unless you need something specific from\
+            NOTE: Use a late pass unless you need something specific from\n\
             an early pass, as they lack many features and utilities"
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index bd12ee40628..1df5a25f674 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -1,12 +1,14 @@
 use clippy_utils::consts::{constant, Constant};
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::{method_chain_args, sext};
-use rustc_hir::{Expr, ExprKind};
+use clippy_utils::{clip, method_chain_args, sext};
+use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Ty, UintTy};
 
 use super::CAST_SIGN_LOSS;
 
+const METHODS_RET_POSITIVE: &[&str] = &["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];
+
 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
     if should_lint(cx, cast_op, cast_from, cast_to) {
         span_lint(
@@ -25,33 +27,28 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
                 return false;
             }
 
-            // Don't lint for positive constants.
-            let const_val = constant(cx, cx.typeck_results(), cast_op);
-            if let Some(Constant::Int(n)) = const_val
-                && let ty::Int(ity) = *cast_from.kind()
-                && sext(cx.tcx, n, ity) >= 0
-            {
+            // Don't lint if `cast_op` is known to be positive.
+            if let Sign::ZeroOrPositive = expr_sign(cx, cast_op, cast_from) {
                 return false;
             }
 
-            // Don't lint for the result of methods that always return non-negative values.
-            if let ExprKind::MethodCall(path, ..) = cast_op.kind {
-                let mut method_name = path.ident.name.as_str();
-                let allowed_methods = ["abs", "checked_abs", "rem_euclid", "checked_rem_euclid"];
-
-                if method_name == "unwrap"
-                    && let Some(arglist) = method_chain_args(cast_op, &["unwrap"])
-                    && let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind
-                {
-                    method_name = inner_path.ident.name.as_str();
-                }
-
-                if allowed_methods.iter().any(|&name| method_name == name) {
-                    return false;
-                }
+            let (mut uncertain_count, mut negative_count) = (0, 0);
+            // Peel off possible binary expressions, e.g. x * x * y => [x, x, y]
+            let Some(exprs) = exprs_with_selected_binop_peeled(cast_op) else {
+                // Assume cast sign lose if we cannot determine the sign of `cast_op`
+                return true;
+            };
+            for expr in exprs {
+                let ty = cx.typeck_results().expr_ty(expr);
+                match expr_sign(cx, expr, ty) {
+                    Sign::Negative => negative_count += 1,
+                    Sign::Uncertain => uncertain_count += 1,
+                    Sign::ZeroOrPositive => (),
+                };
             }
 
-            true
+            // Lint if there are odd number of uncertain or negative results
+            uncertain_count % 2 == 1 || negative_count % 2 == 1
         },
 
         (false, true) => !cast_to.is_signed(),
@@ -59,3 +56,97 @@ fn should_lint(cx: &LateContext<'_>, cast_op: &Expr<'_>, cast_from: Ty<'_>, cast
         (_, _) => false,
     }
 }
+
+fn get_const_int_eval(cx: &LateContext<'_>, expr: &Expr<'_>, ty: Ty<'_>) -> Option<i128> {
+    if let Constant::Int(n) = constant(cx, cx.typeck_results(), expr)?
+        && let ty::Int(ity) = *ty.kind()
+    {
+        return Some(sext(cx.tcx, n, ity));
+    }
+    None
+}
+
+enum Sign {
+    ZeroOrPositive,
+    Negative,
+    Uncertain,
+}
+
+fn expr_sign(cx: &LateContext<'_>, expr: &Expr<'_>, ty: Ty<'_>) -> Sign {
+    // Try evaluate this expr first to see if it's positive
+    if let Some(val) = get_const_int_eval(cx, expr, ty) {
+        return if val >= 0 { Sign::ZeroOrPositive } else { Sign::Negative };
+    }
+    // Calling on methods that always return non-negative values.
+    if let ExprKind::MethodCall(path, caller, args, ..) = expr.kind {
+        let mut method_name = path.ident.name.as_str();
+
+        if method_name == "unwrap"
+            && let Some(arglist) = method_chain_args(expr, &["unwrap"])
+            && let ExprKind::MethodCall(inner_path, ..) = &arglist[0].0.kind
+        {
+            method_name = inner_path.ident.name.as_str();
+        }
+
+        if method_name == "pow"
+            && let [arg] = args
+        {
+            return pow_call_result_sign(cx, caller, arg);
+        } else if METHODS_RET_POSITIVE.iter().any(|&name| method_name == name) {
+            return Sign::ZeroOrPositive;
+        }
+    }
+
+    Sign::Uncertain
+}
+
+/// Return the sign of the `pow` call's result.
+///
+/// If the caller is a positive number, the result is always positive,
+/// If the `power_of` is a even number, the result is always positive as well,
+/// Otherwise a [`Sign::Uncertain`] will be returned.
+fn pow_call_result_sign(cx: &LateContext<'_>, caller: &Expr<'_>, power_of: &Expr<'_>) -> Sign {
+    let caller_ty = cx.typeck_results().expr_ty(caller);
+    if let Some(caller_val) = get_const_int_eval(cx, caller, caller_ty)
+        && caller_val >= 0
+    {
+        return Sign::ZeroOrPositive;
+    }
+
+    if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), power_of)
+        && clip(cx.tcx, n, UintTy::U32) % 2 == 0
+    {
+        return Sign::ZeroOrPositive;
+    }
+
+    Sign::Uncertain
+}
+
+/// Peels binary operators such as [`BinOpKind::Mul`], [`BinOpKind::Div`] or [`BinOpKind::Rem`],
+/// which the result could always be positive under certain condition.
+///
+/// Other operators such as `+`/`-` causing the result's sign hard to determine, which we will
+/// return `None`
+fn exprs_with_selected_binop_peeled<'a>(expr: &'a Expr<'_>) -> Option<Vec<&'a Expr<'a>>> {
+    #[inline]
+    fn collect_operands<'a>(expr: &'a Expr<'a>, operands: &mut Vec<&'a Expr<'a>>) -> Option<()> {
+        match expr.kind {
+            ExprKind::Binary(op, lhs, rhs) => {
+                if matches!(op.node, BinOpKind::Mul | BinOpKind::Div | BinOpKind::Rem) {
+                    collect_operands(lhs, operands);
+                    operands.push(rhs);
+                } else {
+                    // Things are complicated when there are other binary ops exist,
+                    // abort checking by returning `None` for now.
+                    return None;
+                }
+            },
+            _ => operands.push(expr),
+        }
+        Some(())
+    }
+
+    let mut res = vec![];
+    collect_operands(expr, &mut res)?;
+    Some(res)
+}
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index eae9dfac064..20230106d53 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -150,7 +150,8 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO,
     crate::empty_drop::EMPTY_DROP_INFO,
     crate::empty_enum::EMPTY_ENUM_INFO,
-    crate::empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO,
+    crate::empty_with_brackets::EMPTY_ENUM_VARIANTS_WITH_BRACKETS_INFO,
+    crate::empty_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO,
     crate::endian_bytes::BIG_ENDIAN_BYTES_INFO,
     crate::endian_bytes::HOST_ENDIAN_BYTES_INFO,
     crate::endian_bytes::LITTLE_ENDIAN_BYTES_INFO,
@@ -385,6 +386,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::JOIN_ABSOLUTE_PATHS_INFO,
     crate::methods::MANUAL_FILTER_MAP_INFO,
     crate::methods::MANUAL_FIND_MAP_INFO,
+    crate::methods::MANUAL_IS_VARIANT_AND_INFO,
     crate::methods::MANUAL_NEXT_BACK_INFO,
     crate::methods::MANUAL_OK_OR_INFO,
     crate::methods::MANUAL_SATURATING_ARITHMETIC_INFO,
@@ -408,6 +410,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::NO_EFFECT_REPLACE_INFO,
     crate::methods::OBFUSCATED_IF_ELSE_INFO,
     crate::methods::OK_EXPECT_INFO,
+    crate::methods::OPTION_AS_REF_CLONED_INFO,
     crate::methods::OPTION_AS_REF_DEREF_INFO,
     crate::methods::OPTION_FILTER_MAP_INFO,
     crate::methods::OPTION_MAP_OR_ERR_OK_INFO,
@@ -433,6 +436,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::STABLE_SORT_PRIMITIVE_INFO,
     crate::methods::STRING_EXTEND_CHARS_INFO,
     crate::methods::STRING_LIT_CHARS_ANY_INFO,
+    crate::methods::STR_SPLIT_AT_NEWLINE_INFO,
     crate::methods::SUSPICIOUS_COMMAND_ARG_SPACE_INFO,
     crate::methods::SUSPICIOUS_MAP_INFO,
     crate::methods::SUSPICIOUS_SPLITN_INFO,
@@ -576,6 +580,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::ptr::MUT_FROM_REF_INFO,
     crate::ptr::PTR_ARG_INFO,
     crate::ptr_offset_with_cast::PTR_OFFSET_WITH_CAST_INFO,
+    crate::pub_underscore_fields::PUB_UNDERSCORE_FIELDS_INFO,
     crate::pub_use::PUB_USE_INFO,
     crate::question_mark::QUESTION_MARK_INFO,
     crate::question_mark_used::QUESTION_MARK_USED_INFO,
@@ -648,6 +653,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     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::thread_local_initializer_can_be_made_const::THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST_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,
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 64a924a776a..712bc075650 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -4,7 +4,7 @@ use clippy_utils::{get_parent_node, numeric_literal};
 use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_expr, walk_stmt, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, HirId, ItemKind, Lit, Node, Stmt, StmtKind};
+use rustc_hir::{Block, Body, Expr, ExprKind, FnRetTy, HirId, ItemKind, Lit, Node, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
@@ -122,13 +122,42 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
 impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
         match &expr.kind {
+            ExprKind::Block(
+                Block {
+                    stmts, expr: Some(_), ..
+                },
+                _,
+            ) => {
+                if let Some(parent) = self.cx.tcx.hir().find_parent(expr.hir_id)
+                    && let Some(fn_sig) = parent.fn_sig()
+                    && let FnRetTy::Return(_ty) = fn_sig.decl.output
+                {
+                    // We cannot check the exact type since it's a `hir::Ty`` which does not implement `is_numeric`
+                    self.ty_bounds.push(ExplicitTyBound(true));
+                    for stmt in *stmts {
+                        self.visit_stmt(stmt);
+                    }
+                    self.ty_bounds.pop();
+                    // Ignore return expr since we know its type was inferred from return ty
+                    return;
+                }
+            },
+
+            // Ignore return expr since we know its type was inferred from return ty
+            ExprKind::Ret(_) => return,
+
             ExprKind::Call(func, args) => {
                 if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) {
                     for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) {
-                        // Push found arg type, then visit arg.
-                        self.ty_bounds.push((*bound).into());
-                        self.visit_expr(expr);
-                        self.ty_bounds.pop();
+                        // If is from macro, try to use last bound type (typically pushed when visiting stmt),
+                        // otherwise push found arg type, then visit arg,
+                        if expr.span.from_expansion() {
+                            self.visit_expr(expr);
+                        } else {
+                            self.ty_bounds.push((*bound).into());
+                            self.visit_expr(expr);
+                            self.ty_bounds.pop();
+                        }
                     }
                     return;
                 }
@@ -137,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
             ExprKind::MethodCall(_, receiver, args, _) => {
                 if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
                     let fn_sig = self.cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
-                    for (expr, bound) in iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) {
+                    for (expr, bound) in iter::zip(iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) {
                         self.ty_bounds.push((*bound).into());
                         self.visit_expr(expr);
                         self.ty_bounds.pop();
diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
index a744b69ecb4..8b018220c17 100644
--- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
+++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs
@@ -53,7 +53,7 @@ pub fn check(
                 let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) {
                     Ok(p) => p,
                     Err(errs) => {
-                        drop(errs);
+                        errs.into_iter().for_each(|err| err.cancel());
                         return (false, test_attr_spans);
                     },
                 };
diff --git a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
index 3cf67b3ecbf..969df6d85b5 100644
--- a/src/tools/clippy/clippy_lints/src/empty_structs_with_brackets.rs
+++ b/src/tools/clippy/clippy_lints/src/empty_with_brackets.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_opt;
-use rustc_ast::ast::{Item, ItemKind, VariantData};
+use rustc_ast::ast::{Item, ItemKind, Variant, VariantData};
 use rustc_errors::Applicability;
 use rustc_lexer::TokenKind;
 use rustc_lint::{EarlyContext, EarlyLintPass};
@@ -27,9 +27,38 @@ declare_clippy_lint! {
     restriction,
     "finds struct declarations with empty brackets"
 }
-declare_lint_pass!(EmptyStructsWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS]);
 
-impl EarlyLintPass for EmptyStructsWithBrackets {
+declare_clippy_lint! {
+    /// ### What it does
+    /// Finds enum variants without fields that are declared with empty brackets.
+    ///
+    /// ### Why is this bad?
+    /// Empty brackets while defining enum variants are redundant and can be omitted.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// enum MyEnum {
+    ///     HasData(u8),
+    ///     HasNoData(), // redundant parentheses
+    /// }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// enum MyEnum {
+    ///     HasData(u8),
+    ///     HasNoData,
+    /// }
+    /// ```
+    #[clippy::version = "1.77.0"]
+    pub EMPTY_ENUM_VARIANTS_WITH_BRACKETS,
+    restriction,
+    "finds enum variants with empty brackets"
+}
+
+declare_lint_pass!(EmptyWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS, EMPTY_ENUM_VARIANTS_WITH_BRACKETS]);
+
+impl EarlyLintPass for EmptyWithBrackets {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
         let span_after_ident = item.span.with_lo(item.ident.span.hi());
 
@@ -53,6 +82,27 @@ impl EarlyLintPass for EmptyStructsWithBrackets {
             );
         }
     }
+
+    fn check_variant(&mut self, cx: &EarlyContext<'_>, variant: &Variant) {
+        let span_after_ident = variant.span.with_lo(variant.ident.span.hi());
+
+        if has_brackets(&variant.data) && has_no_fields(cx, &variant.data, span_after_ident) {
+            span_lint_and_then(
+                cx,
+                EMPTY_ENUM_VARIANTS_WITH_BRACKETS,
+                span_after_ident,
+                "enum variant has empty brackets",
+                |diagnostic| {
+                    diagnostic.span_suggestion_hidden(
+                        span_after_ident,
+                        "remove the brackets",
+                        "",
+                        Applicability::MaybeIncorrect,
+                    );
+                },
+            );
+        }
+    }
 }
 
 fn has_no_ident_token(braces_span_str: &str) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
index cd6c46a71a8..8f48941c4a9 100644
--- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
+++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::eager_or_lazy::switch_to_eager_eval;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::sugg::Sugg;
-use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks};
+use clippy_utils::{contains_return, higher, in_constant, is_else_clause, is_res_lang_ctor, path_res, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_hir::{Expr, ExprKind};
@@ -74,6 +74,11 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
             return;
         }
 
+        // `bool::then()` and `bool::then_some()` are not const
+        if in_constant(cx, expr.hir_id) {
+            return;
+        }
+
         let ctxt = expr.span.ctxt();
 
         if let Some(higher::If {
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
index 655f4b82aa4..17b6256f982 100644
--- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -40,7 +40,7 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Lints subtraction between an [`Instant`] and a [`Duration`].
+    /// Lints subtraction between an `Instant` and a `Duration`.
     ///
     /// ### Why is this bad?
     /// Unchecked subtraction could cause underflow on certain platforms, leading to
@@ -57,9 +57,6 @@ declare_clippy_lint! {
     /// # use std::time::{Instant, Duration};
     /// let time_passed = Instant::now().checked_sub(Duration::from_secs(5));
     /// ```
-    ///
-    /// [`Duration`]: std::time::Duration
-    /// [`Instant::now()`]: std::time::Instant::now;
     #[clippy::version = "1.67.0"]
     pub UNCHECKED_DURATION_SUBTRACTION,
     pedantic,
diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
index a9f1612ff05..276c1abb60c 100644
--- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
+++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs
@@ -1,6 +1,7 @@
 //! lint on enum variants that are prefixed or suffixed by the same characters
 
 use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir};
+use clippy_utils::is_bool;
 use clippy_utils::macros::span_is_local;
 use clippy_utils::source::is_present_in_source;
 use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case};
@@ -231,6 +232,10 @@ fn check_fields(cx: &LateContext<'_>, threshold: u64, item: &Item<'_>, fields: &
             (false, _) => ("pre", prefix),
             (true, false) => ("post", postfix),
         };
+        if fields.iter().all(|field| is_bool(field.ty)) {
+            // If all fields are booleans, we don't want to emit this lint.
+            return;
+        }
         span_lint_and_help(
             cx,
             STRUCT_FIELD_NAMES,
diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
index c9dc48668f2..903d3a2ab89 100644
--- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs
@@ -5,7 +5,8 @@ use clippy_utils::ty::{implements_trait, make_normalized_projection};
 use rustc_ast::Mutability;
 use rustc_errors::Applicability;
 use rustc_hir::{FnRetTy, ImplItemKind, ImplicitSelfKind, ItemKind, TyKind};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty};
 use rustc_session::declare_lint_pass;
 use rustc_span::{sym, Symbol};
@@ -152,7 +153,8 @@ fn adt_has_inherent_method(cx: &LateContext<'_>, ty: Ty<'_>, method_name: Symbol
 
 impl LateLintPass<'_> for IterWithoutIntoIter {
     fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
-        if let ItemKind::Impl(imp) = item.kind
+        if !in_external_macro(cx.sess(), item.span)
+            && let ItemKind::Impl(imp) = item.kind
             && let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind
             && let Some(trait_ref) = imp.of_trait
             && trait_ref
@@ -219,7 +221,8 @@ impl {self_ty_without_ref} {{
             _ => return,
         };
 
-        if let ImplItemKind::Fn(sig, _) = item.kind
+        if !in_external_macro(cx.sess(), item.span)
+            && let ImplItemKind::Fn(sig, _) = item.kind
             && let FnRetTy::Return(ret) = sig.decl.output
             && is_nameable_in_impl_trait(ret)
             && cx.tcx.generics_of(item_did).params.is_empty()
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 755a4ff525d..efdd3925949 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -115,7 +115,7 @@ mod duplicate_mod;
 mod else_if_without_else;
 mod empty_drop;
 mod empty_enum;
-mod empty_structs_with_brackets;
+mod empty_with_brackets;
 mod endian_bytes;
 mod entry;
 mod enum_clike;
@@ -272,6 +272,7 @@ mod permissions_set_readonly_false;
 mod precedence;
 mod ptr;
 mod ptr_offset_with_cast;
+mod pub_underscore_fields;
 mod pub_use;
 mod question_mark;
 mod question_mark_used;
@@ -322,6 +323,7 @@ mod swap_ptr_to_ref;
 mod tabs_in_doc_comments;
 mod temporary_assignment;
 mod tests_outside_test_module;
+mod thread_local_initializer_can_be_made_const;
 mod to_digit_is_some;
 mod trailing_empty_array;
 mod trait_bounds;
@@ -571,6 +573,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         verbose_bit_mask_threshold,
         warn_on_all_wildcard_imports,
         check_private_items,
+        pub_underscore_fields_behavior,
 
         blacklisted_names: _,
         cyclomatic_complexity_threshold: _,
@@ -947,7 +950,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         })
     });
     store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
-    store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets));
+    store.register_early_pass(|| Box::new(empty_with_brackets::EmptyWithBrackets));
     store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
     store.register_early_pass(|| Box::new(pub_use::PubUse));
     store.register_late_pass(|_| Box::new(format_push_string::FormatPushString));
@@ -1080,7 +1083,15 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(repeat_vec_with_capacity::RepeatVecWithCapacity));
     store.register_late_pass(|_| Box::new(uninhabited_references::UninhabitedReferences));
     store.register_late_pass(|_| Box::new(ineffective_open_options::IneffectiveOpenOptions));
-    store.register_late_pass(|_| Box::new(unconditional_recursion::UnconditionalRecursion));
+    store.register_late_pass(|_| Box::<unconditional_recursion::UnconditionalRecursion>::default());
+    store.register_late_pass(move |_| {
+        Box::new(pub_underscore_fields::PubUnderscoreFields {
+            behavior: pub_underscore_fields_behavior,
+        })
+    });
+    store.register_late_pass(move |_| {
+        Box::new(thread_local_initializer_can_be_made_const::ThreadLocalInitializerCanBeMadeConst::new(msrv()))
+    });
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
index 8a0955147bb..29957e423b0 100644
--- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
@@ -96,8 +96,7 @@ fn should_lint(cx: &LateContext<'_>, args: &[Expr<'_>], method_str: &str) -> boo
                 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(),
+                    .is_some_and(|did| match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)),
                 // Detect `|x| x.ok()`
                 ExprKind::Closure(Closure { body, .. }) => {
                     if let Body {
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
index 7cfd3d346b6..e489899c19e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map.rs
@@ -26,13 +26,14 @@ fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) ->
         hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
             let body = cx.tcx.hir().body(body);
             let closure_expr = peel_blocks(body.value);
-            let arg_id = body.params[0].pat.hir_id;
             match closure_expr.kind {
                 hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
                     if ident.name == method_name
                         && let hir::ExprKind::Path(path) = &receiver.kind
                         && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id)
+                        && !body.params.is_empty()
                     {
+                        let arg_id = body.params[0].pat.hir_id;
                         return arg_id == *local;
                     }
                     false
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
index ade8e3155fa..9f84321ced4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_filter.rs
@@ -1,87 +1,197 @@
+use clippy_utils::ty::get_iterator_item_ty;
+use hir::ExprKind;
 use rustc_lint::{LateContext, LintContext};
 
 use super::{ITER_FILTER_IS_OK, ITER_FILTER_IS_SOME};
 
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{indent_of, reindent_multiline};
-use clippy_utils::{is_trait_method, peel_blocks, span_contains_comment};
+use clippy_utils::{get_parent_expr, is_trait_method, peel_blocks, span_contains_comment};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::def::Res;
 use rustc_hir::QPath;
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
 use std::borrow::Cow;
 
-fn is_method(cx: &LateContext<'_>, expr: &hir::Expr<'_>, method_name: Symbol) -> bool {
-    match &expr.kind {
-        hir::ExprKind::Path(QPath::TypeRelative(_, mname)) => mname.ident.name == method_name,
-        hir::ExprKind::Path(QPath::Resolved(_, segments)) => {
-            segments.segments.last().unwrap().ident.name == method_name
+///
+/// Returns true if the expression is a method call to `method_name`
+/// e.g. `a.method_name()` or `Option::method_name`.
+///
+/// The type-checker verifies for us that the method accepts the right kind of items
+/// (e.g. `Option::is_some` accepts `Option<_>`), so we don't need to check that.
+///
+/// How to capture each case:
+///
+/// `.filter(|a| { std::option::Option::is_some(a) })`
+///          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- this is a closure, getting unwrapped and
+/// recursively checked.
+/// `std::option::Option::is_some(a)`
+///  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- this is a call. It unwraps to a path with
+/// `QPath::TypeRelative`. Since this is a type relative path, we need to check the method name, the
+/// type, and that the parameter of the closure is passed in the call. This part is the dual of
+/// `receiver.method_name()` below.
+///
+/// `filter(std::option::Option::is_some);`
+///          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- this is a type relative path, like above, we check the
+/// type and the method name.
+///
+/// `filter(|a| a.is_some());`
+///         ^^^^^^^^^^^^^^^ <- this is a method call inside a closure,
+/// we check that the parameter of the closure is the receiver of the method call and don't allow
+/// any other parameters.
+fn is_method(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    type_symbol: Symbol,
+    method_name: Symbol,
+    params: &[&hir::Pat<'_>],
+) -> bool {
+    fn pat_is_recv(ident: Ident, param: &hir::Pat<'_>) -> bool {
+        match param.kind {
+            hir::PatKind::Binding(_, _, other, _) => ident == other,
+            hir::PatKind::Ref(pat, _) => pat_is_recv(ident, pat),
+            _ => false,
+        }
+    }
+    match expr.kind {
+        hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, recv, ..) => {
+            // compare the identifier of the receiver to the parameter
+            // we are in a filter => closure has a single parameter and a single, non-block
+            // expression, this means that the parameter shadows all outside variables with
+            // the same name => avoid FPs. If the parameter is not the receiver, then this hits
+            // outside variables => avoid FP
+            if ident.name == method_name
+                && let ExprKind::Path(QPath::Resolved(None, path)) = recv.kind
+                && let &[seg] = path.segments
+                && params.iter().any(|p| pat_is_recv(seg.ident, p))
+            {
+                return true;
+            }
+            false
+        },
+        // This is used to check for complete paths via `|a| std::option::Option::is_some(a)`
+        // this then unwraps to a path with `QPath::TypeRelative`
+        // we pass the params as they've been passed to the current call through the closure
+        hir::ExprKind::Call(expr, [param]) => {
+            // this will hit the `QPath::TypeRelative` case and check that the method name is correct
+            if is_method(cx, expr, type_symbol, method_name, params)
+                // we then check that this is indeed passing the parameter of the closure
+                && let ExprKind::Path(QPath::Resolved(None, path)) = param.kind
+                && let &[seg] = path.segments
+                && params.iter().any(|p| pat_is_recv(seg.ident, p))
+            {
+                return true;
+            }
+            false
+        },
+        hir::ExprKind::Path(QPath::TypeRelative(ty, mname)) => {
+            let ty = cx.typeck_results().node_type(ty.hir_id);
+            if let Some(did) = cx.tcx.get_diagnostic_item(type_symbol)
+                && ty.ty_adt_def() == cx.tcx.type_of(did).skip_binder().ty_adt_def()
+            {
+                return mname.ident.name == method_name;
+            }
+            false
         },
-        hir::ExprKind::MethodCall(segment, _, _, _) => segment.ident.name == method_name,
         hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
             let body = cx.tcx.hir().body(body);
             let closure_expr = peel_blocks(body.value);
-            let arg_id = body.params[0].pat.hir_id;
-            match closure_expr.kind {
-                hir::ExprKind::MethodCall(hir::PathSegment { ident, .. }, receiver, ..) => {
-                    if ident.name == method_name
-                        && let hir::ExprKind::Path(path) = &receiver.kind
-                        && let Res::Local(ref local) = cx.qpath_res(path, receiver.hir_id)
-                    {
-                        return arg_id == *local;
-                    }
-                    false
-                },
-                _ => false,
-            }
+            let params = body.params.iter().map(|param| param.pat).collect::<Vec<_>>();
+            is_method(cx, closure_expr, type_symbol, method_name, params.as_slice())
         },
         _ => false,
     }
 }
 
 fn parent_is_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
-    if let hir::Node::Expr(parent_expr) = cx.tcx.hir().get_parent(expr.hir_id) {
-        is_method(cx, parent_expr, rustc_span::sym::map)
-    } else {
-        false
+    if let Some(expr) = get_parent_expr(cx, expr)
+        && is_trait_method(cx, expr, sym::Iterator)
+        && let hir::ExprKind::MethodCall(path, _, _, _) = expr.kind
+        && path.ident.name == rustc_span::sym::map
+    {
+        return true;
     }
+    false
 }
 
-#[allow(clippy::too_many_arguments)]
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_arg: &hir::Expr<'_>, filter_span: Span) {
-    let is_iterator = is_trait_method(cx, expr, sym::Iterator);
-    let parent_is_not_map = !parent_is_map(cx, expr);
+enum FilterType {
+    IsSome,
+    IsOk,
+}
 
-    if is_iterator
-        && parent_is_not_map
-        && is_method(cx, filter_arg, sym!(is_some))
-        && !span_contains_comment(cx.sess().source_map(), filter_span.with_hi(expr.span.hi()))
+/// Returns the `FilterType` of the expression if it is a filter over an Iter<Option> or
+/// Iter<Result> with the parent expression not being a map, and not having a comment in the span of
+/// the filter. If it is not a filter over an Iter<Option> or Iter<Result> then it returns None
+///
+/// How this is done:
+/// 1. we know that this is invoked in a method call with `filter` as the method name via `mod.rs`
+/// 2. we check that we are in a trait method. Therefore we are in an
+/// `(x as Iterator).filter({filter_arg})` method call.
+/// 3. we check that the parent expression is not a map. This is because we don't want to lint
+///    twice, and we already have a specialized lint for that.
+/// 4. we check that the span of the filter does not contain a comment.
+/// 5. we get the type of the `Item` in the `Iterator`, and compare against the type of Option and
+///   Result.
+/// 6. we finally check the contents of the filter argument to see if it is a call to `is_some` or
+///   `is_ok`.
+/// 7. if all of the above are true, then we return the `FilterType`
+fn expression_type(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    filter_arg: &hir::Expr<'_>,
+    filter_span: Span,
+) -> Option<FilterType> {
+    if !is_trait_method(cx, expr, sym::Iterator)
+        || parent_is_map(cx, expr)
+        || span_contains_comment(cx.sess().source_map(), filter_span.with_hi(expr.span.hi()))
     {
-        span_lint_and_sugg(
+        return None;
+    }
+    if let hir::ExprKind::MethodCall(_, receiver, _, _) = expr.kind
+        && let receiver_ty = cx.typeck_results().expr_ty(receiver)
+        && let Some(iter_item_ty) = get_iterator_item_ty(cx, receiver_ty)
+    {
+        if let Some(opt_defid) = cx.tcx.get_diagnostic_item(sym::Option)
+            && let opt_ty = cx.tcx.type_of(opt_defid).skip_binder()
+            && iter_item_ty.ty_adt_def() == opt_ty.ty_adt_def()
+            && is_method(cx, filter_arg, sym::Option, sym!(is_some), &[])
+        {
+            return Some(FilterType::IsSome);
+        }
+
+        if let Some(opt_defid) = cx.tcx.get_diagnostic_item(sym::Result)
+            && let opt_ty = cx.tcx.type_of(opt_defid).skip_binder()
+            && iter_item_ty.ty_adt_def() == opt_ty.ty_adt_def()
+            && is_method(cx, filter_arg, sym::Result, sym!(is_ok), &[])
+        {
+            return Some(FilterType::IsOk);
+        }
+    }
+    None
+}
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, filter_arg: &hir::Expr<'_>, filter_span: Span) {
+    // we are in a filter inside an iterator
+    match expression_type(cx, expr, filter_arg, filter_span) {
+        None => (),
+        Some(FilterType::IsOk) => span_lint_and_sugg(
             cx,
-            ITER_FILTER_IS_SOME,
+            ITER_FILTER_IS_OK,
             filter_span.with_hi(expr.span.hi()),
-            "`filter` for `is_some` on iterator over `Option`",
+            "`filter` for `is_ok` on iterator over `Result`s",
             "consider using `flatten` instead",
             reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, filter_span)).into_owned(),
             Applicability::HasPlaceholders,
-        );
-    }
-    if is_iterator
-        && parent_is_not_map
-        && is_method(cx, filter_arg, sym!(is_ok))
-        && !span_contains_comment(cx.sess().source_map(), filter_span.with_hi(expr.span.hi()))
-    {
-        span_lint_and_sugg(
+        ),
+        Some(FilterType::IsSome) => span_lint_and_sugg(
             cx,
-            ITER_FILTER_IS_OK,
+            ITER_FILTER_IS_SOME,
             filter_span.with_hi(expr.span.hi()),
-            "`filter` for `is_ok` on iterator over `Result`s",
+            "`filter` for `is_some` on iterator over `Option`",
             "consider using `flatten` instead",
             reindent_multiline(Cow::Borrowed("flatten()"), true, indent_of(cx, filter_span)).into_owned(),
             Applicability::HasPlaceholders,
-        );
+        ),
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
new file mode 100644
index 00000000000..d29acd4622a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_is_variant_and.rs
@@ -0,0 +1,59 @@
+use clippy_config::msrvs::{Msrv, OPTION_RESULT_IS_VARIANT_AND};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
+use rustc_errors::Applicability;
+use rustc_lint::LateContext;
+use rustc_span::{sym, Span};
+
+use super::MANUAL_IS_VARIANT_AND;
+
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'_>,
+    expr: &'tcx rustc_hir::Expr<'_>,
+    map_recv: &'tcx rustc_hir::Expr<'_>,
+    map_arg: &'tcx rustc_hir::Expr<'_>,
+    map_span: Span,
+    msrv: &Msrv,
+) {
+    // Don't lint if:
+
+    // 1. the `expr` is generated by a macro
+    if expr.span.from_expansion() {
+        return;
+    }
+
+    // 2. the caller of `map()` is neither `Option` nor `Result`
+    let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(map_recv), sym::Option);
+    let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(map_recv), sym::Result);
+    if !is_option && !is_result {
+        return;
+    }
+
+    // 3. the caller of `unwrap_or_default` is neither `Option<bool>` nor `Result<bool, _>`
+    if !cx.typeck_results().expr_ty(expr).is_bool() {
+        return;
+    }
+
+    // 4. msrv doesn't meet `OPTION_RESULT_IS_VARIANT_AND`
+    if !msrv.meets(OPTION_RESULT_IS_VARIANT_AND) {
+        return;
+    }
+
+    let lint_msg = if is_option {
+        "called `map(<f>).unwrap_or_default()` on an `Option` value"
+    } else {
+        "called `map(<f>).unwrap_or_default()` on a `Result` value"
+    };
+    let suggestion = if is_option { "is_some_and" } else { "is_ok_and" };
+
+    span_lint_and_sugg(
+        cx,
+        MANUAL_IS_VARIANT_AND,
+        expr.span.with_lo(map_span.lo()),
+        lint_msg,
+        "use",
+        format!("{}({})", suggestion, snippet(cx, map_arg.span, "..")),
+        Applicability::MachineApplicable,
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
index cc6eeaa86e5..f9f636bbbf7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -2,9 +2,10 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
-use clippy_utils::{is_diag_trait_item, peel_blocks};
+use clippy_utils::{is_diag_trait_item, match_def_path, paths, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_lint::LateContext;
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty;
@@ -14,60 +15,110 @@ use rustc_span::{sym, Span};
 
 use super::MAP_CLONE;
 
+// If this `map` is called on an `Option` or a `Result` and the previous call is `as_ref`, we don't
+// run this lint because it would overlap with `useless_asref` which provides a better suggestion
+// in this case.
+fn should_run_lint(cx: &LateContext<'_>, e: &hir::Expr<'_>, method_id: DefId) -> bool {
+    if is_diag_trait_item(cx, method_id, sym::Iterator) {
+        return true;
+    }
+    // We check if it's an `Option` or a `Result`.
+    if let Some(id) = cx.tcx.impl_of_method(method_id) {
+        let identity = cx.tcx.type_of(id).instantiate_identity();
+        if !is_type_diagnostic_item(cx, identity, sym::Option) && !is_type_diagnostic_item(cx, identity, sym::Result) {
+            return false;
+        }
+    } else {
+        return false;
+    }
+    // We check if the previous method call is `as_ref`.
+    if let hir::ExprKind::MethodCall(path1, receiver, _, _) = &e.kind
+        && let hir::ExprKind::MethodCall(path2, _, _, _) = &receiver.kind
+    {
+        return path2.ident.name != sym::as_ref || path1.ident.name != sym::map;
+    }
+
+    true
+}
+
 pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, msrv: &Msrv) {
     if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
-        && (cx.tcx.impl_of_method(method_id).map_or(false, |id| {
-            is_type_diagnostic_item(cx, cx.tcx.type_of(id).instantiate_identity(), sym::Option)
-        }) || is_diag_trait_item(cx, method_id, sym::Iterator))
-        && let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind
+        && should_run_lint(cx, e, method_id)
     {
-        let closure_body = cx.tcx.hir().body(body);
-        let closure_expr = peel_blocks(closure_body.value);
-        match closure_body.params[0].pat.kind {
-            hir::PatKind::Ref(inner, hir::Mutability::Not) => {
-                if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) = inner.kind {
-                    if ident_eq(name, closure_expr) {
-                        lint_explicit_closure(cx, e.span, recv.span, true, msrv);
-                    }
-                }
-            },
-            hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) => {
-                match closure_expr.kind {
-                    hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
-                        if ident_eq(name, inner) {
-                            if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() {
+        match arg.kind {
+            hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
+                let closure_body = cx.tcx.hir().body(body);
+                let closure_expr = peel_blocks(closure_body.value);
+                match closure_body.params[0].pat.kind {
+                    hir::PatKind::Ref(inner, hir::Mutability::Not) => {
+                        if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) = inner.kind {
+                            if ident_eq(name, closure_expr) {
                                 lint_explicit_closure(cx, e.span, recv.span, true, msrv);
                             }
                         }
                     },
-                    hir::ExprKind::MethodCall(method, obj, [], _) => {
-                        if ident_eq(name, obj) && method.ident.name == sym::clone
-                        && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id)
-                        && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
-                        && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id)
-                        // no autoderefs
-                        && !cx.typeck_results().expr_adjustments(obj).iter()
-                            .any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
-                        {
-                            let obj_ty = cx.typeck_results().expr_ty(obj);
-                            if let ty::Ref(_, ty, mutability) = obj_ty.kind() {
-                                if matches!(mutability, Mutability::Not) {
-                                    let copy = is_copy(cx, *ty);
-                                    lint_explicit_closure(cx, e.span, recv.span, copy, msrv);
+                    hir::PatKind::Binding(hir::BindingAnnotation::NONE, .., name, None) => {
+                        match closure_expr.kind {
+                            hir::ExprKind::Unary(hir::UnOp::Deref, inner) => {
+                                if ident_eq(name, inner) {
+                                    if let ty::Ref(.., Mutability::Not) = cx.typeck_results().expr_ty(inner).kind() {
+                                        lint_explicit_closure(cx, e.span, recv.span, true, msrv);
+                                    }
                                 }
-                            } else {
-                                lint_needless_cloning(cx, e.span, recv.span);
-                            }
+                            },
+                            hir::ExprKind::MethodCall(method, obj, [], _) => {
+                                if ident_eq(name, obj) && method.ident.name == sym::clone
+                                && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id)
+                                && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
+                                && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id)
+                                // no autoderefs
+                                && !cx.typeck_results().expr_adjustments(obj).iter()
+                                    .any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
+                                {
+                                    let obj_ty = cx.typeck_results().expr_ty(obj);
+                                    if let ty::Ref(_, ty, mutability) = obj_ty.kind() {
+                                        if matches!(mutability, Mutability::Not) {
+                                            let copy = is_copy(cx, *ty);
+                                            lint_explicit_closure(cx, e.span, recv.span, copy, msrv);
+                                        }
+                                    } else {
+                                        lint_needless_cloning(cx, e.span, recv.span);
+                                    }
+                                }
+                            },
+                            hir::ExprKind::Call(call, [_]) => {
+                                if let hir::ExprKind::Path(qpath) = call.kind {
+                                    handle_path(cx, call, &qpath, e, recv);
+                                }
+                            },
+                            _ => {},
                         }
                     },
                     _ => {},
                 }
             },
+            hir::ExprKind::Path(qpath) => handle_path(cx, arg, &qpath, e, recv),
             _ => {},
         }
     }
 }
 
+fn handle_path(
+    cx: &LateContext<'_>,
+    arg: &hir::Expr<'_>,
+    qpath: &hir::QPath<'_>,
+    e: &hir::Expr<'_>,
+    recv: &hir::Expr<'_>,
+) {
+    if let Some(path_def_id) = cx.qpath_res(qpath, arg.hir_id).opt_def_id()
+        && match_def_path(cx, path_def_id, &paths::CLONE_TRAIT_METHOD)
+    {
+        // FIXME: It would be better to infer the type to check if it's copyable or not
+        // to suggest to use `.copied()` instead of `.cloned()` where applicable.
+        lint_path(cx, e.span, recv.span);
+    }
+}
+
 fn ident_eq(name: Ident, path: &hir::Expr<'_>) -> bool {
     if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = path.kind {
         path.segments.len() == 1 && path.segments[0].ident == name
@@ -88,6 +139,23 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) {
     );
 }
 
+fn lint_path(cx: &LateContext<'_>, replace: Span, root: Span) {
+    let mut applicability = Applicability::MachineApplicable;
+
+    span_lint_and_sugg(
+        cx,
+        MAP_CLONE,
+        replace,
+        "you are explicitly cloning with `.map()`",
+        "consider calling the dedicated `cloned` method",
+        format!(
+            "{}.cloned()",
+            snippet_with_applicability(cx, root, "..", &mut applicability),
+        ),
+        applicability,
+    );
+}
+
 fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool, msrv: &Msrv) {
     let mut applicability = Applicability::MachineApplicable;
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index c1e126137df..89ea3597dc0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -51,6 +51,7 @@ mod iter_skip_zero;
 mod iter_with_drain;
 mod iterator_step_by_zero;
 mod join_absolute_paths;
+mod manual_is_variant_and;
 mod manual_next_back;
 mod manual_ok_or;
 mod manual_saturating_arithmetic;
@@ -70,6 +71,7 @@ mod no_effect_replace;
 mod obfuscated_if_else;
 mod ok_expect;
 mod open_options;
+mod option_as_ref_cloned;
 mod option_as_ref_deref;
 mod option_map_or_err_ok;
 mod option_map_or_none;
@@ -93,6 +95,7 @@ mod single_char_pattern;
 mod single_char_push_string;
 mod skip_while_next;
 mod stable_sort_primitive;
+mod str_split;
 mod str_splitn;
 mod string_extend_chars;
 mod string_lit_chars_any;
@@ -2589,11 +2592,11 @@ declare_clippy_lint! {
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for usage of `x.get(0)` instead of
-    /// `x.first()`.
+    /// `x.first()` or `x.front()`.
     ///
     /// ### Why is this bad?
-    /// Using `x.first()` is easier to read and has the same
-    /// result.
+    /// Using `x.first()` for `Vec`s and slices or `x.front()`
+    /// for `VecDeque`s is easier to read and has the same result.
     ///
     /// ### Example
     /// ```no_run
@@ -2609,7 +2612,7 @@ declare_clippy_lint! {
     #[clippy::version = "1.63.0"]
     pub GET_FIRST,
     style,
-    "Using `x.get(0)` when `x.first()` is simpler"
+    "Using `x.get(0)` when `x.first()` or `x.front()` is simpler"
 }
 
 declare_clippy_lint! {
@@ -3784,7 +3787,7 @@ declare_clippy_lint! {
     ///
     /// ### Why is this bad?
     /// This pattern is often followed by manual unwrapping of the `Option`. The simplification
-    /// results in more readable and succint code without the need for manual unwrapping.
+    /// results in more readable and succinct code without the need for manual unwrapping.
     ///
     /// ### Example
     /// ```no_run
@@ -3810,7 +3813,7 @@ declare_clippy_lint! {
     ///
     /// ### Why is this bad?
     /// This pattern is often followed by manual unwrapping of `Result`. The simplification
-    /// results in more readable and succint code without the need for manual unwrapping.
+    /// results in more readable and succinct code without the need for manual unwrapping.
     ///
     /// ### Example
     /// ```no_run
@@ -3829,6 +3832,87 @@ declare_clippy_lint! {
     "filtering an iterator over `Result`s for `Ok` can be achieved with `flatten`"
 }
 
+declare_clippy_lint! {
+    /// Checks for usage of `option.map(f).unwrap_or_default()` and `result.map(f).unwrap_or_default()` where f is a function or closure that returns the `bool` type.
+    ///
+    /// ### Why is this bad?
+    /// Readability. These can be written more concisely as `option.is_some_and(f)` and `result.is_ok_and(f)`.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// # let option = Some(1);
+    /// # let result: Result<usize, ()> = Ok(1);
+    /// option.map(|a| a > 10).unwrap_or_default();
+    /// result.map(|a| a > 10).unwrap_or_default();
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// # let option = Some(1);
+    /// # let result: Result<usize, ()> = Ok(1);
+    /// option.is_some_and(|a| a > 10);
+    /// result.is_ok_and(|a| a > 10);
+    /// ```
+    #[clippy::version = "1.76.0"]
+    pub MANUAL_IS_VARIANT_AND,
+    pedantic,
+    "using `.map(f).unwrap_or_default()`, which is more succinctly expressed as `is_some_and(f)` or `is_ok_and(f)`"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Checks for usages of `str.trim().split("\n")` and `str.trim().split("\r\n")`.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// Hard-coding the line endings makes the code less compatible. `str.lines` should be used instead.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// "some\ntext\nwith\nnewlines\n".trim().split('\n');
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// "some\ntext\nwith\nnewlines\n".lines();
+    /// ```
+    ///
+    /// ### Known Problems
+    ///
+    /// This lint cannot detect if the split is intentionally restricted to a single type of newline (`"\n"` or
+    /// `"\r\n"`), for example during the parsing of a specific file format in which precisely one newline type is
+    /// valid.
+    /// ```
+    #[clippy::version = "1.76.0"]
+    pub STR_SPLIT_AT_NEWLINE,
+    pedantic,
+    "splitting a trimmed string at hard-coded newlines"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for usage of `.as_ref().cloned()` and `.as_mut().cloned()` on `Option`s
+    ///
+    /// ### Why is this bad?
+    /// This can be written more concisely by cloning the `Option` directly.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// fn foo(bar: &Option<Vec<u8>>) -> Option<Vec<u8>> {
+    ///     bar.as_ref().cloned()
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// fn foo(bar: &Option<Vec<u8>>) -> Option<Vec<u8>> {
+    ///     bar.clone()
+    /// }
+    /// ```
+    #[clippy::version = "1.77.0"]
+    pub OPTION_AS_REF_CLONED,
+    pedantic,
+    "cloning an `Option` via `as_ref().cloned()`"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -3983,6 +4067,9 @@ impl_lint_pass!(Methods => [
     RESULT_FILTER_MAP,
     ITER_FILTER_IS_SOME,
     ITER_FILTER_IS_OK,
+    MANUAL_IS_VARIANT_AND,
+    STR_SPLIT_AT_NEWLINE,
+    OPTION_AS_REF_CLONED,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -4230,7 +4317,10 @@ impl Methods {
                 ("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv),
                 ("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv),
                 ("assume_init", []) => uninit_assumed_init::check(cx, expr, recv),
-                ("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, &self.msrv),
+                ("cloned", []) => {
+                    cloned_instead_of_copied::check(cx, expr, recv, span, &self.msrv);
+                    option_as_ref_cloned::check(cx, recv, span);
+                },
                 ("collect", []) if is_trait_method(cx, expr, sym::Iterator) => {
                     needless_collect::check(cx, span, expr, recv, call_span);
                     match method_call(recv) {
@@ -4569,6 +4659,9 @@ impl Methods {
                 ("sort_unstable_by", [arg]) => {
                     unnecessary_sort_by::check(cx, expr, recv, arg, true);
                 },
+                ("split", [arg]) => {
+                    str_split::check(cx, expr, recv, arg);
+                },
                 ("splitn" | "rsplitn", [count_arg, pat_arg]) => {
                     if let Some(Constant::Int(count)) = constant(cx, cx.typeck_results(), count_arg) {
                         suspicious_splitn::check(cx, name, expr, recv, count);
@@ -4664,7 +4757,13 @@ impl Methods {
                     }
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
                 },
-                ("unwrap_or_default" | "unwrap_unchecked" | "unwrap_err_unchecked", []) => {
+                ("unwrap_or_default", []) => {
+                    if let Some(("map", m_recv, [arg], span, _)) = method_call(recv) {
+                        manual_is_variant_and::check(cx, expr, m_recv, arg, span, &self.msrv);
+                    }
+                    unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
+                },
+                ("unwrap_unchecked" | "unwrap_err_unchecked", []) => {
                     unnecessary_literal_unwrap::check(cx, expr, recv, name, args);
                 },
                 ("unwrap_or_else", [u_arg]) => {
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_cloned.rs
new file mode 100644
index 00000000000..d7fec360fa2
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_cloned.rs
@@ -0,0 +1,24 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_span::{sym, Span};
+
+use super::{method_call, OPTION_AS_REF_CLONED};
+
+pub(super) fn check(cx: &LateContext<'_>, cloned_recv: &Expr<'_>, cloned_ident_span: Span) {
+    if let Some((method @ ("as_ref" | "as_mut"), as_ref_recv, [], as_ref_ident_span, _)) = method_call(cloned_recv)
+        && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(as_ref_recv).peel_refs(), sym::Option)
+    {
+        span_lint_and_sugg(
+            cx,
+            OPTION_AS_REF_CLONED,
+            as_ref_ident_span.to(cloned_ident_span),
+            &format!("cloning an `Option<_>` using `.{method}().cloned()`"),
+            "this can be written more concisely by cloning the `Option<_>` directly",
+            "clone".into(),
+            Applicability::MachineApplicable,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index 47c9438c588..624597ffca9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -72,7 +72,7 @@ pub(super) fn check<'tcx>(
         }
 
         // is_some_and is stabilised && `unwrap_or` argument is false; suggest `is_some_and` instead
-        let suggest_is_some_and = msrv.meets(msrvs::OPTION_IS_SOME_AND)
+        let suggest_is_some_and = msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND)
             && matches!(&unwrap_arg.kind, ExprKind::Lit(lit)
             if matches!(lit.node, rustc_ast::LitKind::Bool(false)));
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs
index 094ead9f4ad..29f44ec2a4d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/path_ends_with_ext.rs
@@ -33,7 +33,7 @@ pub(super) fn check(
         && path.chars().all(char::is_alphanumeric)
     {
         let mut sugg = snippet(cx, recv.span, "..").into_owned();
-        if msrv.meets(msrvs::OPTION_IS_SOME_AND) {
+        if msrv.meets(msrvs::OPTION_RESULT_IS_VARIANT_AND) {
             let _ = write!(sugg, r#".extension().is_some_and(|ext| ext == "{path}")"#);
         } else {
             let _ = write!(sugg, r#".extension().map_or(false, |ext| ext == "{path}")"#);
diff --git a/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs b/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs
index 2a2feedd2b4..24de1979c63 100644
--- a/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/redundant_as_str.rs
@@ -13,7 +13,11 @@ pub(super) fn check(
     as_str_span: Span,
     other_method_span: Span,
 ) {
-    if cx.typeck_results().expr_ty(recv).ty_adt_def().is_some_and(|adt| Some(adt.did()) == cx.tcx.lang_items().string())
+    if cx
+        .typeck_results()
+        .expr_ty(recv)
+        .ty_adt_def()
+        .is_some_and(|adt| Some(adt.did()) == cx.tcx.lang_items().string())
     {
         let mut applicability = Applicability::MachineApplicable;
         span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_split.rs b/src/tools/clippy/clippy_lints/src/methods/str_split.rs
new file mode 100644
index 00000000000..3586e11f56a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/str_split.rs
@@ -0,0 +1,38 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_context;
+use clippy_utils::visitors::is_const_evaluatable;
+use rustc_ast::ast::LitKind;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+
+use super::STR_SPLIT_AT_NEWLINE;
+
+pub(super) fn check<'a>(cx: &LateContext<'a>, expr: &'_ Expr<'_>, split_recv: &'a Expr<'_>, split_arg: &'_ Expr<'_>) {
+    // We're looking for `A.trim().split(B)`, where the adjusted type of `A` is `&str` (e.g. an
+    // expression returning `String`), and `B` is a `Pattern` that hard-codes a newline (either `"\n"`
+    // or `"\r\n"`). There are a lot of ways to specify a pattern, and this lint only checks the most
+    // basic ones: a `'\n'`, `"\n"`, and `"\r\n"`.
+    if let ExprKind::MethodCall(trim_method_name, trim_recv, [], _) = split_recv.kind
+        && trim_method_name.ident.as_str() == "trim"
+        && cx.typeck_results().expr_ty_adjusted(trim_recv).peel_refs().is_str()
+        && !is_const_evaluatable(cx, trim_recv)
+        && let ExprKind::Lit(split_lit) = split_arg.kind
+        && (matches!(split_lit.node, LitKind::Char('\n'))
+            || matches!(split_lit.node, LitKind::Str(sym, _) if (sym.as_str() == "\n" || sym.as_str() == "\r\n")))
+    {
+        let mut app = Applicability::MaybeIncorrect;
+        span_lint_and_sugg(
+            cx,
+            STR_SPLIT_AT_NEWLINE,
+            expr.span,
+            "using `str.trim().split()` with hard-coded newlines",
+            "use `str.lines()` instead",
+            format!(
+                "{}.lines()",
+                snippet_with_context(cx, trim_recv.span, expr.span.ctxt(), "..", &mut app).0
+            ),
+            app,
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 637368e9361..64fcd9f8f45 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -3,13 +3,13 @@ use super::unnecessary_iter_cloned::{self, is_into_iter};
 use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
+use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_lang_item, peel_mid_ty_refs};
 use clippy_utils::visitors::find_all_ret_expressions;
 use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
-use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, Node};
+use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
 use rustc_hir_typeck::{FnCtxt, Inherited};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
@@ -246,6 +246,19 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb
         && let Some(receiver_snippet) = snippet_opt(cx, receiver.span)
         && let Some(arg_snippet) = snippet_opt(cx, argument_expr.span)
     {
+        // We may end-up here because of an expression like `x.to_string().split(…)` where the type of `x`
+        // implements `AsRef<str>` but does not implement `Deref<Target = str>`. In this case, we have to
+        // add `.as_ref()` to the suggestion.
+        let as_ref = if is_type_lang_item(cx, cx.typeck_results().expr_ty(expr), LangItem::String)
+            && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref)
+            && cx.get_associated_type(cx.typeck_results().expr_ty(receiver), deref_trait_id, "Target")
+                != Some(cx.tcx.types.str_)
+        {
+            ".as_ref()"
+        } else {
+            ""
+        };
+
         // The next suggestion may be incorrect because the removal of the `to_owned`-like
         // function could cause the iterator to hold a reference to a resource that is used
         // mutably. See https://github.com/rust-lang/rust-clippy/issues/8148.
@@ -255,7 +268,7 @@ fn check_split_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: Symb
             parent.span,
             &format!("unnecessary use of `{method_name}`"),
             "use",
-            format!("{receiver_snippet}.split({arg_snippet})"),
+            format!("{receiver_snippet}{as_ref}.split({arg_snippet})"),
             Applicability::MaybeIncorrect,
         );
         return true;
@@ -445,7 +458,10 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
                 {
                     let bound_fn_sig = cx.tcx.fn_sig(callee_def_id);
                     let fn_sig = bound_fn_sig.skip_binder();
-                    if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
+                    if let Some(arg_index) = recv
+                        .into_iter()
+                        .chain(call_args)
+                        .position(|arg| arg.hir_id == expr.hir_id)
                         && let param_ty = fn_sig.input(arg_index).skip_binder()
                         && let ty::Param(ParamTy { index: param_index , ..}) = *param_ty.kind()
                         // https://github.com/rust-lang/rust-clippy/issues/9504 and https://github.com/rust-lang/rust-clippy/issues/10021
diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
index 84ee64e88a6..66727e5a29d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -1,19 +1,52 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::walk_ptrs_ty_depth;
-use clippy_utils::{get_parent_expr, is_trait_method};
+use clippy_utils::{get_parent_expr, is_diag_trait_item, match_def_path, paths, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
-use rustc_span::sym;
+use rustc_middle::ty::adjustment::Adjust;
+use rustc_middle::ty::{Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use rustc_span::{sym, Span};
+
+use core::ops::ControlFlow;
 
 use super::USELESS_ASREF;
 
+/// Returns the first type inside the `Option`/`Result` type passed as argument.
+fn get_enum_ty(enum_ty: Ty<'_>) -> Option<Ty<'_>> {
+    struct ContainsTyVisitor {
+        level: usize,
+    }
+
+    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTyVisitor {
+        type BreakTy = Ty<'tcx>;
+
+        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            self.level += 1;
+            if self.level == 1 {
+                t.super_visit_with(self)
+            } else {
+                ControlFlow::Break(t)
+            }
+        }
+    }
+
+    match enum_ty.visit_with(&mut ContainsTyVisitor { level: 0 }) {
+        ControlFlow::Break(ty) => Some(ty),
+        ControlFlow::Continue(()) => None,
+    }
+}
+
 /// Checks for the `USELESS_ASREF` lint.
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, recvr: &hir::Expr<'_>) {
     // when we get here, we've already checked that the call name is "as_ref" or "as_mut"
     // check if the call is to the actual `AsRef` or `AsMut` trait
-    if is_trait_method(cx, expr, sym::AsRef) || is_trait_method(cx, expr, sym::AsMut) {
+    let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) else {
+        return;
+    };
+
+    if is_diag_trait_item(cx, def_id, sym::AsRef) || is_diag_trait_item(cx, def_id, sym::AsMut) {
         // check if the type after `as_ref` or `as_mut` is the same as before
         let rcv_ty = cx.typeck_results().expr_ty(recvr);
         let res_ty = cx.typeck_results().expr_ty(expr);
@@ -39,5 +72,89 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
                 applicability,
             );
         }
+    } else if match_def_path(cx, def_id, &["core", "option", "Option", call_name])
+        || match_def_path(cx, def_id, &["core", "result", "Result", call_name])
+    {
+        let rcv_ty = cx.typeck_results().expr_ty(recvr).peel_refs();
+        let res_ty = cx.typeck_results().expr_ty(expr).peel_refs();
+
+        if let Some(rcv_ty) = get_enum_ty(rcv_ty)
+            && let Some(res_ty) = get_enum_ty(res_ty)
+            // If the only thing the `as_mut`/`as_ref` call is doing is adding references and not
+            // changing the type, then we can move forward.
+            && rcv_ty.peel_refs() == res_ty.peel_refs()
+            && let Some(parent) = get_parent_expr(cx, expr)
+            && let hir::ExprKind::MethodCall(segment, _, args, _) = parent.kind
+            && segment.ident.span != expr.span
+            // We check that the called method name is `map`.
+            && segment.ident.name == sym::map
+            // And that it only has one argument.
+            && let [arg] = args
+            && is_calling_clone(cx, arg)
+        {
+            lint_as_ref_clone(cx, expr.span.with_hi(parent.span.hi()), recvr, call_name);
+        }
+    }
+}
+
+fn check_qpath(cx: &LateContext<'_>, qpath: hir::QPath<'_>, hir_id: hir::HirId) -> bool {
+    // We check it's calling the `clone` method of the `Clone` trait.
+    if let Some(path_def_id) = cx.qpath_res(&qpath, hir_id).opt_def_id() {
+        match_def_path(cx, path_def_id, &paths::CLONE_TRAIT_METHOD)
+    } else {
+        false
     }
 }
+
+fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
+    match arg.kind {
+        hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
+            // If it's a closure, we need to check what is called.
+            let closure_body = cx.tcx.hir().body(body);
+            let closure_expr = peel_blocks(closure_body.value);
+            match closure_expr.kind {
+                hir::ExprKind::MethodCall(method, obj, [], _) => {
+                    if method.ident.name == sym::clone
+                        && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id)
+                        && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
+                        // We check it's the `Clone` trait.
+                        && cx.tcx.lang_items().clone_trait().map_or(false, |id| id == trait_id)
+                        // no autoderefs
+                        && !cx.typeck_results().expr_adjustments(obj).iter()
+                            .any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
+                    {
+                        true
+                    } else {
+                        false
+                    }
+                },
+                hir::ExprKind::Call(call, [_]) => {
+                    if let hir::ExprKind::Path(qpath) = call.kind {
+                        check_qpath(cx, qpath, call.hir_id)
+                    } else {
+                        false
+                    }
+                },
+                _ => false,
+            }
+        },
+        hir::ExprKind::Path(qpath) => check_qpath(cx, qpath, arg.hir_id),
+        _ => false,
+    }
+}
+
+fn lint_as_ref_clone(cx: &LateContext<'_>, span: Span, recvr: &hir::Expr<'_>, call_name: &str) {
+    let mut applicability = Applicability::MachineApplicable;
+    span_lint_and_sugg(
+        cx,
+        USELESS_ASREF,
+        span,
+        &format!("this call to `{call_name}.map(...)` does nothing"),
+        "try",
+        format!(
+            "{}.clone()",
+            snippet_with_applicability(cx, recvr.span, "..", &mut applicability)
+        ),
+        applicability,
+    );
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs
index 9ad4250a141..3a0305b4d55 100644
--- a/src/tools/clippy/clippy_lints/src/methods/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs
@@ -74,6 +74,7 @@ pub(super) fn get_hint_if_single_char_arg(
             match ch {
                 "'" => "\\'",
                 r"\" => "\\\\",
+                "\\\"" => "\"", // no need to escape `"` in `'"'`
                 _ => ch,
             }
         );
diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs
index 0f18e943451..bbc4d0a0f9a 100644
--- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs
@@ -331,7 +331,7 @@ fn report_indexes(cx: &LateContext<'_>, map: &UnhashMap<u64, Vec<IndexEntry<'_>>
                     slice,
                 } if indexes.len() > 1 => {
                     // if we have found an `assert!`, let's also check that it's actually right
-                    // and if it convers the highest index and if not, suggest the correct length
+                    // and if it covers the highest index and if not, suggest the correct length
                     let sugg = match comparison {
                         // `v.len() < 5` and `v.len() <= 5` does nothing in terms of bounds checks.
                         // The user probably meant `v.len() > 5`
diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
index c1f6c71a63e..c6c188854fd 100644
--- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
@@ -13,21 +13,23 @@ use rustc_span::Symbol;
 declare_clippy_lint! {
     /// ### What it does
     /// Checks for imports that do not rename the item as specified
-    /// in the `enforce-import-renames` config option.
+    /// in the `enforced-import-renames` config option.
     ///
     /// Note: Even though this lint is warn-by-default, it will only trigger if
-    /// import renames are defined in the clippy.toml file.
+    /// import renames are defined in the `clippy.toml` file.
     ///
     /// ### Why is this bad?
-    /// Consistency is important, if a project has defined import
-    /// renames they should be followed. More practically, some item names are too
-    /// vague outside of their defining scope this can enforce a more meaningful naming.
+    /// Consistency is important; if a project has defined import renames, then they should be
+    /// followed. More practically, some item names are too vague outside of their defining scope,
+    /// in which case this can enforce a more meaningful naming.
     ///
     /// ### Example
     /// An example clippy.toml configuration:
     /// ```toml
     /// # clippy.toml
-    /// enforced-import-renames = [ { path = "serde_json::Value", rename = "JsonValue" }]
+    /// enforced-import-renames = [
+    ///     { path = "serde_json::Value", rename = "JsonValue" },
+    /// ]
     /// ```
     ///
     /// ```rust,ignore
diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
index a23e12f7a18..4ae4fc9b096 100644
--- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
+++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
@@ -6,7 +6,7 @@ use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_hir::Expr;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, IntTy, Ty, UintTy};
 use rustc_session::declare_lint_pass;
 use rustc_span::sym;
 
@@ -105,8 +105,28 @@ impl<'tcx> LateLintPass<'tcx> for Mutex {
 fn get_atomic_name(ty: Ty<'_>) -> Option<&'static str> {
     match ty.kind() {
         ty::Bool => Some("AtomicBool"),
-        ty::Uint(_) => Some("AtomicUsize"),
-        ty::Int(_) => Some("AtomicIsize"),
+        ty::Uint(uint_ty) => {
+            match uint_ty {
+                UintTy::U8 => Some("AtomicU8"),
+                UintTy::U16 => Some("AtomicU16"),
+                UintTy::U32 => Some("AtomicU32"),
+                UintTy::U64 => Some("AtomicU64"),
+                UintTy::Usize => Some("AtomicUsize"),
+                // There's no `AtomicU128`.
+                UintTy::U128 => None,
+            }
+        },
+        ty::Int(int_ty) => {
+            match int_ty {
+                IntTy::I8 => Some("AtomicI8"),
+                IntTy::I16 => Some("AtomicI16"),
+                IntTy::I32 => Some("AtomicI32"),
+                IntTy::I64 => Some("AtomicI64"),
+                IntTy::Isize => Some("AtomicIsize"),
+                // There's no `AtomicI128`.
+                IntTy::I128 => None,
+            }
+        },
         ty::RawPtr(_) => Some("AtomicPtr"),
         _ => None,
     }
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 5978da83199..6bbe427ea29 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -165,7 +165,7 @@ fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
 }
 
 fn is_operator_overridden(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    // It's very hard or impossable to check whether overridden operator have side-effect this lint.
+    // It's very hard or impossible to check whether overridden operator have side-effect this lint.
     // So, this function assume user-defined operator is overridden with an side-effect.
     // The definition of user-defined structure here is ADT-type,
     // Althrough this will weaken the ability of this lint, less error lint-fix happen.
diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
index 49e9e2c00cc..2701d6bdca3 100644
--- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
@@ -53,14 +53,10 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
                             && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did())))
                     && let ExprKind::Lit(_) = param.kind
                     && param.span.eq_ctxt(expr.span)
+                    && let Some(snip) = snippet_opt(cx, param.span)
+                    && !(snip.starts_with("0o") || snip.starts_with("0b"))
                 {
-                    let Some(snip) = snippet_opt(cx, param.span) else {
-                        return;
-                    };
-
-                    if !snip.starts_with("0o") {
-                        show_error(cx, param);
-                    }
+                    show_error(cx, param);
                 }
             },
             ExprKind::Call(func, [param]) => {
@@ -70,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
                     && let ExprKind::Lit(_) = param.kind
                     && param.span.eq_ctxt(expr.span)
                     && let Some(snip) = snippet_opt(cx, param.span)
-                    && !snip.starts_with("0o")
+                    && !(snip.starts_with("0o") || snip.starts_with("0b"))
                 {
                     show_error(cx, param);
                 }
diff --git a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
index 8ecb038627f..f671517c134 100644
--- a/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/identity_op.rs
@@ -18,82 +18,118 @@ pub(crate) fn check<'tcx>(
     right: &'tcx Expr<'_>,
 ) {
     if !is_allowed(cx, op, left, right) {
-        match op {
-            BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
-                check_op(
-                    cx,
-                    left,
-                    0,
-                    expr.span,
-                    peel_hir_expr_refs(right).0.span,
-                    needs_parenthesis(cx, expr, right),
-                );
-                check_op(
-                    cx,
-                    right,
-                    0,
-                    expr.span,
-                    peel_hir_expr_refs(left).0.span,
-                    Parens::Unneeded,
-                );
-            },
-            BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => {
-                check_op(
-                    cx,
-                    right,
-                    0,
-                    expr.span,
-                    peel_hir_expr_refs(left).0.span,
-                    Parens::Unneeded,
-                );
-            },
-            BinOpKind::Mul => {
-                check_op(
-                    cx,
-                    left,
-                    1,
-                    expr.span,
-                    peel_hir_expr_refs(right).0.span,
-                    needs_parenthesis(cx, expr, right),
-                );
-                check_op(
-                    cx,
-                    right,
-                    1,
-                    expr.span,
-                    peel_hir_expr_refs(left).0.span,
-                    Parens::Unneeded,
-                );
-            },
-            BinOpKind::Div => check_op(
+        return;
+    }
+
+    // we need to know whether a ref is coerced to a value
+    // if a ref is coerced, then the suggested lint must deref it
+    // e.g. `let _: i32 = x+0` with `x: &i32` should be replaced with `let _: i32 = *x`.
+    // we do this by checking the _kind_ of the type of the expression
+    // if it's a ref, we then check whether it is erased, and that's it.
+    let (peeled_left_span, left_is_coerced_to_value) = {
+        let expr = peel_hir_expr_refs(left).0;
+        let span = expr.span;
+        let is_coerced = expr_is_erased_ref(cx, expr);
+        (span, is_coerced)
+    };
+
+    let (peeled_right_span, right_is_coerced_to_value) = {
+        let expr = peel_hir_expr_refs(right).0;
+        let span = expr.span;
+        let is_coerced = expr_is_erased_ref(cx, expr);
+        (span, is_coerced)
+    };
+
+    match op {
+        BinOpKind::Add | BinOpKind::BitOr | BinOpKind::BitXor => {
+            check_op(
+                cx,
+                left,
+                0,
+                expr.span,
+                peeled_right_span,
+                needs_parenthesis(cx, expr, right),
+                right_is_coerced_to_value,
+            );
+            check_op(
+                cx,
+                right,
+                0,
+                expr.span,
+                peeled_left_span,
+                Parens::Unneeded,
+                left_is_coerced_to_value,
+            );
+        },
+        BinOpKind::Shl | BinOpKind::Shr | BinOpKind::Sub => {
+            check_op(
+                cx,
+                right,
+                0,
+                expr.span,
+                peeled_left_span,
+                Parens::Unneeded,
+                left_is_coerced_to_value,
+            );
+        },
+        BinOpKind::Mul => {
+            check_op(
+                cx,
+                left,
+                1,
+                expr.span,
+                peeled_right_span,
+                needs_parenthesis(cx, expr, right),
+                right_is_coerced_to_value,
+            );
+            check_op(
                 cx,
                 right,
                 1,
                 expr.span,
-                peel_hir_expr_refs(left).0.span,
+                peeled_left_span,
                 Parens::Unneeded,
-            ),
-            BinOpKind::BitAnd => {
-                check_op(
-                    cx,
-                    left,
-                    -1,
-                    expr.span,
-                    peel_hir_expr_refs(right).0.span,
-                    needs_parenthesis(cx, expr, right),
-                );
-                check_op(
-                    cx,
-                    right,
-                    -1,
-                    expr.span,
-                    peel_hir_expr_refs(left).0.span,
-                    Parens::Unneeded,
-                );
-            },
-            BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span),
-            _ => (),
-        }
+                left_is_coerced_to_value,
+            );
+        },
+        BinOpKind::Div => check_op(
+            cx,
+            right,
+            1,
+            expr.span,
+            peeled_left_span,
+            Parens::Unneeded,
+            left_is_coerced_to_value,
+        ),
+        BinOpKind::BitAnd => {
+            check_op(
+                cx,
+                left,
+                -1,
+                expr.span,
+                peeled_right_span,
+                needs_parenthesis(cx, expr, right),
+                right_is_coerced_to_value,
+            );
+            check_op(
+                cx,
+                right,
+                -1,
+                expr.span,
+                peeled_left_span,
+                Parens::Unneeded,
+                left_is_coerced_to_value,
+            );
+        },
+        BinOpKind::Rem => check_remainder(cx, left, right, expr.span, left.span),
+        _ => (),
+    }
+}
+
+fn expr_is_erased_ref(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    match cx.typeck_results().expr_ty(expr).kind() {
+        ty::Ref(r, ..) => r.is_erased(),
+        _ => false,
     }
 }
 
@@ -144,11 +180,11 @@ fn needs_parenthesis(cx: &LateContext<'_>, binary: &Expr<'_>, right: &Expr<'_>)
 }
 
 fn is_allowed(cx: &LateContext<'_>, cmp: BinOpKind, left: &Expr<'_>, right: &Expr<'_>) -> bool {
-    // This lint applies to integers
-    !cx.typeck_results().expr_ty(left).peel_refs().is_integral()
-        || !cx.typeck_results().expr_ty(right).peel_refs().is_integral()
+    // This lint applies to integers and their references
+    cx.typeck_results().expr_ty(left).peel_refs().is_integral()
+        && cx.typeck_results().expr_ty(right).peel_refs().is_integral()
         // `1 << 0` is a common pattern in bit manipulation code
-        || (cmp == BinOpKind::Shl
+        && !(cmp == BinOpKind::Shl
             && constant_simple(cx, cx.typeck_results(), right) == Some(Constant::Int(0))
             && constant_simple(cx, cx.typeck_results(), left) == Some(Constant::Int(1)))
 }
@@ -161,11 +197,11 @@ fn check_remainder(cx: &LateContext<'_>, left: &Expr<'_>, right: &Expr<'_>, span
         (Some(FullInt::U(lv)), Some(FullInt::U(rv))) => lv < rv,
         _ => return,
     } {
-        span_ineffective_operation(cx, span, arg, Parens::Unneeded);
+        span_ineffective_operation(cx, span, arg, Parens::Unneeded, false);
     }
 }
 
-fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens) {
+fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, parens: Parens, is_erased: bool) {
     if let Some(Constant::Int(v)) = constant_simple(cx, cx.typeck_results(), e).map(Constant::peel_refs) {
         let check = match *cx.typeck_results().expr_ty(e).peel_refs().kind() {
             ty::Int(ity) => unsext(cx.tcx, -1_i128, ity),
@@ -178,18 +214,28 @@ fn check_op(cx: &LateContext<'_>, e: &Expr<'_>, m: i8, span: Span, arg: Span, pa
             1 => v == 1,
             _ => unreachable!(),
         } {
-            span_ineffective_operation(cx, span, arg, parens);
+            span_ineffective_operation(cx, span, arg, parens, is_erased);
         }
     }
 }
 
-fn span_ineffective_operation(cx: &LateContext<'_>, span: Span, arg: Span, parens: Parens) {
+fn span_ineffective_operation(
+    cx: &LateContext<'_>,
+    span: Span,
+    arg: Span,
+    parens: Parens,
+    is_ref_coerced_to_val: bool,
+) {
     let mut applicability = Applicability::MachineApplicable;
     let expr_snippet = snippet_with_applicability(cx, arg, "..", &mut applicability);
-
+    let expr_snippet = if is_ref_coerced_to_val {
+        format!("*{expr_snippet}")
+    } else {
+        expr_snippet.into_owned()
+    };
     let suggestion = match parens {
         Parens::Needed => format!("({expr_snippet})"),
-        Parens::Unneeded => expr_snippet.into_owned(),
+        Parens::Unneeded => expr_snippet,
     };
 
     span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
new file mode 100644
index 00000000000..00465ce4381
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
@@ -0,0 +1,83 @@
+use clippy_config::types::PubUnderscoreFieldsBehaviour;
+use clippy_utils::attrs::is_doc_hidden;
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_path_lang_item;
+use rustc_hir::{FieldDef, Item, ItemKind, LangItem};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::impl_lint_pass;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks whether any field of the struct is prefixed with an `_` (underscore) and also marked
+    /// `pub` (public)
+    ///
+    /// ### Why is this bad?
+    /// Fields prefixed with an `_` are inferred as unused, which suggests it should not be marked
+    /// as `pub`, because marking it as `pub` infers it will be used.
+    ///
+    /// ### Example
+    /// ```rust
+    /// struct FileHandle {
+    ///     pub _descriptor: usize,
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// struct FileHandle {
+    ///     _descriptor: usize,
+    /// }
+    /// ```
+    ///
+    /// OR
+    ///
+    /// ```rust
+    /// struct FileHandle {
+    ///     pub descriptor: usize,
+    /// }
+    /// ```
+    #[clippy::version = "1.77.0"]
+    pub PUB_UNDERSCORE_FIELDS,
+    pedantic,
+    "struct field prefixed with underscore and marked public"
+}
+
+pub struct PubUnderscoreFields {
+    pub behavior: PubUnderscoreFieldsBehaviour,
+}
+impl_lint_pass!(PubUnderscoreFields => [PUB_UNDERSCORE_FIELDS]);
+
+impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+        // This lint only pertains to structs.
+        let ItemKind::Struct(variant_data, _) = &item.kind else {
+            return;
+        };
+
+        let is_visible = |field: &FieldDef<'_>| match self.behavior {
+            PubUnderscoreFieldsBehaviour::PublicallyExported => cx.effective_visibilities.is_reachable(field.def_id),
+            PubUnderscoreFieldsBehaviour::AllPubFields => {
+                // If there is a visibility span then the field is marked pub in some way.
+                !field.vis_span.is_empty()
+            },
+        };
+
+        for field in variant_data.fields() {
+            // Only pertains to fields that start with an underscore, and are public.
+            if field.ident.as_str().starts_with('_') && is_visible(field)
+                // We ignore fields that have `#[doc(hidden)]`.
+                && !is_doc_hidden(cx.tcx.hir().attrs(field.hir_id))
+                // We ignore fields that are `PhantomData`.
+                && !is_path_lang_item(cx, field.ty, LangItem::PhantomData)
+            {
+                span_lint_and_help(
+                    cx,
+                    PUB_UNDERSCORE_FIELDS,
+                    field.vis_span.to(field.ident.span),
+                    "field marked as public but also inferred as unused because it's prefixed with `_`",
+                    None,
+                    "consider removing the underscore, or making the field private",
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 9469888a4d4..bd3128a0f97 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -75,12 +75,7 @@ enum IfBlockType<'hir> {
     /// An `if x.is_xxx() { a } else { b } ` expression.
     ///
     /// Contains: caller (x), caller_type, call_sym (is_xxx), if_then (a), if_else (b)
-    IfIs(
-        &'hir Expr<'hir>,
-        Ty<'hir>,
-        Symbol,
-        &'hir Expr<'hir>,
-    ),
+    IfIs(&'hir Expr<'hir>, Ty<'hir>, Symbol, &'hir Expr<'hir>),
     /// An `if let Xxx(a) = b { c } else { d }` expression.
     ///
     /// Contains: let_pat_qpath (Xxx), let_pat_type, let_pat_sym (a), let_expr (b), if_then (c),
diff --git a/src/tools/clippy/clippy_lints/src/serde_api.rs b/src/tools/clippy/clippy_lints/src/serde_api.rs
index 90834d784a5..b4278d879e5 100644
--- a/src/tools/clippy/clippy_lints/src/serde_api.rs
+++ b/src/tools/clippy/clippy_lints/src/serde_api.rs
@@ -6,7 +6,7 @@ use rustc_session::declare_lint_pass;
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for mis-uses of the serde API.
+    /// Checks for misuses of the serde API.
     ///
     /// ### Why is this bad?
     /// Serde is very finnicky about how its API should be
diff --git a/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
new file mode 100644
index 00000000000..9fee4c06200
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/thread_local_initializer_can_be_made_const.rs
@@ -0,0 +1,102 @@
+use clippy_config::msrvs::Msrv;
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::fn_has_unsatisfiable_preds;
+use clippy_utils::qualify_min_const_fn::is_min_const_fn;
+use clippy_utils::source::snippet;
+use rustc_errors::Applicability;
+use rustc_hir::{intravisit, ExprKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::impl_lint_pass;
+use rustc_span::sym::thread_local_macro;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Suggests to use `const` in `thread_local!` macro if possible.
+    /// ### Why is this bad?
+    ///
+    /// The `thread_local!` macro wraps static declarations and makes them thread-local.
+    /// It supports using a `const` keyword that may be used for declarations that can
+    /// be evaluated as a constant expression. This can enable a more efficient thread
+    /// local implementation that can avoid lazy initialization. For types that do not
+    /// need to be dropped, this can enable an even more efficient implementation that
+    /// does not need to track any additional state.
+    ///
+    /// https://doc.rust-lang.org/std/macro.thread_local.html
+    ///
+    /// ### Example
+    /// ```no_run
+    /// // example code where clippy issues a warning
+    /// thread_local! {
+    ///     static BUF: String = String::new();
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// // example code which does not raise clippy warning
+    /// thread_local! {
+    ///     static BUF: String = const { String::new() };
+    /// }
+    /// ```
+    #[clippy::version = "1.76.0"]
+    pub THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST,
+    perf,
+    "suggest using `const` in `thread_local!` macro"
+}
+
+pub struct ThreadLocalInitializerCanBeMadeConst {
+    msrv: Msrv,
+}
+
+impl ThreadLocalInitializerCanBeMadeConst {
+    #[must_use]
+    pub fn new(msrv: Msrv) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(ThreadLocalInitializerCanBeMadeConst => [THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST]);
+
+impl<'tcx> LateLintPass<'tcx> for ThreadLocalInitializerCanBeMadeConst {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        fn_kind: rustc_hir::intravisit::FnKind<'tcx>,
+        _: &'tcx rustc_hir::FnDecl<'tcx>,
+        body: &'tcx rustc_hir::Body<'tcx>,
+        span: rustc_span::Span,
+        defid: rustc_span::def_id::LocalDefId,
+    ) {
+        if in_external_macro(cx.sess(), span)
+            && let Some(callee) = span.source_callee()
+            && let Some(macro_def_id) = callee.macro_def_id
+            && cx.tcx.is_diagnostic_item(thread_local_macro, macro_def_id)
+            && let intravisit::FnKind::ItemFn(..) = fn_kind
+            // Building MIR for `fn`s with unsatisfiable preds results in ICE.
+            && !fn_has_unsatisfiable_preds(cx, defid.to_def_id())
+            && let mir = cx.tcx.optimized_mir(defid.to_def_id())
+            && let Ok(()) = is_min_const_fn(cx.tcx, mir, &self.msrv)
+            // this is the `__init` function emitted by the `thread_local!` macro
+            // when the `const` keyword is not used. We avoid checking the `__init` directly
+            // as that is not a public API.
+            // we know that the function is const-qualifiable, so now we need only to get the
+            // initializer expression to span-lint it.
+            && let ExprKind::Block(block, _) = body.value.kind
+            && let Some(ret_expr) = block.expr
+            && let initializer_snippet = snippet(cx, ret_expr.span, "thread_local! { ... }")
+            && initializer_snippet != "thread_local! { ... }"
+        {
+            span_lint_and_sugg(
+                cx,
+                THREAD_LOCAL_INITIALIZER_CAN_BE_MADE_CONST,
+                ret_expr.span,
+                "initializer for `thread_local` value can be made `const`",
+                "replace with",
+                format!("const {{ {initializer_snippet} }}"),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
+    extract_msrv_attr!(LateContext);
+}
diff --git a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs
index 01a23c515f5..c44f5150dd1 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/eager_transmute.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_normalizable;
-use clippy_utils::{path_to_local, path_to_local_id};
+use clippy_utils::{eq_expr_value, path_to_local};
 use rustc_abi::WrappingRange;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Node};
@@ -25,6 +25,52 @@ fn range_fully_contained(from: WrappingRange, to: WrappingRange) -> bool {
     to.contains(from.start) && to.contains(from.end)
 }
 
+/// Checks if a given expression is a binary operation involving a local variable or is made up of
+/// other (nested) binary expressions involving the local. There must be at least one local
+/// reference that is the same as `local_expr`.
+///
+/// This is used as a heuristic to detect if a variable
+/// is checked to be within the valid range of a transmuted type.
+/// All of these would return true:
+/// * `x < 4`
+/// * `x < 4 && x > 1`
+/// * `x.field < 4 && x.field > 1` (given `x.field`)
+/// * `x.field < 4 && unrelated()`
+/// * `(1..=3).contains(&x)`
+fn binops_with_local(cx: &LateContext<'_>, local_expr: &Expr<'_>, expr: &Expr<'_>) -> bool {
+    match expr.kind {
+        ExprKind::Binary(_, lhs, rhs) => {
+            binops_with_local(cx, local_expr, lhs) || binops_with_local(cx, local_expr, rhs)
+        },
+        ExprKind::MethodCall(path, receiver, [arg], _)
+            if path.ident.name == sym!(contains)
+                // ... `contains` called on some kind of range
+                && let Some(receiver_adt) = cx.typeck_results().expr_ty(receiver).peel_refs().ty_adt_def()
+                && let lang_items = cx.tcx.lang_items()
+                && [
+                    lang_items.range_from_struct(),
+                    lang_items.range_inclusive_struct(),
+                    lang_items.range_struct(),
+                    lang_items.range_to_inclusive_struct(),
+                    lang_items.range_to_struct()
+                ].into_iter().any(|did| did == Some(receiver_adt.did())) =>
+        {
+            eq_expr_value(cx, local_expr, arg.peel_borrows())
+        },
+        _ => eq_expr_value(cx, local_expr, expr),
+    }
+}
+
+/// Checks if an expression is a path to a local variable (with optional projections), e.g.
+/// `x.field[0].field2` would return true.
+fn is_local_with_projections(expr: &Expr<'_>) -> bool {
+    match expr.kind {
+        ExprKind::Path(_) => path_to_local(expr).is_some(),
+        ExprKind::Field(expr, _) | ExprKind::Index(expr, ..) => is_local_with_projections(expr),
+        _ => false,
+    }
+}
+
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'tcx>,
@@ -36,9 +82,8 @@ pub(super) fn check<'tcx>(
         && let ExprKind::MethodCall(path, receiver, [arg], _) = then_some_call.kind
         && cx.typeck_results().expr_ty(receiver).is_bool()
         && path.ident.name == sym!(then_some)
-        && let ExprKind::Binary(_, lhs, rhs) = receiver.kind
-        && let Some(local_id) = path_to_local(transmutable)
-        && (path_to_local_id(lhs, local_id) || path_to_local_id(rhs, local_id))
+        && is_local_with_projections(transmutable)
+        && binops_with_local(cx, transmutable, receiver)
         && is_normalizable(cx, cx.param_env, from_ty)
         && is_normalizable(cx, cx.param_env, to_ty)
         // we only want to lint if the target type has a niche that is larger than the one of the source type
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
index db378cfd755..a6f03c85b4f 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs
@@ -37,9 +37,7 @@ pub(super) fn check<'tcx>(
                 to_ty = to_sub_ty;
                 continue;
             },
-            (ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(Some(to_sub_ty)))
-                if reduced_tys.from_fat_ptr =>
-            {
+            (ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(Some(to_sub_ty))) if reduced_tys.from_fat_ptr => {
                 from_ty = from_sub_ty;
                 to_ty = to_sub_ty;
                 continue;
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index b1fa30aa068..e90306ded61 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -1,14 +1,21 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::{get_trait_def_id, path_res};
+use clippy_utils::{expr_or_init, get_trait_def_id, path_def_id};
 use rustc_ast::BinOpKind;
-use rustc_hir::def::Res;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::FnKind;
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, Item, ItemKind, Node};
+use rustc_hir::intravisit::{walk_body, walk_expr, FnKind, Visitor};
+use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, Node, QPath, TyKind};
+use rustc_hir_analysis::hir_ty_to_ty;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{self, Ty};
-use rustc_session::declare_lint_pass;
+use rustc_middle::hir::map::Map;
+use rustc_middle::hir::nested_filter;
+use rustc_middle::ty::{self, AssocKind, Ty, TyCtxt};
+use rustc_session::impl_lint_pass;
+use rustc_span::symbol::{kw, Ident};
 use rustc_span::{sym, Span};
+use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -41,7 +48,26 @@ declare_clippy_lint! {
     "detect unconditional recursion in some traits implementation"
 }
 
-declare_lint_pass!(UnconditionalRecursion => [UNCONDITIONAL_RECURSION]);
+#[derive(Default)]
+pub struct UnconditionalRecursion {
+    /// The key is the `DefId` of the type implementing the `Default` trait and the value is the
+    /// `DefId` of the return call.
+    default_impl_for_type: FxHashMap<DefId, DefId>,
+}
+
+impl_lint_pass!(UnconditionalRecursion => [UNCONDITIONAL_RECURSION]);
+
+fn span_error(cx: &LateContext<'_>, method_span: Span, expr: &Expr<'_>) {
+    span_lint_and_then(
+        cx,
+        UNCONDITIONAL_RECURSION,
+        method_span,
+        "function cannot return without recursing",
+        |diag| {
+            diag.span_note(expr.span, "recursive call site");
+        },
+    );
+}
 
 fn get_ty_def_id(ty: Ty<'_>) -> Option<DefId> {
     match ty.peel_refs().kind() {
@@ -51,84 +77,329 @@ fn get_ty_def_id(ty: Ty<'_>) -> Option<DefId> {
     }
 }
 
-fn is_local(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    matches!(path_res(cx, expr), Res::Local(_))
+fn get_hir_ty_def_id(tcx: TyCtxt<'_>, hir_ty: rustc_hir::Ty<'_>) -> Option<DefId> {
+    let TyKind::Path(qpath) = hir_ty.kind else { return None };
+    match qpath {
+        QPath::Resolved(_, path) => path.res.opt_def_id(),
+        QPath::TypeRelative(_, _) => {
+            let ty = hir_ty_to_ty(tcx, &hir_ty);
+
+            match ty.kind() {
+                ty::Alias(ty::Projection, proj) => {
+                    Res::<HirId>::Def(DefKind::Trait, proj.trait_ref(tcx).def_id).opt_def_id()
+                },
+                _ => None,
+            }
+        },
+        QPath::LangItem(..) => None,
+    }
 }
 
-impl<'tcx> LateLintPass<'tcx> for UnconditionalRecursion {
+fn get_return_calls_in_body<'tcx>(body: &'tcx Body<'tcx>) -> Vec<&'tcx Expr<'tcx>> {
+    let mut visitor = ReturnsVisitor::default();
+
+    visitor.visit_body(body);
+    visitor.returns
+}
+
+fn has_conditional_return(body: &Body<'_>, expr: &Expr<'_>) -> bool {
+    match get_return_calls_in_body(body).as_slice() {
+        [] => false,
+        [return_expr] => return_expr.hir_id != expr.hir_id,
+        _ => true,
+    }
+}
+
+fn get_impl_trait_def_id(cx: &LateContext<'_>, method_def_id: LocalDefId) -> Option<DefId> {
+    let hir_id = cx.tcx.local_def_id_to_hir_id(method_def_id);
+    if let Some((
+        _,
+        Node::Item(Item {
+            kind: ItemKind::Impl(impl_),
+            owner_id,
+            ..
+        }),
+    )) = cx.tcx.hir().parent_iter(hir_id).next()
+        // We exclude `impl` blocks generated from rustc's proc macros.
+        && !cx.tcx.has_attr(*owner_id, sym::automatically_derived)
+        // It is a implementation of a trait.
+        && let Some(trait_) = impl_.of_trait
+    {
+        trait_.trait_def_id()
+    } else {
+        None
+    }
+}
+
+#[allow(clippy::unnecessary_def_path)]
+fn check_partial_eq(cx: &LateContext<'_>, method_span: Span, method_def_id: LocalDefId, name: Ident, expr: &Expr<'_>) {
+    let args = cx
+        .tcx
+        .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(method_def_id).skip_binder())
+        .inputs();
+    // That has two arguments.
+    if let [self_arg, other_arg] = args
+        && let Some(self_arg) = get_ty_def_id(*self_arg)
+        && let Some(other_arg) = get_ty_def_id(*other_arg)
+        // The two arguments are of the same type.
+        && self_arg == other_arg
+        && let Some(trait_def_id) = get_impl_trait_def_id(cx, method_def_id)
+        // The trait is `PartialEq`.
+        && Some(trait_def_id) == get_trait_def_id(cx, &["core", "cmp", "PartialEq"])
+    {
+        let to_check_op = if name.name == sym::eq {
+            BinOpKind::Eq
+        } else {
+            BinOpKind::Ne
+        };
+        let is_bad = match expr.kind {
+            ExprKind::Binary(op, left, right) if op.node == to_check_op => {
+                // Then we check if the left-hand element is of the same type as `self`.
+                if let Some(left_ty) = cx.typeck_results().expr_ty_opt(left)
+                    && let Some(left_id) = get_ty_def_id(left_ty)
+                    && self_arg == left_id
+                    && let Some(right_ty) = cx.typeck_results().expr_ty_opt(right)
+                    && let Some(right_id) = get_ty_def_id(right_ty)
+                    && other_arg == right_id
+                {
+                    true
+                } else {
+                    false
+                }
+            },
+            ExprKind::MethodCall(segment, _receiver, &[_arg], _) if segment.ident.name == name.name => {
+                if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+                    && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
+                    && trait_id == trait_def_id
+                {
+                    true
+                } else {
+                    false
+                }
+            },
+            _ => false,
+        };
+        if is_bad {
+            span_error(cx, method_span, expr);
+        }
+    }
+}
+
+#[allow(clippy::unnecessary_def_path)]
+fn check_to_string(cx: &LateContext<'_>, method_span: Span, method_def_id: LocalDefId, name: Ident, expr: &Expr<'_>) {
+    let args = cx
+        .tcx
+        .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(method_def_id).skip_binder())
+        .inputs();
+    // That has one argument.
+    if let [_self_arg] = args
+        && let hir_id = cx.tcx.local_def_id_to_hir_id(method_def_id)
+        && let Some((
+            _,
+            Node::Item(Item {
+                kind: ItemKind::Impl(impl_),
+                owner_id,
+                ..
+            }),
+        )) = cx.tcx.hir().parent_iter(hir_id).next()
+        // We exclude `impl` blocks generated from rustc's proc macros.
+        && !cx.tcx.has_attr(*owner_id, sym::automatically_derived)
+        // It is a implementation of a trait.
+        && let Some(trait_) = impl_.of_trait
+        && let Some(trait_def_id) = trait_.trait_def_id()
+        // The trait is `ToString`.
+        && Some(trait_def_id) == get_trait_def_id(cx, &["alloc", "string", "ToString"])
+    {
+        let is_bad = match expr.kind {
+            ExprKind::MethodCall(segment, _receiver, &[_arg], _) if segment.ident.name == name.name => {
+                if let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+                    && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
+                    && trait_id == trait_def_id
+                {
+                    true
+                } else {
+                    false
+                }
+            },
+            _ => false,
+        };
+        if is_bad {
+            span_error(cx, method_span, expr);
+        }
+    }
+}
+
+fn is_default_method_on_current_ty(tcx: TyCtxt<'_>, qpath: QPath<'_>, implemented_ty_id: DefId) -> bool {
+    match qpath {
+        QPath::Resolved(_, path) => match path.segments {
+            [first, .., last] => last.ident.name == kw::Default && first.res.opt_def_id() == Some(implemented_ty_id),
+            _ => false,
+        },
+        QPath::TypeRelative(ty, segment) => {
+            if segment.ident.name != kw::Default {
+                return false;
+            }
+            if matches!(
+                ty.kind,
+                TyKind::Path(QPath::Resolved(
+                    _,
+                    hir::Path {
+                        res: Res::SelfTyAlias { .. },
+                        ..
+                    },
+                ))
+            ) {
+                return true;
+            }
+            get_hir_ty_def_id(tcx, *ty) == Some(implemented_ty_id)
+        },
+        QPath::LangItem(..) => false,
+    }
+}
+
+struct CheckCalls<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    map: Map<'tcx>,
+    implemented_ty_id: DefId,
+    found_default_call: bool,
+    method_span: Span,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for CheckCalls<'a, 'tcx>
+where
+    'tcx: 'a,
+{
+    type NestedFilter = nested_filter::OnlyBodies;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.map
+    }
+
     #[allow(clippy::unnecessary_def_path)]
+    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
+        if self.found_default_call {
+            return;
+        }
+        walk_expr(self, expr);
+
+        if let ExprKind::Call(f, _) = expr.kind
+            && let ExprKind::Path(qpath) = f.kind
+            && is_default_method_on_current_ty(self.cx.tcx, qpath, self.implemented_ty_id)
+            && let Some(method_def_id) = path_def_id(self.cx, f)
+            && let Some(trait_def_id) = self.cx.tcx.trait_of_item(method_def_id)
+            && Some(trait_def_id) == get_trait_def_id(self.cx, &["core", "default", "Default"])
+        {
+            self.found_default_call = true;
+            span_error(self.cx, self.method_span, expr);
+        }
+    }
+}
+
+impl UnconditionalRecursion {
+    #[allow(clippy::unnecessary_def_path)]
+    fn init_default_impl_for_type_if_needed(&mut self, cx: &LateContext<'_>) {
+        if self.default_impl_for_type.is_empty()
+            && let Some(default_trait_id) = get_trait_def_id(cx, &["core", "default", "Default"])
+        {
+            let impls = cx.tcx.trait_impls_of(default_trait_id);
+            for (ty, impl_def_ids) in impls.non_blanket_impls() {
+                let Some(self_def_id) = ty.def() else { continue };
+                for impl_def_id in impl_def_ids {
+                    if !cx.tcx.has_attr(*impl_def_id, sym::automatically_derived) &&
+                        let Some(assoc_item) = cx
+                            .tcx
+                            .associated_items(impl_def_id)
+                            .in_definition_order()
+                            // We're not interested in foreign implementations of the `Default` trait.
+                            .find(|item| {
+                                item.kind == AssocKind::Fn && item.def_id.is_local() && item.name == kw::Default
+                            })
+                        && let Some(body_node) = cx.tcx.hir().get_if_local(assoc_item.def_id)
+                        && let Some(body_id) = body_node.body_id()
+                        && let body = cx.tcx.hir().body(body_id)
+                        // We don't want to keep it if it has conditional return.
+                        && let [return_expr] = get_return_calls_in_body(body).as_slice()
+                        && let ExprKind::Call(call_expr, _) = return_expr.kind
+                        // We need to use typeck here to infer the actual function being called.
+                        && let body_def_id = cx.tcx.hir().enclosing_body_owner(call_expr.hir_id)
+                        && let Some(body_owner) = cx.tcx.hir().maybe_body_owned_by(body_def_id)
+                        && let typeck = cx.tcx.typeck_body(body_owner)
+                        && let Some(call_def_id) = typeck.type_dependent_def_id(call_expr.hir_id)
+                    {
+                        self.default_impl_for_type.insert(self_def_id, call_def_id);
+                    }
+                }
+            }
+        }
+    }
+
+    fn check_default_new<'tcx>(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        decl: &FnDecl<'tcx>,
+        body: &'tcx Body<'tcx>,
+        method_span: Span,
+        method_def_id: LocalDefId,
+    ) {
+        // We're only interested into static methods.
+        if decl.implicit_self.has_implicit_self() {
+            return;
+        }
+        // We don't check trait implementations.
+        if get_impl_trait_def_id(cx, method_def_id).is_some() {
+            return;
+        }
+
+        let hir_id = cx.tcx.local_def_id_to_hir_id(method_def_id);
+        if let Some((
+            _,
+            Node::Item(Item {
+                kind: ItemKind::Impl(impl_),
+                ..
+            }),
+        )) = cx.tcx.hir().parent_iter(hir_id).next()
+            && let Some(implemented_ty_id) = get_hir_ty_def_id(cx.tcx, *impl_.self_ty)
+            && {
+                self.init_default_impl_for_type_if_needed(cx);
+                true
+            }
+            && let Some(return_def_id) = self.default_impl_for_type.get(&implemented_ty_id)
+            && method_def_id.to_def_id() == *return_def_id
+        {
+            let mut c = CheckCalls {
+                cx,
+                map: cx.tcx.hir(),
+                implemented_ty_id,
+                found_default_call: false,
+                method_span,
+            };
+            walk_body(&mut c, body);
+        }
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for UnconditionalRecursion {
     fn check_fn(
         &mut self,
         cx: &LateContext<'tcx>,
         kind: FnKind<'tcx>,
-        _decl: &'tcx FnDecl<'tcx>,
+        decl: &'tcx FnDecl<'tcx>,
         body: &'tcx Body<'tcx>,
         method_span: Span,
-        def_id: LocalDefId,
+        method_def_id: LocalDefId,
     ) {
         // If the function is a method...
         if let FnKind::Method(name, _) = kind
-            // That has two arguments.
-            && let [self_arg, other_arg] = cx
-                .tcx
-                .instantiate_bound_regions_with_erased(cx.tcx.fn_sig(def_id).skip_binder())
-                .inputs()
-            && let Some(self_arg) = get_ty_def_id(*self_arg)
-            && let Some(other_arg) = get_ty_def_id(*other_arg)
-            // The two arguments are of the same type.
-            && self_arg == other_arg
-            && let hir_id = cx.tcx.local_def_id_to_hir_id(def_id)
-            && let Some((
-                _,
-                Node::Item(Item {
-                    kind: ItemKind::Impl(impl_),
-                    owner_id,
-                    ..
-                }),
-            )) = cx.tcx.hir().parent_iter(hir_id).next()
-            // We exclude `impl` blocks generated from rustc's proc macros.
-            && !cx.tcx.has_attr(*owner_id, sym::automatically_derived)
-            // It is a implementation of a trait.
-            && let Some(trait_) = impl_.of_trait
-            && let Some(trait_def_id) = trait_.trait_def_id()
-            // The trait is `PartialEq`.
-            && Some(trait_def_id) == get_trait_def_id(cx, &["core", "cmp", "PartialEq"])
+            && let expr = expr_or_init(cx, body.value).peel_blocks()
+            // Doesn't have a conditional return.
+            && !has_conditional_return(body, expr)
         {
-            let to_check_op = if name.name == sym::eq {
-                BinOpKind::Eq
-            } else {
-                BinOpKind::Ne
-            };
-            let expr = body.value.peel_blocks();
-            let is_bad = match expr.kind {
-                ExprKind::Binary(op, left, right) if op.node == to_check_op => {
-                    is_local(cx, left) && is_local(cx, right)
-                },
-                ExprKind::MethodCall(segment, receiver, &[arg], _) if segment.ident.name == name.name => {
-                    if is_local(cx, receiver)
-                        && is_local(cx, &arg)
-                        && let Some(fn_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
-                        && let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
-                        && trait_id == trait_def_id
-                    {
-                        true
-                    } else {
-                        false
-                    }
-                },
-                _ => false,
-            };
-            if is_bad {
-                span_lint_and_then(
-                    cx,
-                    UNCONDITIONAL_RECURSION,
-                    method_span,
-                    "function cannot return without recursing",
-                    |diag| {
-                        diag.span_note(expr.span, "recursive call site");
-                    },
-                );
+            if name.name == sym::eq || name.name == sym::ne {
+                check_partial_eq(cx, method_span, method_def_id, name, expr);
+            } else if name.name == sym::to_string {
+                check_to_string(cx, method_span, method_def_id, name, expr);
             }
+            self.check_default_new(cx, decl, body, method_span, method_def_id);
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
index e5bc3b5a25f..add4b3e5637 100644
--- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
+++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs
@@ -681,11 +681,19 @@ fn text_has_safety_comment(src: &str, line_starts: &[RelativeBytePos], start_pos
         .filter(|(_, text)| !text.is_empty());
 
     let (line_start, line) = lines.next()?;
+    let mut in_codeblock = false;
     // Check for a sequence of line comments.
     if line.starts_with("//") {
         let (mut line, mut line_start) = (line, line_start);
         loop {
-            if line.to_ascii_uppercase().contains("SAFETY:") {
+            // Don't lint if the safety comment is part of a codeblock in a doc comment.
+            // It may or may not be required, and we can't very easily check it (and we shouldn't, since
+            // the safety comment isn't referring to the node we're currently checking)
+            if line.trim_start_matches("///").trim_start().starts_with("```") {
+                in_codeblock = !in_codeblock;
+            }
+
+            if line.to_ascii_uppercase().contains("SAFETY:") && !in_codeblock {
                 return Some(start_pos + BytePos(u32::try_from(line_start).unwrap()));
             }
             match lines.next() {
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
index ef67f4b04b5..ed0958197f8 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs
@@ -13,12 +13,31 @@ use rustc_middle::ty;
 use super::LET_UNIT_VALUE;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
+    // skip `let () = { ... }`
+    if let PatKind::Tuple(fields, ..) = local.pat.kind
+        && fields.is_empty()
+    {
+        return;
+    }
+
     if let Some(init) = local.init
         && !local.pat.span.from_expansion()
         && !in_external_macro(cx.sess(), local.span)
         && !is_from_async_await(local.span)
         && cx.typeck_results().pat_ty(local.pat).is_unit()
     {
+        // skip `let awa = ()`
+        if let ExprKind::Tup([]) = init.kind {
+            return;
+        }
+
+        // skip `let _: () = { ... }`
+        if let Some(ty) = local.ty
+            && let TyKind::Tup([]) = ty.kind
+        {
+            return;
+        }
+
         if (local.ty.map_or(false, |ty| !matches!(ty.kind, TyKind::Infer))
             || matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none()))
             && expr_needs_inferred_result(cx, init)
@@ -34,7 +53,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>) {
                     |diag| {
                         diag.span_suggestion(
                             local.pat.span,
-                            "use a wild (`_`) binding",
+                            "use a wildcard binding",
                             "_",
                             Applicability::MaybeIncorrect, // snippet
                         );
diff --git a/src/tools/clippy/clippy_lints/src/vec.rs b/src/tools/clippy/clippy_lints/src/vec.rs
index 5e13c73f035..2c33c93412a 100644
--- a/src/tools/clippy/clippy_lints/src/vec.rs
+++ b/src/tools/clippy/clippy_lints/src/vec.rs
@@ -11,8 +11,8 @@ use clippy_utils::{get_parent_expr, higher, is_trait_method};
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty;
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::{sym, DesugaringKind, Span};
 
@@ -79,7 +79,6 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec {
                 // this is to avoid compile errors when doing the suggestion here: let _: Vec<_> = vec![..];
                 && local.ty.is_none()
                 && let PatKind::Binding(_, id, ..) = local.pat.kind
-                && is_copy(cx, vec_type(cx.typeck_results().expr_ty_adjusted(expr.peel_borrows())))
             {
                 let only_slice_uses = for_each_local_use_after_expr(cx, id, expr.hir_id, |expr| {
                     // allow indexing into a vec and some set of allowed method calls that exist on slices, too
@@ -185,6 +184,11 @@ impl UselessVec {
         let snippet = match *vec_args {
             higher::VecArgs::Repeat(elem, len) => {
                 if let Some(Constant::Int(len_constant)) = constant(cx, cx.typeck_results(), len) {
+                    // vec![ty; N] works when ty is Clone, [ty; N] requires it to be Copy also
+                    if !is_copy(cx, cx.typeck_results().expr_ty(elem)) {
+                        return;
+                    }
+
                     #[expect(clippy::cast_possible_truncation)]
                     if len_constant as u64 * size_of(cx, elem) > self.too_large_for_stack {
                         return;
@@ -241,12 +245,3 @@ fn size_of(cx: &LateContext<'_>, expr: &Expr<'_>) -> u64 {
     let ty = cx.typeck_results().expr_ty_adjusted(expr);
     cx.layout_of(ty).map_or(0, |l| l.size.bytes())
 }
-
-/// Returns the item type of the vector (i.e., the `T` in `Vec<T>`).
-fn vec_type(ty: Ty<'_>) -> Ty<'_> {
-    if let ty::Adt(_, args) = ty.kind() {
-        args.type_at(0)
-    } else {
-        panic!("The type of `vec!` is a not a struct?");
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 9b0dac6af25..b82bd1d7e7c 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -142,7 +142,7 @@ impl LateLintPass<'_> for WildcardImports {
             } else {
                 // In this case, the `use_path.span` ends right before the `::*`, so we need to
                 // extend it up to the `*`. Since it is hard to find the `*` in weird
-                // formattings like `use _ ::  *;`, we extend it up to, but not including the
+                // formatting like `use _ ::  *;`, we extend it up to, but not including the
                 // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we
                 // can just use the end of the item span
                 let mut span = use_path.span.with_hi(item.span.hi());
diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
index 4e71c6483e6..6c40029a9de 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -99,7 +99,10 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg:
 }
 
 fn res_has_significant_drop(res: Res, cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
-    if let Res::Def(DefKind::Ctor(..) | DefKind::Variant, _) | Res::SelfCtor(_) = res {
+    if let Res::Def(DefKind::Ctor(..) | DefKind::Variant | DefKind::Enum | DefKind::Struct, _)
+    | Res::SelfCtor(_)
+    | Res::SelfTyAlias { .. } = res
+    {
         cx.typeck_results()
             .expr_ty(e)
             .has_significant_drop(cx.tcx, cx.param_env)
@@ -173,6 +176,13 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                     self.eagerness |= NoChange;
                     return;
                 },
+                #[expect(clippy::match_same_arms)] // arm pattern can't be merged due to `ref`, see rust#105778
+                ExprKind::Struct(path, ..) => {
+                    if res_has_significant_drop(self.cx.qpath_res(path, e.hir_id), self.cx, e) {
+                        self.eagerness = ForceNoChange;
+                        return;
+                    }
+                },
                 ExprKind::Path(ref path) => {
                     if res_has_significant_drop(self.cx.qpath_res(path, e.hir_id), self.cx, e) {
                         self.eagerness = ForceNoChange;
@@ -291,7 +301,6 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
                 | ExprKind::Closure { .. }
                 | ExprKind::Field(..)
                 | ExprKind::AddrOf(..)
-                | ExprKind::Struct(..)
                 | ExprKind::Repeat(..)
                 | ExprKind::Block(Block { stmts: [], .. }, _)
                 | ExprKind::OffsetOf(..) => (),
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index a23105691bf..07b72e3f570 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -865,7 +865,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
 
                 for arm in arms {
                     self.hash_pat(arm.pat);
-                    if let Some(ref e) = arm.guard {
+                    if let Some(e) = arm.guard {
                         self.hash_expr(e);
                     }
                     self.hash_expr(arm.body);
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 46ce4ffdce5..c475e7b7c43 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -420,7 +420,7 @@ pub fn find_format_args(cx: &LateContext<'_>, start: &Expr<'_>, expn_id: ExpnId)
         ast_format_args
             .get()?
             .get(&format_args_expr.span.with_parent(None))
-            .map(Rc::clone)
+            .cloned()
     })
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
index da71fc3aaa8..adca2ca1c3e 100644
--- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs
@@ -38,7 +38,7 @@ fn expr_type_certainty(cx: &LateContext<'_>, expr: &Expr<'_>) -> Certainty {
 
         ExprKind::Call(callee, args) => {
             let lhs = expr_type_certainty(cx, callee);
-            let rhs = if type_is_inferrable_from_arguments(cx, expr) {
+            let rhs = if type_is_inferable_from_arguments(cx, expr) {
                 meet(args.iter().map(|arg| expr_type_certainty(cx, arg)))
             } else {
                 Certainty::Uncertain
@@ -57,7 +57,7 @@ fn expr_type_certainty(cx: &LateContext<'_>, expr: &Expr<'_>) -> Certainty {
                 receiver_type_certainty = receiver_type_certainty.with_def_id(self_ty_def_id);
             };
             let lhs = path_segment_certainty(cx, receiver_type_certainty, method, false);
-            let rhs = if type_is_inferrable_from_arguments(cx, expr) {
+            let rhs = if type_is_inferable_from_arguments(cx, expr) {
                 meet(
                     std::iter::once(receiver_type_certainty).chain(args.iter().map(|arg| expr_type_certainty(cx, arg))),
                 )
@@ -279,7 +279,7 @@ fn update_res(cx: &LateContext<'_>, parent_certainty: Certainty, path_segment: &
 }
 
 #[allow(clippy::cast_possible_truncation)]
-fn type_is_inferrable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+fn type_is_inferable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
     let Some(callee_def_id) = (match expr.kind {
         ExprKind::Call(callee, _) => {
             let callee_ty = cx.typeck_results().expr_ty(callee);
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 5a2526fd267..2589d46e7da 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-12-28"
+channel = "nightly-2024-01-11"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/rustc_tools_util/README.md b/src/tools/clippy/rustc_tools_util/README.md
index e197ea048a0..56f62b867a6 100644
--- a/src/tools/clippy/rustc_tools_util/README.md
+++ b/src/tools/clippy/rustc_tools_util/README.md
@@ -51,7 +51,7 @@ The changelog for `rustc_tools_util` is available under:
 
 <!-- REUSE-IgnoreStart -->
 
-Copyright 2014-2022 The Rust Project Developers
+Copyright 2014-2024 The Rust Project Developers
 
 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
diff --git a/src/tools/clippy/tests/ui-toml/pub_underscore_fields/all_pub_fields/clippy.toml b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/all_pub_fields/clippy.toml
new file mode 100644
index 00000000000..95835d101b1
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/all_pub_fields/clippy.toml
@@ -0,0 +1 @@
+pub-underscore-fields-behavior = "AllPubFields"
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui-toml/pub_underscore_fields/exported/clippy.toml b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/exported/clippy.toml
new file mode 100644
index 00000000000..94a0d3554bc
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/exported/clippy.toml
@@ -0,0 +1 @@
+pub-underscore-fields-behavior = "PublicallyExported"
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr
new file mode 100644
index 00000000000..c6bd499fd8c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.all_pub_fields.stderr
@@ -0,0 +1,60 @@
+error: field marked as public but also inferred as unused because it's prefixed with `_`
+  --> $DIR/pub_underscore_fields.rs:15:9
+   |
+LL |         pub _b: u8,
+   |         ^^^^^^
+   |
+   = help: consider removing the underscore, or making the field private
+   = note: `-D clippy::pub-underscore-fields` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::pub_underscore_fields)]`
+
+error: field marked as public but also inferred as unused because it's prefixed with `_`
+  --> $DIR/pub_underscore_fields.rs:23:13
+   |
+LL |             pub(in crate::inner) _f: Option<()>,
+   |             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider removing the underscore, or making the field private
+
+error: field marked as public but also inferred as unused because it's prefixed with `_`
+  --> $DIR/pub_underscore_fields.rs:27:13
+   |
+LL |             pub _g: String,
+   |             ^^^^^^
+   |
+   = help: consider removing the underscore, or making the field private
+
+error: field marked as public but also inferred as unused because it's prefixed with `_`
+  --> $DIR/pub_underscore_fields.rs:34:9
+   |
+LL |         pub _a: usize,
+   |         ^^^^^^
+   |
+   = help: consider removing the underscore, or making the field private
+
+error: field marked as public but also inferred as unused because it's prefixed with `_`
+  --> $DIR/pub_underscore_fields.rs:41:9
+   |
+LL |         pub _c: i64,
+   |         ^^^^^^
+   |
+   = help: consider removing the underscore, or making the field private
+
+error: field marked as public but also inferred as unused because it's prefixed with `_`
+  --> $DIR/pub_underscore_fields.rs:44:9
+   |
+LL |         pub _e: Option<u8>,
+   |         ^^^^^^
+   |
+   = help: consider removing the underscore, or making the field private
+
+error: field marked as public but also inferred as unused because it's prefixed with `_`
+  --> $DIR/pub_underscore_fields.rs:57:9
+   |
+LL |         pub(crate) _b: Option<String>,
+   |         ^^^^^^^^^^^^^
+   |
+   = help: consider removing the underscore, or making the field private
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.exported.stderr b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.exported.stderr
new file mode 100644
index 00000000000..b76f6b3d388
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.exported.stderr
@@ -0,0 +1,12 @@
+error: field marked as public but also inferred as unused because it's prefixed with `_`
+  --> $DIR/pub_underscore_fields.rs:15:9
+   |
+LL |         pub _b: u8,
+   |         ^^^^^^
+   |
+   = help: consider removing the underscore, or making the field private
+   = note: `-D clippy::pub-underscore-fields` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::pub_underscore_fields)]`
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs
new file mode 100644
index 00000000000..1d8fee7daad
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_underscore_fields/pub_underscore_fields.rs
@@ -0,0 +1,66 @@
+//@revisions: exported all_pub_fields
+//@[all_pub_fields] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/pub_underscore_fields/all_pub_fields
+//@[exported] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/pub_underscore_fields/exported
+
+#![allow(unused)]
+#![warn(clippy::pub_underscore_fields)]
+
+use std::marker::PhantomData;
+
+pub mod inner {
+    use std::marker;
+
+    pub struct PubSuper {
+        pub(super) a: usize,
+        pub _b: u8,
+        _c: i32,
+        pub _mark: marker::PhantomData<u8>,
+    }
+
+    mod inner2 {
+        pub struct PubModVisibility {
+            pub(in crate::inner) e: bool,
+            pub(in crate::inner) _f: Option<()>,
+        }
+
+        struct PrivateStructPubField {
+            pub _g: String,
+        }
+    }
+}
+
+fn main() {
+    pub struct StructWithOneViolation {
+        pub _a: usize,
+    }
+
+    // should handle structs with multiple violations
+    pub struct StructWithMultipleViolations {
+        a: u8,
+        _b: usize,
+        pub _c: i64,
+        #[doc(hidden)]
+        pub d: String,
+        pub _e: Option<u8>,
+    }
+
+    // shouldn't warn on anonymous fields
+    pub struct AnonymousFields(pub usize, i32);
+
+    // don't warn on empty structs
+    pub struct Empty1;
+    pub struct Empty2();
+    pub struct Empty3 {};
+
+    pub struct PubCrate {
+        pub(crate) a: String,
+        pub(crate) _b: Option<String>,
+    }
+
+    // shouldn't warn on fields named pub
+    pub struct NamedPub {
+        r#pub: bool,
+        _pub: String,
+        pub(crate) _mark: PhantomData<u8>,
+    }
+}
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 12828cf9dec..ed4fb84df1a 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
@@ -49,6 +49,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            missing-docs-in-crate-items
            msrv
            pass-by-value-size-limit
+           pub-underscore-fields-behavior
            semicolon-inside-block-ignore-singleline
            semicolon-outside-block-ignore-multiline
            single-char-binding-names-threshold
@@ -124,6 +125,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            missing-docs-in-crate-items
            msrv
            pass-by-value-size-limit
+           pub-underscore-fields-behavior
            semicolon-inside-block-ignore-singleline
            semicolon-outside-block-ignore-multiline
            single-char-binding-names-threshold
diff --git a/src/tools/clippy/tests/ui/as_conversions.rs b/src/tools/clippy/tests/ui/as_conversions.rs
index 192eb51ea99..8499c0ac5a0 100644
--- a/src/tools/clippy/tests/ui/as_conversions.rs
+++ b/src/tools/clippy/tests/ui/as_conversions.rs
@@ -17,7 +17,7 @@ fn main() {
 with_span!(
     span
 
-    fn coverting() {
+    fn converting() {
         let x = 0u32 as u64;
     }
 );
diff --git a/src/tools/clippy/tests/ui/cast.rs b/src/tools/clippy/tests/ui/cast.rs
index 1ca18170f8a..e9476c80ccb 100644
--- a/src/tools/clippy/tests/ui/cast.rs
+++ b/src/tools/clippy/tests/ui/cast.rs
@@ -365,3 +365,52 @@ fn avoid_subtract_overflow(q: u32) {
 fn issue11426() {
     (&42u8 >> 0xa9008fb6c9d81e42_0e25730562a601c8_u128) as usize;
 }
+
+fn issue11642() {
+    fn square(x: i16) -> u32 {
+        let x = x as i32;
+        (x * x) as u32;
+        x.pow(2) as u32;
+        (-2_i32).pow(2) as u32
+    }
+
+    let _a = |x: i32| -> u32 { (x * x * x * x) as u32 };
+
+    (-2_i32).pow(3) as u32;
+    //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
+
+    let x: i32 = 10;
+    (x * x) as u32;
+    (x * x * x) as u32;
+    //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
+
+    let y: i16 = -2;
+    (y * y * y * y * -2) as u16;
+    //~^ ERROR: casting `i16` to `u16` may lose the sign of the value
+    (y * y * y * y * 2) as u16;
+    (y * y * y * 2) as u16;
+    //~^ ERROR: casting `i16` to `u16` may lose the sign of the value
+    (y * y * y * -2) as u16;
+    //~^ ERROR: casting `i16` to `u16` may lose the sign of the value
+
+    fn foo(a: i32, b: i32, c: i32) -> u32 {
+        (a * a * b * b * c * c) as u32;
+        (a * b * c) as u32;
+        //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
+        (a * -b * c) as u32;
+        //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
+        (a * b * c * c) as u32;
+        (a * -2) as u32;
+        //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
+        (a * b * c * -2) as u32;
+        //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
+        (a / b) as u32;
+        (a / b * c) as u32;
+        //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
+        (a / b + b * c) as u32;
+        //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
+        a.pow(3) as u32;
+        //~^ ERROR: casting `i32` to `u32` may lose the sign of the value
+        (a.abs() * b.pow(2) / c.abs()) as u32
+    }
+}
diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr
index bc74f7b728e..4e37af7f378 100644
--- a/src/tools/clippy/tests/ui/cast.stderr
+++ b/src/tools/clippy/tests/ui/cast.stderr
@@ -444,5 +444,77 @@ help: ... or use `try_from` and handle the error accordingly
 LL |     let c = u8::try_from(q / 1000);
    |             ~~~~~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 51 previous errors
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:379:5
+   |
+LL |     (-2_i32).pow(3) as u32;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:384:5
+   |
+LL |     (x * x * x) as u32;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: casting `i16` to `u16` may lose the sign of the value
+  --> $DIR/cast.rs:388:5
+   |
+LL |     (y * y * y * y * -2) as u16;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `i16` to `u16` may lose the sign of the value
+  --> $DIR/cast.rs:391:5
+   |
+LL |     (y * y * y * 2) as u16;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `i16` to `u16` may lose the sign of the value
+  --> $DIR/cast.rs:393:5
+   |
+LL |     (y * y * y * -2) as u16;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:398:9
+   |
+LL |         (a * b * c) as u32;
+   |         ^^^^^^^^^^^^^^^^^^
+
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:400:9
+   |
+LL |         (a * -b * c) as u32;
+   |         ^^^^^^^^^^^^^^^^^^^
+
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:403:9
+   |
+LL |         (a * -2) as u32;
+   |         ^^^^^^^^^^^^^^^
+
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:405:9
+   |
+LL |         (a * b * c * -2) as u32;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:408:9
+   |
+LL |         (a / b * c) as u32;
+   |         ^^^^^^^^^^^^^^^^^^
+
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:410:9
+   |
+LL |         (a / b + b * c) as u32;
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `i32` to `u32` may lose the sign of the value
+  --> $DIR/cast.rs:412:9
+   |
+LL |         a.pow(3) as u32;
+   |         ^^^^^^^^^^^^^^^
+
+error: aborting due to 63 previous errors
 
diff --git a/src/tools/clippy/tests/ui/crashes/ice-8821.fixed b/src/tools/clippy/tests/ui/crashes/ice-8821.fixed
deleted file mode 100644
index a25bb46f9ff..00000000000
--- a/src/tools/clippy/tests/ui/crashes/ice-8821.fixed
+++ /dev/null
@@ -1,10 +0,0 @@
-#![warn(clippy::let_unit_value)]
-
-fn f() {}
-static FN: fn() = f;
-
-fn main() {
-    FN();
-    //~^ ERROR: this let-binding has unit value
-    //~| NOTE: `-D clippy::let-unit-value` implied by `-D warnings`
-}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-8821.rs b/src/tools/clippy/tests/ui/crashes/ice-8821.rs
index 082f7c92646..fb87b79aeed 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-8821.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-8821.rs
@@ -5,6 +5,4 @@ static FN: fn() = f;
 
 fn main() {
     let _: () = FN();
-    //~^ ERROR: this let-binding has unit value
-    //~| NOTE: `-D clippy::let-unit-value` implied by `-D warnings`
 }
diff --git a/src/tools/clippy/tests/ui/crashes/ice-8821.stderr b/src/tools/clippy/tests/ui/crashes/ice-8821.stderr
deleted file mode 100644
index 94ebb20918e..00000000000
--- a/src/tools/clippy/tests/ui/crashes/ice-8821.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: this let-binding has unit value
-  --> $DIR/ice-8821.rs:7:5
-   |
-LL |     let _: () = FN();
-   |     ^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `FN();`
-   |
-   = note: `-D clippy::let-unit-value` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
-
-error: aborting due to 1 previous error
-
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
index 9072d233563..00f0d764434 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
@@ -73,9 +73,7 @@ mod nested_local {
 
 mod function_def {
     fn ret_f64() -> f64 {
-        // Even though the output type is specified,
-        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
-        1.0_f64
+        1.
     }
 
     fn test() {
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
index 256b94f6c05..942cedac275 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
@@ -73,8 +73,6 @@ mod nested_local {
 
 mod function_def {
     fn ret_f64() -> f64 {
-        // Even though the output type is specified,
-        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
         1.
     }
 
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr
index 7ea2e3e6819..c95679c9eb8 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr
@@ -86,66 +86,60 @@ LL |             let y = 1.;
    |                     ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:78:9
-   |
-LL |         1.
-   |         ^^ help: consider adding suffix: `1.0_f64`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:84:27
+  --> $DIR/default_numeric_fallback_f64.rs:82:27
    |
 LL |         let f = || -> _ { 1. };
    |                           ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:88:29
+  --> $DIR/default_numeric_fallback_f64.rs:86:29
    |
 LL |         let f = || -> f64 { 1. };
    |                             ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:102:21
+  --> $DIR/default_numeric_fallback_f64.rs:100:21
    |
 LL |         generic_arg(1.);
    |                     ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:105:32
+  --> $DIR/default_numeric_fallback_f64.rs:103:32
    |
 LL |         let x: _ = generic_arg(1.);
    |                                ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:123:28
+  --> $DIR/default_numeric_fallback_f64.rs:121:28
    |
 LL |         GenericStruct { x: 1. };
    |                            ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:126:36
+  --> $DIR/default_numeric_fallback_f64.rs:124:36
    |
 LL |         let _ = GenericStruct { x: 1. };
    |                                    ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:144:24
+  --> $DIR/default_numeric_fallback_f64.rs:142:24
    |
 LL |         GenericEnum::X(1.);
    |                        ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:164:23
+  --> $DIR/default_numeric_fallback_f64.rs:162:23
    |
 LL |         s.generic_arg(1.);
    |                       ^^ help: consider adding suffix: `1.0_f64`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_f64.rs:174:25
+  --> $DIR/default_numeric_fallback_f64.rs:172:25
    |
 LL |         inline!(let x = 22.;);
    |                         ^^^ help: consider adding suffix: `22.0_f64`
    |
    = note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 24 previous errors
+error: aborting due to 23 previous errors
 
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
index 920cd9f8f77..c364c683057 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
@@ -74,9 +74,7 @@ mod nested_local {
 
 mod function_def {
     fn ret_i32() -> i32 {
-        // Even though the output type is specified,
-        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
-        1_i32
+        1
     }
 
     fn test() {
@@ -186,4 +184,36 @@ fn check_expect_suppression() {
     let x = 21;
 }
 
+mod type_already_inferred {
+    // Should NOT lint if bound to return type
+    fn ret_i32() -> i32 {
+        1
+    }
+
+    // Should NOT lint if bound to return type
+    fn ret_if_i32(b: bool) -> i32 {
+        if b { 100 } else { 0 }
+    }
+
+    // Should NOT lint if bound to return type
+    fn ret_i32_tuple() -> (i32, i32) {
+        (0, 1)
+    }
+
+    // Should NOT lint if bound to return type
+    fn ret_stmt(b: bool) -> (i32, i32) {
+        if b {
+            return (0, 1);
+        }
+        (0, 0)
+    }
+
+    #[allow(clippy::useless_vec)]
+    fn vec_macro() {
+        // Should NOT lint in `vec!` call if the type was already stated
+        let data_i32: Vec<i32> = vec![1, 2, 3];
+        let data_i32 = vec![1_i32, 2_i32, 3_i32];
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
index bdb7b5f47bc..ffa7b961d1c 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
@@ -74,8 +74,6 @@ mod nested_local {
 
 mod function_def {
     fn ret_i32() -> i32 {
-        // Even though the output type is specified,
-        // this unsuffixed literal is linted to reduce heuristics and keep codebase simple.
         1
     }
 
@@ -186,4 +184,36 @@ fn check_expect_suppression() {
     let x = 21;
 }
 
+mod type_already_inferred {
+    // Should NOT lint if bound to return type
+    fn ret_i32() -> i32 {
+        1
+    }
+
+    // Should NOT lint if bound to return type
+    fn ret_if_i32(b: bool) -> i32 {
+        if b { 100 } else { 0 }
+    }
+
+    // Should NOT lint if bound to return type
+    fn ret_i32_tuple() -> (i32, i32) {
+        (0, 1)
+    }
+
+    // Should NOT lint if bound to return type
+    fn ret_stmt(b: bool) -> (i32, i32) {
+        if b {
+            return (0, 1);
+        }
+        (0, 0)
+    }
+
+    #[allow(clippy::useless_vec)]
+    fn vec_macro() {
+        // Should NOT lint in `vec!` call if the type was already stated
+        let data_i32: Vec<i32> = vec![1, 2, 3];
+        let data_i32 = vec![1, 2, 3];
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr
index b03b8b84c33..7663977fb65 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr
@@ -98,66 +98,78 @@ LL |             let y = 1;
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:79:9
-   |
-LL |         1
-   |         ^ help: consider adding suffix: `1_i32`
-
-error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:85:27
+  --> $DIR/default_numeric_fallback_i32.rs:83:27
    |
 LL |         let f = || -> _ { 1 };
    |                           ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:89:29
+  --> $DIR/default_numeric_fallback_i32.rs:87:29
    |
 LL |         let f = || -> i32 { 1 };
    |                             ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:103:21
+  --> $DIR/default_numeric_fallback_i32.rs:101:21
    |
 LL |         generic_arg(1);
    |                     ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:106:32
+  --> $DIR/default_numeric_fallback_i32.rs:104:32
    |
 LL |         let x: _ = generic_arg(1);
    |                                ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:124:28
+  --> $DIR/default_numeric_fallback_i32.rs:122:28
    |
 LL |         GenericStruct { x: 1 };
    |                            ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:127:36
+  --> $DIR/default_numeric_fallback_i32.rs:125:36
    |
 LL |         let _ = GenericStruct { x: 1 };
    |                                    ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:145:24
+  --> $DIR/default_numeric_fallback_i32.rs:143:24
    |
 LL |         GenericEnum::X(1);
    |                        ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:165:23
+  --> $DIR/default_numeric_fallback_i32.rs:163:23
    |
 LL |         s.generic_arg(1);
    |                       ^ help: consider adding suffix: `1_i32`
 
 error: default numeric fallback might occur
-  --> $DIR/default_numeric_fallback_i32.rs:175:25
+  --> $DIR/default_numeric_fallback_i32.rs:173:25
    |
 LL |         inline!(let x = 22;);
    |                         ^^ help: consider adding suffix: `22_i32`
    |
    = note: this error originates in the macro `__inline_mac_fn_internal` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 26 previous errors
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:215:29
+   |
+LL |         let data_i32 = vec![1, 2, 3];
+   |                             ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:215:32
+   |
+LL |         let data_i32 = vec![1, 2, 3];
+   |                                ^ help: consider adding suffix: `2_i32`
+
+error: default numeric fallback might occur
+  --> $DIR/default_numeric_fallback_i32.rs:215:35
+   |
+LL |         let data_i32 = vec![1, 2, 3];
+   |                                   ^ help: consider adding suffix: `3_i32`
+
+error: aborting due to 28 previous errors
 
diff --git a/src/tools/clippy/tests/ui/eager_transmute.fixed b/src/tools/clippy/tests/ui/eager_transmute.fixed
index e06aa2cc9fd..bece09bba1a 100644
--- a/src/tools/clippy/tests/ui/eager_transmute.fixed
+++ b/src/tools/clippy/tests/ui/eager_transmute.fixed
@@ -12,16 +12,49 @@ enum Opcode {
     Div = 3,
 }
 
+struct Data {
+    foo: &'static [u8],
+    bar: &'static [u8],
+}
+
 fn int_to_opcode(op: u8) -> Option<Opcode> {
     (op < 4).then(|| unsafe { std::mem::transmute(op) })
 }
 
-fn f(op: u8, unrelated: u8) {
+fn f(op: u8, op2: Data, unrelated: u8) {
     true.then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
     (unrelated < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
     (op < 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
     (op > 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
     (op == 0).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
+
+    let _: Option<Opcode> = (op > 0 && op < 10).then(|| unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (op > 0 && op < 10 && unrelated == 0).then(|| unsafe { std::mem::transmute(op) });
+
+    // lint even when the transmutable goes through field/array accesses
+    let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then(|| unsafe { std::mem::transmute(op2.foo[0]) });
+
+    // don't lint: wrong index used in the transmute
+    let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[1]) });
+
+    // don't lint: no check for the transmutable in the condition
+    let _: Option<Opcode> = (op2.foo[0] > 0 && op2.bar[1] < 10).then_some(unsafe { std::mem::transmute(op2.bar[0]) });
+
+    // don't lint: wrong variable
+    let _: Option<Opcode> = (op2.foo[0] > 0 && op2.bar[1] < 10).then_some(unsafe { std::mem::transmute(op) });
+
+    // range contains checks
+    let _: Option<Opcode> = (1..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = ((1..=3).contains(&op) || op == 4).then(|| unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (1..3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (1..).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (..3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+
+    // unrelated binding in contains
+    let _: Option<Opcode> = (1..=3)
+        .contains(&unrelated)
+        .then_some(unsafe { std::mem::transmute(op) });
 }
 
 unsafe fn f2(op: u8) {
diff --git a/src/tools/clippy/tests/ui/eager_transmute.rs b/src/tools/clippy/tests/ui/eager_transmute.rs
index 89ccdf583f3..a82bd578f76 100644
--- a/src/tools/clippy/tests/ui/eager_transmute.rs
+++ b/src/tools/clippy/tests/ui/eager_transmute.rs
@@ -12,16 +12,49 @@ enum Opcode {
     Div = 3,
 }
 
+struct Data {
+    foo: &'static [u8],
+    bar: &'static [u8],
+}
+
 fn int_to_opcode(op: u8) -> Option<Opcode> {
     (op < 4).then_some(unsafe { std::mem::transmute(op) })
 }
 
-fn f(op: u8, unrelated: u8) {
+fn f(op: u8, op2: Data, unrelated: u8) {
     true.then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
     (unrelated < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
     (op < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
     (op > 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
     (op == 0).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
+
+    let _: Option<Opcode> = (op > 0 && op < 10).then_some(unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (op > 0 && op < 10 && unrelated == 0).then_some(unsafe { std::mem::transmute(op) });
+
+    // lint even when the transmutable goes through field/array accesses
+    let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[0]) });
+
+    // don't lint: wrong index used in the transmute
+    let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[1]) });
+
+    // don't lint: no check for the transmutable in the condition
+    let _: Option<Opcode> = (op2.foo[0] > 0 && op2.bar[1] < 10).then_some(unsafe { std::mem::transmute(op2.bar[0]) });
+
+    // don't lint: wrong variable
+    let _: Option<Opcode> = (op2.foo[0] > 0 && op2.bar[1] < 10).then_some(unsafe { std::mem::transmute(op) });
+
+    // range contains checks
+    let _: Option<Opcode> = (1..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = ((1..=3).contains(&op) || op == 4).then_some(unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (1..3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (1..).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (..3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+    let _: Option<Opcode> = (..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+
+    // unrelated binding in contains
+    let _: Option<Opcode> = (1..=3)
+        .contains(&unrelated)
+        .then_some(unsafe { std::mem::transmute(op) });
 }
 
 unsafe fn f2(op: u8) {
diff --git a/src/tools/clippy/tests/ui/eager_transmute.stderr b/src/tools/clippy/tests/ui/eager_transmute.stderr
index 5eb163c5fcb..5f42eec544f 100644
--- a/src/tools/clippy/tests/ui/eager_transmute.stderr
+++ b/src/tools/clippy/tests/ui/eager_transmute.stderr
@@ -1,5 +1,5 @@
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> $DIR/eager_transmute.rs:16:33
+  --> $DIR/eager_transmute.rs:21:33
    |
 LL |     (op < 4).then_some(unsafe { std::mem::transmute(op) })
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^
@@ -12,7 +12,7 @@ LL |     (op < 4).then(|| unsafe { std::mem::transmute(op) })
    |              ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> $DIR/eager_transmute.rs:22:33
+  --> $DIR/eager_transmute.rs:27:33
    |
 LL |     (op < 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL |     (op < 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
    |              ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> $DIR/eager_transmute.rs:23:33
+  --> $DIR/eager_transmute.rs:28:33
    |
 LL |     (op > 4).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,7 +34,7 @@ LL |     (op > 4).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
    |              ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> $DIR/eager_transmute.rs:24:34
+  --> $DIR/eager_transmute.rs:29:34
    |
 LL |     (op == 0).then_some(unsafe { std::mem::transmute::<_, Opcode>(op) });
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +45,106 @@ LL |     (op == 0).then(|| unsafe { std::mem::transmute::<_, Opcode>(op) });
    |               ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> $DIR/eager_transmute.rs:28:24
+  --> $DIR/eager_transmute.rs:31:68
+   |
+LL |     let _: Option<Opcode> = (op > 0 && op < 10).then_some(unsafe { std::mem::transmute(op) });
+   |                                                                    ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `bool::then` to only transmute if the condition holds
+   |
+LL |     let _: Option<Opcode> = (op > 0 && op < 10).then(|| unsafe { std::mem::transmute(op) });
+   |                                                 ~~~~ ++
+
+error: this transmute is always evaluated eagerly, even if the condition is false
+  --> $DIR/eager_transmute.rs:32:86
+   |
+LL |     let _: Option<Opcode> = (op > 0 && op < 10 && unrelated == 0).then_some(unsafe { std::mem::transmute(op) });
+   |                                                                                      ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `bool::then` to only transmute if the condition holds
+   |
+LL |     let _: Option<Opcode> = (op > 0 && op < 10 && unrelated == 0).then(|| unsafe { std::mem::transmute(op) });
+   |                                                                   ~~~~ ++
+
+error: this transmute is always evaluated eagerly, even if the condition is false
+  --> $DIR/eager_transmute.rs:35:84
+   |
+LL |     let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then_some(unsafe { std::mem::transmute(op2.foo[0]) });
+   |                                                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `bool::then` to only transmute if the condition holds
+   |
+LL |     let _: Option<Opcode> = (op2.foo[0] > 0 && op2.foo[0] < 10).then(|| unsafe { std::mem::transmute(op2.foo[0]) });
+   |                                                                 ~~~~ ++
+
+error: this transmute is always evaluated eagerly, even if the condition is false
+  --> $DIR/eager_transmute.rs:47:70
+   |
+LL |     let _: Option<Opcode> = (1..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+   |                                                                      ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `bool::then` to only transmute if the condition holds
+   |
+LL |     let _: Option<Opcode> = (1..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+   |                                                   ~~~~ ++
+
+error: this transmute is always evaluated eagerly, even if the condition is false
+  --> $DIR/eager_transmute.rs:48:83
+   |
+LL |     let _: Option<Opcode> = ((1..=3).contains(&op) || op == 4).then_some(unsafe { std::mem::transmute(op) });
+   |                                                                                   ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `bool::then` to only transmute if the condition holds
+   |
+LL |     let _: Option<Opcode> = ((1..=3).contains(&op) || op == 4).then(|| unsafe { std::mem::transmute(op) });
+   |                                                                ~~~~ ++
+
+error: this transmute is always evaluated eagerly, even if the condition is false
+  --> $DIR/eager_transmute.rs:49:69
+   |
+LL |     let _: Option<Opcode> = (1..3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+   |                                                                     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `bool::then` to only transmute if the condition holds
+   |
+LL |     let _: Option<Opcode> = (1..3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+   |                                                  ~~~~ ++
+
+error: this transmute is always evaluated eagerly, even if the condition is false
+  --> $DIR/eager_transmute.rs:50:68
+   |
+LL |     let _: Option<Opcode> = (1..).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+   |                                                                    ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `bool::then` to only transmute if the condition holds
+   |
+LL |     let _: Option<Opcode> = (1..).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+   |                                                 ~~~~ ++
+
+error: this transmute is always evaluated eagerly, even if the condition is false
+  --> $DIR/eager_transmute.rs:51:68
+   |
+LL |     let _: Option<Opcode> = (..3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+   |                                                                    ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `bool::then` to only transmute if the condition holds
+   |
+LL |     let _: Option<Opcode> = (..3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+   |                                                 ~~~~ ++
+
+error: this transmute is always evaluated eagerly, even if the condition is false
+  --> $DIR/eager_transmute.rs:52:69
+   |
+LL |     let _: Option<Opcode> = (..=3).contains(&op).then_some(unsafe { std::mem::transmute(op) });
+   |                                                                     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: consider using `bool::then` to only transmute if the condition holds
+   |
+LL |     let _: Option<Opcode> = (..=3).contains(&op).then(|| unsafe { std::mem::transmute(op) });
+   |                                                  ~~~~ ++
+
+error: this transmute is always evaluated eagerly, even if the condition is false
+  --> $DIR/eager_transmute.rs:61:24
    |
 LL |     (op < 4).then_some(std::mem::transmute::<_, Opcode>(op));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -56,7 +155,7 @@ LL |     (op < 4).then(|| std::mem::transmute::<_, Opcode>(op));
    |              ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> $DIR/eager_transmute.rs:57:60
+  --> $DIR/eager_transmute.rs:90:60
    |
 LL |     let _: Option<NonZeroU8> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
    |                                                            ^^^^^^^^^^^^^^^^^^^^^^^
@@ -67,7 +166,7 @@ LL |     let _: Option<NonZeroU8> = (v1 > 0).then(|| unsafe { std::mem::transmut
    |                                         ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> $DIR/eager_transmute.rs:63:86
+  --> $DIR/eager_transmute.rs:96:86
    |
 LL |     let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
    |                                                                                      ^^^^^^^^^^^^^^^^^^^^^^^
@@ -78,7 +177,7 @@ LL |     let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| u
    |                                                                   ~~~~ ++
 
 error: this transmute is always evaluated eagerly, even if the condition is false
-  --> $DIR/eager_transmute.rs:69:93
+  --> $DIR/eager_transmute.rs:102:93
    |
 LL |     let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
    |                                                                                             ^^^^^^^^^^^^^^^^^^^^^^^
@@ -88,5 +187,5 @@ help: consider using `bool::then` to only transmute if the condition holds
 LL |     let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
    |                                                                          ~~~~ ++
 
-error: aborting due to 8 previous errors
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.fixed b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.fixed
new file mode 100644
index 00000000000..1a5e78dd47f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.fixed
@@ -0,0 +1,27 @@
+#![warn(clippy::empty_enum_variants_with_brackets)]
+#![allow(dead_code)]
+
+pub enum PublicTestEnum {
+    NonEmptyBraces { x: i32, y: i32 }, // No error
+    NonEmptyParentheses(i32, i32),     // No error
+    EmptyBraces,                    //~ ERROR: enum variant has empty brackets
+    EmptyParentheses,                //~ ERROR: enum variant has empty brackets
+}
+
+enum TestEnum {
+    NonEmptyBraces { x: i32, y: i32 }, // No error
+    NonEmptyParentheses(i32, i32),     // No error
+    EmptyBraces,                    //~ ERROR: enum variant has empty brackets
+    EmptyParentheses,                //~ ERROR: enum variant has empty brackets
+    AnotherEnum,                       // No error
+}
+
+enum TestEnumWithFeatures {
+    NonEmptyBraces {
+        #[cfg(feature = "thisisneverenabled")]
+        x: i32,
+    }, // No error
+    NonEmptyParentheses(#[cfg(feature = "thisisneverenabled")] i32), // No error
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.rs b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.rs
new file mode 100644
index 00000000000..ca20b969a24
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.rs
@@ -0,0 +1,27 @@
+#![warn(clippy::empty_enum_variants_with_brackets)]
+#![allow(dead_code)]
+
+pub enum PublicTestEnum {
+    NonEmptyBraces { x: i32, y: i32 }, // No error
+    NonEmptyParentheses(i32, i32),     // No error
+    EmptyBraces {},                    //~ ERROR: enum variant has empty brackets
+    EmptyParentheses(),                //~ ERROR: enum variant has empty brackets
+}
+
+enum TestEnum {
+    NonEmptyBraces { x: i32, y: i32 }, // No error
+    NonEmptyParentheses(i32, i32),     // No error
+    EmptyBraces {},                    //~ ERROR: enum variant has empty brackets
+    EmptyParentheses(),                //~ ERROR: enum variant has empty brackets
+    AnotherEnum,                       // No error
+}
+
+enum TestEnumWithFeatures {
+    NonEmptyBraces {
+        #[cfg(feature = "thisisneverenabled")]
+        x: i32,
+    }, // No error
+    NonEmptyParentheses(#[cfg(feature = "thisisneverenabled")] i32), // No error
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.stderr b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.stderr
new file mode 100644
index 00000000000..6b2f286147f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/empty_enum_variants_with_brackets.stderr
@@ -0,0 +1,36 @@
+error: enum variant has empty brackets
+  --> $DIR/empty_enum_variants_with_brackets.rs:7:16
+   |
+LL |     EmptyBraces {},
+   |                ^^^
+   |
+   = note: `-D clippy::empty-enum-variants-with-brackets` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::empty_enum_variants_with_brackets)]`
+   = help: remove the brackets
+
+error: enum variant has empty brackets
+  --> $DIR/empty_enum_variants_with_brackets.rs:8:21
+   |
+LL |     EmptyParentheses(),
+   |                     ^^
+   |
+   = help: remove the brackets
+
+error: enum variant has empty brackets
+  --> $DIR/empty_enum_variants_with_brackets.rs:14:16
+   |
+LL |     EmptyBraces {},
+   |                ^^^
+   |
+   = help: remove the brackets
+
+error: enum variant has empty brackets
+  --> $DIR/empty_enum_variants_with_brackets.rs:15:21
+   |
+LL |     EmptyParentheses(),
+   |                     ^^
+   |
+   = help: remove the brackets
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/identity_op.fixed b/src/tools/clippy/tests/ui/identity_op.fixed
index f3b4b1fffa0..660e9a21b18 100644
--- a/src/tools/clippy/tests/ui/identity_op.fixed
+++ b/src/tools/clippy/tests/ui/identity_op.fixed
@@ -6,7 +6,9 @@
     clippy::unnecessary_operation,
     clippy::op_ref,
     clippy::double_parens,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::borrow_deref_ref,
+    clippy::deref_addrof
 )]
 
 use std::fmt::Write as _;
@@ -40,32 +42,45 @@ fn main() {
     let x = 0;
 
     x;
+    //~^ ERROR: this operation has no effect
     x;
+    //~^ ERROR: this operation has no effect
     x + 1;
     x;
+    //~^ ERROR: this operation has no effect
     1 + x;
     x - ZERO; //no error, as we skip lookups (for now)
     x;
+    //~^ ERROR: this operation has no effect
     ((ZERO)) | x; //no error, as we skip lookups (for now)
 
     x;
+    //~^ ERROR: this operation has no effect
     x;
+    //~^ ERROR: this operation has no effect
     x / ONE; //no error, as we skip lookups (for now)
 
     x / 2; //no false positive
 
     x & NEG_ONE; //no error, as we skip lookups (for now)
     x;
+    //~^ ERROR: this operation has no effect
 
     let u: u8 = 0;
     u;
+    //~^ ERROR: this operation has no effect
 
     1 << 0; // no error, this case is allowed, see issue 3430
     42;
+    //~^ ERROR: this operation has no effect
     1;
+    //~^ ERROR: this operation has no effect
     42;
+    //~^ ERROR: this operation has no effect
     x;
+    //~^ ERROR: this operation has no effect
     x;
+    //~^ ERROR: this operation has no effect
 
     let mut a = A(String::new());
     let b = a << 0; // no error: non-integer
@@ -73,10 +88,15 @@ fn main() {
     1 * Meter; // no error: non-integer
 
     2;
+    //~^ ERROR: this operation has no effect
     -2;
+    //~^ ERROR: this operation has no effect
     2 + x;
+    //~^ ERROR: this operation has no effect
     -2 + x;
+    //~^ ERROR: this operation has no effect
     x + 1;
+    //~^ ERROR: this operation has no effect
     (x + 1) % 3; // no error
     4 % 3; // no error
     4 % -3; // no error
@@ -85,38 +105,110 @@ fn main() {
     let a = 0;
     let b = true;
     (if b { 1 } else { 2 });
+    //~^ ERROR: this operation has no effect
     (if b { 1 } else { 2 }) + if b { 3 } else { 4 };
+    //~^ ERROR: this operation has no effect
     (match a { 0 => 10, _ => 20 });
+    //~^ ERROR: this operation has no effect
     (match a { 0 => 10, _ => 20 }) + match a { 0 => 30, _ => 40 };
+    //~^ ERROR: this operation has no effect
     (if b { 1 } else { 2 }) + match a { 0 => 30, _ => 40 };
+    //~^ ERROR: this operation has no effect
     (match a { 0 => 10, _ => 20 }) + if b { 3 } else { 4 };
+    //~^ ERROR: this operation has no effect
     (if b { 1 } else { 2 });
+    //~^ ERROR: this operation has no effect
 
     ({ a }) + 3;
+    //~^ ERROR: this operation has no effect
     ({ a } * 2);
+    //~^ ERROR: this operation has no effect
     (loop { let mut c = 0; if c == 10 { break c; } c += 1; }) + { a * 2 };
+    //~^ ERROR: this operation has no effect
 
     fn f(_: i32) {
         todo!();
     }
+
     f(a + { 8 * 5 });
+    //~^ ERROR: this operation has no effect
     f(if b { 1 } else { 2 } + 3);
+    //~^ ERROR: this operation has no effect
+    
     const _: i32 = { 2 * 4 } + 3;
+    //~^ ERROR: this operation has no effect
     const _: i32 = { 1 + 2 * 3 } + 3;
+    //~^ ERROR: this operation has no effect
 
     a as usize;
+    //~^ ERROR: this operation has no effect
     let _ = a as usize;
+    //~^ ERROR: this operation has no effect
     ({ a } as usize);
+    //~^ ERROR: this operation has no effect
 
     2 * { a };
+    //~^ ERROR: this operation has no effect
     (({ a } + 4));
+    //~^ ERROR: this operation has no effect
     1;
+    //~^ ERROR: this operation has no effect
 
     // Issue #9904
     let x = 0i32;
     let _: i32 = x;
+    //~^ ERROR: this operation has no effect
 }
 
 pub fn decide(a: bool, b: bool) -> u32 {
     (if a { 1 } else { 2 }) + if b { 3 } else { 5 }
 }
+
+/// The following tests are from / for issue #12050
+/// In short, the lint didn't work for coerced references,
+/// e.g. let x = &0; let y = x + 0;
+/// because the suggested fix was `let y = x;` but
+/// it should have been `let y = *x;`
+fn issue_12050() {
+    {
+        let x = &0i32;
+        let _: i32 = *x;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = *x;
+        //~^ ERROR: this operation has no effect
+    }
+    {
+        let x = &&0i32;
+        let _: i32 = **x;
+        //~^ ERROR: this operation has no effect
+        let x = &&0i32;
+        let _: i32 = **x;
+        //~^ ERROR: this operation has no effect
+    }
+    {
+        // this is just silly
+        let x = &&&0i32;
+        let _: i32 = ***x;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = ***x;
+        //~^ ERROR: this operation has no effect
+        let x = 0i32;
+        let _: i32 = *&x;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = **&&x;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = *&*&x;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = **&&*&x;
+        //~^ ERROR: this operation has no effect
+    }
+    {
+        // this is getting ridiculous, but we should still see the same
+        // error message so let's just keep going
+        let x = &0i32;
+        let _: i32 = ***&&*&x;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = ***&&*&x;
+        //~^ ERROR: this operation has no effect
+    }
+}
diff --git a/src/tools/clippy/tests/ui/identity_op.rs b/src/tools/clippy/tests/ui/identity_op.rs
index 631aa3b0215..bbef531e9dc 100644
--- a/src/tools/clippy/tests/ui/identity_op.rs
+++ b/src/tools/clippy/tests/ui/identity_op.rs
@@ -6,7 +6,9 @@
     clippy::unnecessary_operation,
     clippy::op_ref,
     clippy::double_parens,
-    clippy::uninlined_format_args
+    clippy::uninlined_format_args,
+    clippy::borrow_deref_ref,
+    clippy::deref_addrof
 )]
 
 use std::fmt::Write as _;
@@ -40,32 +42,45 @@ fn main() {
     let x = 0;
 
     x + 0;
+    //~^ ERROR: this operation has no effect
     x + (1 - 1);
+    //~^ ERROR: this operation has no effect
     x + 1;
     0 + x;
+    //~^ ERROR: this operation has no effect
     1 + x;
     x - ZERO; //no error, as we skip lookups (for now)
     x | (0);
+    //~^ ERROR: this operation has no effect
     ((ZERO)) | x; //no error, as we skip lookups (for now)
 
     x * 1;
+    //~^ ERROR: this operation has no effect
     1 * x;
+    //~^ ERROR: this operation has no effect
     x / ONE; //no error, as we skip lookups (for now)
 
     x / 2; //no false positive
 
     x & NEG_ONE; //no error, as we skip lookups (for now)
     -1 & x;
+    //~^ ERROR: this operation has no effect
 
     let u: u8 = 0;
     u & 255;
+    //~^ ERROR: this operation has no effect
 
     1 << 0; // no error, this case is allowed, see issue 3430
     42 << 0;
+    //~^ ERROR: this operation has no effect
     1 >> 0;
+    //~^ ERROR: this operation has no effect
     42 >> 0;
+    //~^ ERROR: this operation has no effect
     &x >> 0;
+    //~^ ERROR: this operation has no effect
     x >> &0;
+    //~^ ERROR: this operation has no effect
 
     let mut a = A(String::new());
     let b = a << 0; // no error: non-integer
@@ -73,10 +88,15 @@ fn main() {
     1 * Meter; // no error: non-integer
 
     2 % 3;
+    //~^ ERROR: this operation has no effect
     -2 % 3;
+    //~^ ERROR: this operation has no effect
     2 % -3 + x;
+    //~^ ERROR: this operation has no effect
     -2 % -3 + x;
+    //~^ ERROR: this operation has no effect
     x + 1 % 3;
+    //~^ ERROR: this operation has no effect
     (x + 1) % 3; // no error
     4 % 3; // no error
     4 % -3; // no error
@@ -85,38 +105,110 @@ fn main() {
     let a = 0;
     let b = true;
     0 + if b { 1 } else { 2 };
+    //~^ ERROR: this operation has no effect
     0 + if b { 1 } else { 2 } + if b { 3 } else { 4 };
+    //~^ ERROR: this operation has no effect
     0 + match a { 0 => 10, _ => 20 };
+    //~^ ERROR: this operation has no effect
     0 + match a { 0 => 10, _ => 20 } + match a { 0 => 30, _ => 40 };
+    //~^ ERROR: this operation has no effect
     0 + if b { 1 } else { 2 } + match a { 0 => 30, _ => 40 };
+    //~^ ERROR: this operation has no effect
     0 + match a { 0 => 10, _ => 20 } + if b { 3 } else { 4 };
+    //~^ ERROR: this operation has no effect
     (if b { 1 } else { 2 }) + 0;
+    //~^ ERROR: this operation has no effect
 
     0 + { a } + 3;
+    //~^ ERROR: this operation has no effect
     0 + { a } * 2;
+    //~^ ERROR: this operation has no effect
     0 + loop { let mut c = 0; if c == 10 { break c; } c += 1; } + { a * 2 };
+    //~^ ERROR: this operation has no effect
 
     fn f(_: i32) {
         todo!();
     }
+
     f(1 * a + { 8 * 5 });
+    //~^ ERROR: this operation has no effect
     f(0 + if b { 1 } else { 2 } + 3);
+    //~^ ERROR: this operation has no effect
+    
     const _: i32 = { 2 * 4 } + 0 + 3;
+    //~^ ERROR: this operation has no effect
     const _: i32 = 0 + { 1 + 2 * 3 } + 3;
+    //~^ ERROR: this operation has no effect
 
     0 + a as usize;
+    //~^ ERROR: this operation has no effect
     let _ = 0 + a as usize;
+    //~^ ERROR: this operation has no effect
     0 + { a } as usize;
+    //~^ ERROR: this operation has no effect
 
     2 * (0 + { a });
+    //~^ ERROR: this operation has no effect
     1 * ({ a } + 4);
+    //~^ ERROR: this operation has no effect
     1 * 1;
+    //~^ ERROR: this operation has no effect
 
     // Issue #9904
     let x = 0i32;
     let _: i32 = &x + 0;
+    //~^ ERROR: this operation has no effect
 }
 
 pub fn decide(a: bool, b: bool) -> u32 {
     0 + if a { 1 } else { 2 } + if b { 3 } else { 5 }
 }
+
+/// The following tests are from / for issue #12050
+/// In short, the lint didn't work for coerced references,
+/// e.g. let x = &0; let y = x + 0;
+/// because the suggested fix was `let y = x;` but
+/// it should have been `let y = *x;`
+fn issue_12050() {
+    {
+        let x = &0i32;
+        let _: i32 = *x + 0;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = x + 0;
+        //~^ ERROR: this operation has no effect
+    }
+    {
+        let x = &&0i32;
+        let _: i32 = **x + 0;
+        //~^ ERROR: this operation has no effect
+        let x = &&0i32;
+        let _: i32 = *x + 0;
+        //~^ ERROR: this operation has no effect
+    }
+    {
+        // this is just silly
+        let x = &&&0i32;
+        let _: i32 = ***x + 0;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = **x + 0;
+        //~^ ERROR: this operation has no effect
+        let x = 0i32;
+        let _: i32 = *&x + 0;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = **&&x + 0;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = *&*&x + 0;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = **&&*&x + 0;
+        //~^ ERROR: this operation has no effect
+    }
+    {
+        // this is getting ridiculous, but we should still see the same
+        // error message so let's just keep going
+        let x = &0i32;
+        let _: i32 = **&&*&x + 0;
+        //~^ ERROR: this operation has no effect
+        let _: i32 = **&&*&x + 0;
+        //~^ ERROR: this operation has no effect
+    }
+}
diff --git a/src/tools/clippy/tests/ui/identity_op.stderr b/src/tools/clippy/tests/ui/identity_op.stderr
index 2a61327f15f..6bb980035c1 100644
--- a/src/tools/clippy/tests/ui/identity_op.stderr
+++ b/src/tools/clippy/tests/ui/identity_op.stderr
@@ -1,5 +1,5 @@
 error: this operation has no effect
-  --> $DIR/identity_op.rs:42:5
+  --> $DIR/identity_op.rs:44:5
    |
 LL |     x + 0;
    |     ^^^^^ help: consider reducing it to: `x`
@@ -8,238 +8,310 @@ LL |     x + 0;
    = help: to override `-D warnings` add `#[allow(clippy::identity_op)]`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:43:5
+  --> $DIR/identity_op.rs:46:5
    |
 LL |     x + (1 - 1);
    |     ^^^^^^^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:45:5
+  --> $DIR/identity_op.rs:49:5
    |
 LL |     0 + x;
    |     ^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:48:5
+  --> $DIR/identity_op.rs:53:5
    |
 LL |     x | (0);
    |     ^^^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:51:5
+  --> $DIR/identity_op.rs:57:5
    |
 LL |     x * 1;
    |     ^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:52:5
+  --> $DIR/identity_op.rs:59:5
    |
 LL |     1 * x;
    |     ^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:58:5
+  --> $DIR/identity_op.rs:66:5
    |
 LL |     -1 & x;
    |     ^^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:61:5
+  --> $DIR/identity_op.rs:70:5
    |
 LL |     u & 255;
    |     ^^^^^^^ help: consider reducing it to: `u`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:64:5
+  --> $DIR/identity_op.rs:74:5
    |
 LL |     42 << 0;
    |     ^^^^^^^ help: consider reducing it to: `42`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:65:5
+  --> $DIR/identity_op.rs:76:5
    |
 LL |     1 >> 0;
    |     ^^^^^^ help: consider reducing it to: `1`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:66:5
+  --> $DIR/identity_op.rs:78:5
    |
 LL |     42 >> 0;
    |     ^^^^^^^ help: consider reducing it to: `42`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:67:5
+  --> $DIR/identity_op.rs:80:5
    |
 LL |     &x >> 0;
    |     ^^^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:68:5
+  --> $DIR/identity_op.rs:82:5
    |
 LL |     x >> &0;
    |     ^^^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:75:5
+  --> $DIR/identity_op.rs:90:5
    |
 LL |     2 % 3;
    |     ^^^^^ help: consider reducing it to: `2`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:76:5
+  --> $DIR/identity_op.rs:92:5
    |
 LL |     -2 % 3;
    |     ^^^^^^ help: consider reducing it to: `-2`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:77:5
+  --> $DIR/identity_op.rs:94:5
    |
 LL |     2 % -3 + x;
    |     ^^^^^^ help: consider reducing it to: `2`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:78:5
+  --> $DIR/identity_op.rs:96:5
    |
 LL |     -2 % -3 + x;
    |     ^^^^^^^ help: consider reducing it to: `-2`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:79:9
+  --> $DIR/identity_op.rs:98:9
    |
 LL |     x + 1 % 3;
    |         ^^^^^ help: consider reducing it to: `1`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:87:5
+  --> $DIR/identity_op.rs:107:5
    |
 LL |     0 + if b { 1 } else { 2 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:88:5
+  --> $DIR/identity_op.rs:109:5
    |
 LL |     0 + if b { 1 } else { 2 } + if b { 3 } else { 4 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:89:5
+  --> $DIR/identity_op.rs:111:5
    |
 LL |     0 + match a { 0 => 10, _ => 20 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:90:5
+  --> $DIR/identity_op.rs:113:5
    |
 LL |     0 + match a { 0 => 10, _ => 20 } + match a { 0 => 30, _ => 40 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:91:5
+  --> $DIR/identity_op.rs:115:5
    |
 LL |     0 + if b { 1 } else { 2 } + match a { 0 => 30, _ => 40 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:92:5
+  --> $DIR/identity_op.rs:117:5
    |
 LL |     0 + match a { 0 => 10, _ => 20 } + if b { 3 } else { 4 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(match a { 0 => 10, _ => 20 })`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:93:5
+  --> $DIR/identity_op.rs:119:5
    |
 LL |     (if b { 1 } else { 2 }) + 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if b { 1 } else { 2 })`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:95:5
+  --> $DIR/identity_op.rs:122:5
    |
 LL |     0 + { a } + 3;
    |     ^^^^^^^^^ help: consider reducing it to: `({ a })`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:96:5
+  --> $DIR/identity_op.rs:124:5
    |
 LL |     0 + { a } * 2;
    |     ^^^^^^^^^^^^^ help: consider reducing it to: `({ a } * 2)`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:97:5
+  --> $DIR/identity_op.rs:126:5
    |
 LL |     0 + loop { let mut c = 0; if c == 10 { break c; } c += 1; } + { a * 2 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(loop { let mut c = 0; if c == 10 { break c; } c += 1; })`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:102:7
+  --> $DIR/identity_op.rs:133:7
    |
 LL |     f(1 * a + { 8 * 5 });
    |       ^^^^^ help: consider reducing it to: `a`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:103:7
+  --> $DIR/identity_op.rs:135:7
    |
 LL |     f(0 + if b { 1 } else { 2 } + 3);
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `if b { 1 } else { 2 }`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:104:20
+  --> $DIR/identity_op.rs:138:20
    |
 LL |     const _: i32 = { 2 * 4 } + 0 + 3;
    |                    ^^^^^^^^^^^^^ help: consider reducing it to: `{ 2 * 4 }`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:105:20
+  --> $DIR/identity_op.rs:140:20
    |
 LL |     const _: i32 = 0 + { 1 + 2 * 3 } + 3;
    |                    ^^^^^^^^^^^^^^^^^ help: consider reducing it to: `{ 1 + 2 * 3 }`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:107:5
+  --> $DIR/identity_op.rs:143:5
    |
 LL |     0 + a as usize;
    |     ^^^^^^^^^^^^^^ help: consider reducing it to: `a as usize`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:108:13
+  --> $DIR/identity_op.rs:145:13
    |
 LL |     let _ = 0 + a as usize;
    |             ^^^^^^^^^^^^^^ help: consider reducing it to: `a as usize`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:109:5
+  --> $DIR/identity_op.rs:147:5
    |
 LL |     0 + { a } as usize;
    |     ^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `({ a } as usize)`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:111:9
+  --> $DIR/identity_op.rs:150:9
    |
 LL |     2 * (0 + { a });
    |         ^^^^^^^^^^^ help: consider reducing it to: `{ a }`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:112:5
+  --> $DIR/identity_op.rs:152:5
    |
 LL |     1 * ({ a } + 4);
    |     ^^^^^^^^^^^^^^^ help: consider reducing it to: `(({ a } + 4))`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:113:5
+  --> $DIR/identity_op.rs:154:5
    |
 LL |     1 * 1;
    |     ^^^^^ help: consider reducing it to: `1`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:117:18
+  --> $DIR/identity_op.rs:159:18
    |
 LL |     let _: i32 = &x + 0;
    |                  ^^^^^^ help: consider reducing it to: `x`
 
 error: this operation has no effect
-  --> $DIR/identity_op.rs:121:5
+  --> $DIR/identity_op.rs:164:5
    |
 LL |     0 + if a { 1 } else { 2 } + if b { 3 } else { 5 }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `(if a { 1 } else { 2 })`
 
-error: aborting due to 40 previous errors
+error: this operation has no effect
+  --> $DIR/identity_op.rs:175:22
+   |
+LL |         let _: i32 = *x + 0;
+   |                      ^^^^^^ help: consider reducing it to: `*x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:177:22
+   |
+LL |         let _: i32 = x + 0;
+   |                      ^^^^^ help: consider reducing it to: `*x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:182:22
+   |
+LL |         let _: i32 = **x + 0;
+   |                      ^^^^^^^ help: consider reducing it to: `**x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:185:22
+   |
+LL |         let _: i32 = *x + 0;
+   |                      ^^^^^^ help: consider reducing it to: `**x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:191:22
+   |
+LL |         let _: i32 = ***x + 0;
+   |                      ^^^^^^^^ help: consider reducing it to: `***x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:193:22
+   |
+LL |         let _: i32 = **x + 0;
+   |                      ^^^^^^^ help: consider reducing it to: `***x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:196:22
+   |
+LL |         let _: i32 = *&x + 0;
+   |                      ^^^^^^^ help: consider reducing it to: `*&x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:198:22
+   |
+LL |         let _: i32 = **&&x + 0;
+   |                      ^^^^^^^^^ help: consider reducing it to: `**&&x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:200:22
+   |
+LL |         let _: i32 = *&*&x + 0;
+   |                      ^^^^^^^^^ help: consider reducing it to: `*&*&x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:202:22
+   |
+LL |         let _: i32 = **&&*&x + 0;
+   |                      ^^^^^^^^^^^ help: consider reducing it to: `**&&*&x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:209:22
+   |
+LL |         let _: i32 = **&&*&x + 0;
+   |                      ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x`
+
+error: this operation has no effect
+  --> $DIR/identity_op.rs:211:22
+   |
+LL |         let _: i32 = **&&*&x + 0;
+   |                      ^^^^^^^^^^^ help: consider reducing it to: `***&&*&x`
+
+error: aborting due to 52 previous errors
 
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.rs b/src/tools/clippy/tests/ui/if_then_some_else_none.rs
index abc92459148..ccde154bd56 100644
--- a/src/tools/clippy/tests/ui/if_then_some_else_none.rs
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.rs
@@ -130,3 +130,8 @@ fn issue11394(b: bool, v: Result<(), ()>) -> Result<(), ()> {
 
     Ok(())
 }
+
+const fn issue12103(x: u32) -> Option<u32> {
+    // Should not issue an error in `const` context
+    if x > 42 { Some(150) } else { None }
+}
diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.rs b/src/tools/clippy/tests/ui/into_iter_without_iter.rs
index 448d0114dff..c8b9076041a 100644
--- a/src/tools/clippy/tests/ui/into_iter_without_iter.rs
+++ b/src/tools/clippy/tests/ui/into_iter_without_iter.rs
@@ -1,5 +1,7 @@
 //@no-rustfix
+//@aux-build:proc_macros.rs
 #![warn(clippy::into_iter_without_iter)]
+extern crate proc_macros;
 
 use std::iter::IntoIterator;
 
@@ -111,6 +113,43 @@ impl IntoIterator for &Alias {
     }
 }
 
+// Fine to lint, the impls comes from a local macro.
+pub struct Issue12037;
+macro_rules! generate_impl {
+    () => {
+        impl<'a> IntoIterator for &'a Issue12037 {
+            type IntoIter = std::slice::Iter<'a, u8>;
+            type Item = &'a u8;
+            fn into_iter(self) -> Self::IntoIter {
+                todo!()
+            }
+        }
+    };
+}
+generate_impl!();
+
+// Impl comes from an external crate
+proc_macros::external! {
+    pub struct ImplWithForeignSpan;
+    impl<'a> IntoIterator for &'a ImplWithForeignSpan {
+        type IntoIter = std::slice::Iter<'a, u8>;
+        type Item = &'a u8;
+        fn into_iter(self) -> Self::IntoIter {
+            todo!()
+        }
+    }
+}
+
+pub struct Allowed;
+#[allow(clippy::into_iter_without_iter)]
+impl<'a> IntoIterator for &'a Allowed {
+    type IntoIter = std::slice::Iter<'a, u8>;
+    type Item = &'a u8;
+    fn into_iter(self) -> Self::IntoIter {
+        todo!()
+    }
+}
+
 fn main() {}
 
 pub mod issue11635 {
diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr
index 70f3f82a936..a232c7cecc5 100644
--- a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr
+++ b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr
@@ -1,5 +1,5 @@
 error: `IntoIterator` implemented for a reference type without an `iter` method
-  --> $DIR/into_iter_without_iter.rs:7:1
+  --> $DIR/into_iter_without_iter.rs:9:1
    |
 LL | / impl<'a> IntoIterator for &'a S1 {
 LL | |
@@ -23,7 +23,7 @@ LL + }
    |
 
 error: `IntoIterator` implemented for a reference type without an `iter_mut` method
-  --> $DIR/into_iter_without_iter.rs:15:1
+  --> $DIR/into_iter_without_iter.rs:17:1
    |
 LL | / impl<'a> IntoIterator for &'a mut S1 {
 LL | |
@@ -45,7 +45,7 @@ LL + }
    |
 
 error: `IntoIterator` implemented for a reference type without an `iter` method
-  --> $DIR/into_iter_without_iter.rs:25:1
+  --> $DIR/into_iter_without_iter.rs:27:1
    |
 LL | / impl<'a, T> IntoIterator for &'a S2<T> {
 LL | |
@@ -67,7 +67,7 @@ LL + }
    |
 
 error: `IntoIterator` implemented for a reference type without an `iter_mut` method
-  --> $DIR/into_iter_without_iter.rs:33:1
+  --> $DIR/into_iter_without_iter.rs:35:1
    |
 LL | / impl<'a, T> IntoIterator for &'a mut S2<T> {
 LL | |
@@ -89,7 +89,7 @@ LL + }
    |
 
 error: `IntoIterator` implemented for a reference type without an `iter_mut` method
-  --> $DIR/into_iter_without_iter.rs:84:1
+  --> $DIR/into_iter_without_iter.rs:86:1
    |
 LL | / impl<'a, T> IntoIterator for &mut S4<'a, T> {
 LL | |
@@ -110,5 +110,31 @@ LL +     }
 LL + }
    |
 
-error: aborting due to 5 previous errors
+error: `IntoIterator` implemented for a reference type without an `iter` method
+  --> $DIR/into_iter_without_iter.rs:120:9
+   |
+LL | /         impl<'a> IntoIterator for &'a Issue12037 {
+LL | |             type IntoIter = std::slice::Iter<'a, u8>;
+LL | |             type Item = &'a u8;
+LL | |             fn into_iter(self) -> Self::IntoIter {
+LL | |                 todo!()
+LL | |             }
+LL | |         }
+   | |_________^
+...
+LL |   generate_impl!();
+   |   ---------------- in this macro invocation
+   |
+   = note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider implementing `iter`
+   |
+LL ~         
+LL + impl Issue12037 {
+LL +     fn iter(&self) -> std::slice::Iter<'a, u8> {
+LL +         <&Self as IntoIterator>::into_iter(self)
+LL +     }
+LL + }
+   |
+
+error: aborting due to 6 previous errors
 
diff --git a/src/tools/clippy/tests/ui/iter_filter_is_ok.fixed b/src/tools/clippy/tests/ui/iter_filter_is_ok.fixed
index a5ca41528af..80db8b29c18 100644
--- a/src/tools/clippy/tests/ui/iter_filter_is_ok.fixed
+++ b/src/tools/clippy/tests/ui/iter_filter_is_ok.fixed
@@ -1,21 +1,72 @@
 #![warn(clippy::iter_filter_is_ok)]
+#![allow(
+    clippy::map_identity,
+    clippy::result_filter_map,
+    clippy::needless_borrow,
+    clippy::redundant_closure
+)]
 
 fn main() {
-    let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
-    //~^ HELP: consider using `flatten` instead
-    let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
-    //~^ HELP: consider using `flatten` instead
+    {
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Ok(1), Err(2)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+    }
 
-    #[rustfmt::skip]
-    let _ = vec![Ok(1), Err(2)].into_iter().flatten();
-    //~^ HELP: consider using `flatten` instead
+    {
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
 
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+
+        #[rustfmt::skip]
+        let _ = vec![Ok(1), Err(2)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Ok(1), Err(2), Ok(3)]
+            .into_iter()
+            .flatten();
+        //~^ HELP: consider using `flatten` instead
+
+        let _ = vec![Ok(1), Err(2), Ok(3)]
+            .into_iter()
+            .flatten();
+        //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+
+        #[rustfmt::skip]
+        let _ = vec![Ok(1), Err(2)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+    }
+}
+
+fn avoid_linting_when_filter_has_side_effects() {
     // Don't lint below
     let mut counter = 0;
     let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| {
         counter += 1;
         o.is_ok()
     });
+}
+
+fn avoid_linting_when_commented() {
     let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| {
         // Roses are red,
         // Violets are blue,
@@ -24,3 +75,131 @@ fn main() {
         o.is_ok()
     });
 }
+
+fn ice_12058() {
+    // check that checking the parent node doesn't cause an ICE
+    // by indexing the parameters of a closure without parameters
+    Some(1).or_else(|| {
+        vec![Ok(1), Err(())].into_iter().filter(|z| *z != Ok(2));
+        None
+    });
+}
+
+fn avoid_linting_map() {
+    // should not lint
+    let _ = vec![Ok(1), Err(())]
+        .into_iter()
+        .filter(|o| o.is_ok())
+        .map(|o| o.unwrap());
+
+    // should not lint
+    let _ = vec![Ok(1), Err(())].into_iter().filter(|o| o.is_ok()).map(|o| o);
+}
+
+fn avoid_false_positive_due_to_is_ok_and_iterator_impl() {
+    #[derive(Default, Clone)]
+    struct Foo {}
+
+    impl Foo {
+        fn is_ok(&self) -> bool {
+            true
+        }
+    }
+
+    impl Iterator for Foo {
+        type Item = Foo;
+        fn next(&mut self) -> Option<Self::Item> {
+            Some(Foo::default())
+        }
+    }
+
+    let data = vec![Foo::default()];
+    // should not lint
+    let _ = data.clone().into_iter().filter(Foo::is_ok);
+    // should not lint
+    let _ = data.clone().into_iter().filter(|f| f.is_ok());
+}
+
+fn avoid_false_positive_due_to_is_ok_and_into_iterator_impl() {
+    #[derive(Default, Clone)]
+    struct Foo {}
+
+    impl Foo {
+        fn is_ok(&self) -> bool {
+            true
+        }
+    }
+
+    let data = vec![Foo::default()];
+    // should not lint
+    let _ = data.clone().into_iter().filter(Foo::is_ok);
+    // should not lint
+    let _ = data.clone().into_iter().filter(|f| f.is_ok());
+}
+
+fn avoid_fp_for_trivial() {
+    let _ = vec![Ok(1), Err(()), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| (Err(()) as Result<i32, ()>).is_ok());
+}
+
+fn avoid_false_positive_due_to_method_name() {
+    fn is_ok(x: &Result<i32, i32>) -> bool {
+        x.is_ok()
+    }
+
+    vec![Ok(1), Err(2), Ok(3)].into_iter().filter(is_ok);
+    // should not lint
+}
+
+fn avoid_fp_due_to_trait_type() {
+    struct Foo {
+        bar: i32,
+    }
+    impl Foo {
+        fn is_ok(obj: &Result<i32, i32>) -> bool {
+            obj.is_ok()
+        }
+    }
+    vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Foo::is_ok);
+    // should not lint
+}
+
+fn avoid_fp_with_call_to_outside_var() {
+    let outside: Result<i32, ()> = Ok(1);
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| outside.is_ok());
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Result::is_ok(&outside));
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| std::result::Result::is_ok(&outside));
+}
+
+fn avoid_fp_with_call_to_outside_var_mix_match_types() {
+    let outside = Some(1);
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| outside.is_some());
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Option::is_some(&outside));
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| std::option::Option::is_some(&outside));
+}
diff --git a/src/tools/clippy/tests/ui/iter_filter_is_ok.rs b/src/tools/clippy/tests/ui/iter_filter_is_ok.rs
index e4e73f5ada1..89b083b84f3 100644
--- a/src/tools/clippy/tests/ui/iter_filter_is_ok.rs
+++ b/src/tools/clippy/tests/ui/iter_filter_is_ok.rs
@@ -1,21 +1,72 @@
 #![warn(clippy::iter_filter_is_ok)]
+#![allow(
+    clippy::map_identity,
+    clippy::result_filter_map,
+    clippy::needless_borrow,
+    clippy::redundant_closure
+)]
 
 fn main() {
-    let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok);
-    //~^ HELP: consider using `flatten` instead
-    let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok());
-    //~^ HELP: consider using `flatten` instead
+    {
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok);
+        //~^ HELP: consider using `flatten` instead
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok());
+        //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() });
+        //~^ HELP: consider using `flatten` instead
+    }
 
-    #[rustfmt::skip]
-    let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() });
-    //~^ HELP: consider using `flatten` instead
+    {
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok());
+        //~^ HELP: consider using `flatten` instead
 
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok());
+        //~^ HELP: consider using `flatten` instead
+
+        #[rustfmt::skip]
+        let _ = vec![Ok(1), Err(2)].into_iter().filter(|&o| { o.is_ok() });
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Ok(1), Err(2), Ok(3)]
+            .into_iter()
+            .filter(std::result::Result::is_ok);
+        //~^ HELP: consider using `flatten` instead
+
+        let _ = vec![Ok(1), Err(2), Ok(3)]
+            .into_iter()
+            .filter(|a| std::result::Result::is_ok(a));
+        //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| { std::result::Result::is_ok(a) });
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok());
+        //~^ HELP: consider using `flatten` instead
+
+        let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok());
+        //~^ HELP: consider using `flatten` instead
+
+        #[rustfmt::skip]
+        let _ = vec![Ok(1), Err(2)].into_iter().filter(|ref o| { o.is_ok() });
+        //~^ HELP: consider using `flatten` instead
+    }
+}
+
+fn avoid_linting_when_filter_has_side_effects() {
     // Don't lint below
     let mut counter = 0;
     let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| {
         counter += 1;
         o.is_ok()
     });
+}
+
+fn avoid_linting_when_commented() {
     let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| {
         // Roses are red,
         // Violets are blue,
@@ -24,3 +75,131 @@ fn main() {
         o.is_ok()
     });
 }
+
+fn ice_12058() {
+    // check that checking the parent node doesn't cause an ICE
+    // by indexing the parameters of a closure without parameters
+    Some(1).or_else(|| {
+        vec![Ok(1), Err(())].into_iter().filter(|z| *z != Ok(2));
+        None
+    });
+}
+
+fn avoid_linting_map() {
+    // should not lint
+    let _ = vec![Ok(1), Err(())]
+        .into_iter()
+        .filter(|o| o.is_ok())
+        .map(|o| o.unwrap());
+
+    // should not lint
+    let _ = vec![Ok(1), Err(())].into_iter().filter(|o| o.is_ok()).map(|o| o);
+}
+
+fn avoid_false_positive_due_to_is_ok_and_iterator_impl() {
+    #[derive(Default, Clone)]
+    struct Foo {}
+
+    impl Foo {
+        fn is_ok(&self) -> bool {
+            true
+        }
+    }
+
+    impl Iterator for Foo {
+        type Item = Foo;
+        fn next(&mut self) -> Option<Self::Item> {
+            Some(Foo::default())
+        }
+    }
+
+    let data = vec![Foo::default()];
+    // should not lint
+    let _ = data.clone().into_iter().filter(Foo::is_ok);
+    // should not lint
+    let _ = data.clone().into_iter().filter(|f| f.is_ok());
+}
+
+fn avoid_false_positive_due_to_is_ok_and_into_iterator_impl() {
+    #[derive(Default, Clone)]
+    struct Foo {}
+
+    impl Foo {
+        fn is_ok(&self) -> bool {
+            true
+        }
+    }
+
+    let data = vec![Foo::default()];
+    // should not lint
+    let _ = data.clone().into_iter().filter(Foo::is_ok);
+    // should not lint
+    let _ = data.clone().into_iter().filter(|f| f.is_ok());
+}
+
+fn avoid_fp_for_trivial() {
+    let _ = vec![Ok(1), Err(()), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| (Err(()) as Result<i32, ()>).is_ok());
+}
+
+fn avoid_false_positive_due_to_method_name() {
+    fn is_ok(x: &Result<i32, i32>) -> bool {
+        x.is_ok()
+    }
+
+    vec![Ok(1), Err(2), Ok(3)].into_iter().filter(is_ok);
+    // should not lint
+}
+
+fn avoid_fp_due_to_trait_type() {
+    struct Foo {
+        bar: i32,
+    }
+    impl Foo {
+        fn is_ok(obj: &Result<i32, i32>) -> bool {
+            obj.is_ok()
+        }
+    }
+    vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Foo::is_ok);
+    // should not lint
+}
+
+fn avoid_fp_with_call_to_outside_var() {
+    let outside: Result<i32, ()> = Ok(1);
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| outside.is_ok());
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Result::is_ok(&outside));
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| std::result::Result::is_ok(&outside));
+}
+
+fn avoid_fp_with_call_to_outside_var_mix_match_types() {
+    let outside = Some(1);
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| outside.is_some());
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Option::is_some(&outside));
+
+    let _ = vec![Ok(1), Err(2), Ok(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| std::option::Option::is_some(&outside));
+}
diff --git a/src/tools/clippy/tests/ui/iter_filter_is_ok.stderr b/src/tools/clippy/tests/ui/iter_filter_is_ok.stderr
index f3acbe38d8a..d99e2e0446d 100644
--- a/src/tools/clippy/tests/ui/iter_filter_is_ok.stderr
+++ b/src/tools/clippy/tests/ui/iter_filter_is_ok.stderr
@@ -1,23 +1,77 @@
 error: `filter` for `is_ok` on iterator over `Result`s
-  --> $DIR/iter_filter_is_ok.rs:4:52
+  --> $DIR/iter_filter_is_ok.rs:11:56
    |
-LL |     let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok);
-   |                                                    ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+LL |         let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(Result::is_ok);
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
    |
    = note: `-D clippy::iter-filter-is-ok` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::iter_filter_is_ok)]`
 
 error: `filter` for `is_ok` on iterator over `Result`s
-  --> $DIR/iter_filter_is_ok.rs:6:52
+  --> $DIR/iter_filter_is_ok.rs:13:56
    |
-LL |     let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok());
-   |                                                    ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+LL |         let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| a.is_ok());
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
 
 error: `filter` for `is_ok` on iterator over `Result`s
-  --> $DIR/iter_filter_is_ok.rs:10:45
+  --> $DIR/iter_filter_is_ok.rs:16:49
    |
-LL |     let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() });
-   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+LL |         let _ = vec![Ok(1), Err(2)].into_iter().filter(|o| { o.is_ok() });
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
 
-error: aborting due to 3 previous errors
+error: `filter` for `is_ok` on iterator over `Result`s
+  --> $DIR/iter_filter_is_ok.rs:21:56
+   |
+LL |         let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok());
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_ok` on iterator over `Result`s
+  --> $DIR/iter_filter_is_ok.rs:24:56
+   |
+LL |         let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|&a| a.is_ok());
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_ok` on iterator over `Result`s
+  --> $DIR/iter_filter_is_ok.rs:28:49
+   |
+LL |         let _ = vec![Ok(1), Err(2)].into_iter().filter(|&o| { o.is_ok() });
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_ok` on iterator over `Result`s
+  --> $DIR/iter_filter_is_ok.rs:35:14
+   |
+LL |             .filter(std::result::Result::is_ok);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_ok` on iterator over `Result`s
+  --> $DIR/iter_filter_is_ok.rs:40:14
+   |
+LL |             .filter(|a| std::result::Result::is_ok(a));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_ok` on iterator over `Result`s
+  --> $DIR/iter_filter_is_ok.rs:43:56
+   |
+LL |         let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|a| { std::result::Result::is_ok(a) });
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_ok` on iterator over `Result`s
+  --> $DIR/iter_filter_is_ok.rs:48:56
+   |
+LL |         let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok());
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_ok` on iterator over `Result`s
+  --> $DIR/iter_filter_is_ok.rs:51:56
+   |
+LL |         let _ = vec![Ok(1), Err(2), Ok(3)].into_iter().filter(|ref a| a.is_ok());
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_ok` on iterator over `Result`s
+  --> $DIR/iter_filter_is_ok.rs:55:49
+   |
+LL |         let _ = vec![Ok(1), Err(2)].into_iter().filter(|ref o| { o.is_ok() });
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/iter_filter_is_some.fixed b/src/tools/clippy/tests/ui/iter_filter_is_some.fixed
index c3fa93f0ab2..abc3a47fa46 100644
--- a/src/tools/clippy/tests/ui/iter_filter_is_some.fixed
+++ b/src/tools/clippy/tests/ui/iter_filter_is_some.fixed
@@ -1,23 +1,70 @@
 #![warn(clippy::iter_filter_is_some)]
+#![allow(
+    clippy::map_identity,
+    clippy::result_filter_map,
+    clippy::needless_borrow,
+    clippy::option_filter_map,
+    clippy::redundant_closure
+)]
+
+use std::collections::HashMap;
 
 fn main() {
-    let _ = vec![Some(1)].into_iter().flatten();
-    //~^ HELP: consider using `flatten` instead
-    let _ = vec![Some(1)].into_iter().flatten();
-    //~^ HELP: consider using `flatten` instead
+    {
+        let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+        let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Some(1), None, Some(3)]
+            .into_iter()
+            .flatten();
+        //~^ HELP: consider using `flatten` instead
+
+        let _ = vec![Some(1), None, Some(3)]
+            .into_iter()
+            .flatten();
+        //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+
+        #[rustfmt::skip]
+        let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
 
-    #[rustfmt::skip]
-    let _ = vec![Some(1)].into_iter().flatten();
-    //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Some(1), None, Some(3)].into_iter().flatten();
+        //~^ HELP: consider using `flatten` instead
+    }
+}
 
+fn avoid_linting_when_filter_has_side_effects() {
     // Don't lint below
     let mut counter = 0;
-    let _ = vec![Some(1)].into_iter().filter(|o| {
+    let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| {
         counter += 1;
         o.is_some()
     });
+}
 
-    let _ = vec![Some(1)].into_iter().filter(|o| {
+fn avoid_linting_when_commented() {
+    let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| {
         // Roses are red,
         // Violets are blue,
         // `Err` is not an `Option`,
@@ -25,3 +72,169 @@ fn main() {
         o.is_some()
     });
 }
+
+fn ice_12058() {
+    // check that checking the parent node doesn't cause an ICE
+    // by indexing the parameters of a closure without parameters
+    Some(1).or_else(|| {
+        vec![Some(1), None, Some(3)].into_iter().filter(|z| *z != Some(2));
+        None
+    });
+}
+
+fn avoid_linting_map() {
+    // should not lint
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        .filter(|o| o.is_some())
+        .map(|o| o.unwrap());
+
+    // should not lint
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        .filter(|o| o.is_some())
+        .map(|o| o);
+}
+
+fn avoid_false_positive_due_to_is_some_and_iterator_impl() {
+    #[derive(Default, Clone)]
+    struct Foo {}
+
+    impl Foo {
+        fn is_some(&self) -> bool {
+            true
+        }
+    }
+
+    impl Iterator for Foo {
+        type Item = Foo;
+        fn next(&mut self) -> Option<Self::Item> {
+            Some(Foo::default())
+        }
+    }
+
+    let data = vec![Foo::default()];
+    // should not lint
+    let _ = data.clone().into_iter().filter(Foo::is_some);
+    // should not lint
+    let _ = data.clone().into_iter().filter(|f| f.is_some());
+}
+
+fn avoid_false_positive_due_to_is_some_and_into_iterator_impl() {
+    #[derive(Default, Clone)]
+    struct Foo {}
+
+    impl Foo {
+        fn is_some(&self) -> bool {
+            true
+        }
+    }
+
+    let data = vec![Foo::default()];
+    // should not lint
+    let _ = data.clone().into_iter().filter(Foo::is_some);
+    // should not lint
+    let _ = data.clone().into_iter().filter(|f| f.is_some());
+}
+
+fn avoid_unpack_fp() {
+    let _ = vec![(Some(1), None), (None, Some(3))]
+        .into_iter()
+        // should not lint
+        .filter(|(a, _)| a.is_some());
+    let _ = vec![(Some(1), None), (None, Some(3))]
+        .into_iter()
+        // should not lint
+        .filter(|(a, _)| a.is_some())
+        .collect::<Vec<_>>();
+
+    let m = HashMap::from([(1, 1)]);
+    let _ = vec![1, 2, 4].into_iter().filter(|a| m.get(a).is_some());
+    // should not lint
+}
+
+fn avoid_fp_for_external() {
+    let value = HashMap::from([(1, 1)]);
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| value.get(&1).is_some());
+
+    let value = Option::Some(1);
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| value.is_some());
+}
+
+fn avoid_fp_for_trivial() {
+    let value = HashMap::from([(1, 1)]);
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Some(1).is_some());
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| None::<i32>.is_some());
+}
+
+fn avoid_false_positive_due_to_method_name() {
+    fn is_some(x: &Option<i32>) -> bool {
+        x.is_some()
+    }
+
+    vec![Some(1), None, Some(3)].into_iter().filter(is_some);
+    // should not lint
+}
+
+fn avoid_fp_due_to_trait_type() {
+    struct Foo {
+        bar: i32,
+    }
+    impl Foo {
+        fn is_some(obj: &Option<i32>) -> bool {
+            obj.is_some()
+        }
+    }
+    vec![Some(1), None, Some(3)].into_iter().filter(Foo::is_some);
+    // should not lint
+}
+
+fn avoid_fp_with_call_to_outside_var() {
+    let outside = Some(1);
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| outside.is_some());
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Option::is_some(&outside));
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| std::option::Option::is_some(&outside));
+}
+
+fn avoid_fp_with_call_to_outside_var_mix_match_types() {
+    let outside: Result<i32, ()> = Ok(1);
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| outside.is_ok());
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Result::is_ok(&outside));
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| std::result::Result::is_ok(&outside));
+}
diff --git a/src/tools/clippy/tests/ui/iter_filter_is_some.rs b/src/tools/clippy/tests/ui/iter_filter_is_some.rs
index b023776abe4..c74775a82ba 100644
--- a/src/tools/clippy/tests/ui/iter_filter_is_some.rs
+++ b/src/tools/clippy/tests/ui/iter_filter_is_some.rs
@@ -1,23 +1,70 @@
 #![warn(clippy::iter_filter_is_some)]
+#![allow(
+    clippy::map_identity,
+    clippy::result_filter_map,
+    clippy::needless_borrow,
+    clippy::option_filter_map,
+    clippy::redundant_closure
+)]
+
+use std::collections::HashMap;
 
 fn main() {
-    let _ = vec![Some(1)].into_iter().filter(Option::is_some);
-    //~^ HELP: consider using `flatten` instead
-    let _ = vec![Some(1)].into_iter().filter(|o| o.is_some());
-    //~^ HELP: consider using `flatten` instead
+    {
+        let _ = vec![Some(1), None, Some(3)].into_iter().filter(Option::is_some);
+        //~^ HELP: consider using `flatten` instead
+        let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| a.is_some());
+        //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| { o.is_some() });
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Some(1), None, Some(3)]
+            .into_iter()
+            .filter(std::option::Option::is_some);
+        //~^ HELP: consider using `flatten` instead
+
+        let _ = vec![Some(1), None, Some(3)]
+            .into_iter()
+            .filter(|a| std::option::Option::is_some(a));
+        //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| { std::option::Option::is_some(a) });
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&a| a.is_some());
+        //~^ HELP: consider using `flatten` instead
+
+        #[rustfmt::skip]
+        let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&o| { o.is_some() });
+        //~^ HELP: consider using `flatten` instead
+    }
+
+    {
+        let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref a| a.is_some());
+        //~^ HELP: consider using `flatten` instead
 
-    #[rustfmt::skip]
-    let _ = vec![Some(1)].into_iter().filter(|o| { o.is_some() });
-    //~^ HELP: consider using `flatten` instead
+        #[rustfmt::skip]
+        let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref o| { o.is_some() });
+        //~^ HELP: consider using `flatten` instead
+    }
+}
 
+fn avoid_linting_when_filter_has_side_effects() {
     // Don't lint below
     let mut counter = 0;
-    let _ = vec![Some(1)].into_iter().filter(|o| {
+    let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| {
         counter += 1;
         o.is_some()
     });
+}
 
-    let _ = vec![Some(1)].into_iter().filter(|o| {
+fn avoid_linting_when_commented() {
+    let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| {
         // Roses are red,
         // Violets are blue,
         // `Err` is not an `Option`,
@@ -25,3 +72,169 @@ fn main() {
         o.is_some()
     });
 }
+
+fn ice_12058() {
+    // check that checking the parent node doesn't cause an ICE
+    // by indexing the parameters of a closure without parameters
+    Some(1).or_else(|| {
+        vec![Some(1), None, Some(3)].into_iter().filter(|z| *z != Some(2));
+        None
+    });
+}
+
+fn avoid_linting_map() {
+    // should not lint
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        .filter(|o| o.is_some())
+        .map(|o| o.unwrap());
+
+    // should not lint
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        .filter(|o| o.is_some())
+        .map(|o| o);
+}
+
+fn avoid_false_positive_due_to_is_some_and_iterator_impl() {
+    #[derive(Default, Clone)]
+    struct Foo {}
+
+    impl Foo {
+        fn is_some(&self) -> bool {
+            true
+        }
+    }
+
+    impl Iterator for Foo {
+        type Item = Foo;
+        fn next(&mut self) -> Option<Self::Item> {
+            Some(Foo::default())
+        }
+    }
+
+    let data = vec![Foo::default()];
+    // should not lint
+    let _ = data.clone().into_iter().filter(Foo::is_some);
+    // should not lint
+    let _ = data.clone().into_iter().filter(|f| f.is_some());
+}
+
+fn avoid_false_positive_due_to_is_some_and_into_iterator_impl() {
+    #[derive(Default, Clone)]
+    struct Foo {}
+
+    impl Foo {
+        fn is_some(&self) -> bool {
+            true
+        }
+    }
+
+    let data = vec![Foo::default()];
+    // should not lint
+    let _ = data.clone().into_iter().filter(Foo::is_some);
+    // should not lint
+    let _ = data.clone().into_iter().filter(|f| f.is_some());
+}
+
+fn avoid_unpack_fp() {
+    let _ = vec![(Some(1), None), (None, Some(3))]
+        .into_iter()
+        // should not lint
+        .filter(|(a, _)| a.is_some());
+    let _ = vec![(Some(1), None), (None, Some(3))]
+        .into_iter()
+        // should not lint
+        .filter(|(a, _)| a.is_some())
+        .collect::<Vec<_>>();
+
+    let m = HashMap::from([(1, 1)]);
+    let _ = vec![1, 2, 4].into_iter().filter(|a| m.get(a).is_some());
+    // should not lint
+}
+
+fn avoid_fp_for_external() {
+    let value = HashMap::from([(1, 1)]);
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| value.get(&1).is_some());
+
+    let value = Option::Some(1);
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| value.is_some());
+}
+
+fn avoid_fp_for_trivial() {
+    let value = HashMap::from([(1, 1)]);
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Some(1).is_some());
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| None::<i32>.is_some());
+}
+
+fn avoid_false_positive_due_to_method_name() {
+    fn is_some(x: &Option<i32>) -> bool {
+        x.is_some()
+    }
+
+    vec![Some(1), None, Some(3)].into_iter().filter(is_some);
+    // should not lint
+}
+
+fn avoid_fp_due_to_trait_type() {
+    struct Foo {
+        bar: i32,
+    }
+    impl Foo {
+        fn is_some(obj: &Option<i32>) -> bool {
+            obj.is_some()
+        }
+    }
+    vec![Some(1), None, Some(3)].into_iter().filter(Foo::is_some);
+    // should not lint
+}
+
+fn avoid_fp_with_call_to_outside_var() {
+    let outside = Some(1);
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| outside.is_some());
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Option::is_some(&outside));
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| std::option::Option::is_some(&outside));
+}
+
+fn avoid_fp_with_call_to_outside_var_mix_match_types() {
+    let outside: Result<i32, ()> = Ok(1);
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| outside.is_ok());
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| Result::is_ok(&outside));
+
+    let _ = vec![Some(1), None, Some(3)]
+        .into_iter()
+        // should not lint
+        .filter(|o| std::result::Result::is_ok(&outside));
+}
diff --git a/src/tools/clippy/tests/ui/iter_filter_is_some.stderr b/src/tools/clippy/tests/ui/iter_filter_is_some.stderr
index 1f2b10036fe..2eb00633e88 100644
--- a/src/tools/clippy/tests/ui/iter_filter_is_some.stderr
+++ b/src/tools/clippy/tests/ui/iter_filter_is_some.stderr
@@ -1,23 +1,65 @@
 error: `filter` for `is_some` on iterator over `Option`
-  --> $DIR/iter_filter_is_some.rs:4:39
+  --> $DIR/iter_filter_is_some.rs:14:58
    |
-LL |     let _ = vec![Some(1)].into_iter().filter(Option::is_some);
-   |                                       ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+LL |         let _ = vec![Some(1), None, Some(3)].into_iter().filter(Option::is_some);
+   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
    |
    = note: `-D clippy::iter-filter-is-some` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::iter_filter_is_some)]`
 
 error: `filter` for `is_some` on iterator over `Option`
-  --> $DIR/iter_filter_is_some.rs:6:39
+  --> $DIR/iter_filter_is_some.rs:16:58
    |
-LL |     let _ = vec![Some(1)].into_iter().filter(|o| o.is_some());
-   |                                       ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+LL |         let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| a.is_some());
+   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
 
 error: `filter` for `is_some` on iterator over `Option`
-  --> $DIR/iter_filter_is_some.rs:10:39
+  --> $DIR/iter_filter_is_some.rs:19:58
    |
-LL |     let _ = vec![Some(1)].into_iter().filter(|o| { o.is_some() });
-   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+LL |         let _ = vec![Some(1), None, Some(3)].into_iter().filter(|o| { o.is_some() });
+   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
 
-error: aborting due to 3 previous errors
+error: `filter` for `is_some` on iterator over `Option`
+  --> $DIR/iter_filter_is_some.rs:26:14
+   |
+LL |             .filter(std::option::Option::is_some);
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_some` on iterator over `Option`
+  --> $DIR/iter_filter_is_some.rs:31:14
+   |
+LL |             .filter(|a| std::option::Option::is_some(a));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_some` on iterator over `Option`
+  --> $DIR/iter_filter_is_some.rs:34:58
+   |
+LL |         let _ = vec![Some(1), None, Some(3)].into_iter().filter(|a| { std::option::Option::is_some(a) });
+   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_some` on iterator over `Option`
+  --> $DIR/iter_filter_is_some.rs:39:58
+   |
+LL |         let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&a| a.is_some());
+   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_some` on iterator over `Option`
+  --> $DIR/iter_filter_is_some.rs:43:58
+   |
+LL |         let _ = vec![Some(1), None, Some(3)].into_iter().filter(|&o| { o.is_some() });
+   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_some` on iterator over `Option`
+  --> $DIR/iter_filter_is_some.rs:48:58
+   |
+LL |         let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref a| a.is_some());
+   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: `filter` for `is_some` on iterator over `Option`
+  --> $DIR/iter_filter_is_some.rs:52:58
+   |
+LL |         let _ = vec![Some(1), None, Some(3)].into_iter().filter(|ref o| { o.is_some() });
+   |                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `flatten` instead: `flatten()`
+
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/clippy/tests/ui/iter_without_into_iter.rs b/src/tools/clippy/tests/ui/iter_without_into_iter.rs
index 29f526b455c..3054d848efb 100644
--- a/src/tools/clippy/tests/ui/iter_without_into_iter.rs
+++ b/src/tools/clippy/tests/ui/iter_without_into_iter.rs
@@ -1,5 +1,7 @@
 //@no-rustfix
+//@aux-build:proc_macros.rs
 #![warn(clippy::iter_without_into_iter)]
+extern crate proc_macros;
 
 pub struct S1;
 impl S1 {
@@ -121,4 +123,33 @@ impl S12 {
     }
 }
 
+pub struct Issue12037;
+macro_rules! generate_impl {
+    () => {
+        impl Issue12037 {
+            fn iter(&self) -> std::slice::Iter<'_, u8> {
+                todo!()
+            }
+        }
+    };
+}
+generate_impl!();
+
+proc_macros::external! {
+    pub struct ImplWithForeignSpan;
+    impl ImplWithForeignSpan {
+        fn iter(&self) -> std::slice::Iter<'_, u8> {
+            todo!()
+        }
+    }
+}
+
+pub struct Allowed;
+impl Allowed {
+    #[allow(clippy::iter_without_into_iter)]
+    pub fn iter(&self) -> std::slice::Iter<'_, u8> {
+        todo!()
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/iter_without_into_iter.stderr b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr
index af5afd47bfc..4cf20e2aa56 100644
--- a/src/tools/clippy/tests/ui/iter_without_into_iter.stderr
+++ b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr
@@ -1,5 +1,5 @@
 error: `iter` method without an `IntoIterator` impl for `&S1`
-  --> $DIR/iter_without_into_iter.rs:6:5
+  --> $DIR/iter_without_into_iter.rs:8:5
    |
 LL | /     pub fn iter(&self) -> std::slice::Iter<'_, u8> {
 LL | |
@@ -22,7 +22,7 @@ LL + }
    |
 
 error: `iter_mut` method without an `IntoIterator` impl for `&mut S1`
-  --> $DIR/iter_without_into_iter.rs:10:5
+  --> $DIR/iter_without_into_iter.rs:12:5
    |
 LL | /     pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
 LL | |
@@ -43,7 +43,7 @@ LL + }
    |
 
 error: `iter` method without an `IntoIterator` impl for `&S3<'a>`
-  --> $DIR/iter_without_into_iter.rs:26:5
+  --> $DIR/iter_without_into_iter.rs:28:5
    |
 LL | /     pub fn iter(&self) -> std::slice::Iter<'_, u8> {
 LL | |
@@ -64,7 +64,7 @@ LL + }
    |
 
 error: `iter_mut` method without an `IntoIterator` impl for `&mut S3<'a>`
-  --> $DIR/iter_without_into_iter.rs:30:5
+  --> $DIR/iter_without_into_iter.rs:32:5
    |
 LL | /     pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
 LL | |
@@ -85,7 +85,7 @@ LL + }
    |
 
 error: `iter` method without an `IntoIterator` impl for `&S8<T>`
-  --> $DIR/iter_without_into_iter.rs:67:5
+  --> $DIR/iter_without_into_iter.rs:69:5
    |
 LL | /     pub fn iter(&self) -> std::slice::Iter<'static, T> {
 LL | |         todo!()
@@ -105,7 +105,7 @@ LL + }
    |
 
 error: `iter` method without an `IntoIterator` impl for `&S9<T>`
-  --> $DIR/iter_without_into_iter.rs:75:5
+  --> $DIR/iter_without_into_iter.rs:77:5
    |
 LL | /     pub fn iter(&self) -> std::slice::Iter<'_, T> {
 LL | |
@@ -126,7 +126,7 @@ LL + }
    |
 
 error: `iter_mut` method without an `IntoIterator` impl for `&mut S9<T>`
-  --> $DIR/iter_without_into_iter.rs:79:5
+  --> $DIR/iter_without_into_iter.rs:81:5
    |
 LL | /     pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
 LL | |
@@ -146,5 +146,29 @@ LL +     }
 LL + }
    |
 
-error: aborting due to 7 previous errors
+error: `iter` method without an `IntoIterator` impl for `&Issue12037`
+  --> $DIR/iter_without_into_iter.rs:130:13
+   |
+LL | /             fn iter(&self) -> std::slice::Iter<'_, u8> {
+LL | |                 todo!()
+LL | |             }
+   | |_____________^
+...
+LL |   generate_impl!();
+   |   ---------------- in this macro invocation
+   |
+   = note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider implementing `IntoIterator` for `&Issue12037`
+   |
+LL ~         
+LL + impl IntoIterator for &Issue12037 {
+LL +     type IntoIter = std::slice::Iter<'_, u8>;
+LL +     type Item = &u8;
+LL +     fn into_iter(self) -> Self::IntoIter {
+LL +         self.iter()
+LL +     }
+LL + }
+   |
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/let_unit.fixed b/src/tools/clippy/tests/ui/let_unit.fixed
index f98ce9d50a9..4d41b5e5e50 100644
--- a/src/tools/clippy/tests/ui/let_unit.fixed
+++ b/src/tools/clippy/tests/ui/let_unit.fixed
@@ -13,7 +13,14 @@ fn main() {
     let _y = 1; // this is fine
     let _z = ((), 1); // this as well
     if true {
-        ();
+        // do not lint this, since () is explicit
+        let _a = ();
+        let () = dummy();
+        let () = ();
+        () = dummy();
+        () = ();
+        let _a: () = ();
+        let _a: () = dummy();
     }
 
     consume_units_with_for_loop(); // should be fine as well
@@ -23,6 +30,8 @@ fn main() {
     let_and_return!(()) // should be fine
 }
 
+fn dummy() {}
+
 // Related to issue #1964
 fn consume_units_with_for_loop() {
     // `for_let_unit` lint should not be triggered by consuming them using for loop.
@@ -74,40 +83,29 @@ fn _returns_generic() {
         x.then(|| T::default())
     }
 
-    let _: () = f(); // Ok
-    let _: () = f(); // Lint.
+    let _: () = f();
+    let x: () = f();
 
-    let _: () = f2(0i32); // Ok
-    let _: () = f2(0i32); // Lint.
+    let _: () = f2(0i32);
+    let x: () = f2(0i32);
 
-    f3(()); // Lint
-    f3(()); // Lint
+    let _: () = f3(());
+    let x: () = f3(());
 
-    // Should lint:
-    // fn f4<T>(mut x: Vec<T>) -> T {
-    //    x.pop().unwrap()
-    // }
-    // let _: () = f4(vec![()]);
-    // let x: () = f4(vec![()]);
+    fn f4<T>(mut x: Vec<T>) -> T {
+        x.pop().unwrap()
+    }
+    let _: () = f4(vec![()]);
+    let x: () = f4(vec![()]);
 
-    // Ok
     let _: () = {
         let x = 5;
         f2(x)
     };
 
-    let _: () = if true { f() } else { f2(0) }; // Ok
-    let _: () = if true { f() } else { f2(0) }; // Lint
-
-    // Ok
-    let _: () = match Some(0) {
-        None => f2(1),
-        Some(0) => f(),
-        Some(1) => f2(3),
-        Some(_) => f2('x'),
-    };
+    let _: () = if true { f() } else { f2(0) };
+    let x: () = if true { f() } else { f2(0) };
 
-    // Lint
     match Some(0) {
         None => f2(1),
         Some(0) => f(),
@@ -155,7 +153,7 @@ fn _returns_generic() {
         {
             let _: () = x;
             let _: () = y;
-            z;
+            let _: () = z;
             let _: () = x1;
             let _: () = x2;
             let _: () = opt;
diff --git a/src/tools/clippy/tests/ui/let_unit.rs b/src/tools/clippy/tests/ui/let_unit.rs
index 6d942ca8908..daa660be25e 100644
--- a/src/tools/clippy/tests/ui/let_unit.rs
+++ b/src/tools/clippy/tests/ui/let_unit.rs
@@ -13,7 +13,14 @@ fn main() {
     let _y = 1; // this is fine
     let _z = ((), 1); // this as well
     if true {
+        // do not lint this, since () is explicit
         let _a = ();
+        let () = dummy();
+        let () = ();
+        () = dummy();
+        () = ();
+        let _a: () = ();
+        let _a: () = dummy();
     }
 
     consume_units_with_for_loop(); // should be fine as well
@@ -23,6 +30,8 @@ fn main() {
     let_and_return!(()) // should be fine
 }
 
+fn dummy() {}
+
 // Related to issue #1964
 fn consume_units_with_for_loop() {
     // `for_let_unit` lint should not be triggered by consuming them using for loop.
@@ -74,41 +83,30 @@ fn _returns_generic() {
         x.then(|| T::default())
     }
 
-    let _: () = f(); // Ok
-    let x: () = f(); // Lint.
+    let _: () = f();
+    let x: () = f();
 
-    let _: () = f2(0i32); // Ok
-    let x: () = f2(0i32); // Lint.
+    let _: () = f2(0i32);
+    let x: () = f2(0i32);
 
-    let _: () = f3(()); // Lint
-    let x: () = f3(()); // Lint
+    let _: () = f3(());
+    let x: () = f3(());
 
-    // Should lint:
-    // fn f4<T>(mut x: Vec<T>) -> T {
-    //    x.pop().unwrap()
-    // }
-    // let _: () = f4(vec![()]);
-    // let x: () = f4(vec![()]);
+    fn f4<T>(mut x: Vec<T>) -> T {
+        x.pop().unwrap()
+    }
+    let _: () = f4(vec![()]);
+    let x: () = f4(vec![()]);
 
-    // Ok
     let _: () = {
         let x = 5;
         f2(x)
     };
 
-    let _: () = if true { f() } else { f2(0) }; // Ok
-    let x: () = if true { f() } else { f2(0) }; // Lint
-
-    // Ok
-    let _: () = match Some(0) {
-        None => f2(1),
-        Some(0) => f(),
-        Some(1) => f2(3),
-        Some(_) => f2('x'),
-    };
+    let _: () = if true { f() } else { f2(0) };
+    let x: () = if true { f() } else { f2(0) };
 
-    // Lint
-    let _: () = match Some(0) {
+    let x = match Some(0) {
         None => f2(1),
         Some(0) => f(),
         Some(1) => f2(3),
diff --git a/src/tools/clippy/tests/ui/let_unit.stderr b/src/tools/clippy/tests/ui/let_unit.stderr
index de106f50e0e..00a3c439ba0 100644
--- a/src/tools/clippy/tests/ui/let_unit.stderr
+++ b/src/tools/clippy/tests/ui/let_unit.stderr
@@ -8,13 +8,7 @@ LL |     let _x = println!("x");
    = help: to override `-D warnings` add `#[allow(clippy::let_unit_value)]`
 
 error: this let-binding has unit value
-  --> $DIR/let_unit.rs:16:9
-   |
-LL |         let _a = ();
-   |         ^^^^^^^^^^^^ help: omit the `let` binding: `();`
-
-error: this let-binding has unit value
-  --> $DIR/let_unit.rs:51:5
+  --> $DIR/let_unit.rs:60:5
    |
 LL | /     let _ = v
 LL | |         .into_iter()
@@ -37,45 +31,9 @@ LL +         .unwrap();
    |
 
 error: this let-binding has unit value
-  --> $DIR/let_unit.rs:78:5
-   |
-LL |     let x: () = f(); // Lint.
-   |     ^^^^-^^^^^^^^^^^
-   |         |
-   |         help: use a wild (`_`) binding: `_`
-
-error: this let-binding has unit value
-  --> $DIR/let_unit.rs:81:5
+  --> $DIR/let_unit.rs:109:5
    |
-LL |     let x: () = f2(0i32); // Lint.
-   |     ^^^^-^^^^^^^^^^^^^^^^
-   |         |
-   |         help: use a wild (`_`) binding: `_`
-
-error: this let-binding has unit value
-  --> $DIR/let_unit.rs:83:5
-   |
-LL |     let _: () = f3(()); // Lint
-   |     ^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `f3(());`
-
-error: this let-binding has unit value
-  --> $DIR/let_unit.rs:84:5
-   |
-LL |     let x: () = f3(()); // Lint
-   |     ^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `f3(());`
-
-error: this let-binding has unit value
-  --> $DIR/let_unit.rs:100:5
-   |
-LL |     let x: () = if true { f() } else { f2(0) }; // Lint
-   |     ^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         help: use a wild (`_`) binding: `_`
-
-error: this let-binding has unit value
-  --> $DIR/let_unit.rs:111:5
-   |
-LL | /     let _: () = match Some(0) {
+LL | /     let x = match Some(0) {
 LL | |         None => f2(1),
 LL | |         Some(0) => f(),
 LL | |         Some(1) => f2(3),
@@ -93,11 +51,5 @@ LL +         Some(_) => (),
 LL +     };
    |
 
-error: this let-binding has unit value
-  --> $DIR/let_unit.rs:158:13
-   |
-LL |             let _: () = z;
-   |             ^^^^^^^^^^^^^^ help: omit the `let` binding: `z;`
-
-error: aborting due to 10 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_is_variant_and.fixed b/src/tools/clippy/tests/ui/manual_is_variant_and.fixed
new file mode 100644
index 00000000000..8c34b51103c
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_is_variant_and.fixed
@@ -0,0 +1,51 @@
+//@aux-build:option_helpers.rs
+#![warn(clippy::manual_is_variant_and)]
+
+#[macro_use]
+extern crate option_helpers;
+
+#[rustfmt::skip]
+fn option_methods() {
+    let opt = Some(1);
+
+    // Check for `option.map(_).unwrap_or_default()` use.
+    // Single line case.
+    let _ = opt.is_some_and(|x| x > 1);
+    // Multi-line cases.
+    let _ = opt.is_some_and(|x| {
+        x > 1
+    });
+    let _ = opt.is_some_and(|x| x > 1);
+    let _ = opt
+        .is_some_and(|x| x > 1);
+
+    // won't fix because the return type of the closure is not `bool`
+    let _ = opt.map(|x| x + 1).unwrap_or_default();
+
+    let opt2 = Some('a');
+    let _ = opt2.is_some_and(char::is_alphanumeric); // should lint
+    let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
+}
+
+#[rustfmt::skip]
+fn result_methods() {
+    let res: Result<i32, ()> = Ok(1);
+
+    // multi line cases
+    let _ = res.is_ok_and(|x| {
+        x > 1
+    });
+    let _ = res.is_ok_and(|x| x > 1);
+
+    // won't fix because the return type of the closure is not `bool`
+    let _ = res.map(|x| x + 1).unwrap_or_default();
+
+    let res2: Result<char, ()> = Ok('a');
+    let _ = res2.is_ok_and(char::is_alphanumeric); // should lint
+    let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint
+}
+
+fn main() {
+    option_methods();
+    result_methods();
+}
diff --git a/src/tools/clippy/tests/ui/manual_is_variant_and.rs b/src/tools/clippy/tests/ui/manual_is_variant_and.rs
new file mode 100644
index 00000000000..25b2489d942
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_is_variant_and.rs
@@ -0,0 +1,57 @@
+//@aux-build:option_helpers.rs
+#![warn(clippy::manual_is_variant_and)]
+
+#[macro_use]
+extern crate option_helpers;
+
+#[rustfmt::skip]
+fn option_methods() {
+    let opt = Some(1);
+
+    // Check for `option.map(_).unwrap_or_default()` use.
+    // Single line case.
+    let _ = opt.map(|x| x > 1)
+        // Should lint even though this call is on a separate line.
+        .unwrap_or_default();
+    // Multi-line cases.
+    let _ = opt.map(|x| {
+        x > 1
+    }
+    ).unwrap_or_default();
+    let _ = opt.map(|x| x > 1).unwrap_or_default();
+    let _ = opt
+        .map(|x| x > 1)
+        .unwrap_or_default();
+
+    // won't fix because the return type of the closure is not `bool`
+    let _ = opt.map(|x| x + 1).unwrap_or_default();
+
+    let opt2 = Some('a');
+    let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
+    let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint
+}
+
+#[rustfmt::skip]
+fn result_methods() {
+    let res: Result<i32, ()> = Ok(1);
+
+    // multi line cases
+    let _ = res.map(|x| {
+        x > 1
+    }
+    ).unwrap_or_default();
+    let _ = res.map(|x| x > 1)
+        .unwrap_or_default();
+
+    // won't fix because the return type of the closure is not `bool`
+    let _ = res.map(|x| x + 1).unwrap_or_default();
+
+    let res2: Result<char, ()> = Ok('a');
+    let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
+    let _ = opt_map!(res2, |x| x == 'a').unwrap_or_default(); // should not lint
+}
+
+fn main() {
+    option_methods();
+    result_methods();
+}
diff --git a/src/tools/clippy/tests/ui/manual_is_variant_and.stderr b/src/tools/clippy/tests/ui/manual_is_variant_and.stderr
new file mode 100644
index 00000000000..c243de098dc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_is_variant_and.stderr
@@ -0,0 +1,82 @@
+error: called `map(<f>).unwrap_or_default()` on an `Option` value
+  --> $DIR/manual_is_variant_and.rs:13:17
+   |
+LL |       let _ = opt.map(|x| x > 1)
+   |  _________________^
+LL | |         // Should lint even though this call is on a separate line.
+LL | |         .unwrap_or_default();
+   | |____________________________^ help: use: `is_some_and(|x| x > 1)`
+   |
+   = note: `-D clippy::manual-is-variant-and` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::manual_is_variant_and)]`
+
+error: called `map(<f>).unwrap_or_default()` on an `Option` value
+  --> $DIR/manual_is_variant_and.rs:17:17
+   |
+LL |       let _ = opt.map(|x| {
+   |  _________________^
+LL | |         x > 1
+LL | |     }
+LL | |     ).unwrap_or_default();
+   | |_________________________^
+   |
+help: use
+   |
+LL ~     let _ = opt.is_some_and(|x| {
+LL +         x > 1
+LL ~     });
+   |
+
+error: called `map(<f>).unwrap_or_default()` on an `Option` value
+  --> $DIR/manual_is_variant_and.rs:21:17
+   |
+LL |     let _ = opt.map(|x| x > 1).unwrap_or_default();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(|x| x > 1)`
+
+error: called `map(<f>).unwrap_or_default()` on an `Option` value
+  --> $DIR/manual_is_variant_and.rs:23:10
+   |
+LL |           .map(|x| x > 1)
+   |  __________^
+LL | |         .unwrap_or_default();
+   | |____________________________^ help: use: `is_some_and(|x| x > 1)`
+
+error: called `map(<f>).unwrap_or_default()` on an `Option` value
+  --> $DIR/manual_is_variant_and.rs:30:18
+   |
+LL |     let _ = opt2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_some_and(char::is_alphanumeric)`
+
+error: called `map(<f>).unwrap_or_default()` on a `Result` value
+  --> $DIR/manual_is_variant_and.rs:39:17
+   |
+LL |       let _ = res.map(|x| {
+   |  _________________^
+LL | |         x > 1
+LL | |     }
+LL | |     ).unwrap_or_default();
+   | |_________________________^
+   |
+help: use
+   |
+LL ~     let _ = res.is_ok_and(|x| {
+LL +         x > 1
+LL ~     });
+   |
+
+error: called `map(<f>).unwrap_or_default()` on a `Result` value
+  --> $DIR/manual_is_variant_and.rs:43:17
+   |
+LL |       let _ = res.map(|x| x > 1)
+   |  _________________^
+LL | |         .unwrap_or_default();
+   | |____________________________^ help: use: `is_ok_and(|x| x > 1)`
+
+error: called `map(<f>).unwrap_or_default()` on a `Result` value
+  --> $DIR/manual_is_variant_and.rs:50:18
+   |
+LL |     let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_ok_and(char::is_alphanumeric)`
+
+error: aborting due to 8 previous errors
+
diff --git a/src/tools/clippy/tests/ui/map_clone.fixed b/src/tools/clippy/tests/ui/map_clone.fixed
index dd979013d3c..08b155a1aea 100644
--- a/src/tools/clippy/tests/ui/map_clone.fixed
+++ b/src/tools/clippy/tests/ui/map_clone.fixed
@@ -4,6 +4,8 @@
     clippy::iter_cloned_collect,
     clippy::many_single_char_names,
     clippy::redundant_clone,
+    clippy::redundant_closure,
+    clippy::useless_asref,
     clippy::useless_vec
 )]
 
@@ -60,4 +62,26 @@ fn main() {
 
         let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
     }
+
+    let x = Some(String::new());
+    let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
+    let y = x.cloned();
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    let y = x.cloned();
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    let y = x.cloned();
+    //~^ ERROR: you are explicitly cloning with `.map()`
+
+    // Testing with `Result` now.
+    let x: Result<String, ()> = Ok(String::new());
+    let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
+    let y = x.cloned();
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    let y = x.cloned();
+
+    // We ensure that no warning is emitted here because `useless_asref` is taking over.
+    let x = Some(String::new());
+    let y = x.as_ref().map(|x| String::clone(x));
+    let x: Result<String, ()> = Ok(String::new());
+    let y = x.as_ref().map(|x| String::clone(x));
 }
diff --git a/src/tools/clippy/tests/ui/map_clone.rs b/src/tools/clippy/tests/ui/map_clone.rs
index 96cba71965f..901d9b278b4 100644
--- a/src/tools/clippy/tests/ui/map_clone.rs
+++ b/src/tools/clippy/tests/ui/map_clone.rs
@@ -4,6 +4,8 @@
     clippy::iter_cloned_collect,
     clippy::many_single_char_names,
     clippy::redundant_clone,
+    clippy::redundant_closure,
+    clippy::useless_asref,
     clippy::useless_vec
 )]
 
@@ -60,4 +62,26 @@ fn main() {
 
         let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone());
     }
+
+    let x = Some(String::new());
+    let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
+    let y = x.map(|x| String::clone(x));
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    let y = x.map(Clone::clone);
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    let y = x.map(String::clone);
+    //~^ ERROR: you are explicitly cloning with `.map()`
+
+    // Testing with `Result` now.
+    let x: Result<String, ()> = Ok(String::new());
+    let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
+    let y = x.map(|x| String::clone(x));
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    let y = x.map(|x| String::clone(x));
+
+    // We ensure that no warning is emitted here because `useless_asref` is taking over.
+    let x = Some(String::new());
+    let y = x.as_ref().map(|x| String::clone(x));
+    let x: Result<String, ()> = Ok(String::new());
+    let y = x.as_ref().map(|x| String::clone(x));
 }
diff --git a/src/tools/clippy/tests/ui/map_clone.stderr b/src/tools/clippy/tests/ui/map_clone.stderr
index eb11f084887..9d7e9317b58 100644
--- a/src/tools/clippy/tests/ui/map_clone.stderr
+++ b/src/tools/clippy/tests/ui/map_clone.stderr
@@ -1,5 +1,5 @@
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:11:22
+  --> $DIR/map_clone.rs:13:22
    |
 LL |     let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![5_i8; 6].iter().copied()`
@@ -8,34 +8,64 @@ LL |     let _: Vec<i8> = vec![5_i8; 6].iter().map(|x| *x).collect();
    = help: to override `-D warnings` add `#[allow(clippy::map_clone)]`
 
 error: you are using an explicit closure for cloning elements
-  --> $DIR/map_clone.rs:12:26
+  --> $DIR/map_clone.rs:14:26
    |
 LL |     let _: Vec<String> = vec![String::new()].iter().map(|x| x.clone()).collect();
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `vec![String::new()].iter().cloned()`
 
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:13:23
+  --> $DIR/map_clone.rs:15:23
    |
 LL |     let _: Vec<u32> = vec![42, 43].iter().map(|&x| x).collect();
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `vec![42, 43].iter().copied()`
 
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:15:26
+  --> $DIR/map_clone.rs:17:26
    |
 LL |     let _: Option<u64> = Some(&16).map(|b| *b);
    |                          ^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&16).copied()`
 
 error: you are using an explicit closure for copying elements
-  --> $DIR/map_clone.rs:16:25
+  --> $DIR/map_clone.rs:18:25
    |
 LL |     let _: Option<u8> = Some(&1).map(|x| x.clone());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `Some(&1).copied()`
 
 error: you are needlessly cloning iterator elements
-  --> $DIR/map_clone.rs:27:29
+  --> $DIR/map_clone.rs:29:29
    |
 LL |     let _ = std::env::args().map(|v| v.clone());
    |                             ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call
 
-error: aborting due to 6 previous errors
+error: you are explicitly cloning with `.map()`
+  --> $DIR/map_clone.rs:68:13
+   |
+LL |     let y = x.map(|x| String::clone(x));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
+
+error: you are explicitly cloning with `.map()`
+  --> $DIR/map_clone.rs:70:13
+   |
+LL |     let y = x.map(Clone::clone);
+   |             ^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
+
+error: you are explicitly cloning with `.map()`
+  --> $DIR/map_clone.rs:72:13
+   |
+LL |     let y = x.map(String::clone);
+   |             ^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
+
+error: you are explicitly cloning with `.map()`
+  --> $DIR/map_clone.rs:78:13
+   |
+LL |     let y = x.map(|x| String::clone(x));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
+
+error: you are explicitly cloning with `.map()`
+  --> $DIR/map_clone.rs:80:13
+   |
+LL |     let y = x.map(|x| String::clone(x));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
+
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.fixed b/src/tools/clippy/tests/ui/must_use_candidates.fixed
index db20ba29f3d..c057eba4aca 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.fixed
+++ b/src/tools/clippy/tests/ui/must_use_candidates.fixed
@@ -1,9 +1,5 @@
 #![feature(never_type)]
-#![allow(
-    unused_mut,
-    clippy::redundant_allocation,
-    clippy::needless_pass_by_ref_mut
-)]
+#![allow(unused_mut, clippy::redundant_allocation, clippy::needless_pass_by_ref_mut)]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
 use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.rs b/src/tools/clippy/tests/ui/must_use_candidates.rs
index d7e56130245..36019652006 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.rs
+++ b/src/tools/clippy/tests/ui/must_use_candidates.rs
@@ -1,9 +1,5 @@
 #![feature(never_type)]
-#![allow(
-    unused_mut,
-    clippy::redundant_allocation,
-    clippy::needless_pass_by_ref_mut
-)]
+#![allow(unused_mut, clippy::redundant_allocation, clippy::needless_pass_by_ref_mut)]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
 use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.stderr b/src/tools/clippy/tests/ui/must_use_candidates.stderr
index 39446bf6cd9..98175dbd458 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.stderr
+++ b/src/tools/clippy/tests/ui/must_use_candidates.stderr
@@ -1,5 +1,5 @@
 error: this function could have a `#[must_use]` attribute
-  --> $DIR/must_use_candidates.rs:15:1
+  --> $DIR/must_use_candidates.rs:11:1
    |
 LL | pub fn pure(i: u8) -> u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn pure(i: u8) -> u8`
@@ -8,25 +8,25 @@ LL | pub fn pure(i: u8) -> u8 {
    = help: to override `-D warnings` add `#[allow(clippy::must_use_candidate)]`
 
 error: this method could have a `#[must_use]` attribute
-  --> $DIR/must_use_candidates.rs:20:5
+  --> $DIR/must_use_candidates.rs:16:5
    |
 LL |     pub fn inherent_pure(&self) -> u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn inherent_pure(&self) -> u8`
 
 error: this function could have a `#[must_use]` attribute
-  --> $DIR/must_use_candidates.rs:51:1
+  --> $DIR/must_use_candidates.rs:47:1
    |
 LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool`
 
 error: this function could have a `#[must_use]` attribute
-  --> $DIR/must_use_candidates.rs:63:1
+  --> $DIR/must_use_candidates.rs:59:1
    |
 LL | pub fn rcd(_x: Rc<u32>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn rcd(_x: Rc<u32>) -> bool`
 
 error: this function could have a `#[must_use]` attribute
-  --> $DIR/must_use_candidates.rs:71:1
+  --> $DIR/must_use_candidates.rs:67:1
    |
 LL | pub fn arcd(_x: Arc<u32>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn arcd(_x: Arc<u32>) -> bool`
diff --git a/src/tools/clippy/tests/ui/mutex_atomic.rs b/src/tools/clippy/tests/ui/mutex_atomic.rs
index 198b95d8c94..3a51538b742 100644
--- a/src/tools/clippy/tests/ui/mutex_atomic.rs
+++ b/src/tools/clippy/tests/ui/mutex_atomic.rs
@@ -18,9 +18,24 @@ fn main() {
     Mutex::new(&mut x as *mut u32);
     //~^ ERROR: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want
     Mutex::new(0u32);
-    //~^ ERROR: consider using an `AtomicUsize` instead of a `Mutex` here; if you just wan
+    //~^ ERROR: consider using an `AtomicU32` instead of a `Mutex` here; if you just wan
     //~| NOTE: `-D clippy::mutex-integer` implied by `-D warnings`
     Mutex::new(0i32);
-    //~^ ERROR: consider using an `AtomicIsize` instead of a `Mutex` here; if you just wan
+    //~^ ERROR: consider using an `AtomicI32` instead of a `Mutex` here; if you just wan
     Mutex::new(0f32); // there are no float atomics, so this should not lint
+    Mutex::new(0u8);
+    //~^ ERROR: consider using an `AtomicU8` instead of a `Mutex` here; if you just wan
+    Mutex::new(0i16);
+    //~^ ERROR: consider using an `AtomicI16` instead of a `Mutex` here; if you just wan
+    let _x: Mutex<i8> = Mutex::new(0);
+    //~^ ERROR: consider using an `AtomicI8` instead of a `Mutex` here; if you just wan
+    const X: i64 = 0;
+    Mutex::new(X);
+    //~^ ERROR: consider using an `AtomicI64` instead of a `Mutex` here; if you just wan
+
+    // there are no 128 atomics, so these two should not lint
+    {
+        Mutex::new(0u128);
+        let _x: Mutex<i128> = Mutex::new(0);
+    }
 }
diff --git a/src/tools/clippy/tests/ui/mutex_atomic.stderr b/src/tools/clippy/tests/ui/mutex_atomic.stderr
index 483e1ce15f6..91f73d30b53 100644
--- a/src/tools/clippy/tests/ui/mutex_atomic.stderr
+++ b/src/tools/clippy/tests/ui/mutex_atomic.stderr
@@ -31,7 +31,7 @@ error: consider using an `AtomicPtr` instead of a `Mutex` here; if you just want
 LL |     Mutex::new(&mut x as *mut u32);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: consider using an `AtomicUsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
+error: consider using an `AtomicU32` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
   --> $DIR/mutex_atomic.rs:20:5
    |
 LL |     Mutex::new(0u32);
@@ -40,11 +40,35 @@ LL |     Mutex::new(0u32);
    = note: `-D clippy::mutex-integer` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::mutex_integer)]`
 
-error: consider using an `AtomicIsize` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
+error: consider using an `AtomicI32` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
   --> $DIR/mutex_atomic.rs:23:5
    |
 LL |     Mutex::new(0i32);
    |     ^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: consider using an `AtomicU8` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
+  --> $DIR/mutex_atomic.rs:26:5
+   |
+LL |     Mutex::new(0u8);
+   |     ^^^^^^^^^^^^^^^
+
+error: consider using an `AtomicI16` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
+  --> $DIR/mutex_atomic.rs:28:5
+   |
+LL |     Mutex::new(0i16);
+   |     ^^^^^^^^^^^^^^^^
+
+error: consider using an `AtomicI8` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
+  --> $DIR/mutex_atomic.rs:30:25
+   |
+LL |     let _x: Mutex<i8> = Mutex::new(0);
+   |                         ^^^^^^^^^^^^^
+
+error: consider using an `AtomicI64` instead of a `Mutex` here; if you just want the locking behavior and not the internal type, consider using `Mutex<()>`
+  --> $DIR/mutex_atomic.rs:33:5
+   |
+LL |     Mutex::new(X);
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
index 245d36cb734..237f5f5b97a 100644
--- a/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
+++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.fixed
@@ -25,9 +25,13 @@ fn main() {
 
     permissions.set_mode(0o644);
     permissions.set_mode(0o704);
+    // no error
+    permissions.set_mode(0b111_000_100);
 
     // DirBuilderExt::mode
     let mut builder = DirBuilder::new();
     builder.mode(0o755);
     builder.mode(0o406);
+    // no error
+    permissions.set_mode(0b111000100);
 }
diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
index d1559cba554..c8da5dbcec2 100644
--- a/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.rs
@@ -25,9 +25,13 @@ fn main() {
 
     permissions.set_mode(644);
     permissions.set_mode(0o704);
+    // no error
+    permissions.set_mode(0b111_000_100);
 
     // DirBuilderExt::mode
     let mut builder = DirBuilder::new();
     builder.mode(755);
     builder.mode(0o406);
+    // no error
+    permissions.set_mode(0b111000100);
 }
diff --git a/src/tools/clippy/tests/ui/non_octal_unix_permissions.stderr b/src/tools/clippy/tests/ui/non_octal_unix_permissions.stderr
index 78c8f1a2fcf..83688c1b451 100644
--- a/src/tools/clippy/tests/ui/non_octal_unix_permissions.stderr
+++ b/src/tools/clippy/tests/ui/non_octal_unix_permissions.stderr
@@ -20,7 +20,7 @@ LL |     permissions.set_mode(644);
    |                          ^^^ help: consider using an octal literal instead: `0o644`
 
 error: using a non-octal value to set unix file permissions
-  --> $DIR/non_octal_unix_permissions.rs:31:18
+  --> $DIR/non_octal_unix_permissions.rs:33:18
    |
 LL |     builder.mode(755);
    |                  ^^^ help: consider using an octal literal instead: `0o755`
diff --git a/src/tools/clippy/tests/ui/option_as_ref_cloned.fixed b/src/tools/clippy/tests/ui/option_as_ref_cloned.fixed
new file mode 100644
index 00000000000..394dad219f7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/option_as_ref_cloned.fixed
@@ -0,0 +1,21 @@
+#![warn(clippy::option_as_ref_cloned)]
+#![allow(clippy::clone_on_copy)]
+
+fn main() {
+    let mut x = Some(String::new());
+
+    let _: Option<String> = x.clone();
+    let _: Option<String> = x.clone();
+
+    let y = x.as_ref();
+    let _: Option<&String> = y.clone();
+
+    macro_rules! cloned_recv {
+        () => {
+            x.as_ref()
+        };
+    }
+
+    // Don't lint when part of the expression is from a macro
+    let _: Option<String> = cloned_recv!().cloned();
+}
diff --git a/src/tools/clippy/tests/ui/option_as_ref_cloned.rs b/src/tools/clippy/tests/ui/option_as_ref_cloned.rs
new file mode 100644
index 00000000000..7243957927b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/option_as_ref_cloned.rs
@@ -0,0 +1,21 @@
+#![warn(clippy::option_as_ref_cloned)]
+#![allow(clippy::clone_on_copy)]
+
+fn main() {
+    let mut x = Some(String::new());
+
+    let _: Option<String> = x.as_ref().cloned();
+    let _: Option<String> = x.as_mut().cloned();
+
+    let y = x.as_ref();
+    let _: Option<&String> = y.as_ref().cloned();
+
+    macro_rules! cloned_recv {
+        () => {
+            x.as_ref()
+        };
+    }
+
+    // Don't lint when part of the expression is from a macro
+    let _: Option<String> = cloned_recv!().cloned();
+}
diff --git a/src/tools/clippy/tests/ui/option_as_ref_cloned.stderr b/src/tools/clippy/tests/ui/option_as_ref_cloned.stderr
new file mode 100644
index 00000000000..ea03da3b69f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/option_as_ref_cloned.stderr
@@ -0,0 +1,37 @@
+error: cloning an `Option<_>` using `.as_ref().cloned()`
+  --> $DIR/option_as_ref_cloned.rs:7:31
+   |
+LL |     let _: Option<String> = x.as_ref().cloned();
+   |                               ^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::option-as-ref-cloned` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::option_as_ref_cloned)]`
+help: this can be written more concisely by cloning the `Option<_>` directly
+   |
+LL |     let _: Option<String> = x.clone();
+   |                               ~~~~~
+
+error: cloning an `Option<_>` using `.as_mut().cloned()`
+  --> $DIR/option_as_ref_cloned.rs:8:31
+   |
+LL |     let _: Option<String> = x.as_mut().cloned();
+   |                               ^^^^^^^^^^^^^^^
+   |
+help: this can be written more concisely by cloning the `Option<_>` directly
+   |
+LL |     let _: Option<String> = x.clone();
+   |                               ~~~~~
+
+error: cloning an `Option<_>` using `.as_ref().cloned()`
+  --> $DIR/option_as_ref_cloned.rs:11:32
+   |
+LL |     let _: Option<&String> = y.as_ref().cloned();
+   |                                ^^^^^^^^^^^^^^^
+   |
+help: this can be written more concisely by cloning the `Option<_>` directly
+   |
+LL |     let _: Option<&String> = y.clone();
+   |                                ~~~~~
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/redundant_as_str.fixed b/src/tools/clippy/tests/ui/redundant_as_str.fixed
index a38523a7c79..4185b402226 100644
--- a/src/tools/clippy/tests/ui/redundant_as_str.fixed
+++ b/src/tools/clippy/tests/ui/redundant_as_str.fixed
@@ -11,7 +11,7 @@ fn main() {
     let _no_as_str = string.as_bytes();
     let _no_as_str = string.is_empty();
 
-    // These methods are not redundant, and are equivelant to
+    // These methods are not redundant, and are equivalent to
     // doing dereferencing the string and applying the method
     let _not_redundant = string.as_str().escape_unicode();
     let _not_redundant = string.as_str().trim();
diff --git a/src/tools/clippy/tests/ui/redundant_as_str.rs b/src/tools/clippy/tests/ui/redundant_as_str.rs
index 33adb609996..7a74d8a55de 100644
--- a/src/tools/clippy/tests/ui/redundant_as_str.rs
+++ b/src/tools/clippy/tests/ui/redundant_as_str.rs
@@ -11,7 +11,7 @@ fn main() {
     let _no_as_str = string.as_bytes();
     let _no_as_str = string.is_empty();
 
-    // These methods are not redundant, and are equivelant to
+    // These methods are not redundant, and are equivalent to
     // doing dereferencing the string and applying the method
     let _not_redundant = string.as_str().escape_unicode();
     let _not_redundant = string.as_str().trim();
diff --git a/src/tools/clippy/tests/ui/regex.rs b/src/tools/clippy/tests/ui/regex.rs
index 1ea0d65bf1e..4fb6c08bb44 100644
--- a/src/tools/clippy/tests/ui/regex.rs
+++ b/src/tools/clippy/tests/ui/regex.rs
@@ -113,7 +113,7 @@ fn trivial_regex() {
     // #6005: unicode classes in bytes::Regex
     let a_byte_of_unicode = BRegex::new(r"\p{C}");
 
-    // start and end word boundry, introduced in regex 0.10
+    // start and end word boundary, introduced in regex 0.10
     let _ = BRegex::new(r"\<word\>");
     let _ = BRegex::new(r"\b{start}word\b{end}");
 }
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.fixed b/src/tools/clippy/tests/ui/single_char_pattern.fixed
index 79e7eda4070..9573fdbcfde 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.fixed
+++ b/src/tools/clippy/tests/ui/single_char_pattern.fixed
@@ -42,6 +42,8 @@ fn main() {
     x.split('\n');
     x.split('\'');
     x.split('\'');
+    // Issue #11973: Don't escape `"` in `'"'`
+    x.split('"');
 
     let h = HashSet::<String>::new();
     h.contains("X"); // should not warn
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.rs b/src/tools/clippy/tests/ui/single_char_pattern.rs
index 81962c0a6e9..8a04480dbc6 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.rs
+++ b/src/tools/clippy/tests/ui/single_char_pattern.rs
@@ -42,6 +42,8 @@ fn main() {
     x.split("\n");
     x.split("'");
     x.split("\'");
+    // Issue #11973: Don't escape `"` in `'"'`
+    x.split("\"");
 
     let h = HashSet::<String>::new();
     h.contains("X"); // should not warn
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.stderr b/src/tools/clippy/tests/ui/single_char_pattern.stderr
index 6e57ab3489f..781ab316d9d 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.stderr
+++ b/src/tools/clippy/tests/ui/single_char_pattern.stderr
@@ -182,58 +182,64 @@ LL |     x.split("\'");
    |             ^^^^ help: try using a `char` instead: `'\''`
 
 error: single-character string constant used as pattern
-  --> $DIR/single_char_pattern.rs:49:31
+  --> $DIR/single_char_pattern.rs:46:13
+   |
+LL |     x.split("\"");
+   |             ^^^^ help: try using a `char` instead: `'"'`
+
+error: single-character string constant used as pattern
+  --> $DIR/single_char_pattern.rs:51:31
    |
 LL |     x.replace(';', ",").split(","); // issue #2978
    |                               ^^^ help: try using a `char` instead: `','`
 
 error: single-character string constant used as pattern
-  --> $DIR/single_char_pattern.rs:50:19
+  --> $DIR/single_char_pattern.rs:52:19
    |
 LL |     x.starts_with("\x03"); // issue #2996
    |                   ^^^^^^ help: try using a `char` instead: `'\x03'`
 
 error: single-character string constant used as pattern
-  --> $DIR/single_char_pattern.rs:57:13
+  --> $DIR/single_char_pattern.rs:59:13
    |
 LL |     x.split(r"a");
    |             ^^^^ help: try using a `char` instead: `'a'`
 
 error: single-character string constant used as pattern
-  --> $DIR/single_char_pattern.rs:58:13
+  --> $DIR/single_char_pattern.rs:60:13
    |
 LL |     x.split(r#"a"#);
    |             ^^^^^^ help: try using a `char` instead: `'a'`
 
 error: single-character string constant used as pattern
-  --> $DIR/single_char_pattern.rs:59:13
+  --> $DIR/single_char_pattern.rs:61:13
    |
 LL |     x.split(r###"a"###);
    |             ^^^^^^^^^^ help: try using a `char` instead: `'a'`
 
 error: single-character string constant used as pattern
-  --> $DIR/single_char_pattern.rs:60:13
+  --> $DIR/single_char_pattern.rs:62:13
    |
 LL |     x.split(r###"'"###);
    |             ^^^^^^^^^^ help: try using a `char` instead: `'\''`
 
 error: single-character string constant used as pattern
-  --> $DIR/single_char_pattern.rs:61:13
+  --> $DIR/single_char_pattern.rs:63:13
    |
 LL |     x.split(r###"#"###);
    |             ^^^^^^^^^^ help: try using a `char` instead: `'#'`
 
 error: single-character string constant used as pattern
-  --> $DIR/single_char_pattern.rs:63:13
+  --> $DIR/single_char_pattern.rs:65:13
    |
 LL |     x.split(r#"\"#);
    |             ^^^^^^ help: try using a `char` instead: `'\\'`
 
 error: single-character string constant used as pattern
-  --> $DIR/single_char_pattern.rs:64:13
+  --> $DIR/single_char_pattern.rs:66:13
    |
 LL |     x.split(r"\");
    |             ^^^^ help: try using a `char` instead: `'\\'`
 
-error: aborting due to 39 previous errors
+error: aborting due to 40 previous errors
 
diff --git a/src/tools/clippy/tests/ui/str_split.fixed b/src/tools/clippy/tests/ui/str_split.fixed
new file mode 100644
index 00000000000..4f33241da7a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/str_split.fixed
@@ -0,0 +1,145 @@
+#![warn(clippy::str_split_at_newline)]
+
+use core::str::Split;
+use std::ops::Deref;
+
+struct NotStr<'a> {
+    s: &'a str,
+}
+
+impl<'a> NotStr<'a> {
+    fn trim(&'a self) -> &'a str {
+        self.s
+    }
+}
+
+struct DerefsIntoNotStr<'a> {
+    not_str: &'a NotStr<'a>,
+}
+
+impl<'a> Deref for DerefsIntoNotStr<'a> {
+    type Target = NotStr<'a>;
+
+    fn deref(&self) -> &Self::Target {
+        self.not_str
+    }
+}
+
+struct DerefsIntoStr<'a> {
+    s: &'a str,
+}
+
+impl<'a> Deref for DerefsIntoStr<'a> {
+    type Target = str;
+
+    fn deref(&self) -> &Self::Target {
+        self.s
+    }
+}
+
+macro_rules! trim_split {
+    ( $x:expr, $y:expr ) => {
+        $x.trim().split($y);
+    };
+}
+
+macro_rules! make_str {
+    ( $x: expr ) => {
+        format!("x={}", $x)
+    };
+}
+
+fn main() {
+    let s1 = "hello\nworld\n";
+    let s2 = s1.to_owned();
+
+    // CASES THAT SHOULD EMIT A LINT
+
+    // Splitting a `str` variable at "\n" or "\r\n" after trimming should warn
+    let _ = s1.lines();
+    #[allow(clippy::single_char_pattern)]
+    let _ = s1.lines();
+    let _ = s1.lines();
+
+    // Splitting a `String` variable at "\n" or "\r\n" after trimming should warn
+    let _ = s2.lines();
+    #[allow(clippy::single_char_pattern)]
+    let _ = s2.lines();
+    let _ = s2.lines();
+
+    // Splitting a variable that derefs into `str` at "\n" or "\r\n" after trimming should warn.
+    let s3 = DerefsIntoStr { s: s1 };
+    let _ = s3.lines();
+    #[allow(clippy::single_char_pattern)]
+    let _ = s3.lines();
+    let _ = s3.lines();
+
+    // If the `&str` is generated by a macro then the macro should not be expanded in the suggested fix.
+    let _ = make_str!(s1).lines();
+
+    // CASES THAT SHOULD NOT EMIT A LINT
+
+    // Splitting a `str` constant at "\n" or "\r\n" after trimming should not warn
+    let _ = "hello\nworld\n".trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = "hello\nworld\n".trim().split("\n");
+    let _ = "hello\nworld\n".trim().split("\r\n");
+
+    // Splitting a `str` variable at "\n" or "\r\n" without trimming should not warn, since it is not
+    // equivalent
+    let _ = s1.split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s1.split("\n");
+    let _ = s1.split("\r\n");
+
+    // Splitting a `String` variable at "\n" or "\r\n" without trimming should not warn.
+    let _ = s2.split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s2.split("\n");
+
+    // Splitting a variable that derefs into `str` at "\n" or "\r\n" without trimming should not warn.
+    let _ = s3.split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s3.split("\n");
+    let _ = s3.split("\r\n");
+    let _ = s2.split("\r\n");
+
+    // Splitting a `str` variable at other separators should not warn
+    let _ = s1.trim().split('\r');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s1.trim().split("\r");
+    let _ = s1.trim().split("\n\r");
+    let _ = s1.trim().split("\r \n");
+
+    // Splitting a `String` variable at other separators should not warn
+    let _ = s2.trim().split('\r');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s2.trim().split("\r");
+    let _ = s2.trim().split("\n\r");
+
+    // Splitting a variable that derefs into `str` at other separators should not warn
+    let _ = s3.trim().split('\r');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s3.trim().split("\r");
+    let _ = s3.trim().split("\n\r");
+    let _ = s3.trim().split("\r \n");
+    let _ = s2.trim().split("\r \n");
+
+    // Using `trim` and `split` on other types should not warn
+    let not_str = NotStr { s: s1 };
+    let _ = not_str.trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = not_str.trim().split("\n");
+    let _ = not_str.trim().split("\r\n");
+    let derefs_into_not_str = DerefsIntoNotStr { not_str: &not_str };
+    let _ = derefs_into_not_str.trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = derefs_into_not_str.trim().split("\n");
+    let _ = derefs_into_not_str.trim().split("\r\n");
+
+    // Code generated by macros should not create a warning
+    trim_split!(s1, "\r\n");
+    trim_split!("hello\nworld\n", "\r\n");
+    trim_split!(s2, "\r\n");
+    trim_split!(s3, "\r\n");
+}
diff --git a/src/tools/clippy/tests/ui/str_split.rs b/src/tools/clippy/tests/ui/str_split.rs
new file mode 100644
index 00000000000..f24caa61c30
--- /dev/null
+++ b/src/tools/clippy/tests/ui/str_split.rs
@@ -0,0 +1,145 @@
+#![warn(clippy::str_split_at_newline)]
+
+use core::str::Split;
+use std::ops::Deref;
+
+struct NotStr<'a> {
+    s: &'a str,
+}
+
+impl<'a> NotStr<'a> {
+    fn trim(&'a self) -> &'a str {
+        self.s
+    }
+}
+
+struct DerefsIntoNotStr<'a> {
+    not_str: &'a NotStr<'a>,
+}
+
+impl<'a> Deref for DerefsIntoNotStr<'a> {
+    type Target = NotStr<'a>;
+
+    fn deref(&self) -> &Self::Target {
+        self.not_str
+    }
+}
+
+struct DerefsIntoStr<'a> {
+    s: &'a str,
+}
+
+impl<'a> Deref for DerefsIntoStr<'a> {
+    type Target = str;
+
+    fn deref(&self) -> &Self::Target {
+        self.s
+    }
+}
+
+macro_rules! trim_split {
+    ( $x:expr, $y:expr ) => {
+        $x.trim().split($y);
+    };
+}
+
+macro_rules! make_str {
+    ( $x: expr ) => {
+        format!("x={}", $x)
+    };
+}
+
+fn main() {
+    let s1 = "hello\nworld\n";
+    let s2 = s1.to_owned();
+
+    // CASES THAT SHOULD EMIT A LINT
+
+    // Splitting a `str` variable at "\n" or "\r\n" after trimming should warn
+    let _ = s1.trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s1.trim().split("\n");
+    let _ = s1.trim().split("\r\n");
+
+    // Splitting a `String` variable at "\n" or "\r\n" after trimming should warn
+    let _ = s2.trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s2.trim().split("\n");
+    let _ = s2.trim().split("\r\n");
+
+    // Splitting a variable that derefs into `str` at "\n" or "\r\n" after trimming should warn.
+    let s3 = DerefsIntoStr { s: s1 };
+    let _ = s3.trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s3.trim().split("\n");
+    let _ = s3.trim().split("\r\n");
+
+    // If the `&str` is generated by a macro then the macro should not be expanded in the suggested fix.
+    let _ = make_str!(s1).trim().split('\n');
+
+    // CASES THAT SHOULD NOT EMIT A LINT
+
+    // Splitting a `str` constant at "\n" or "\r\n" after trimming should not warn
+    let _ = "hello\nworld\n".trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = "hello\nworld\n".trim().split("\n");
+    let _ = "hello\nworld\n".trim().split("\r\n");
+
+    // Splitting a `str` variable at "\n" or "\r\n" without trimming should not warn, since it is not
+    // equivalent
+    let _ = s1.split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s1.split("\n");
+    let _ = s1.split("\r\n");
+
+    // Splitting a `String` variable at "\n" or "\r\n" without trimming should not warn.
+    let _ = s2.split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s2.split("\n");
+
+    // Splitting a variable that derefs into `str` at "\n" or "\r\n" without trimming should not warn.
+    let _ = s3.split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s3.split("\n");
+    let _ = s3.split("\r\n");
+    let _ = s2.split("\r\n");
+
+    // Splitting a `str` variable at other separators should not warn
+    let _ = s1.trim().split('\r');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s1.trim().split("\r");
+    let _ = s1.trim().split("\n\r");
+    let _ = s1.trim().split("\r \n");
+
+    // Splitting a `String` variable at other separators should not warn
+    let _ = s2.trim().split('\r');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s2.trim().split("\r");
+    let _ = s2.trim().split("\n\r");
+
+    // Splitting a variable that derefs into `str` at other separators should not warn
+    let _ = s3.trim().split('\r');
+    #[allow(clippy::single_char_pattern)]
+    let _ = s3.trim().split("\r");
+    let _ = s3.trim().split("\n\r");
+    let _ = s3.trim().split("\r \n");
+    let _ = s2.trim().split("\r \n");
+
+    // Using `trim` and `split` on other types should not warn
+    let not_str = NotStr { s: s1 };
+    let _ = not_str.trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = not_str.trim().split("\n");
+    let _ = not_str.trim().split("\r\n");
+    let derefs_into_not_str = DerefsIntoNotStr { not_str: &not_str };
+    let _ = derefs_into_not_str.trim().split('\n');
+    #[allow(clippy::single_char_pattern)]
+    let _ = derefs_into_not_str.trim().split("\n");
+    let _ = derefs_into_not_str.trim().split("\r\n");
+
+    // Code generated by macros should not create a warning
+    trim_split!(s1, "\r\n");
+    trim_split!("hello\nworld\n", "\r\n");
+    trim_split!(s2, "\r\n");
+    trim_split!(s3, "\r\n");
+}
diff --git a/src/tools/clippy/tests/ui/str_split.stderr b/src/tools/clippy/tests/ui/str_split.stderr
new file mode 100644
index 00000000000..ee0a9653711
--- /dev/null
+++ b/src/tools/clippy/tests/ui/str_split.stderr
@@ -0,0 +1,65 @@
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:59:13
+   |
+LL |     let _ = s1.trim().split('\n');
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
+   |
+   = note: `-D clippy::str-split-at-newline` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::str_split_at_newline)]`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:61:13
+   |
+LL |     let _ = s1.trim().split("\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:62:13
+   |
+LL |     let _ = s1.trim().split("\r\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s1.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:65:13
+   |
+LL |     let _ = s2.trim().split('\n');
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:67:13
+   |
+LL |     let _ = s2.trim().split("\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:68:13
+   |
+LL |     let _ = s2.trim().split("\r\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s2.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:72:13
+   |
+LL |     let _ = s3.trim().split('\n');
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:74:13
+   |
+LL |     let _ = s3.trim().split("\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:75:13
+   |
+LL |     let _ = s3.trim().split("\r\n");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `s3.lines()`
+
+error: using `str.trim().split()` with hard-coded newlines
+  --> $DIR/str_split.rs:78:13
+   |
+LL |     let _ = make_str!(s1).trim().split('\n');
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `str.lines()` instead: `make_str!(s1).lines()`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/struct_fields.rs b/src/tools/clippy/tests/ui/struct_fields.rs
index 8b1a1446e3c..7c9e9d8ed26 100644
--- a/src/tools/clippy/tests/ui/struct_fields.rs
+++ b/src/tools/clippy/tests/ui/struct_fields.rs
@@ -39,14 +39,14 @@ struct DataStruct {
 struct DoublePrefix {
     //~^ ERROR: all fields have the same prefix: `some_data`
     some_data_a: bool,
-    some_data_b: bool,
+    some_data_b: i8,
     some_data_c: bool,
 }
 
 struct DoublePostfix {
     //~^ ERROR: all fields have the same postfix: `some_data`
     a_some_data: bool,
-    b_some_data: bool,
+    b_some_data: i8,
     c_some_data: bool,
 }
 
@@ -54,18 +54,18 @@ struct DoublePostfix {
 struct NotSnakeCase {
     //~^ ERROR: all fields have the same postfix: `someData`
     a_someData: bool,
-    b_someData: bool,
+    b_someData: i8,
     c_someData: bool,
 }
 #[allow(non_snake_case)]
 struct NotSnakeCase2 {
     //~^ ERROR: all fields have the same prefix: `someData`
     someData_c: bool,
-    someData_b: bool,
+    someData_b: i8,
     someData_a_b: bool,
 }
 
-// no error, threshold is 3 fiels by default
+// no error, threshold is 3 fields by default
 struct Fooo {
     foo: u8,
     bar: u8,
@@ -328,4 +328,18 @@ external! {
 
 }
 
+// Should not warn
+struct Config {
+    use_foo: bool,
+    use_bar: bool,
+    use_baz: bool,
+}
+
+struct Use {
+    use_foo: bool,
+    //~^ ERROR: field name starts with the struct's name
+    use_bar: bool,
+    use_baz: bool,
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/struct_fields.stderr b/src/tools/clippy/tests/ui/struct_fields.stderr
index 4ca57715b18..d2bdbd17d5c 100644
--- a/src/tools/clippy/tests/ui/struct_fields.stderr
+++ b/src/tools/clippy/tests/ui/struct_fields.stderr
@@ -45,7 +45,7 @@ error: all fields have the same prefix: `some_data`
 LL | / struct DoublePrefix {
 LL | |
 LL | |     some_data_a: bool,
-LL | |     some_data_b: bool,
+LL | |     some_data_b: i8,
 LL | |     some_data_c: bool,
 LL | | }
    | |_^
@@ -58,7 +58,7 @@ error: all fields have the same postfix: `some_data`
 LL | / struct DoublePostfix {
 LL | |
 LL | |     a_some_data: bool,
-LL | |     b_some_data: bool,
+LL | |     b_some_data: i8,
 LL | |     c_some_data: bool,
 LL | | }
    | |_^
@@ -71,7 +71,7 @@ error: all fields have the same postfix: `someData`
 LL | / struct NotSnakeCase {
 LL | |
 LL | |     a_someData: bool,
-LL | |     b_someData: bool,
+LL | |     b_someData: i8,
 LL | |     c_someData: bool,
 LL | | }
    | |_^
@@ -84,7 +84,7 @@ error: all fields have the same prefix: `someData`
 LL | / struct NotSnakeCase2 {
 LL | |
 LL | |     someData_c: bool,
-LL | |     someData_b: bool,
+LL | |     someData_b: i8,
 LL | |     someData_a_b: bool,
 LL | | }
    | |_^
@@ -261,5 +261,23 @@ LL |       mk_struct_full_def!(PrefixData, some_data, some_meta, some_other);
    = help: remove the prefixes
    = note: this error originates in the macro `mk_struct_full_def` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 21 previous errors
+error: field name starts with the struct's name
+  --> $DIR/struct_fields.rs:339:5
+   |
+LL |     use_foo: bool,
+   |     ^^^^^^^^^^^^^
+
+error: field name starts with the struct's name
+  --> $DIR/struct_fields.rs:341:5
+   |
+LL |     use_bar: bool,
+   |     ^^^^^^^^^^^^^
+
+error: field name starts with the struct's name
+  --> $DIR/struct_fields.rs:342:5
+   |
+LL |     use_baz: bool,
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed
new file mode 100644
index 00000000000..bbde25b0a88
--- /dev/null
+++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.fixed
@@ -0,0 +1,30 @@
+#![warn(clippy::thread_local_initializer_can_be_made_const)]
+
+use std::cell::RefCell;
+
+fn main() {
+    // lint and suggest const
+    thread_local! {
+        static BUF_1: RefCell<String> = const { RefCell::new(String::new()) };
+    }
+    //~^^ ERROR: initializer for `thread_local` value can be made `const`
+
+    // don't lint
+    thread_local! {
+        static BUF_2: RefCell<String> = const { RefCell::new(String::new()) };
+    }
+
+    thread_local! {
+        static SIMPLE:i32 = const { 1 };
+    }
+    //~^^ ERROR: initializer for `thread_local` value can be made `const`
+
+    // lint and suggest const for all non const items
+    thread_local! {
+        static BUF_3_CAN_BE_MADE_CONST: RefCell<String> = const { RefCell::new(String::new()) };
+        static CONST_MIXED_WITH:i32 = const { 1 };
+        static BUF_4_CAN_BE_MADE_CONST: RefCell<String> = const { RefCell::new(String::new()) };
+    }
+    //~^^^^ ERROR: initializer for `thread_local` value can be made `const`
+    //~^^^ ERROR: initializer for `thread_local` value can be made `const`
+}
diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs
new file mode 100644
index 00000000000..3d7aacf2f09
--- /dev/null
+++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.rs
@@ -0,0 +1,30 @@
+#![warn(clippy::thread_local_initializer_can_be_made_const)]
+
+use std::cell::RefCell;
+
+fn main() {
+    // lint and suggest const
+    thread_local! {
+        static BUF_1: RefCell<String> = RefCell::new(String::new());
+    }
+    //~^^ ERROR: initializer for `thread_local` value can be made `const`
+
+    // don't lint
+    thread_local! {
+        static BUF_2: RefCell<String> = const { RefCell::new(String::new()) };
+    }
+
+    thread_local! {
+        static SIMPLE:i32 = 1;
+    }
+    //~^^ ERROR: initializer for `thread_local` value can be made `const`
+
+    // lint and suggest const for all non const items
+    thread_local! {
+        static BUF_3_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new());
+        static CONST_MIXED_WITH:i32 = const { 1 };
+        static BUF_4_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new());
+    }
+    //~^^^^ ERROR: initializer for `thread_local` value can be made `const`
+    //~^^^ ERROR: initializer for `thread_local` value can be made `const`
+}
diff --git a/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr
new file mode 100644
index 00000000000..b35bd306b52
--- /dev/null
+++ b/src/tools/clippy/tests/ui/thread_local_initializer_can_be_made_const.stderr
@@ -0,0 +1,29 @@
+error: initializer for `thread_local` value can be made `const`
+  --> $DIR/thread_local_initializer_can_be_made_const.rs:8:41
+   |
+LL |         static BUF_1: RefCell<String> = RefCell::new(String::new());
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }`
+   |
+   = note: `-D clippy::thread-local-initializer-can-be-made-const` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::thread_local_initializer_can_be_made_const)]`
+
+error: initializer for `thread_local` value can be made `const`
+  --> $DIR/thread_local_initializer_can_be_made_const.rs:18:29
+   |
+LL |         static SIMPLE:i32 = 1;
+   |                             ^ help: replace with: `const { 1 }`
+
+error: initializer for `thread_local` value can be made `const`
+  --> $DIR/thread_local_initializer_can_be_made_const.rs:24:59
+   |
+LL |         static BUF_3_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new());
+   |                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }`
+
+error: initializer for `thread_local` value can be made `const`
+  --> $DIR/thread_local_initializer_can_be_made_const.rs:26:59
+   |
+LL |         static BUF_4_CAN_BE_MADE_CONST: RefCell<String> = RefCell::new(String::new());
+   |                                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `const { RefCell::new(String::new()) }`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.rs b/src/tools/clippy/tests/ui/unconditional_recursion.rs
index 1169118de83..e1a2d6a90b8 100644
--- a/src/tools/clippy/tests/ui/unconditional_recursion.rs
+++ b/src/tools/clippy/tests/ui/unconditional_recursion.rs
@@ -1,7 +1,7 @@
 //@no-rustfix
 
 #![warn(clippy::unconditional_recursion)]
-#![allow(clippy::partialeq_ne_impl)]
+#![allow(clippy::partialeq_ne_impl, clippy::default_constructed_unit_structs)]
 
 enum Foo {
     A,
@@ -158,6 +158,112 @@ struct S5;
 impl_partial_eq!(S5);
 //~^ ERROR: function cannot return without recursing
 
+struct S6 {
+    field: String,
+}
+
+impl PartialEq for S6 {
+    fn eq(&self, other: &Self) -> bool {
+        let mine = &self.field;
+        let theirs = &other.field;
+        mine == theirs // Should not warn!
+    }
+}
+
+struct S7<'a> {
+    field: &'a S7<'a>,
+}
+
+impl<'a> PartialEq for S7<'a> {
+    fn eq(&self, other: &Self) -> bool {
+        //~^ ERROR: function cannot return without recursing
+        let mine = &self.field;
+        let theirs = &other.field;
+        mine == theirs
+    }
+}
+
+struct S8 {
+    num: i32,
+    field: Option<Box<S8>>,
+}
+
+impl PartialEq for S8 {
+    fn eq(&self, other: &Self) -> bool {
+        if self.num != other.num {
+            return false;
+        }
+
+        let (this, other) = match (self.field.as_deref(), other.field.as_deref()) {
+            (Some(x1), Some(x2)) => (x1, x2),
+            (None, None) => return true,
+            _ => return false,
+        };
+
+        this == other
+    }
+}
+
+struct S9;
+
+impl std::string::ToString for S9 {
+    fn to_string(&self) -> String {
+        //~^ ERROR: function cannot return without recursing
+        self.to_string()
+    }
+}
+
+struct S10;
+
+impl std::string::ToString for S10 {
+    fn to_string(&self) -> String {
+        //~^ ERROR: function cannot return without recursing
+        let x = self;
+        x.to_string()
+    }
+}
+
+struct S11;
+
+impl std::string::ToString for S11 {
+    fn to_string(&self) -> String {
+        //~^ ERROR: function cannot return without recursing
+        (self as &Self).to_string()
+    }
+}
+
+struct S12;
+
+impl std::default::Default for S12 {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl S12 {
+    fn new() -> Self {
+        //~^ ERROR: function cannot return without recursing
+        Self::default()
+    }
+
+    fn bar() -> Self {
+        // Should not warn!
+        Self::default()
+    }
+}
+
+#[derive(Default)]
+struct S13 {
+    f: u32,
+}
+
+impl S13 {
+    fn new() -> Self {
+        // Shoud not warn!
+        Self::default()
+    }
+}
+
 fn main() {
     // test code goes here
 }
diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.stderr b/src/tools/clippy/tests/ui/unconditional_recursion.stderr
index 1fb01c00f19..5d82e2a9f31 100644
--- a/src/tools/clippy/tests/ui/unconditional_recursion.stderr
+++ b/src/tools/clippy/tests/ui/unconditional_recursion.stderr
@@ -23,6 +23,39 @@ LL |         self.eq(other)
    = help: a `loop` may express intention better if this is on purpose
 
 error: function cannot return without recursing
+  --> $DIR/unconditional_recursion.rs:210:5
+   |
+LL |     fn to_string(&self) -> String {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |         self.to_string()
+   |         ---------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/unconditional_recursion.rs:219:5
+   |
+LL |     fn to_string(&self) -> String {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+...
+LL |         x.to_string()
+   |         ------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
+  --> $DIR/unconditional_recursion.rs:229:5
+   |
+LL |     fn to_string(&self) -> String {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
+LL |
+LL |         (self as &Self).to_string()
+   |         --------------------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+
+error: function cannot return without recursing
   --> $DIR/unconditional_recursion.rs:12:5
    |
 LL | /     fn ne(&self, other: &Self) -> bool {
@@ -55,6 +88,34 @@ LL |         self == other
    |         ^^^^^^^^^^^^^
 
 error: function cannot return without recursing
+  --> $DIR/unconditional_recursion.rs:28:5
+   |
+LL | /     fn ne(&self, other: &Self) -> bool {
+LL | |         self != &Foo2::B // no error here
+LL | |     }
+   | |_____^
+   |
+note: recursive call site
+  --> $DIR/unconditional_recursion.rs:29:9
+   |
+LL |         self != &Foo2::B // no error here
+   |         ^^^^^^^^^^^^^^^^
+
+error: function cannot return without recursing
+  --> $DIR/unconditional_recursion.rs:31:5
+   |
+LL | /     fn eq(&self, other: &Self) -> bool {
+LL | |         self == &Foo2::B // no error here
+LL | |     }
+   | |_____^
+   |
+note: recursive call site
+  --> $DIR/unconditional_recursion.rs:32:9
+   |
+LL |         self == &Foo2::B // no error here
+   |         ^^^^^^^^^^^^^^^^
+
+error: function cannot return without recursing
   --> $DIR/unconditional_recursion.rs:42:5
    |
 LL | /     fn ne(&self, other: &Self) -> bool {
@@ -247,5 +308,37 @@ LL | impl_partial_eq!(S5);
    | -------------------- in this macro invocation
    = note: this error originates in the macro `impl_partial_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 19 previous errors
+error: function cannot return without recursing
+  --> $DIR/unconditional_recursion.rs:178:5
+   |
+LL | /     fn eq(&self, other: &Self) -> bool {
+LL | |
+LL | |         let mine = &self.field;
+LL | |         let theirs = &other.field;
+LL | |         mine == theirs
+LL | |     }
+   | |_____^
+   |
+note: recursive call site
+  --> $DIR/unconditional_recursion.rs:182:9
+   |
+LL |         mine == theirs
+   |         ^^^^^^^^^^^^^^
+
+error: function cannot return without recursing
+  --> $DIR/unconditional_recursion.rs:244:5
+   |
+LL | /     fn new() -> Self {
+LL | |
+LL | |         Self::default()
+LL | |     }
+   | |_____^
+   |
+note: recursive call site
+  --> $DIR/unconditional_recursion.rs:246:9
+   |
+LL |         Self::default()
+   |         ^^^^^^^^^^^^^^^
+
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed b/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed
index cba32ce6b77..c0ccd41c19a 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.fixed
@@ -7,10 +7,12 @@
 #[warn(clippy::if_not_else)]
 #[warn(clippy::unnecessary_cast)]
 #[warn(clippy::useless_transmute)]
-// Shouldn't suggest rustc lint name(`dead_code`)
-#[warn(clippy::eq_op)]
+// Should suggest rustc lint name(`dead_code`)
+#[warn(dead_code)]
 // Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`)
 #[warn(clippy::unused_self)]
 // Shouldn't suggest renamed clippy lint name(`const_static_lifetime`)
 #[warn(clippy::redundant_static_lifetimes)]
+// issue #118183, should report `missing_docs` from rustc lint
+#[warn(missing_docs)]
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.rs b/src/tools/clippy/tests/ui/unknown_clippy_lints.rs
index c15d541974f..7a59ad364aa 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.rs
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.rs
@@ -7,10 +7,12 @@
 #[warn(clippy::if_not_els)]
 #[warn(clippy::UNNecsaRy_cAst)]
 #[warn(clippy::useles_transute)]
-// Shouldn't suggest rustc lint name(`dead_code`)
+// Should suggest rustc lint name(`dead_code`)
 #[warn(clippy::dead_cod)]
 // Shouldn't suggest removed/deprecated clippy lint name(`unused_collect`)
 #[warn(clippy::unused_colle)]
 // Shouldn't suggest renamed clippy lint name(`const_static_lifetime`)
 #[warn(clippy::const_static_lifetim)]
+// issue #118183, should report `missing_docs` from rustc lint
+#[warn(clippy::missing_docs)]
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
index ee82db31c2c..432c7f72e32 100644
--- a/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
+++ b/src/tools/clippy/tests/ui/unknown_clippy_lints.stderr
@@ -35,7 +35,12 @@ error: unknown lint: `clippy::dead_cod`
   --> $DIR/unknown_clippy_lints.rs:11:8
    |
 LL | #[warn(clippy::dead_cod)]
-   |        ^^^^^^^^^^^^^^^^ help: did you mean: `clippy::eq_op`
+   |        ^^^^^^^^^^^^^^^^
+   |
+help: a lint with a similar name exists in `rustc` lints
+   |
+LL | #[warn(dead_code)]
+   |        ~~~~~~~~~
 
 error: unknown lint: `clippy::unused_colle`
   --> $DIR/unknown_clippy_lints.rs:13:8
@@ -49,5 +54,16 @@ error: unknown lint: `clippy::const_static_lifetim`
 LL | #[warn(clippy::const_static_lifetim)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::redundant_static_lifetimes`
 
-error: aborting due to 8 previous errors
+error: unknown lint: `clippy::missing_docs`
+  --> $DIR/unknown_clippy_lints.rs:17:8
+   |
+LL | #[warn(clippy::missing_docs)]
+   |        ^^^^^^^^^^^^^^^^^^^^
+   |
+help: a lint with a similar name exists in `rustc` lints
+   |
+LL | #[warn(missing_docs)]
+   |        ~~~~~~~~~~~~
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
index 66598f89208..d8031c484e5 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
@@ -47,6 +47,18 @@ impl Drop for Issue9427FollowUp {
     }
 }
 
+struct Issue9427Followup2 {
+    ptr: *const (),
+}
+impl Issue9427Followup2 {
+    fn from_owned(ptr: *const ()) -> Option<Self> {
+        (!ptr.is_null()).then(|| Self { ptr })
+    }
+}
+impl Drop for Issue9427Followup2 {
+    fn drop(&mut self) {}
+}
+
 struct Issue10437;
 impl Deref for Issue10437 {
     type Target = u32;
@@ -128,6 +140,7 @@ fn main() {
     // Should not lint - bool
     let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
     let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop
+    let _ = false.then(|| Issue9427Followup2 { ptr: std::ptr::null() });
 
     // should not lint, bind_instead_of_map takes priority
     let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
index 5045fcd790e..ea55b1d9a90 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
@@ -47,6 +47,18 @@ impl Drop for Issue9427FollowUp {
     }
 }
 
+struct Issue9427Followup2 {
+    ptr: *const (),
+}
+impl Issue9427Followup2 {
+    fn from_owned(ptr: *const ()) -> Option<Self> {
+        (!ptr.is_null()).then(|| Self { ptr })
+    }
+}
+impl Drop for Issue9427Followup2 {
+    fn drop(&mut self) {}
+}
+
 struct Issue10437;
 impl Deref for Issue10437 {
     type Target = u32;
@@ -128,6 +140,7 @@ fn main() {
     // Should not lint - bool
     let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
     let _ = false.then(|| Issue9427FollowUp); // Issue9427FollowUp has a significant drop
+    let _ = false.then(|| Issue9427Followup2 { ptr: std::ptr::null() });
 
     // should not lint, bind_instead_of_map takes priority
     let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
index 466664aee6c..6ff2691a461 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
@@ -1,5 +1,5 @@
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:71:13
+  --> $DIR/unnecessary_lazy_eval.rs:83:13
    |
 LL |     let _ = opt.unwrap_or_else(|| 2);
    |             ^^^^--------------------
@@ -10,7 +10,7 @@ LL |     let _ = opt.unwrap_or_else(|| 2);
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_lazy_evaluations)]`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:72:13
+  --> $DIR/unnecessary_lazy_eval.rs:84:13
    |
 LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |             ^^^^---------------------------------
@@ -18,7 +18,7 @@ LL |     let _ = opt.unwrap_or_else(|| astronomers_pi);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:73:13
+  --> $DIR/unnecessary_lazy_eval.rs:85:13
    |
 LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |             ^^^^-------------------------------------
@@ -26,7 +26,7 @@ LL |     let _ = opt.unwrap_or_else(|| ext_str.some_field);
    |                 help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:75:13
+  --> $DIR/unnecessary_lazy_eval.rs:87:13
    |
 LL |     let _ = opt.and_then(|_| ext_opt);
    |             ^^^^---------------------
@@ -34,7 +34,7 @@ LL |     let _ = opt.and_then(|_| ext_opt);
    |                 help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:76:13
+  --> $DIR/unnecessary_lazy_eval.rs:88:13
    |
 LL |     let _ = opt.or_else(|| ext_opt);
    |             ^^^^-------------------
@@ -42,7 +42,7 @@ LL |     let _ = opt.or_else(|| ext_opt);
    |                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:77:13
+  --> $DIR/unnecessary_lazy_eval.rs:89:13
    |
 LL |     let _ = opt.or_else(|| None);
    |             ^^^^----------------
@@ -50,7 +50,7 @@ LL |     let _ = opt.or_else(|| None);
    |                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:78:13
+  --> $DIR/unnecessary_lazy_eval.rs:90:13
    |
 LL |     let _ = opt.get_or_insert_with(|| 2);
    |             ^^^^------------------------
@@ -58,7 +58,7 @@ LL |     let _ = opt.get_or_insert_with(|| 2);
    |                 help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:79:13
+  --> $DIR/unnecessary_lazy_eval.rs:91:13
    |
 LL |     let _ = opt.ok_or_else(|| 2);
    |             ^^^^----------------
@@ -66,7 +66,7 @@ LL |     let _ = opt.ok_or_else(|| 2);
    |                 help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:80:13
+  --> $DIR/unnecessary_lazy_eval.rs:92:13
    |
 LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
    |             ^^^^^^^^^^^^^^^^^-------------------------------
@@ -74,7 +74,7 @@ LL |     let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
    |                              help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:81:13
+  --> $DIR/unnecessary_lazy_eval.rs:93:13
    |
 LL |     let _ = cond.then(|| astronomers_pi);
    |             ^^^^^-----------------------
@@ -82,7 +82,7 @@ LL |     let _ = cond.then(|| astronomers_pi);
    |                  help: use `then_some(..)` instead: `then_some(astronomers_pi)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:82:13
+  --> $DIR/unnecessary_lazy_eval.rs:94:13
    |
 LL |     let _ = true.then(|| -> _ {});
    |             ^^^^^----------------
@@ -90,7 +90,7 @@ LL |     let _ = true.then(|| -> _ {});
    |                  help: use `then_some(..)` instead: `then_some({})`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:83:13
+  --> $DIR/unnecessary_lazy_eval.rs:95:13
    |
 LL |     let _ = true.then(|| {});
    |             ^^^^^-----------
@@ -98,7 +98,7 @@ LL |     let _ = true.then(|| {});
    |                  help: use `then_some(..)` instead: `then_some({})`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:87:13
+  --> $DIR/unnecessary_lazy_eval.rs:99:13
    |
 LL |     let _ = Some(1).unwrap_or_else(|| *r);
    |             ^^^^^^^^---------------------
@@ -106,7 +106,7 @@ LL |     let _ = Some(1).unwrap_or_else(|| *r);
    |                     help: use `unwrap_or(..)` instead: `unwrap_or(*r)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:89:13
+  --> $DIR/unnecessary_lazy_eval.rs:101:13
    |
 LL |     let _ = Some(1).unwrap_or_else(|| *b);
    |             ^^^^^^^^---------------------
@@ -114,7 +114,7 @@ LL |     let _ = Some(1).unwrap_or_else(|| *b);
    |                     help: use `unwrap_or(..)` instead: `unwrap_or(*b)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:91:13
+  --> $DIR/unnecessary_lazy_eval.rs:103:13
    |
 LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &r);
    |             ^^^^^^^^^^^^^^^^^---------------------
@@ -122,7 +122,7 @@ LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &r);
    |                              help: use `unwrap_or(..)` instead: `unwrap_or(&r)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:92:13
+  --> $DIR/unnecessary_lazy_eval.rs:104:13
    |
 LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &b);
    |             ^^^^^^^^^^^^^^^^^---------------------
@@ -130,7 +130,7 @@ LL |     let _ = Some(1).as_ref().unwrap_or_else(|| &b);
    |                              help: use `unwrap_or(..)` instead: `unwrap_or(&b)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:95:13
+  --> $DIR/unnecessary_lazy_eval.rs:107:13
    |
 LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |             ^^^^^^^^^--------------------
@@ -138,7 +138,7 @@ LL |     let _ = Some(10).unwrap_or_else(|| 2);
    |                      help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:96:13
+  --> $DIR/unnecessary_lazy_eval.rs:108:13
    |
 LL |     let _ = Some(10).and_then(|_| ext_opt);
    |             ^^^^^^^^^---------------------
@@ -146,7 +146,7 @@ LL |     let _ = Some(10).and_then(|_| ext_opt);
    |                      help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:97:28
+  --> $DIR/unnecessary_lazy_eval.rs:109:28
    |
 LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                            ^^^^^-------------------
@@ -154,7 +154,7 @@ LL |     let _: Option<usize> = None.or_else(|| ext_opt);
    |                                 help: use `or(..)` instead: `or(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:98:13
+  --> $DIR/unnecessary_lazy_eval.rs:110:13
    |
 LL |     let _ = None.get_or_insert_with(|| 2);
    |             ^^^^^------------------------
@@ -162,7 +162,7 @@ LL |     let _ = None.get_or_insert_with(|| 2);
    |                  help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:99:35
+  --> $DIR/unnecessary_lazy_eval.rs:111:35
    |
 LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                   ^^^^^----------------
@@ -170,7 +170,7 @@ LL |     let _: Result<usize, usize> = None.ok_or_else(|| 2);
    |                                        help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:100:28
+  --> $DIR/unnecessary_lazy_eval.rs:112:28
    |
 LL |     let _: Option<usize> = None.or_else(|| None);
    |                            ^^^^^----------------
@@ -178,7 +178,7 @@ LL |     let _: Option<usize> = None.or_else(|| None);
    |                                 help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:103:13
+  --> $DIR/unnecessary_lazy_eval.rs:115:13
    |
 LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |             ^^^^^^^--------------------
@@ -186,7 +186,7 @@ LL |     let _ = deep.0.unwrap_or_else(|| 2);
    |                    help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:104:13
+  --> $DIR/unnecessary_lazy_eval.rs:116:13
    |
 LL |     let _ = deep.0.and_then(|_| ext_opt);
    |             ^^^^^^^---------------------
@@ -194,7 +194,7 @@ LL |     let _ = deep.0.and_then(|_| ext_opt);
    |                    help: use `and(..)` instead: `and(ext_opt)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:105:13
+  --> $DIR/unnecessary_lazy_eval.rs:117:13
    |
 LL |     let _ = deep.0.or_else(|| None);
    |             ^^^^^^^----------------
@@ -202,7 +202,7 @@ LL |     let _ = deep.0.or_else(|| None);
    |                    help: use `or(..)` instead: `or(None)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:106:13
+  --> $DIR/unnecessary_lazy_eval.rs:118:13
    |
 LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |             ^^^^^^^------------------------
@@ -210,7 +210,7 @@ LL |     let _ = deep.0.get_or_insert_with(|| 2);
    |                    help: use `get_or_insert(..)` instead: `get_or_insert(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:107:13
+  --> $DIR/unnecessary_lazy_eval.rs:119:13
    |
 LL |     let _ = deep.0.ok_or_else(|| 2);
    |             ^^^^^^^----------------
@@ -218,7 +218,7 @@ LL |     let _ = deep.0.ok_or_else(|| 2);
    |                    help: use `ok_or(..)` instead: `ok_or(2)`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:137:28
+  --> $DIR/unnecessary_lazy_eval.rs:150:28
    |
 LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                            ^^^^^-------------------
@@ -226,7 +226,7 @@ LL |     let _: Option<usize> = None.or_else(|| Some(3));
    |                                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:138:13
+  --> $DIR/unnecessary_lazy_eval.rs:151:13
    |
 LL |     let _ = deep.0.or_else(|| Some(3));
    |             ^^^^^^^-------------------
@@ -234,7 +234,7 @@ LL |     let _ = deep.0.or_else(|| Some(3));
    |                    help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Option::None`
-  --> $DIR/unnecessary_lazy_eval.rs:139:13
+  --> $DIR/unnecessary_lazy_eval.rs:152:13
    |
 LL |     let _ = opt.or_else(|| Some(3));
    |             ^^^^-------------------
@@ -242,7 +242,7 @@ LL |     let _ = opt.or_else(|| Some(3));
    |                 help: use `or(..)` instead: `or(Some(3))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:145:13
+  --> $DIR/unnecessary_lazy_eval.rs:158:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| 2);
    |             ^^^^^---------------------
@@ -250,7 +250,7 @@ LL |     let _ = res2.unwrap_or_else(|_| 2);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(2)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:146:13
+  --> $DIR/unnecessary_lazy_eval.rs:159:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |             ^^^^^----------------------------------
@@ -258,7 +258,7 @@ LL |     let _ = res2.unwrap_or_else(|_| astronomers_pi);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:147:13
+  --> $DIR/unnecessary_lazy_eval.rs:160:13
    |
 LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |             ^^^^^--------------------------------------
@@ -266,7 +266,7 @@ LL |     let _ = res2.unwrap_or_else(|_| ext_str.some_field);
    |                  help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:169:35
+  --> $DIR/unnecessary_lazy_eval.rs:182:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                   ^^^^--------------------
@@ -274,7 +274,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(2));
    |                                       help: use `and(..)` instead: `and(Err(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:170:35
+  --> $DIR/unnecessary_lazy_eval.rs:183:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                   ^^^^---------------------------------
@@ -282,7 +282,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
    |                                       help: use `and(..)` instead: `and(Err(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:171:35
+  --> $DIR/unnecessary_lazy_eval.rs:184:35
    |
 LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
    |                                   ^^^^-------------------------------------
@@ -290,7 +290,7 @@ LL |     let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field))
    |                                       help: use `and(..)` instead: `and(Err(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:173:35
+  --> $DIR/unnecessary_lazy_eval.rs:186:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                   ^^^^------------------
@@ -298,7 +298,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(2));
    |                                       help: use `or(..)` instead: `or(Ok(2))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:174:35
+  --> $DIR/unnecessary_lazy_eval.rs:187:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                   ^^^^-------------------------------
@@ -306,7 +306,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
    |                                       help: use `or(..)` instead: `or(Ok(astronomers_pi))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:175:35
+  --> $DIR/unnecessary_lazy_eval.rs:188:35
    |
 LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                   ^^^^-----------------------------------
@@ -314,7 +314,7 @@ LL |     let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
    |                                       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
 
 error: unnecessary closure used to substitute value for `Result::Err`
-  --> $DIR/unnecessary_lazy_eval.rs:176:35
+  --> $DIR/unnecessary_lazy_eval.rs:189:35
    |
 LL |       let _: Result<usize, usize> = res.
    |  ___________________________________^
@@ -329,7 +329,7 @@ LL | |     or_else(|_| Ok(ext_str.some_field));
    |       help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:206:14
+  --> $DIR/unnecessary_lazy_eval.rs:219:14
    |
 LL |     let _x = false.then(|| i32::MAX + 1);
    |              ^^^^^^---------------------
@@ -337,7 +337,7 @@ LL |     let _x = false.then(|| i32::MAX + 1);
    |                    help: use `then_some(..)` instead: `then_some(i32::MAX + 1)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:208:14
+  --> $DIR/unnecessary_lazy_eval.rs:221:14
    |
 LL |     let _x = false.then(|| i32::MAX * 2);
    |              ^^^^^^---------------------
@@ -345,7 +345,7 @@ LL |     let _x = false.then(|| i32::MAX * 2);
    |                    help: use `then_some(..)` instead: `then_some(i32::MAX * 2)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:210:14
+  --> $DIR/unnecessary_lazy_eval.rs:223:14
    |
 LL |     let _x = false.then(|| i32::MAX - 1);
    |              ^^^^^^---------------------
@@ -353,7 +353,7 @@ LL |     let _x = false.then(|| i32::MAX - 1);
    |                    help: use `then_some(..)` instead: `then_some(i32::MAX - 1)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:212:14
+  --> $DIR/unnecessary_lazy_eval.rs:225:14
    |
 LL |     let _x = false.then(|| i32::MIN - 1);
    |              ^^^^^^---------------------
@@ -361,7 +361,7 @@ LL |     let _x = false.then(|| i32::MIN - 1);
    |                    help: use `then_some(..)` instead: `then_some(i32::MIN - 1)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:214:14
+  --> $DIR/unnecessary_lazy_eval.rs:227:14
    |
 LL |     let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2);
    |              ^^^^^^-------------------------------------
@@ -369,7 +369,7 @@ LL |     let _x = false.then(|| (1 + 2 * 3 - 2 / 3 + 9) << 2);
    |                    help: use `then_some(..)` instead: `then_some((1 + 2 * 3 - 2 / 3 + 9) << 2)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:216:14
+  --> $DIR/unnecessary_lazy_eval.rs:229:14
    |
 LL |     let _x = false.then(|| 255u8 << 7);
    |              ^^^^^^-------------------
@@ -377,7 +377,7 @@ LL |     let _x = false.then(|| 255u8 << 7);
    |                    help: use `then_some(..)` instead: `then_some(255u8 << 7)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:218:14
+  --> $DIR/unnecessary_lazy_eval.rs:231:14
    |
 LL |     let _x = false.then(|| 255u8 << 8);
    |              ^^^^^^-------------------
@@ -385,7 +385,7 @@ LL |     let _x = false.then(|| 255u8 << 8);
    |                    help: use `then_some(..)` instead: `then_some(255u8 << 8)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:220:14
+  --> $DIR/unnecessary_lazy_eval.rs:233:14
    |
 LL |     let _x = false.then(|| 255u8 >> 8);
    |              ^^^^^^-------------------
@@ -393,7 +393,7 @@ LL |     let _x = false.then(|| 255u8 >> 8);
    |                    help: use `then_some(..)` instead: `then_some(255u8 >> 8)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:223:14
+  --> $DIR/unnecessary_lazy_eval.rs:236:14
    |
 LL |     let _x = false.then(|| i32::MAX + -1);
    |              ^^^^^^----------------------
@@ -401,7 +401,7 @@ LL |     let _x = false.then(|| i32::MAX + -1);
    |                    help: use `then_some(..)` instead: `then_some(i32::MAX + -1)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:225:14
+  --> $DIR/unnecessary_lazy_eval.rs:238:14
    |
 LL |     let _x = false.then(|| -i32::MAX);
    |              ^^^^^^------------------
@@ -409,7 +409,7 @@ LL |     let _x = false.then(|| -i32::MAX);
    |                    help: use `then_some(..)` instead: `then_some(-i32::MAX)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:227:14
+  --> $DIR/unnecessary_lazy_eval.rs:240:14
    |
 LL |     let _x = false.then(|| -i32::MIN);
    |              ^^^^^^------------------
@@ -417,7 +417,7 @@ LL |     let _x = false.then(|| -i32::MIN);
    |                    help: use `then_some(..)` instead: `then_some(-i32::MIN)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:230:14
+  --> $DIR/unnecessary_lazy_eval.rs:243:14
    |
 LL |     let _x = false.then(|| 255 >> -7);
    |              ^^^^^^------------------
@@ -425,7 +425,7 @@ LL |     let _x = false.then(|| 255 >> -7);
    |                    help: use `then_some(..)` instead: `then_some(255 >> -7)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:232:14
+  --> $DIR/unnecessary_lazy_eval.rs:245:14
    |
 LL |     let _x = false.then(|| 255 << -1);
    |              ^^^^^^------------------
@@ -433,7 +433,7 @@ LL |     let _x = false.then(|| 255 << -1);
    |                    help: use `then_some(..)` instead: `then_some(255 << -1)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:234:14
+  --> $DIR/unnecessary_lazy_eval.rs:247:14
    |
 LL |     let _x = false.then(|| 1 / 0);
    |              ^^^^^^--------------
@@ -441,7 +441,7 @@ LL |     let _x = false.then(|| 1 / 0);
    |                    help: use `then_some(..)` instead: `then_some(1 / 0)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:236:14
+  --> $DIR/unnecessary_lazy_eval.rs:249:14
    |
 LL |     let _x = false.then(|| x << -1);
    |              ^^^^^^----------------
@@ -449,7 +449,7 @@ LL |     let _x = false.then(|| x << -1);
    |                    help: use `then_some(..)` instead: `then_some(x << -1)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:238:14
+  --> $DIR/unnecessary_lazy_eval.rs:251:14
    |
 LL |     let _x = false.then(|| x << 2);
    |              ^^^^^^---------------
@@ -457,7 +457,7 @@ LL |     let _x = false.then(|| x << 2);
    |                    help: use `then_some(..)` instead: `then_some(x << 2)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:248:14
+  --> $DIR/unnecessary_lazy_eval.rs:261:14
    |
 LL |     let _x = false.then(|| x / 0);
    |              ^^^^^^--------------
@@ -465,7 +465,7 @@ LL |     let _x = false.then(|| x / 0);
    |                    help: use `then_some(..)` instead: `then_some(x / 0)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:250:14
+  --> $DIR/unnecessary_lazy_eval.rs:263:14
    |
 LL |     let _x = false.then(|| x % 0);
    |              ^^^^^^--------------
@@ -473,7 +473,7 @@ LL |     let _x = false.then(|| x % 0);
    |                    help: use `then_some(..)` instead: `then_some(x % 0)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:253:14
+  --> $DIR/unnecessary_lazy_eval.rs:266:14
    |
 LL |     let _x = false.then(|| 1 / -1);
    |              ^^^^^^---------------
@@ -481,7 +481,7 @@ LL |     let _x = false.then(|| 1 / -1);
    |                    help: use `then_some(..)` instead: `then_some(1 / -1)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:255:14
+  --> $DIR/unnecessary_lazy_eval.rs:268:14
    |
 LL |     let _x = false.then(|| i32::MIN / -1);
    |              ^^^^^^----------------------
@@ -489,7 +489,7 @@ LL |     let _x = false.then(|| i32::MIN / -1);
    |                    help: use `then_some(..)` instead: `then_some(i32::MIN / -1)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:258:14
+  --> $DIR/unnecessary_lazy_eval.rs:271:14
    |
 LL |     let _x = false.then(|| i32::MIN / 0);
    |              ^^^^^^---------------------
@@ -497,7 +497,7 @@ LL |     let _x = false.then(|| i32::MIN / 0);
    |                    help: use `then_some(..)` instead: `then_some(i32::MIN / 0)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:260:14
+  --> $DIR/unnecessary_lazy_eval.rs:273:14
    |
 LL |     let _x = false.then(|| 4 / 2);
    |              ^^^^^^--------------
@@ -505,7 +505,7 @@ LL |     let _x = false.then(|| 4 / 2);
    |                    help: use `then_some(..)` instead: `then_some(4 / 2)`
 
 error: unnecessary closure used with `bool::then`
-  --> $DIR/unnecessary_lazy_eval.rs:268:14
+  --> $DIR/unnecessary_lazy_eval.rs:281:14
    |
 LL |     let _x = false.then(|| f1 + f2);
    |              ^^^^^^----------------
diff --git a/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs b/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
index d9a7ad8e56c..bdc6fa0f46b 100644
--- a/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_safety_comment.rs
@@ -73,4 +73,25 @@ mod issue_10084 {
     }
 }
 
+mod issue_12048 {
+    pub const X: u8 = 0;
+
+    /// Returns a pointer to five.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use foo::point_to_five;
+    ///
+    /// let five_pointer = point_to_five();
+    /// // Safety: this pointer always points to a valid five.
+    /// let five = unsafe { *five_pointer };
+    /// assert_eq!(five, 5);
+    /// ```
+    pub fn point_to_five() -> *const u8 {
+        static FIVE: u8 = 5;
+        &FIVE
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed
index 53dc3c43e2f..f87c898f9b7 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.fixed
@@ -1,4 +1,18 @@
-#[allow(clippy::single_char_pattern)]
+#![allow(clippy::single_char_pattern)]
+
+struct Issue12068;
+
+impl AsRef<str> for Issue12068 {
+    fn as_ref(&self) -> &str {
+        ""
+    }
+}
+
+impl ToString for Issue12068 {
+    fn to_string(&self) -> String {
+        String::new()
+    }
+}
 
 fn main() {
     let _ = "a".split('a').next().unwrap();
@@ -9,6 +23,8 @@ fn main() {
     //~^ ERROR: unnecessary use of `to_owned`
     let _ = "a".split("a").next().unwrap();
     //~^ ERROR: unnecessary use of `to_owned`
+    let _ = Issue12068.as_ref().split('a').next().unwrap();
+    //~^ ERROR: unnecessary use of `to_string`
 
     let _ = [1].split(|x| *x == 2).next().unwrap();
     //~^ ERROR: unnecessary use of `to_vec`
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs
index 62400e7eee1..db5719e5880 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.rs
@@ -1,4 +1,18 @@
-#[allow(clippy::single_char_pattern)]
+#![allow(clippy::single_char_pattern)]
+
+struct Issue12068;
+
+impl AsRef<str> for Issue12068 {
+    fn as_ref(&self) -> &str {
+        ""
+    }
+}
+
+impl ToString for Issue12068 {
+    fn to_string(&self) -> String {
+        String::new()
+    }
+}
 
 fn main() {
     let _ = "a".to_string().split('a').next().unwrap();
@@ -9,6 +23,8 @@ fn main() {
     //~^ ERROR: unnecessary use of `to_owned`
     let _ = "a".to_owned().split("a").next().unwrap();
     //~^ ERROR: unnecessary use of `to_owned`
+    let _ = Issue12068.to_string().split('a').next().unwrap();
+    //~^ ERROR: unnecessary use of `to_string`
 
     let _ = [1].to_vec().split(|x| *x == 2).next().unwrap();
     //~^ ERROR: unnecessary use of `to_vec`
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr
index cfb3766d15e..4cfaeed3384 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned_on_split.stderr
@@ -1,5 +1,5 @@
 error: unnecessary use of `to_string`
-  --> $DIR/unnecessary_to_owned_on_split.rs:4:13
+  --> $DIR/unnecessary_to_owned_on_split.rs:18:13
    |
 LL |     let _ = "a".to_string().split('a').next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split('a')`
@@ -8,46 +8,52 @@ LL |     let _ = "a".to_string().split('a').next().unwrap();
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_to_owned)]`
 
 error: unnecessary use of `to_string`
-  --> $DIR/unnecessary_to_owned_on_split.rs:6:13
+  --> $DIR/unnecessary_to_owned_on_split.rs:20:13
    |
 LL |     let _ = "a".to_string().split("a").next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned_on_split.rs:8:13
+  --> $DIR/unnecessary_to_owned_on_split.rs:22:13
    |
 LL |     let _ = "a".to_owned().split('a').next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split('a')`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned_on_split.rs:10:13
+  --> $DIR/unnecessary_to_owned_on_split.rs:24:13
    |
 LL |     let _ = "a".to_owned().split("a").next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `"a".split("a")`
 
+error: unnecessary use of `to_string`
+  --> $DIR/unnecessary_to_owned_on_split.rs:26:13
+   |
+LL |     let _ = Issue12068.to_string().split('a').next().unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Issue12068.as_ref().split('a')`
+
 error: unnecessary use of `to_vec`
-  --> $DIR/unnecessary_to_owned_on_split.rs:13:13
+  --> $DIR/unnecessary_to_owned_on_split.rs:29:13
    |
 LL |     let _ = [1].to_vec().split(|x| *x == 2).next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)`
 
 error: unnecessary use of `to_vec`
-  --> $DIR/unnecessary_to_owned_on_split.rs:15:13
+  --> $DIR/unnecessary_to_owned_on_split.rs:31:13
    |
 LL |     let _ = [1].to_vec().split(|x| *x == 2).next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned_on_split.rs:17:13
+  --> $DIR/unnecessary_to_owned_on_split.rs:33:13
    |
 LL |     let _ = [1].to_owned().split(|x| *x == 2).next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)`
 
 error: unnecessary use of `to_owned`
-  --> $DIR/unnecessary_to_owned_on_split.rs:19:13
+  --> $DIR/unnecessary_to_owned_on_split.rs:35:13
    |
 LL |     let _ = [1].to_owned().split(|x| *x == 2).next().unwrap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `[1].split(|x| *x == 2)`
 
-error: aborting due to 8 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_asref.fixed b/src/tools/clippy/tests/ui/useless_asref.fixed
index f6770558bd8..88b95095bc0 100644
--- a/src/tools/clippy/tests/ui/useless_asref.fixed
+++ b/src/tools/clippy/tests/ui/useless_asref.fixed
@@ -2,7 +2,9 @@
 #![allow(
     clippy::explicit_auto_deref,
     clippy::uninlined_format_args,
-    clippy::needless_pass_by_ref_mut
+    clippy::map_clone,
+    clippy::needless_pass_by_ref_mut,
+    clippy::redundant_closure
 )]
 
 use std::fmt::Debug;
@@ -132,6 +134,16 @@ fn generic_ok<U: AsMut<T> + AsRef<T> + ?Sized, T: Debug + ?Sized>(mru: &mut U) {
     foo_rt(mru.as_ref());
 }
 
+fn foo() {
+    let x = Some(String::new());
+    let z = x.clone();
+    //~^ ERROR: this call to `as_ref.map(...)` does nothing
+    let z = x.clone();
+    //~^ ERROR: this call to `as_ref.map(...)` does nothing
+    let z = x.clone();
+    //~^ ERROR: this call to `as_ref.map(...)` does nothing
+}
+
 fn main() {
     not_ok();
     ok();
diff --git a/src/tools/clippy/tests/ui/useless_asref.rs b/src/tools/clippy/tests/ui/useless_asref.rs
index 0996218076b..504dc1f5cbf 100644
--- a/src/tools/clippy/tests/ui/useless_asref.rs
+++ b/src/tools/clippy/tests/ui/useless_asref.rs
@@ -2,7 +2,9 @@
 #![allow(
     clippy::explicit_auto_deref,
     clippy::uninlined_format_args,
-    clippy::needless_pass_by_ref_mut
+    clippy::map_clone,
+    clippy::needless_pass_by_ref_mut,
+    clippy::redundant_closure
 )]
 
 use std::fmt::Debug;
@@ -132,6 +134,16 @@ fn generic_ok<U: AsMut<T> + AsRef<T> + ?Sized, T: Debug + ?Sized>(mru: &mut U) {
     foo_rt(mru.as_ref());
 }
 
+fn foo() {
+    let x = Some(String::new());
+    let z = x.as_ref().map(String::clone);
+    //~^ ERROR: this call to `as_ref.map(...)` does nothing
+    let z = x.as_ref().map(|z| z.clone());
+    //~^ ERROR: this call to `as_ref.map(...)` does nothing
+    let z = x.as_ref().map(|z| String::clone(z));
+    //~^ ERROR: this call to `as_ref.map(...)` does nothing
+}
+
 fn main() {
     not_ok();
     ok();
diff --git a/src/tools/clippy/tests/ui/useless_asref.stderr b/src/tools/clippy/tests/ui/useless_asref.stderr
index 163eb7b1437..deb5d90f2f6 100644
--- a/src/tools/clippy/tests/ui/useless_asref.stderr
+++ b/src/tools/clippy/tests/ui/useless_asref.stderr
@@ -1,5 +1,5 @@
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:46:18
+  --> $DIR/useless_asref.rs:48:18
    |
 LL |         foo_rstr(rstr.as_ref());
    |                  ^^^^^^^^^^^^^ help: try: `rstr`
@@ -11,64 +11,82 @@ LL | #![deny(clippy::useless_asref)]
    |         ^^^^^^^^^^^^^^^^^^^^^
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:48:20
+  --> $DIR/useless_asref.rs:50:20
    |
 LL |         foo_rslice(rslice.as_ref());
    |                    ^^^^^^^^^^^^^^^ help: try: `rslice`
 
 error: this call to `as_mut` does nothing
-  --> $DIR/useless_asref.rs:52:21
+  --> $DIR/useless_asref.rs:54:21
    |
 LL |         foo_mrslice(mrslice.as_mut());
    |                     ^^^^^^^^^^^^^^^^ help: try: `mrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:54:20
+  --> $DIR/useless_asref.rs:56:20
    |
 LL |         foo_rslice(mrslice.as_ref());
    |                    ^^^^^^^^^^^^^^^^ help: try: `mrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:61:20
+  --> $DIR/useless_asref.rs:63:20
    |
 LL |         foo_rslice(rrrrrslice.as_ref());
    |                    ^^^^^^^^^^^^^^^^^^^ help: try: `rrrrrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:63:18
+  --> $DIR/useless_asref.rs:65:18
    |
 LL |         foo_rstr(rrrrrstr.as_ref());
    |                  ^^^^^^^^^^^^^^^^^ help: try: `rrrrrstr`
 
 error: this call to `as_mut` does nothing
-  --> $DIR/useless_asref.rs:68:21
+  --> $DIR/useless_asref.rs:70:21
    |
 LL |         foo_mrslice(mrrrrrslice.as_mut());
    |                     ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:70:20
+  --> $DIR/useless_asref.rs:72:20
    |
 LL |         foo_rslice(mrrrrrslice.as_ref());
    |                    ^^^^^^^^^^^^^^^^^^^^ help: try: `mrrrrrslice`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:74:16
+  --> $DIR/useless_asref.rs:76:16
    |
 LL |     foo_rrrrmr((&&&&MoreRef).as_ref());
    |                ^^^^^^^^^^^^^^^^^^^^^^ help: try: `(&&&&MoreRef)`
 
 error: this call to `as_mut` does nothing
-  --> $DIR/useless_asref.rs:124:13
+  --> $DIR/useless_asref.rs:126:13
    |
 LL |     foo_mrt(mrt.as_mut());
    |             ^^^^^^^^^^^^ help: try: `mrt`
 
 error: this call to `as_ref` does nothing
-  --> $DIR/useless_asref.rs:126:12
+  --> $DIR/useless_asref.rs:128:12
    |
 LL |     foo_rt(mrt.as_ref());
    |            ^^^^^^^^^^^^ help: try: `mrt`
 
-error: aborting due to 11 previous errors
+error: this call to `as_ref.map(...)` does nothing
+  --> $DIR/useless_asref.rs:139:13
+   |
+LL |     let z = x.as_ref().map(String::clone);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
+
+error: this call to `as_ref.map(...)` does nothing
+  --> $DIR/useless_asref.rs:141:13
+   |
+LL |     let z = x.as_ref().map(|z| z.clone());
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
+
+error: this call to `as_ref.map(...)` does nothing
+  --> $DIR/useless_asref.rs:143:13
+   |
+LL |     let z = x.as_ref().map(|z| String::clone(z));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
+
+error: aborting due to 14 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index ed8387b7eb2..ce00fde2f99 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -241,7 +241,7 @@ mod issue11300 {
         foo2::<(), _>([1, 2, 3].into_iter());
 
         // This should lint. Removing the `.into_iter()` means that `I` gets substituted with `[i32; 3]`,
-        // and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unncessary.
+        // and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unnecessary.
         foo3([1, 2, 3]);
     }
 
@@ -253,7 +253,7 @@ mod issue11300 {
 
         S1.foo([1, 2]);
 
-        // ICE that occured in itertools
+        // ICE that occurred in itertools
         trait Itertools {
             fn interleave_shortest<J>(self, other: J)
             where
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index 991a7762fc6..39979619586 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -241,7 +241,7 @@ mod issue11300 {
         foo2::<(), _>([1, 2, 3].into_iter());
 
         // This should lint. Removing the `.into_iter()` means that `I` gets substituted with `[i32; 3]`,
-        // and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unncessary.
+        // and `i32: Helper2<[i32, 3]>` is true, so this call is indeed unnecessary.
         foo3([1, 2, 3].into_iter());
     }
 
@@ -253,7 +253,7 @@ mod issue11300 {
 
         S1.foo([1, 2].into_iter());
 
-        // ICE that occured in itertools
+        // ICE that occurred in itertools
         trait Itertools {
             fn interleave_shortest<J>(self, other: J)
             where
diff --git a/src/tools/clippy/tests/ui/vec.fixed b/src/tools/clippy/tests/ui/vec.fixed
index 81b8bd7da77..b318fd42f7c 100644
--- a/src/tools/clippy/tests/ui/vec.fixed
+++ b/src/tools/clippy/tests/ui/vec.fixed
@@ -210,3 +210,10 @@ fn issue11861() {
     // should not lint
     m!(vec![1]);
 }
+
+fn issue_11958() {
+    fn f(_s: &[String]) {}
+
+    // should not lint, `String` is not `Copy`
+    f(&vec!["test".to_owned(); 2]);
+}
diff --git a/src/tools/clippy/tests/ui/vec.rs b/src/tools/clippy/tests/ui/vec.rs
index 5aca9b2925c..08ad6efa37f 100644
--- a/src/tools/clippy/tests/ui/vec.rs
+++ b/src/tools/clippy/tests/ui/vec.rs
@@ -210,3 +210,10 @@ fn issue11861() {
     // should not lint
     m!(vec![1]);
 }
+
+fn issue_11958() {
+    fn f(_s: &[String]) {}
+
+    // should not lint, `String` is not `Copy`
+    f(&vec!["test".to_owned(); 2]);
+}
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index 96085bcf9ee..a05765b3981 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -28,7 +28,6 @@ users_on_vacation = ["blyxyas"]
 "*" = [
     "@Manishearth",
     "@llogiq",
-    "@giraffate",
     "@xFrednet",
     "@Alexendoo",
     "@dswij",
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 61aa9c12822..ebc704f785f 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-65b323b168daa6c723a8a5b4ddf939f3b12e0329
+f1f8687b06a5908dd096f51da32347b3313279db
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index aead55a6996..e8e10f64ad2 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -165,7 +165,6 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
                                     level: SymbolExportLevel::C,
                                     kind: SymbolExportKind::Text,
                                     used: false,
-                                    used_compiler: false,
                                 },
                             ))
                         }),
diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index 7045a7dd9ce..31226cf8c30 100644
--- a/src/tools/rustfmt/src/parse/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -3,7 +3,7 @@ use std::path::{Path, PathBuf};
 
 use rustc_ast::token::TokenKind;
 use rustc_ast::{ast, attr, ptr};
-use rustc_errors::Diagnostic;
+use rustc_errors::DiagnosticBuilder;
 use rustc_parse::{new_parser_from_file, parser::Parser as RawParser};
 use rustc_span::{sym, Span};
 use thin_vec::ThinVec;
@@ -65,7 +65,7 @@ impl<'a> ParserBuilder<'a> {
     fn parser(
         sess: &'a rustc_session::parse::ParseSess,
         input: Input,
-    ) -> Result<rustc_parse::parser::Parser<'a>, Option<Vec<Diagnostic>>> {
+    ) -> Result<rustc_parse::parser::Parser<'a>, Option<Vec<DiagnosticBuilder<'a>>>> {
         match input {
             Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || {
                 new_parser_from_file(sess, file, None)
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index f4fb5073dfd..6dc3eac44d4 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -4,7 +4,9 @@ use std::sync::atomic::{AtomicBool, Ordering};
 use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
 use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter};
 use rustc_errors::translation::Translate;
-use rustc_errors::{ColorConfig, DiagCtxt, Diagnostic, Level as DiagnosticLevel};
+use rustc_errors::{
+    ColorConfig, DiagCtxt, Diagnostic, DiagnosticBuilder, Level as DiagnosticLevel,
+};
 use rustc_session::parse::ParseSess as RawParseSess;
 use rustc_span::{
     source_map::{FilePathMapping, SourceMap},
@@ -283,9 +285,9 @@ impl ParseSess {
 
 // Methods that should be restricted within the parse module.
 impl ParseSess {
-    pub(super) fn emit_diagnostics(&self, diagnostics: Vec<Diagnostic>) {
+    pub(super) fn emit_diagnostics(&self, diagnostics: Vec<DiagnosticBuilder<'_>>) {
         for diagnostic in diagnostics {
-            self.parse_sess.dcx.emit_diagnostic(diagnostic);
+            diagnostic.emit();
         }
     }
 
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 62d48315d43..c198c116282 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -194,6 +194,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "aho-corasick",
     "allocator-api2", // FIXME: only appears in Cargo.lock due to https://github.com/rust-lang/cargo/issues/10801
     "annotate-snippets",
+    "anstyle",
     "ar_archive_writer",
     "arrayvec",
     "autocfg",
@@ -391,7 +392,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "windows_x86_64_gnullvm",
     "windows_x86_64_msvc",
     "writeable",
-    "yansi-term", // this is a false-positive: it's only used by rustfmt, but because it's enabled through a feature, tidy thinks it's used by rustc as well.
     "yoke",
     "yoke-derive",
     "zerocopy",
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 32e271d4a56..ba569078f3d 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
 const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
 const ISSUES_ENTRY_LIMIT: usize = 1849;
-const ROOT_ENTRY_LIMIT: usize = 868;
+const ROOT_ENTRY_LIMIT: usize = 869;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/tests/codegen/issues/issue-119422.rs b/tests/codegen/issues/issue-119422.rs
new file mode 100644
index 00000000000..9c99d96317d
--- /dev/null
+++ b/tests/codegen/issues/issue-119422.rs
@@ -0,0 +1,83 @@
+//! This test checks that compiler don't generate useless compares to zeros
+//! for NonZero integer types.
+
+// compile-flags: -O --edition=2021 -Zmerge-functions=disabled
+// only-64bit (because the LLVM type of i64 for usize shows up)
+
+#![crate_type = "lib"]
+
+use core::num::*;
+use core::ptr::NonNull;
+
+// CHECK-LABEL: @check_non_null
+#[no_mangle]
+pub fn check_non_null(x: NonNull<u8>) -> bool {
+    // CHECK: ret i1 false
+    x.as_ptr().is_null()
+}
+
+// CHECK-LABEL: @equals_zero_is_false_u8
+#[no_mangle]
+pub fn equals_zero_is_false_u8(x: NonZeroU8) -> bool {
+    // CHECK-NOT: br
+    // CHECK: ret i1 false
+    // CHECK-NOT: br
+    x.get() == 0
+}
+
+// CHECK-LABEL: @not_equals_zero_is_true_u8
+#[no_mangle]
+pub fn not_equals_zero_is_true_u8(x: NonZeroU8) -> bool {
+    // CHECK-NOT: br
+    // CHECK: ret i1 true
+    // CHECK-NOT: br
+    x.get() != 0
+}
+
+// CHECK-LABEL: @equals_zero_is_false_i8
+#[no_mangle]
+pub fn equals_zero_is_false_i8(x: NonZeroI8) -> bool {
+    // CHECK-NOT: br
+    // CHECK: ret i1 false
+    // CHECK-NOT: br
+    x.get() == 0
+}
+
+// CHECK-LABEL: @not_equals_zero_is_true_i8
+#[no_mangle]
+pub fn not_equals_zero_is_true_i8(x: NonZeroI8) -> bool {
+    // CHECK-NOT: br
+    // CHECK: ret i1 true
+    // CHECK-NOT: br
+    x.get() != 0
+}
+
+// CHECK-LABEL: @usize_try_from_u32
+#[no_mangle]
+pub fn usize_try_from_u32(x: NonZeroU32) -> NonZeroUsize {
+    // CHECK-NOT: br
+    // CHECK: zext i32 %{{.*}} to i64
+    // CHECK-NOT: br
+    // CHECK: ret i64
+    x.try_into().unwrap()
+}
+
+// CHECK-LABEL: @isize_try_from_i32
+#[no_mangle]
+pub fn isize_try_from_i32(x: NonZeroI32) -> NonZeroIsize {
+    // CHECK-NOT: br
+    // CHECK: sext i32 %{{.*}} to i64
+    // CHECK-NOT: br
+    // CHECK: ret i64
+    x.try_into().unwrap()
+}
+
+// CHECK-LABEL: @u64_from_nonzero_is_not_zero
+#[no_mangle]
+pub fn u64_from_nonzero_is_not_zero(x: NonZeroU64)->bool {
+    // CHECK-NOT: br
+    // CHECK: ret i1 false
+    // CHECK-NOT: br
+    let v: u64 = x.into();
+    v == 0
+}
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
index 6e681b4f970..5f2a096bb1f 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-abort.diff
@@ -61,7 +61,6 @@
 +         StorageDead(_10);
 +         StorageDead(_11);
 +         nop;
-          nop;
           StorageDead(_8);
           StorageDead(_3);
           StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
index e987969d313..a49546f158c 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.32bit.panic-unwind.diff
@@ -61,7 +61,6 @@
 +         StorageDead(_10);
 +         StorageDead(_11);
 +         nop;
-          nop;
           StorageDead(_8);
           StorageDead(_3);
           StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
index 6e681b4f970..5f2a096bb1f 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-abort.diff
@@ -61,7 +61,6 @@
 +         StorageDead(_10);
 +         StorageDead(_11);
 +         nop;
-          nop;
           StorageDead(_8);
           StorageDead(_3);
           StorageDead(_1);
diff --git a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
index e987969d313..a49546f158c 100644
--- a/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/optimizes_into_variable.main.ScalarReplacementOfAggregates.64bit.panic-unwind.diff
@@ -61,7 +61,6 @@
 +         StorageDead(_10);
 +         StorageDead(_11);
 +         nop;
-          nop;
           StorageDead(_8);
           StorageDead(_3);
           StorageDead(_1);
diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-abort.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-abort.diff
index 64a435f2245..c3076fb67c2 100644
--- a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-abort.diff
+++ b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-abort.diff
@@ -6,8 +6,8 @@
       let _1: ();
   
       bb0: {
--         switchInt(const false) -> [0: bb3, otherwise: bb1];
-+         goto -> bb3;
+-         switchInt(const false) -> [0: bb2, otherwise: bb1];
++         goto -> bb2;
       }
   
       bb1: {
@@ -15,14 +15,6 @@
       }
   
       bb2: {
-          goto -> bb4;
-      }
-  
-      bb3: {
-          goto -> bb4;
-      }
-  
-      bb4: {
           return;
       }
   }
diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff
index 146e00686ed..6c346e20e58 100644
--- a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff
+++ b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.panic-unwind.diff
@@ -6,8 +6,8 @@
       let _1: ();
   
       bb0: {
--         switchInt(const false) -> [0: bb3, otherwise: bb1];
-+         goto -> bb3;
+-         switchInt(const false) -> [0: bb2, otherwise: bb1];
++         goto -> bb2;
       }
   
       bb1: {
@@ -15,14 +15,6 @@
       }
   
       bb2: {
-          goto -> bb4;
-      }
-  
-      bb3: {
-          goto -> bb4;
-      }
-  
-      bb4: {
           return;
       }
   }
diff --git a/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff
index 825babe7994..d7ade041e4c 100644
--- a/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff
+++ b/tests/mir-opt/simplify_match.main.GVN.panic-abort.diff
@@ -11,19 +11,15 @@
   
       bb0: {
           _2 = const false;
--         switchInt(_2) -> [0: bb1, otherwise: bb2];
-+         switchInt(const false) -> [0: bb1, otherwise: bb2];
+-         switchInt(_2) -> [0: bb2, otherwise: bb1];
++         switchInt(const false) -> [0: bb2, otherwise: bb1];
       }
   
       bb1: {
-          goto -> bb3;
+          _0 = noop() -> [return: bb2, unwind unreachable];
       }
   
       bb2: {
-          _0 = noop() -> [return: bb3, unwind unreachable];
-      }
-  
-      bb3: {
           return;
       }
   }
diff --git a/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff
index 24ab6c39788..931c5c43c4c 100644
--- a/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff
+++ b/tests/mir-opt/simplify_match.main.GVN.panic-unwind.diff
@@ -11,19 +11,15 @@
   
       bb0: {
           _2 = const false;
--         switchInt(_2) -> [0: bb1, otherwise: bb2];
-+         switchInt(const false) -> [0: bb1, otherwise: bb2];
+-         switchInt(_2) -> [0: bb2, otherwise: bb1];
++         switchInt(const false) -> [0: bb2, otherwise: bb1];
       }
   
       bb1: {
-          goto -> bb3;
+          _0 = noop() -> [return: bb2, unwind continue];
       }
   
       bb2: {
-          _0 = noop() -> [return: bb3, unwind continue];
-      }
-  
-      bb3: {
           return;
       }
   }
diff --git a/tests/run-make/libtest-padding/Makefile b/tests/run-make/libtest-padding/Makefile
new file mode 100644
index 00000000000..42bc1192925
--- /dev/null
+++ b/tests/run-make/libtest-padding/Makefile
@@ -0,0 +1,14 @@
+# ignore-cross-compile because we run the compiled code
+# needs-unwind because #[bench] and -Cpanic=abort requires -Zpanic-abort-tests
+include ../tools.mk
+
+NORMALIZE=sed 's%[0-9,]\{1,\} ns/iter (+/- [0-9,]\{1,\})%?? ns/iter (+/- ??)%' | sed 's%finished in [0-9\.]\{1,\}%finished in ??%'
+
+all:
+	$(RUSTC) --test tests.rs
+
+	$(call RUN,tests) --test-threads=1 | $(NORMALIZE) > "$(TMPDIR)"/test.stdout
+	$(RUSTC_TEST_OP) "$(TMPDIR)"/test.stdout test.stdout
+
+	$(call RUN,tests) --test-threads=1 --bench | $(NORMALIZE) > "$(TMPDIR)"/bench.stdout
+	$(RUSTC_TEST_OP) "$(TMPDIR)"/bench.stdout bench.stdout
diff --git a/tests/run-make/libtest-padding/bench.stdout b/tests/run-make/libtest-padding/bench.stdout
new file mode 100644
index 00000000000..3d55401c93a
--- /dev/null
+++ b/tests/run-make/libtest-padding/bench.stdout
@@ -0,0 +1,9 @@
+
+running 4 tests
+test short_test_name ... ignored
+test this_is_a_really_long_test_name ... ignored
+test short_bench_name                 ... bench:           ?? ns/iter (+/- ??)
+test this_is_a_really_long_bench_name ... bench:           ?? ns/iter (+/- ??)
+
+test result: ok. 0 passed; 0 failed; 2 ignored; 2 measured; 0 filtered out; finished in ??s
+
diff --git a/tests/run-make/libtest-padding/test.stdout b/tests/run-make/libtest-padding/test.stdout
new file mode 100644
index 00000000000..8ffc810f6cd
--- /dev/null
+++ b/tests/run-make/libtest-padding/test.stdout
@@ -0,0 +1,9 @@
+
+running 4 tests
+test short_bench_name ... ok
+test short_test_name ... ok
+test this_is_a_really_long_bench_name ... ok
+test this_is_a_really_long_test_name ... ok
+
+test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in ??s
+
diff --git a/tests/run-make/libtest-padding/tests.rs b/tests/run-make/libtest-padding/tests.rs
new file mode 100644
index 00000000000..cadf07237e9
--- /dev/null
+++ b/tests/run-make/libtest-padding/tests.rs
@@ -0,0 +1,18 @@
+#![feature(test)]
+extern crate test;
+
+#[test]
+fn short_test_name() {}
+
+#[test]
+fn this_is_a_really_long_test_name() {}
+
+#[bench]
+fn short_bench_name(b: &mut test::Bencher) {
+    b.iter(|| 1);
+}
+
+#[bench]
+fn this_is_a_really_long_bench_name(b: &mut test::Bencher) {
+    b.iter(|| 1);
+}
diff --git a/tests/run-make/no-builtins-lto/Makefile b/tests/run-make/no-builtins-lto/Makefile
index c7be4836466..c8f05d9918b 100644
--- a/tests/run-make/no-builtins-lto/Makefile
+++ b/tests/run-make/no-builtins-lto/Makefile
@@ -1,15 +1,9 @@
 include ../tools.mk
 
-# only-x86_64
-
-# We want to check that `no_builtins` is correctly participating in LTO.
-# First, verify that the `foo::foo` symbol can be found when linking.
-# Next, verify that `memcpy` can be customized using `no_builtins` under LTO.
-# Others will use the built-in memcpy.
-
 all:
-	$(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 foo.rs
-	$(RUSTC) -C linker-plugin-lto -C opt-level=2 -C debuginfo=0 no_builtins.rs
-	$(RUSTC) main.rs -C lto -C opt-level=2 -C debuginfo=0 -C save-temps -C metadata=1 -C codegen-units=1
-	"$(LLVM_BIN_DIR)"/llvm-dis $(TMPDIR)/main.main.*-cgu.0.rcgu.lto.input.bc -o $(TMPDIR)/lto.ll
-	cat "$(TMPDIR)"/lto.ll | "$(LLVM_FILECHECK)" filecheck.lto.txt
+	# Compile a `#![no_builtins]` rlib crate
+	$(RUSTC) no_builtins.rs
+	# Build an executable that depends on that crate using LTO. The no_builtins crate doesn't
+	# participate in LTO, so its rlib must be explicitly linked into the final binary. Verify this by
+	# grepping the linker arguments.
+	$(RUSTC) main.rs -C lto --print link-args | $(CGREP) 'libno_builtins.rlib'
diff --git a/tests/run-make/no-builtins-lto/filecheck.lto.txt b/tests/run-make/no-builtins-lto/filecheck.lto.txt
deleted file mode 100644
index 79dc3a51501..00000000000
--- a/tests/run-make/no-builtins-lto/filecheck.lto.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-CHECK: define{{.*}} void @bar
-CHECK-NEXT: call void @no_builtins
-CHECK-NEXT: call void @llvm.memcpy
-
-CHECK: define{{.*}} i32 @main
-CHECK: call void @bar
-
-CHECK: define{{.*}} void @foo
-CHECK-NEXT: call void @llvm.memcpy
-
-CHECK: define{{.*}} void @no_builtins
-CHECK-SAME: #[[ATTR:[0-9]+]] {
-CHECK: call void @foo
-CHECK-NEXT: call{{.*}} @memcpy
-
-CHECK: attributes #[[ATTR]]
-CHECK-SAME: no-builtins
diff --git a/tests/run-make/no-builtins-lto/foo.rs b/tests/run-make/no-builtins-lto/foo.rs
deleted file mode 100644
index f09ac40b152..00000000000
--- a/tests/run-make/no-builtins-lto/foo.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-#![feature(lang_items, no_core)]
-#![no_std]
-#![no_core]
-#![crate_type = "lib"]
-
-#[inline(never)]
-#[no_mangle]
-pub unsafe fn foo(dest: *mut u8, src: *const u8) {
-    // should call `@llvm.memcpy`.
-    memcpy(dest, src, 1024);
-}
-
-#[no_mangle]
-#[inline(never)]
-pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, _n: usize) -> *mut u8 {
-    *dest = 0;
-    return src as *mut u8;
-}
-
-#[lang = "sized"]
-trait Sized {}
-#[lang = "copy"]
-trait Copy {}
-impl Copy for *mut u8 {}
-impl Copy for *const u8 {}
-
-#[lang = "drop_in_place"]
-#[allow(unconditional_recursion)]
-pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-    // Code here does not matter - this is replaced by the
-    // real drop glue by the compiler.
-    drop_in_place(to_drop);
-}
diff --git a/tests/run-make/no-builtins-lto/main.rs b/tests/run-make/no-builtins-lto/main.rs
index 4421a2afbce..890c999c8cc 100644
--- a/tests/run-make/no-builtins-lto/main.rs
+++ b/tests/run-make/no-builtins-lto/main.rs
@@ -1,29 +1,3 @@
-#![feature(no_core, start, lang_items)]
-#![no_std]
-// We use `no_core` to reduce the LTO products is small enough.
-#![no_core]
-
 extern crate no_builtins;
-extern crate foo;
-
-#[cfg_attr(unix, link(name = "c"))]
-#[cfg_attr(target_env = "msvc", link(name = "msvcrt"))]
-extern "C" {}
-
-#[start]
-fn main(_: isize, p: *const *const u8) -> isize {
-    // Make sure the symbols are retained.
-    unsafe { bar(*p as *mut u8, *p); }
-    0
-}
-
-#[no_mangle]
-#[inline(never)]
-pub unsafe extern "C" fn bar(dest: *mut u8, src: *const u8) {
-    no_builtins::no_builtins(dest, src);
-    // should call `@llvm.memcpy`
-    foo::memcpy(dest, src, 1024);
-}
 
-#[lang = "eh_personality"]
-fn eh_personality() {}
+fn main() {}
diff --git a/tests/run-make/no-builtins-lto/no_builtins.rs b/tests/run-make/no-builtins-lto/no_builtins.rs
index 33ed68e3aee..5d001031a57 100644
--- a/tests/run-make/no-builtins-lto/no_builtins.rs
+++ b/tests/run-make/no-builtins-lto/no_builtins.rs
@@ -1,15 +1,2 @@
-#![feature(lang_items, no_core)]
-#![no_std]
-#![no_core]
 #![crate_type = "lib"]
 #![no_builtins]
-
-extern crate foo;
-
-#[no_mangle]
-pub unsafe fn no_builtins(dest: *mut u8, src: *const u8) {
-    // There should be no "undefined reference to `foo::foo'".
-    foo::foo(dest, src);
-    // should call `@memcpy` instead of `@llvm.memcpy`.
-    foo::memcpy(dest, src, 1024);
-}
diff --git a/tests/run-make/no-builtins-symbols/Makefile b/tests/run-make/no-builtins-symbols/Makefile
deleted file mode 100644
index 4bb35c1d486..00000000000
--- a/tests/run-make/no-builtins-symbols/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-include ../tools.mk
-
-# only-x86_64-unknown-linux-gnu
-
-all:
-	$(RUSTC) main.rs -o $(TMPDIR)/main
-	[ "$$("$(LLVM_BIN_DIR)"/llvm-nm -U $(TMPDIR)/main | grep -c __fixunssfti)" -eq "0" ]
diff --git a/tests/run-make/no-builtins-symbols/main.rs b/tests/run-make/no-builtins-symbols/main.rs
deleted file mode 100644
index f328e4d9d04..00000000000
--- a/tests/run-make/no-builtins-symbols/main.rs
+++ /dev/null
@@ -1 +0,0 @@
-fn main() {}
diff --git a/tests/run-make/wasm-builtins-import/Makefile b/tests/run-make/wasm-spurious-import/Makefile
index ff9dfeac6d0..ff9dfeac6d0 100644
--- a/tests/run-make/wasm-builtins-import/Makefile
+++ b/tests/run-make/wasm-spurious-import/Makefile
diff --git a/tests/run-make/wasm-builtins-import/main.rs b/tests/run-make/wasm-spurious-import/main.rs
index 5eb99df6ff7..fcbead5e28b 100644
--- a/tests/run-make/wasm-builtins-import/main.rs
+++ b/tests/run-make/wasm-spurious-import/main.rs
@@ -8,8 +8,7 @@ fn my_panic(_info: &core::panic::PanicInfo) -> ! {
 
 #[no_mangle]
 pub fn multer(a: i128, b: i128) -> i128 {
-    // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported function
-    // such as panic or __multi3 (externally defined) in case of a bug. We verify that
-    // no imports exist in our verifier.
+    // Trigger usage of the __multi3 compiler intrinsic which then leads to an imported
+    // panic function in case of a bug. We verify that no imports exist in our verifier.
     a * b
 }
diff --git a/tests/run-make/wasm-builtins-import/verify.js b/tests/run-make/wasm-spurious-import/verify.js
index d3b2101b662..d3b2101b662 100644
--- a/tests/run-make/wasm-builtins-import/verify.js
+++ b/tests/run-make/wasm-spurious-import/verify.js
diff --git a/tests/rustdoc-ui/ice-bug-report-url.stderr b/tests/rustdoc-ui/ice-bug-report-url.stderr
index 869fcd20fac..06a52691310 100644
--- a/tests/rustdoc-ui/ice-bug-report-url.stderr
+++ b/tests/rustdoc-ui/ice-bug-report-url.stderr
@@ -1,4 +1,4 @@
-error: expected one of `->`, `where`, or `{`, found `<eof>`
+error: internal compiler error: expected one of `->`, `where`, or `{`, found `<eof>`
   --> $DIR/ice-bug-report-url.rs:14:10
    |
 LL | fn wrong()
diff --git a/tests/rustdoc-ui/unable-fulfill-trait.rs b/tests/rustdoc-ui/unable-fulfill-trait.rs
index 10887ab1903..a69f74b09ac 100644
--- a/tests/rustdoc-ui/unable-fulfill-trait.rs
+++ b/tests/rustdoc-ui/unable-fulfill-trait.rs
@@ -4,7 +4,6 @@ pub struct Foo<'a, 'b, T> {
     field1: dyn Bar<'a, 'b,>,
     //~^ ERROR
     //~| ERROR
-    //~| ERROR
 }
 
 pub trait Bar<'x, 's, U>
diff --git a/tests/rustdoc-ui/unable-fulfill-trait.stderr b/tests/rustdoc-ui/unable-fulfill-trait.stderr
index d7735a4fd11..72f35cb9224 100644
--- a/tests/rustdoc-ui/unable-fulfill-trait.stderr
+++ b/tests/rustdoc-ui/unable-fulfill-trait.stderr
@@ -5,7 +5,7 @@ LL |     field1: dyn Bar<'a, 'b,>,
    |                 ^^^ expected 1 generic argument
    |
 note: trait defined here, with 1 generic parameter: `U`
-  --> $DIR/unable-fulfill-trait.rs:10:11
+  --> $DIR/unable-fulfill-trait.rs:9:11
    |
 LL | pub trait Bar<'x, 's, U>
    |           ^^^         -
@@ -20,24 +20,7 @@ error[E0227]: ambiguous lifetime bound, explicit lifetime bound required
 LL |     field1: dyn Bar<'a, 'b,>,
    |             ^^^^^^^^^^^^^^^^
 
-error[E0478]: lifetime bound not satisfied
-  --> $DIR/unable-fulfill-trait.rs:4:13
-   |
-LL |     field1: dyn Bar<'a, 'b,>,
-   |             ^^^^^^^^^^^^^^^^
-   |
-note: lifetime parameter instantiated with the lifetime `'b` as defined here
-  --> $DIR/unable-fulfill-trait.rs:3:20
-   |
-LL | pub struct Foo<'a, 'b, T> {
-   |                    ^^
-note: but lifetime parameter must outlive the lifetime `'a` as defined here
-  --> $DIR/unable-fulfill-trait.rs:3:16
-   |
-LL | pub struct Foo<'a, 'b, T> {
-   |                ^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0107, E0227, E0478.
+Some errors have detailed explanations: E0107, E0227.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
index 3acec9c085a..e3eddf489b0 100644
--- a/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
+++ b/tests/ui/associated-inherent-types/issue-109071.no_gate.stderr
@@ -30,7 +30,7 @@ LL |     type Item = &[T];
    = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable
 
 error[E0223]: ambiguous associated type
-  --> $DIR/issue-109071.rs:16:22
+  --> $DIR/issue-109071.rs:15:22
    |
 LL |     fn T() -> Option<Self::Item> {}
    |                      ^^^^^^^^^^
diff --git a/tests/ui/associated-inherent-types/issue-109071.rs b/tests/ui/associated-inherent-types/issue-109071.rs
index a897aaebc58..cbe8cce0924 100644
--- a/tests/ui/associated-inherent-types/issue-109071.rs
+++ b/tests/ui/associated-inherent-types/issue-109071.rs
@@ -9,13 +9,11 @@ impl<T> Windows { //~ ERROR: missing generics for struct `Windows`
     //[no_gate]~^ ERROR: inherent associated types are unstable
 
     fn next() -> Option<Self::Item> {}
-    //[with_gate]~^ ERROR type annotations needed
 }
 
 impl<T> Windows<T> {
     fn T() -> Option<Self::Item> {}
-    //[no_gate]~^ ERROR: ambiguous associated type
-    //[with_gate]~^^ ERROR type annotations needed
+    //~^ ERROR: ambiguous associated type
 }
 
 fn main() {}
diff --git a/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr b/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr
index d413c65dccb..a7d17e2d5eb 100644
--- a/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr
+++ b/tests/ui/associated-inherent-types/issue-109071.with_gate.stderr
@@ -20,19 +20,20 @@ help: add missing generic argument
 LL | impl<T> Windows<T> {
    |                +++
 
-error[E0282]: type annotations needed
-  --> $DIR/issue-109071.rs:11:18
-   |
-LL |     fn next() -> Option<Self::Item> {}
-   |                  ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
-
-error[E0282]: type annotations needed
-  --> $DIR/issue-109071.rs:16:15
+error[E0223]: ambiguous associated type
+  --> $DIR/issue-109071.rs:15:22
    |
 LL |     fn T() -> Option<Self::Item> {}
-   |               ^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
+   |                      ^^^^^^^^^^
+   |
+help: use fully-qualified syntax
+   |
+LL |     fn T() -> Option<<Windows<T> as IntoAsyncIterator>::Item> {}
+   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL |     fn T() -> Option<<Windows<T> as IntoIterator>::Item> {}
+   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0107, E0282, E0637.
+Some errors have detailed explanations: E0107, E0223, E0637.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/associated-types/issue-23595-1.rs b/tests/ui/associated-types/issue-23595-1.rs
index 9222f5b6650..579fde34f53 100644
--- a/tests/ui/associated-types/issue-23595-1.rs
+++ b/tests/ui/associated-types/issue-23595-1.rs
@@ -5,9 +5,8 @@ use std::ops::Index;
 trait Hierarchy {
     type Value;
     type ChildKey;
-    type Children = dyn Index<Self::ChildKey, Output=dyn Hierarchy>;
+    type Children = dyn Index<Self::ChildKey, Output = dyn Hierarchy>;
     //~^ ERROR: the value of the associated types
-    //~| ERROR: the size for values of type
 
     fn data(&self) -> Option<(Self::Value, Self::Children)>;
 }
diff --git a/tests/ui/associated-types/issue-23595-1.stderr b/tests/ui/associated-types/issue-23595-1.stderr
index 46906ab3fb7..694b68ef090 100644
--- a/tests/ui/associated-types/issue-23595-1.stderr
+++ b/tests/ui/associated-types/issue-23595-1.stderr
@@ -1,27 +1,13 @@
 error[E0191]: the value of the associated types `Value`, `ChildKey` and `Children` in `Hierarchy` must be specified
-  --> $DIR/issue-23595-1.rs:8:58
+  --> $DIR/issue-23595-1.rs:8:60
    |
 LL |     type Value;
    |     ---------- `Value` defined here
 LL |     type ChildKey;
    |     ------------- `ChildKey` defined here
-LL |     type Children = dyn Index<Self::ChildKey, Output=dyn Hierarchy>;
-   |     ------------- `Children` defined here                ^^^^^^^^^ help: specify the associated types: `Hierarchy<Value = Type, ChildKey = Type, Children = Type>`
+LL |     type Children = dyn Index<Self::ChildKey, Output = dyn Hierarchy>;
+   |     ------------- `Children` defined here                  ^^^^^^^^^ help: specify the associated types: `Hierarchy<Value = Type, ChildKey = Type, Children = Type>`
 
-error[E0277]: the size for values of type `(dyn Index<<Self as Hierarchy>::ChildKey, Output = (dyn Hierarchy + 'static)> + 'static)` cannot be known at compilation time
-  --> $DIR/issue-23595-1.rs:8:21
-   |
-LL |     type Children = dyn Index<Self::ChildKey, Output=dyn Hierarchy>;
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `(dyn Index<<Self as Hierarchy>::ChildKey, Output = (dyn Hierarchy + 'static)> + 'static)`
-note: required by a bound in `Hierarchy::Children`
-  --> $DIR/issue-23595-1.rs:8:5
-   |
-LL |     type Children = dyn Index<Self::ChildKey, Output=dyn Hierarchy>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Hierarchy::Children`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0191, E0277.
-For more information about an error, try `rustc --explain E0191`.
+For more information about this error, try `rustc --explain E0191`.
diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr
index 10276af4d8f..661ee7bff52 100644
--- a/tests/ui/check-cfg/compact-values.stderr
+++ b/tests/ui/check-cfg/compact-values.stderr
@@ -5,7 +5,6 @@ LL | #[cfg(target(os = "linux", pointer_width = "X"))]
    |                            ^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_pointer_width` are: `16`, `32`, `64`
-   = help: to expect this configuration use `--check-cfg=cfg(target_pointer_width, values("X"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index 27af8212026..040f727a840 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -18,7 +18,6 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = help: to expect this configuration use `--check-cfg=cfg(test, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition name: `feature`
diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
index a5aa80ef8e5..3cde11cf0f8 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
@@ -18,7 +18,6 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = help: to expect this configuration use `--check-cfg=cfg(test, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `unk`
diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
index a5aa80ef8e5..3cde11cf0f8 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
@@ -18,7 +18,6 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = help: to expect this configuration use `--check-cfg=cfg(test, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `unk`
diff --git a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr
index 0a7bd81b8aa..e8cf29ae982 100644
--- a/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-values.empty_cfg.stderr
@@ -7,7 +7,6 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = help: to expect this configuration use `--check-cfg=cfg(test, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
diff --git a/tests/ui/check-cfg/exhaustive-values.without_names.stderr b/tests/ui/check-cfg/exhaustive-values.without_names.stderr
index 0a7bd81b8aa..e8cf29ae982 100644
--- a/tests/ui/check-cfg/exhaustive-values.without_names.stderr
+++ b/tests/ui/check-cfg/exhaustive-values.without_names.stderr
@@ -7,7 +7,6 @@ LL | #[cfg(test = "value")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = help: to expect this configuration use `--check-cfg=cfg(test, values("value"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
diff --git a/tests/ui/check-cfg/no-expected-values.empty.stderr b/tests/ui/check-cfg/no-expected-values.empty.stderr
index ae55c95c0b1..0c0dbe9bac6 100644
--- a/tests/ui/check-cfg/no-expected-values.empty.stderr
+++ b/tests/ui/check-cfg/no-expected-values.empty.stderr
@@ -20,7 +20,6 @@ LL | #[cfg(test = "foo")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = help: to expect this configuration use `--check-cfg=cfg(test, values("foo"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
diff --git a/tests/ui/check-cfg/no-expected-values.mixed.stderr b/tests/ui/check-cfg/no-expected-values.mixed.stderr
index ae55c95c0b1..0c0dbe9bac6 100644
--- a/tests/ui/check-cfg/no-expected-values.mixed.stderr
+++ b/tests/ui/check-cfg/no-expected-values.mixed.stderr
@@ -20,7 +20,6 @@ LL | #[cfg(test = "foo")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = help: to expect this configuration use `--check-cfg=cfg(test, values("foo"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
diff --git a/tests/ui/check-cfg/no-expected-values.simple.stderr b/tests/ui/check-cfg/no-expected-values.simple.stderr
index ae55c95c0b1..0c0dbe9bac6 100644
--- a/tests/ui/check-cfg/no-expected-values.simple.stderr
+++ b/tests/ui/check-cfg/no-expected-values.simple.stderr
@@ -20,7 +20,6 @@ LL | #[cfg(test = "foo")]
    |           help: remove the value
    |
    = note: no expected value for `test`
-   = help: to expect this configuration use `--check-cfg=cfg(test, values("foo"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: 2 warnings emitted
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 4f708e62cd3..9d134dcfcfd 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -7,7 +7,6 @@ LL |     debug_assertions = "_UNEXPECTED_VALUE",
    |                     help: remove the value
    |
    = note: no expected value for `debug_assertions`
-   = help: to expect this configuration use `--check-cfg=cfg(debug_assertions, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
    = note: `#[warn(unexpected_cfgs)]` on by default
 
@@ -20,7 +19,6 @@ LL |     doc = "_UNEXPECTED_VALUE",
    |        help: remove the value
    |
    = note: no expected value for `doc`
-   = help: to expect this configuration use `--check-cfg=cfg(doc, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -32,7 +30,6 @@ LL |     doctest = "_UNEXPECTED_VALUE",
    |            help: remove the value
    |
    = note: no expected value for `doctest`
-   = help: to expect this configuration use `--check-cfg=cfg(doctest, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -44,7 +41,6 @@ LL |     miri = "_UNEXPECTED_VALUE",
    |         help: remove the value
    |
    = note: no expected value for `miri`
-   = help: to expect this configuration use `--check-cfg=cfg(miri, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -56,7 +52,6 @@ LL |     overflow_checks = "_UNEXPECTED_VALUE",
    |                    help: remove the value
    |
    = note: no expected value for `overflow_checks`
-   = help: to expect this configuration use `--check-cfg=cfg(overflow_checks, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -66,7 +61,6 @@ LL |     panic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `panic` are: `abort`, `unwind`
-   = help: to expect this configuration use `--check-cfg=cfg(panic, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -78,7 +72,6 @@ LL |     proc_macro = "_UNEXPECTED_VALUE",
    |               help: remove the value
    |
    = note: no expected value for `proc_macro`
-   = help: to expect this configuration use `--check-cfg=cfg(proc_macro, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -88,7 +81,6 @@ LL |     relocation_model = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `relocation_model` are: `dynamic-no-pic`, `pic`, `pie`, `ropi`, `ropi-rwpi`, `rwpi`, `static`
-   = help: to expect this configuration use `--check-cfg=cfg(relocation_model, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -98,7 +90,6 @@ LL |     sanitize = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `sanitize` are: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`
-   = help: to expect this configuration use `--check-cfg=cfg(sanitize, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -108,7 +99,6 @@ LL |     target_abi = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, `x32`
-   = help: to expect this configuration use `--check-cfg=cfg(target_abi, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -118,7 +108,6 @@ LL |     target_arch = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
-   = help: to expect this configuration use `--check-cfg=cfg(target_arch, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -128,7 +117,6 @@ LL |     target_endian = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_endian` are: `big`, `little`
-   = help: to expect this configuration use `--check-cfg=cfg(target_endian, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -138,7 +126,6 @@ LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `psx`, `relibc`, `sgx`, `uclibc`
-   = help: to expect this configuration use `--check-cfg=cfg(target_env, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -148,7 +135,6 @@ LL |     target_family = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_family` are: `unix`, `wasm`, `windows`
-   = help: to expect this configuration use `--check-cfg=cfg(target_family, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -158,7 +144,6 @@ LL |     target_feature = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512er`, `avx512f`, `avx512ifma`, `avx512pf`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `f`, `f16c`, `f32mm`, `f64mm`, `fast-unaligned-access`, `fcma`, `fdivdu`, `fhm`, `flagm`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lasx`, `lbt`, `lor`, `lse`, `lsx`, `lvz`, `lzcnt`, `m`, `mclass`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sign-ext`, `simd128`, `sm4`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `sve`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, `zkt`
-   = help: to expect this configuration use `--check-cfg=cfg(target_feature, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -168,7 +153,6 @@ LL |     target_has_atomic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
-   = help: to expect this configuration use `--check-cfg=cfg(target_has_atomic, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -178,7 +162,6 @@ LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_has_atomic_equal_alignment` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
-   = help: to expect this configuration use `--check-cfg=cfg(target_has_atomic_equal_alignment, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -188,7 +171,6 @@ LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_has_atomic_load_store` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
-   = help: to expect this configuration use `--check-cfg=cfg(target_has_atomic_load_store, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -198,7 +180,6 @@ LL |     target_os = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`
-   = help: to expect this configuration use `--check-cfg=cfg(target_os, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -208,7 +189,6 @@ LL |     target_pointer_width = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_pointer_width` are: `16`, `32`, `64`
-   = help: to expect this configuration use `--check-cfg=cfg(target_pointer_width, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -220,7 +200,6 @@ LL |     target_thread_local = "_UNEXPECTED_VALUE",
    |                        help: remove the value
    |
    = note: no expected value for `target_thread_local`
-   = help: to expect this configuration use `--check-cfg=cfg(target_thread_local, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -230,7 +209,6 @@ LL |     target_vendor = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `nintendo`, `nvidia`, `pc`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, `wrs`
-   = help: to expect this configuration use `--check-cfg=cfg(target_vendor, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -242,7 +220,6 @@ LL |     test = "_UNEXPECTED_VALUE",
    |         help: remove the value
    |
    = note: no expected value for `test`
-   = help: to expect this configuration use `--check-cfg=cfg(test, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -254,7 +231,6 @@ LL |     unix = "_UNEXPECTED_VALUE",
    |         help: remove the value
    |
    = note: no expected value for `unix`
-   = help: to expect this configuration use `--check-cfg=cfg(unix, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@@ -266,7 +242,6 @@ LL |     windows = "_UNEXPECTED_VALUE",
    |            help: remove the value
    |
    = note: no expected value for `windows`
-   = help: to expect this configuration use `--check-cfg=cfg(windows, values("_UNEXPECTED_VALUE"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `linuz`
@@ -278,7 +253,6 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
    |                   help: there is a expected value with a similar name: `"linux"`
    |
    = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`
-   = help: to expect this configuration use `--check-cfg=cfg(target_os, values("linuz"))`
    = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
 
 warning: 26 warnings emitted
diff --git a/tests/ui/const-generics/issues/issue-71381.full.stderr b/tests/ui/const-generics/issues/issue-71381.full.stderr
index b6460e0017f..5d780074696 100644
--- a/tests/ui/const-generics/issues/issue-71381.full.stderr
+++ b/tests/ui/const-generics/issues/issue-71381.full.stderr
@@ -7,7 +7,7 @@ LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "
    = note: type parameters may not be used in the type of const parameters
 
 error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/issue-71381.rs:23:40
+  --> $DIR/issue-71381.rs:22:40
    |
 LL |         const FN: unsafe extern "C" fn(Args),
    |                                        ^^^^ the type must not depend on the parameter `Args`
diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr
index e16d3b7a8a4..5d780074696 100644
--- a/tests/ui/const-generics/issues/issue-71381.min.stderr
+++ b/tests/ui/const-generics/issues/issue-71381.min.stderr
@@ -7,29 +7,13 @@ LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "
    = note: type parameters may not be used in the type of const parameters
 
 error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/issue-71381.rs:23:40
+  --> $DIR/issue-71381.rs:22:40
    |
 LL |         const FN: unsafe extern "C" fn(Args),
    |                                        ^^^^ the type must not depend on the parameter `Args`
    |
    = note: type parameters may not be used in the type of const parameters
 
-error: using function pointers as const generic parameters is forbidden
-  --> $DIR/issue-71381.rs:14:61
-   |
-LL |     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
-   |                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-
-error: using function pointers as const generic parameters is forbidden
-  --> $DIR/issue-71381.rs:23:19
-   |
-LL |         const FN: unsafe extern "C" fn(Args),
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/issues/issue-71381.rs b/tests/ui/const-generics/issues/issue-71381.rs
index 8a878efb42a..75ad4545371 100644
--- a/tests/ui/const-generics/issues/issue-71381.rs
+++ b/tests/ui/const-generics/issues/issue-71381.rs
@@ -12,8 +12,7 @@ unsafe extern "C" fn pass(args: PassArg) {
 
 impl Test {
     pub fn call_me<Args: Sized, const IDX: usize, const FN: unsafe extern "C" fn(Args)>(&self) {
-        //[min]~^ ERROR: using function pointers as const generic parameters is forbidden
-        //~^^ ERROR: the type of const parameters must not depend on other generic parameters
+        //~^ ERROR: the type of const parameters must not depend on other generic parameters
         self.0 = Self::trampiline::<Args, IDX, FN> as _
     }
 
@@ -21,8 +20,7 @@ impl Test {
         Args: Sized,
         const IDX: usize,
         const FN: unsafe extern "C" fn(Args),
-        //[min]~^ ERROR: using function pointers as const generic parameters is forbidden
-        //~^^ ERROR: the type of const parameters must not depend on other generic parameters
+        //~^ ERROR: the type of const parameters must not depend on other generic parameters
     >(
         args: Args,
     ) {
diff --git a/tests/ui/const-generics/issues/issue-71611.min.stderr b/tests/ui/const-generics/issues/issue-71611.min.stderr
index b01936f4d25..6f6a9fc21a6 100644
--- a/tests/ui/const-generics/issues/issue-71611.min.stderr
+++ b/tests/ui/const-generics/issues/issue-71611.min.stderr
@@ -6,14 +6,6 @@ LL | fn func<A, const F: fn(inner: A)>(outer: A) {
    |
    = note: type parameters may not be used in the type of const parameters
 
-error: using function pointers as const generic parameters is forbidden
-  --> $DIR/issue-71611.rs:5:21
-   |
-LL | fn func<A, const F: fn(inner: A)>(outer: A) {
-   |                     ^^^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0770`.
diff --git a/tests/ui/const-generics/issues/issue-71611.rs b/tests/ui/const-generics/issues/issue-71611.rs
index c917f66818b..92930092482 100644
--- a/tests/ui/const-generics/issues/issue-71611.rs
+++ b/tests/ui/const-generics/issues/issue-71611.rs
@@ -3,8 +3,7 @@
 #![cfg_attr(full, allow(incomplete_features))]
 
 fn func<A, const F: fn(inner: A)>(outer: A) {
-    //[min]~^ ERROR: using function pointers as const generic parameters is forbidden
-    //~^^ ERROR: the type of const parameters must not depend on other generic parameters
+    //~^ ERROR: the type of const parameters must not depend on other generic parameters
     F(outer);
 }
 
diff --git a/tests/ui/consts/const-err4.rs b/tests/ui/consts/const-err-enum-discriminant.rs
index 107dc3f8234..ebb3e551ba8 100644
--- a/tests/ui/consts/const-err4.rs
+++ b/tests/ui/consts/const-err-enum-discriminant.rs
@@ -1,4 +1,3 @@
-// stderr-per-bitwidth
 #[derive(Copy, Clone)]
 union Foo {
     a: isize,
diff --git a/tests/ui/consts/const-err4.32bit.stderr b/tests/ui/consts/const-err-enum-discriminant.stderr
index 582a848ca60..7cf34595dc9 100644
--- a/tests/ui/consts/const-err4.32bit.stderr
+++ b/tests/ui/consts/const-err-enum-discriminant.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const-err4.rs:9:21
+  --> $DIR/const-err-enum-discriminant.rs:8:21
    |
 LL |     Boo = [unsafe { Foo { b: () }.a }; 4][3],
    |                     ^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
diff --git a/tests/ui/consts/const-err4.64bit.stderr b/tests/ui/consts/const-err4.64bit.stderr
deleted file mode 100644
index 582a848ca60..00000000000
--- a/tests/ui/consts/const-err4.64bit.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: evaluation of constant value failed
-  --> $DIR/const-err4.rs:9:21
-   |
-LL |     Boo = [unsafe { Foo { b: () }.a }; 4][3],
-   |                     ^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/const-eval-query-stack.stderr b/tests/ui/consts/const-eval/const-eval-query-stack.stderr
index 01fb8153cf3..c748af608d1 100644
--- a/tests/ui/consts/const-eval/const-eval-query-stack.stderr
+++ b/tests/ui/consts/const-eval/const-eval-query-stack.stderr
@@ -1,4 +1,4 @@
-error[E0080]: evaluation of constant value failed
+error: internal compiler error[E0080]: evaluation of constant value failed
   --> $DIR/const-eval-query-stack.rs:16:16
    |
 LL | const X: i32 = 1 / 0;
diff --git a/tests/ui/coroutine/clone-rpit.next.stderr b/tests/ui/coroutine/clone-rpit.next.stderr
new file mode 100644
index 00000000000..2dbdbcc7b05
--- /dev/null
+++ b/tests/ui/coroutine/clone-rpit.next.stderr
@@ -0,0 +1,52 @@
+error[E0391]: cycle detected when type-checking `foo`
+  --> $DIR/clone-rpit.rs:12:1
+   |
+LL | pub fn foo<'a, 'b>() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires coroutine witness types for `foo::{closure#0}`...
+  --> $DIR/clone-rpit.rs:13:5
+   |
+LL |     move |_: ()| {
+   |     ^^^^^^^^^^^^
+note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
+  --> $DIR/clone-rpit.rs:13:5
+   |
+LL |     move |_: ()| {
+   |     ^^^^^^^^^^^^
+note: ...which requires preparing `foo::{closure#0}` for borrow checking...
+  --> $DIR/clone-rpit.rs:13:5
+   |
+LL |     move |_: ()| {
+   |     ^^^^^^^^^^^^
+note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
+  --> $DIR/clone-rpit.rs:13:5
+   |
+LL |     move |_: ()| {
+   |     ^^^^^^^^^^^^
+note: ...which requires building MIR for `foo::{closure#0}`...
+  --> $DIR/clone-rpit.rs:13:5
+   |
+LL |     move |_: ()| {
+   |     ^^^^^^^^^^^^
+note: ...which requires match-checking `foo::{closure#0}`...
+  --> $DIR/clone-rpit.rs:13:5
+   |
+LL |     move |_: ()| {
+   |     ^^^^^^^^^^^^
+note: ...which requires type-checking `foo::{closure#0}`...
+  --> $DIR/clone-rpit.rs:13:5
+   |
+LL |     move |_: ()| {
+   |     ^^^^^^^^^^^^
+   = note: ...which again requires type-checking `foo`, completing the cycle
+note: cycle used when computing type of opaque `foo::{opaque#0}`
+  --> $DIR/clone-rpit.rs:12:25
+   |
+LL | pub fn foo<'a, 'b>() -> impl Clone {
+   |                         ^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/coroutine/clone-rpit.rs b/tests/ui/coroutine/clone-rpit.rs
index cbd28f88fcb..22a553c83d6 100644
--- a/tests/ui/coroutine/clone-rpit.rs
+++ b/tests/ui/coroutine/clone-rpit.rs
@@ -1,6 +1,7 @@
 // revisions: current next
 //[next] compile-flags: -Znext-solver
-// check-pass
+//[current] check-pass
+//[next] known-bug: trait-system-refactor-initiative#82
 
 #![feature(coroutines, coroutine_trait, coroutine_clone)]
 
diff --git a/tests/ui/derives/issue-97343.rs b/tests/ui/derives/issue-97343.rs
index 91f0aa376e9..6f0e4d55aeb 100644
--- a/tests/ui/derives/issue-97343.rs
+++ b/tests/ui/derives/issue-97343.rs
@@ -2,7 +2,6 @@ use std::fmt::Debug;
 
 #[derive(Debug)]
 pub struct Irrelevant<Irrelevant> { //~ ERROR type arguments are not allowed on type parameter
-    //~^ ERROR `Irrelevant` must be used
     irrelevant: Irrelevant,
 }
 
diff --git a/tests/ui/derives/issue-97343.stderr b/tests/ui/derives/issue-97343.stderr
index 45612ae6f47..efb2fb70f5a 100644
--- a/tests/ui/derives/issue-97343.stderr
+++ b/tests/ui/derives/issue-97343.stderr
@@ -16,16 +16,6 @@ LL | pub struct Irrelevant<Irrelevant> {
    |                       ^^^^^^^^^^
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0210]: type parameter `Irrelevant` must be used as the type parameter for some local type (e.g., `MyStruct<Irrelevant>`)
-  --> $DIR/issue-97343.rs:4:23
-   |
-LL | pub struct Irrelevant<Irrelevant> {
-   |                       ^^^^^^^^^^ type parameter `Irrelevant` must be used as the type parameter for some local type
-   |
-   = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
-   = note: only traits defined in the current crate can be implemented for a type parameter
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0109, E0210.
-For more information about an error, try `rustc --explain E0109`.
+For more information about this error, try `rustc --explain E0109`.
diff --git a/tests/ui/error-codes/E0227.rs b/tests/ui/error-codes/E0227.rs
index 4dd4da55fa3..bab6d8af476 100644
--- a/tests/ui/error-codes/E0227.rs
+++ b/tests/ui/error-codes/E0227.rs
@@ -6,8 +6,6 @@ trait FooBar<'foo, 'bar>: Foo<'foo> + Bar<'bar> {}
 struct Baz<'foo, 'bar> {
     baz: dyn FooBar<'foo, 'bar>,
     //~^ ERROR ambiguous lifetime bound, explicit lifetime bound required
-    //~| ERROR lifetime bound not satisfied
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/error-codes/E0227.stderr b/tests/ui/error-codes/E0227.stderr
index 6338034a022..c77a2e98af7 100644
--- a/tests/ui/error-codes/E0227.stderr
+++ b/tests/ui/error-codes/E0227.stderr
@@ -4,24 +4,6 @@ error[E0227]: ambiguous lifetime bound, explicit lifetime bound required
 LL |     baz: dyn FooBar<'foo, 'bar>,
    |          ^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0478]: lifetime bound not satisfied
-  --> $DIR/E0227.rs:7:10
-   |
-LL |     baz: dyn FooBar<'foo, 'bar>,
-   |          ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: lifetime parameter instantiated with the lifetime `'bar` as defined here
-  --> $DIR/E0227.rs:6:18
-   |
-LL | struct Baz<'foo, 'bar> {
-   |                  ^^^^
-note: but lifetime parameter must outlive the lifetime `'foo` as defined here
-  --> $DIR/E0227.rs:6:12
-   |
-LL | struct Baz<'foo, 'bar> {
-   |            ^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0227, E0478.
-For more information about an error, try `rustc --explain E0227`.
+For more information about this error, try `rustc --explain E0227`.
diff --git a/tests/ui/extenv/extenv-env-overload.rs b/tests/ui/extenv/extenv-env-overload.rs
index b82bb2fe966..8b3b565fe83 100644
--- a/tests/ui/extenv/extenv-env-overload.rs
+++ b/tests/ui/extenv/extenv-env-overload.rs
@@ -1,6 +1,6 @@
 // run-pass
 // rustc-env:MY_VAR=tadam
-// compile-flags: --env MY_VAR=123abc -Zunstable-options
+// compile-flags: --env-set MY_VAR=123abc -Zunstable-options
 
 // This test ensures that variables provided with `--env` take precedence over
 // variables from environment.
diff --git a/tests/ui/extenv/extenv-env.rs b/tests/ui/extenv/extenv-env.rs
index 9fda52b8941..051ea214c1b 100644
--- a/tests/ui/extenv/extenv-env.rs
+++ b/tests/ui/extenv/extenv-env.rs
@@ -1,4 +1,4 @@
-// compile-flags: --env FOO=123abc -Zunstable-options
+// compile-flags: --env-set FOO=123abc -Zunstable-options
 // run-pass
 fn main() {
     assert_eq!(env!("FOO"), "123abc");
diff --git a/tests/ui/extenv/extenv-not-env.rs b/tests/ui/extenv/extenv-not-env.rs
index d6c4a43b003..b0355e073e4 100644
--- a/tests/ui/extenv/extenv-not-env.rs
+++ b/tests/ui/extenv/extenv-not-env.rs
@@ -1,6 +1,6 @@
 // run-pass
 // rustc-env:MY_ENV=/
-// Ensures that variables not defined through `--env` are still available.
+// Ensures that variables not defined through `--env-set` are still available.
 
 fn main() {
     assert!(!env!("MY_ENV").is_empty());
diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr
index 54b5e66fc21..79efcc5d8b0 100644
--- a/tests/ui/extern-flag/empty-extern-arg.stderr
+++ b/tests/ui/extern-flag/empty-extern-arg.stderr
@@ -2,10 +2,10 @@ error: extern location for std does not exist:
 
 error: `#[panic_handler]` function required, but not found
 
-error: language item required, but not found: `eh_personality`
+error: unwinding panics are not supported without std
    |
-   = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
-   = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`
+   = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
+   = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/env-flag.rs b/tests/ui/feature-gates/env-flag.rs
index 9dfda2584fb..598773cf3e4 100644
--- a/tests/ui/feature-gates/env-flag.rs
+++ b/tests/ui/feature-gates/env-flag.rs
@@ -1,3 +1,3 @@
-// compile-flags: --env A=B
+// compile-flags: --env-set A=B
 
 fn main() {}
diff --git a/tests/ui/feature-gates/env-flag.stderr b/tests/ui/feature-gates/env-flag.stderr
index 5cb18cef9fb..a9fa1b65ea1 100644
--- a/tests/ui/feature-gates/env-flag.stderr
+++ b/tests/ui/feature-gates/env-flag.stderr
@@ -1,2 +1,2 @@
-error: the `-Z unstable-options` flag must also be passed to enable the flag `env`
+error: the `-Z unstable-options` flag must also be passed to enable the flag `env-set`
 
diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs
index e58b6f6091e..f0e162d825f 100644
--- a/tests/ui/generic-associated-types/issue-71176.rs
+++ b/tests/ui/generic-associated-types/issue-71176.rs
@@ -9,9 +9,6 @@ impl Provider for () {
 struct Holder<B> {
   inner: Box<dyn Provider<A = B>>,
   //~^ ERROR: missing generics for associated type
-  //~| ERROR: missing generics for associated type
-  //~| ERROR: missing generics for associated type
-  //~| ERROR: the trait `Provider` cannot be made into an object
 }
 
 fn main() {
diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr
index a1913bb618b..ed837f34753 100644
--- a/tests/ui/generic-associated-types/issue-71176.stderr
+++ b/tests/ui/generic-associated-types/issue-71176.stderr
@@ -14,57 +14,6 @@ help: add missing lifetime argument
 LL |   inner: Box<dyn Provider<A<'a> = B>>,
    |                            ++++
 
-error[E0107]: missing generics for associated type `Provider::A`
-  --> $DIR/issue-71176.rs:10:27
-   |
-LL |   inner: Box<dyn Provider<A = B>>,
-   |                           ^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-71176.rs:2:10
-   |
-LL |     type A<'a>;
-   |          ^ --
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-help: add missing lifetime argument
-   |
-LL |   inner: Box<dyn Provider<A<'a> = B>>,
-   |                            ++++
-
-error[E0107]: missing generics for associated type `Provider::A`
-  --> $DIR/issue-71176.rs:10:27
-   |
-LL |   inner: Box<dyn Provider<A = B>>,
-   |                           ^ expected 1 lifetime argument
-   |
-note: associated type defined here, with 1 lifetime parameter: `'a`
-  --> $DIR/issue-71176.rs:2:10
-   |
-LL |     type A<'a>;
-   |          ^ --
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-help: add missing lifetime argument
-   |
-LL |   inner: Box<dyn Provider<A<'a> = B>>,
-   |                            ++++
-
-error[E0038]: the trait `Provider` cannot be made into an object
-  --> $DIR/issue-71176.rs:10:14
-   |
-LL |   inner: Box<dyn Provider<A = B>>,
-   |              ^^^^^^^^^^^^^^^^^^^ `Provider` cannot be made into an object
-   |
-note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/issue-71176.rs:2:10
-   |
-LL | trait Provider {
-   |       -------- this trait cannot be made into an object...
-LL |     type A<'a>;
-   |          ^ ...because it contains the generic associated type `A`
-   = help: consider moving `A` to another trait
-   = help: only type `()` implements the trait, consider using it directly instead
-
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0038, E0107.
-For more information about an error, try `rustc --explain E0038`.
+For more information about this error, try `rustc --explain E0107`.
diff --git a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs
new file mode 100644
index 00000000000..cd3acf9bc41
--- /dev/null
+++ b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.rs
@@ -0,0 +1,16 @@
+trait Foo {
+    type Context<'c>
+    where
+        Self: 'c;
+}
+
+impl Foo for Box<dyn Foo> {}
+//~^ ERROR `Foo` cannot be made into an object
+//~| ERROR `Foo` cannot be made into an object
+//~| ERROR cycle detected
+//~| ERROR cycle detected
+//~| ERROR cycle detected
+//~| ERROR the trait bound `Box<(dyn Foo + 'static)>: Foo` is not satisfied
+//~| ERROR not all trait items implemented
+
+fn main() {}
diff --git a/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr
new file mode 100644
index 00000000000..8e6b69f7461
--- /dev/null
+++ b/tests/ui/generic-associated-types/unknown-lifetime-ice-119827.stderr
@@ -0,0 +1,119 @@
+error[E0391]: cycle detected when computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>`
+  --> $DIR/unknown-lifetime-ice-119827.rs:7:1
+   |
+LL | impl Foo for Box<dyn Foo> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: ...which requires finding trait impls of `Foo`...
+  --> $DIR/unknown-lifetime-ice-119827.rs:1:1
+   |
+LL | trait Foo {
+   | ^^^^^^^^^
+   = note: ...which again requires computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>`, completing the cycle
+note: cycle used when collecting item types in top-level module
+  --> $DIR/unknown-lifetime-ice-119827.rs:1:1
+   |
+LL | / trait Foo {
+LL | |     type Context<'c>
+LL | |     where
+LL | |         Self: 'c;
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error[E0391]: cycle detected when computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>`
+  --> $DIR/unknown-lifetime-ice-119827.rs:7:1
+   |
+LL | impl Foo for Box<dyn Foo> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: ...which immediately requires computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>` again
+note: cycle used when collecting item types in top-level module
+  --> $DIR/unknown-lifetime-ice-119827.rs:1:1
+   |
+LL | / trait Foo {
+LL | |     type Context<'c>
+LL | |     where
+LL | |         Self: 'c;
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error[E0391]: cycle detected when computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>`
+  --> $DIR/unknown-lifetime-ice-119827.rs:7:1
+   |
+LL | impl Foo for Box<dyn Foo> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: ...which immediately requires computing type of `<impl at $DIR/unknown-lifetime-ice-119827.rs:7:1: 7:26>` again
+note: cycle used when collecting item types in top-level module
+  --> $DIR/unknown-lifetime-ice-119827.rs:1:1
+   |
+LL | / trait Foo {
+LL | |     type Context<'c>
+LL | |     where
+LL | |         Self: 'c;
+...  |
+LL | |
+LL | | fn main() {}
+   | |____________^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/unknown-lifetime-ice-119827.rs:7:22
+   |
+LL | impl Foo for Box<dyn Foo> {}
+   |                      ^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/unknown-lifetime-ice-119827.rs:2:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type Context<'c>
+   |          ^^^^^^^ ...because it contains the generic associated type `Context`
+   = help: consider moving `Context` to another trait
+   = help: only type `{type error}` implements the trait, consider using it directly instead
+
+error[E0277]: the trait bound `Box<(dyn Foo + 'static)>: Foo` is not satisfied
+  --> $DIR/unknown-lifetime-ice-119827.rs:7:14
+   |
+LL | impl Foo for Box<dyn Foo> {}
+   |              ^^^^^^^^^^^^ the trait `Foo` is not implemented for `Box<(dyn Foo + 'static)>`
+   |
+   = help: the trait `Foo` is implemented for `Box<(dyn Foo + 'static)>`
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/unknown-lifetime-ice-119827.rs:7:14
+   |
+LL | impl Foo for Box<dyn Foo> {}
+   |              ^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/unknown-lifetime-ice-119827.rs:2:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type Context<'c>
+   |          ^^^^^^^ ...because it contains the generic associated type `Context`
+   = help: consider moving `Context` to another trait
+   = help: only type `std::boxed::Box<(dyn Foo + 'static)>` implements the trait, consider using it directly instead
+
+error[E0046]: not all trait items implemented, missing: `Context`
+  --> $DIR/unknown-lifetime-ice-119827.rs:7:1
+   |
+LL |     type Context<'c>
+   |     ---------------- `Context` from trait
+...
+LL | impl Foo for Box<dyn Foo> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Context` in implementation
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0038, E0046, E0277, E0391.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr
index 5c552411da7..5824ef31211 100644
--- a/tests/ui/hygiene/panic-location.run.stderr
+++ b/tests/ui/hygiene/panic-location.run.stderr
@@ -1,3 +1,3 @@
-thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5:
+thread 'main' panicked at library/alloc/src/raw_vec.rs:570:5:
 capacity overflow
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/tests/ui/impl-trait/eagerly-reveal-in-local-body.rs b/tests/ui/impl-trait/eagerly-reveal-in-local-body.rs
new file mode 100644
index 00000000000..a08c2c8765b
--- /dev/null
+++ b/tests/ui/impl-trait/eagerly-reveal-in-local-body.rs
@@ -0,0 +1,13 @@
+// check-pass
+// compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait)]
+
+fn main() {
+    type Tait = impl Sized;
+    struct S {
+        i: i32,
+    }
+    let x: Tait = S { i: 0 };
+    println!("{}", x.i);
+}
diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr
index 07ba8eb021b..7af4846a959 100644
--- a/tests/ui/impl-trait/issues/issue-86800.stderr
+++ b/tests/ui/impl-trait/issues/issue-86800.stderr
@@ -4,7 +4,7 @@ error: unconstrained opaque type
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-error[E0792]: expected generic lifetime parameter, found `'_`
+error: internal compiler error[E0792]: expected generic lifetime parameter, found `'_`
   --> $DIR/issue-86800.rs:39:5
    |
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
index 11b3c4ef007..df457c13e70 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
@@ -1,5 +1,5 @@
 error[E0733]: recursion in a coroutine requires boxing
-  --> $DIR/recursive-coroutine-indirect.rs:6:5
+  --> $DIR/recursive-coroutine-indirect.rs:10:5
    |
 LL |     move || {
    |     ^^^^^^^
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
index 11b3c4ef007..df457c13e70 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
@@ -1,5 +1,5 @@
 error[E0733]: recursion in a coroutine requires boxing
-  --> $DIR/recursive-coroutine-indirect.rs:6:5
+  --> $DIR/recursive-coroutine-indirect.rs:10:5
    |
 LL |     move || {
    |     ^^^^^^^
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.rs b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
index 4f8d4d33050..99b6be3358f 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.rs
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
@@ -1,5 +1,9 @@
 // revisions: current next
 //[next] compile-flags: -Znext-solver
+
+//[next] build-fail
+// Deeply normalizing writeback results of opaques makes this into a post-mono error :(
+
 #![feature(coroutines)]
 #![allow(unconditional_recursion)]
 fn coroutine_hold() -> impl Sized {
diff --git a/tests/ui/issues/issue-3214.rs b/tests/ui/issues/issue-3214.rs
index 03d8d6ba246..b2c27f5be95 100644
--- a/tests/ui/issues/issue-3214.rs
+++ b/tests/ui/issues/issue-3214.rs
@@ -5,7 +5,6 @@ fn foo<T>() {
 
     impl<T> Drop for Foo<T> {
         //~^ ERROR struct takes 0 generic arguments but 1 generic argument
-        //~| ERROR `T` is not constrained
         fn drop(&mut self) {}
     }
 }
diff --git a/tests/ui/issues/issue-3214.stderr b/tests/ui/issues/issue-3214.stderr
index 26ac6d39f60..5b57c1baf90 100644
--- a/tests/ui/issues/issue-3214.stderr
+++ b/tests/ui/issues/issue-3214.stderr
@@ -22,13 +22,7 @@ note: struct defined here, with 0 generic parameters
 LL |     struct Foo {
    |            ^^^
 
-error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/issue-3214.rs:6:10
-   |
-LL |     impl<T> Drop for Foo<T> {
-   |          ^ unconstrained type parameter
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0107, E0207, E0401.
+Some errors have detailed explanations: E0107, E0401.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/lang-items/required-lang-item.rs b/tests/ui/lang-items/required-lang-item.rs
index 3b17c5b7255..7f8933ac2ad 100644
--- a/tests/ui/lang-items/required-lang-item.rs
+++ b/tests/ui/lang-items/required-lang-item.rs
@@ -1,11 +1,10 @@
-// build-fail
+// edition: 2018
 
 #![feature(lang_items, no_core)]
 #![no_core]
+#![no_main]
 
 #[lang="copy"] pub trait Copy { }
 #[lang="sized"] pub trait Sized { }
 
-// error-pattern:requires `start` lang_item
-
-fn main() {}
+async fn x() {} //~ ERROR requires `ResumeTy` lang_item
diff --git a/tests/ui/lang-items/required-lang-item.stderr b/tests/ui/lang-items/required-lang-item.stderr
index bb53d336bb2..13c07ee6529 100644
--- a/tests/ui/lang-items/required-lang-item.stderr
+++ b/tests/ui/lang-items/required-lang-item.stderr
@@ -1,4 +1,8 @@
-error: requires `start` lang_item
+error: requires `ResumeTy` lang_item
+  --> $DIR/required-lang-item.rs:10:14
+   |
+LL | async fn x() {}
+   |              ^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/layout/issue-84108.rs b/tests/ui/layout/issue-84108.rs
index af21d1d6210..44d6ac8db72 100644
--- a/tests/ui/layout/issue-84108.rs
+++ b/tests/ui/layout/issue-84108.rs
@@ -8,8 +8,6 @@ static FOO: (dyn AsRef<OsStr>, u8) = ("hello", 42);
 
 const BAR: (&Path, [u8], usize) = ("hello", [], 42);
 //~^ ERROR cannot find type `Path` in this scope
-//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
-//~| ERROR mismatched types
 
 static BAZ: ([u8], usize) = ([], 0);
 //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr
index d6d75851034..58bddb069fc 100644
--- a/tests/ui/layout/issue-84108.stderr
+++ b/tests/ui/layout/issue-84108.stderr
@@ -21,25 +21,7 @@ LL + use std::path::Path;
    |
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-84108.rs:9:12
-   |
-LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
-   |            ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `[u8]`
-   = note: only the last element of a tuple may have a dynamically sized type
-
-error[E0308]: mismatched types
-  --> $DIR/issue-84108.rs:9:45
-   |
-LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
-   |                                             ^^ expected `[u8]`, found `[_; 0]`
-   |
-   = note: expected slice `[u8]`
-              found array `[_; 0]`
-
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-84108.rs:14:13
+  --> $DIR/issue-84108.rs:12:13
    |
 LL | static BAZ: ([u8], usize) = ([], 0);
    |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -48,7 +30,7 @@ LL | static BAZ: ([u8], usize) = ([], 0);
    = note: only the last element of a tuple may have a dynamically sized type
 
 error[E0308]: mismatched types
-  --> $DIR/issue-84108.rs:14:30
+  --> $DIR/issue-84108.rs:12:30
    |
 LL | static BAZ: ([u8], usize) = ([], 0);
    |                              ^^ expected `[u8]`, found `[_; 0]`
@@ -56,7 +38,7 @@ LL | static BAZ: ([u8], usize) = ([], 0);
    = note: expected slice `[u8]`
               found array `[_; 0]`
 
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0412.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.rs b/tests/ui/lifetimes/unusual-rib-combinations.rs
index 2f5ba98445b..a2461cff932 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.rs
+++ b/tests/ui/lifetimes/unusual-rib-combinations.rs
@@ -28,6 +28,5 @@ fn d<const C: S>() {}
 trait Foo<'a> {}
 struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
 //~^ ERROR the type of const parameters must not depend on other generic parameters
-//~| ERROR `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter
 
 fn main() {}
diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr
index 92a2ef2f432..e3b70232ef8 100644
--- a/tests/ui/lifetimes/unusual-rib-combinations.stderr
+++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr
@@ -58,16 +58,7 @@ LL | fn d<const C: S>() {}
    = note: the only supported types are integers, `bool` and `char`
    = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
 
-error: `&dyn for<'a> Foo<'a>` is forbidden as the type of a const generic parameter
-  --> $DIR/unusual-rib-combinations.rs:29:21
-   |
-LL | struct Bar<const N: &'a (dyn for<'a> Foo<'a>)>;
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the only supported types are integers, `bool` and `char`
-   = help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types
-
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0106, E0214, E0308, E0770.
 For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/lint/unused/issue-117142-invalid-remove-parens.rs b/tests/ui/lint/unused/issue-117142-invalid-remove-parens.rs
new file mode 100644
index 00000000000..8af9e6f3d95
--- /dev/null
+++ b/tests/ui/lint/unused/issue-117142-invalid-remove-parens.rs
@@ -0,0 +1,19 @@
+// check-pass
+#![warn(unused_parens)]
+
+fn main() {
+    let a: i32 = 1;
+    let b: i64 = 1;
+
+    if b + a as (i64) < 0 {
+        println!(":D");
+    }
+    if b + b + a as (i64) < 0 {
+        println!(":D");
+    }
+    let c = a + b as (i32) < 0;
+    let mut x = false;
+    x |= false || (b as (i32) < 0);
+
+    let d = 1 + 2 + 3 * 4 as (i32) < 10;
+}
diff --git a/tests/ui/no_std/no-std-no-start-binary.rs b/tests/ui/no_std/no-std-no-start-binary.rs
new file mode 100644
index 00000000000..ce1c871f6a6
--- /dev/null
+++ b/tests/ui/no_std/no-std-no-start-binary.rs
@@ -0,0 +1,13 @@
+// compile-flags: -Cpanic=abort --emit link
+// error-pattern:using `fn main` requires the standard library
+
+// Make sure that we don't emit an error message mentioning internal lang items.
+
+#![no_std]
+
+#[panic_handler]
+fn handler(_info: &core::panic::PanicInfo<'_>) -> ! {
+    loop {}
+}
+
+fn main() {}
diff --git a/tests/ui/no_std/no-std-no-start-binary.stderr b/tests/ui/no_std/no-std-no-start-binary.stderr
new file mode 100644
index 00000000000..dd06c234da2
--- /dev/null
+++ b/tests/ui/no_std/no-std-no-start-binary.stderr
@@ -0,0 +1,6 @@
+error: using `fn main` requires the standard library
+   |
+   = help: use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/no_std/no-std-unwind-binary.rs b/tests/ui/no_std/no-std-unwind-binary.rs
new file mode 100644
index 00000000000..7a9dfd7a48d
--- /dev/null
+++ b/tests/ui/no_std/no-std-unwind-binary.rs
@@ -0,0 +1,15 @@
+// error-pattern:unwinding panics are not supported without std
+// needs-unwind
+// compile-flags: -Cpanic=unwind
+
+// Make sure that we don't emit an error message mentioning internal lang items.
+
+#![no_std]
+#![no_main]
+
+#[panic_handler]
+fn handler(_info: &core::panic::PanicInfo<'_>) -> ! {
+    loop {}
+}
+
+fn main() {}
diff --git a/tests/ui/no_std/no-std-unwind-binary.stderr b/tests/ui/no_std/no-std-unwind-binary.stderr
new file mode 100644
index 00000000000..a3b54fe33ab
--- /dev/null
+++ b/tests/ui/no_std/no-std-unwind-binary.stderr
@@ -0,0 +1,7 @@
+error: unwinding panics are not supported without std
+   |
+   = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
+   = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/panic-handler/weak-lang-item.rs b/tests/ui/panic-handler/weak-lang-item.rs
index 14a07a9ef1b..296a2c1514f 100644
--- a/tests/ui/panic-handler/weak-lang-item.rs
+++ b/tests/ui/panic-handler/weak-lang-item.rs
@@ -1,6 +1,6 @@
 // aux-build:weak-lang-items.rs
 // error-pattern: `#[panic_handler]` function required, but not found
-// error-pattern: language item required, but not found: `eh_personality`
+// error-pattern: unwinding panics are not supported without std
 // needs-unwind since it affects the error output
 // ignore-emscripten missing eh_catch_typeinfo lang item
 
diff --git a/tests/ui/panic-handler/weak-lang-item.stderr b/tests/ui/panic-handler/weak-lang-item.stderr
index 202f3309d03..de351d2c3e4 100644
--- a/tests/ui/panic-handler/weak-lang-item.stderr
+++ b/tests/ui/panic-handler/weak-lang-item.stderr
@@ -12,10 +12,10 @@ LL | extern crate core as other_core;
 
 error: `#[panic_handler]` function required, but not found
 
-error: language item required, but not found: `eh_personality`
+error: unwinding panics are not supported without std
    |
-   = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
-   = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`
+   = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
+   = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr
index 4b00f135047..9d27cb22ae9 100644
--- a/tests/ui/panics/default-backtrace-ice.stderr
+++ b/tests/ui/panics/default-backtrace-ice.stderr
@@ -1,4 +1,4 @@
-error[E0425]: cannot find value `missing_ident` in this scope
+error: internal compiler error[E0425]: cannot find value `missing_ident` in this scope
   --> $DIR/default-backtrace-ice.rs:21:13
    |
 LL | fn main() { missing_ident; }
diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs
index 8012cb652bd..f6aa39df27d 100644
--- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs
+++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs
@@ -5,4 +5,3 @@ struct Apple((Apple, Option(Banana ? Citron)));
 //~| ERROR expected one of `)` or `,`, found `Citron`
 //~| ERROR cannot find type `Citron` in this scope [E0412]
 //~| ERROR parenthesized type parameters may only be used with a `Fn` trait [E0214]
-//~| ERROR recursive type `Apple` has infinite size [E0072]
diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr
index b0d8b03ae08..71d2d7b7975 100644
--- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr
+++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr
@@ -34,18 +34,7 @@ help: use angle brackets instead
 LL | struct Apple((Apple, Option<Banana ? Citron>));
    |                            ~               ~
 
-error[E0072]: recursive type `Apple` has infinite size
-  --> $DIR/issue-103748-ICE-wrong-braces.rs:3:1
-   |
-LL | struct Apple((Apple, Option(Banana ? Citron)));
-   | ^^^^^^^^^^^^  ----- recursive without indirection
-   |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
-   |
-LL | struct Apple((Box<Apple>, Option(Banana ? Citron)));
-   |               ++++     +
-
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0072, E0214, E0412.
-For more information about an error, try `rustc --explain E0072`.
+Some errors have detailed explanations: E0214, E0412.
+For more information about an error, try `rustc --explain E0214`.
diff --git a/tests/ui/pattern/usefulness/integer-ranges/issue-117648-overlapping_range_endpoints-false-positive.rs b/tests/ui/pattern/usefulness/integer-ranges/issue-117648-overlapping_range_endpoints-false-positive.rs
new file mode 100644
index 00000000000..37fcb4b4af9
--- /dev/null
+++ b/tests/ui/pattern/usefulness/integer-ranges/issue-117648-overlapping_range_endpoints-false-positive.rs
@@ -0,0 +1,9 @@
+// check-pass
+fn main() {
+    match (0i8, 0i8) {
+        (0, _) => {}
+        (..=-1, ..=0) => {}
+        (1.., 0..) => {}
+        (1.., ..=-1) | (..=-1, 1..) => {}
+    }
+}
diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
index 33c1dfd39d4..7e56880a87f 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
+++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.rs
@@ -44,13 +44,13 @@ fn main() {
     match (0u8, true) {
         (0..=10, true) => {}
         (10..20, true) => {} //~ ERROR multiple patterns overlap on their endpoints
-        (10..20, false) => {} //~ ERROR multiple patterns overlap on their endpoints
+        (10..20, false) => {}
         _ => {}
     }
     match (true, 0u8) {
         (true, 0..=10) => {}
         (true, 10..20) => {} //~ ERROR multiple patterns overlap on their endpoints
-        (false, 10..20) => {} //~ ERROR multiple patterns overlap on their endpoints
+        (false, 10..20) => {}
         _ => {}
     }
     match Some(0u8) {
@@ -58,4 +58,11 @@ fn main() {
         Some(10..20) => {} //~ ERROR multiple patterns overlap on their endpoints
         _ => {}
     }
+
+    // The lint has false negatives when we skip some cases because of relevancy.
+    match (true, true, 0u8) {
+        (true, _, 0..=10) => {}
+        (_, true, 10..20) => {}
+        _ => {}
+    }
 }
diff --git a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
index a87205d76d1..aa37bd9bc9c 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
@@ -85,17 +85,6 @@ LL |         (10..20, true) => {}
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:47:10
-   |
-LL |         (0..=10, true) => {}
-   |          ------ this range overlaps on `10_u8`...
-LL |         (10..20, true) => {}
-LL |         (10..20, false) => {}
-   |          ^^^^^^ ... with this range
-   |
-   = note: you likely meant to write mutually exclusive ranges
-
-error: multiple patterns overlap on their endpoints
   --> $DIR/overlapping_range_endpoints.rs:52:16
    |
 LL |         (true, 0..=10) => {}
@@ -106,17 +95,6 @@ LL |         (true, 10..20) => {}
    = note: you likely meant to write mutually exclusive ranges
 
 error: multiple patterns overlap on their endpoints
-  --> $DIR/overlapping_range_endpoints.rs:53:17
-   |
-LL |         (true, 0..=10) => {}
-   |                ------ this range overlaps on `10_u8`...
-LL |         (true, 10..20) => {}
-LL |         (false, 10..20) => {}
-   |                 ^^^^^^ ... with this range
-   |
-   = note: you likely meant to write mutually exclusive ranges
-
-error: multiple patterns overlap on their endpoints
   --> $DIR/overlapping_range_endpoints.rs:58:14
    |
 LL |         Some(0..=10) => {}
@@ -126,5 +104,5 @@ LL |         Some(10..20) => {}
    |
    = note: you likely meant to write mutually exclusive ranges
 
-error: aborting due to 12 previous errors
+error: aborting due to 10 previous errors
 
diff --git a/tests/ui/proc-macro/env.rs b/tests/ui/proc-macro/env.rs
index 1b1d1873eb3..c0edda4f7df 100644
--- a/tests/ui/proc-macro/env.rs
+++ b/tests/ui/proc-macro/env.rs
@@ -1,7 +1,7 @@
 // aux-build:env.rs
 // run-pass
 // rustc-env: THE_CONST=1
-// compile-flags: -Zunstable-options --env THE_CONST=12 --env ANOTHER=4
+// compile-flags: -Zunstable-options --env-set THE_CONST=12 --env-set ANOTHER=4
 
 #![crate_name = "foo"]
 
diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs
index 4cbc36f4650..52ecbcc9e2c 100644
--- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs
+++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.rs
@@ -39,7 +39,6 @@ impl<T: Trait<u32, String>> Struct<T> {}
 trait YetAnotherTrait {}
 impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {}
 //~^ ERROR struct takes 1 generic argument but 2 generic arguments were supplied
-//~| ERROR `U` is not constrained
 
 
 fn main() {
diff --git a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
index 3c2b726fcce..e7ceb7372bf 100644
--- a/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
+++ b/tests/ui/traits/associated_type_bound/116464-invalid-assoc-type-suggestion-in-trait-impl.stderr
@@ -116,13 +116,7 @@ error[E0207]: the type parameter `S` is not constrained by the impl trait, self
 LL | impl<T, S> Trait<T, S> for () {}
    |         ^ unconstrained type parameter
 
-error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/116464-invalid-assoc-type-suggestion-in-trait-impl.rs:40:35
-   |
-LL | impl<T: Trait<u32, Assoc=String>, U> YetAnotherTrait for Struct<T, U> {}
-   |                                   ^ unconstrained type parameter
-
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0107, E0207.
 For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
index e1e93f79920..01a98a30895 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
@@ -13,11 +13,8 @@ fn main() {
 }
 
 fn weird0() -> impl Sized + !Sized {}
-//~^ ERROR mismatched types
-//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
+//~^ ERROR type mismatch resolving `() == impl !Sized + Sized`
 fn weird1() -> impl !Sized + Sized {}
-//~^ ERROR mismatched types
-//~| ERROR type mismatch resolving `() == impl !Sized + Sized`
+//~^ ERROR type mismatch resolving `() == impl !Sized + Sized`
 fn weird2() -> impl !Sized {}
-//~^ ERROR mismatched types
-//~| ERROR type mismatch resolving `() == impl !Sized`
+//~^ ERROR type mismatch resolving `() == impl !Sized`
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
index 62792761870..d803e56e817 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
@@ -1,50 +1,17 @@
-error[E0308]: mismatched types
-  --> $DIR/opaque-type-unsatisfied-bound.rs:15:36
-   |
-LL | fn weird0() -> impl Sized + !Sized {}
-   |                ------------------- ^^ types differ
-   |                |
-   |                the expected opaque type
-   |
-   = note: expected opaque type `impl !Sized + Sized`
-                found unit type `()`
-
 error[E0271]: type mismatch resolving `() == impl !Sized + Sized`
   --> $DIR/opaque-type-unsatisfied-bound.rs:15:16
    |
 LL | fn weird0() -> impl Sized + !Sized {}
    |                ^^^^^^^^^^^^^^^^^^^ types differ
 
-error[E0308]: mismatched types
-  --> $DIR/opaque-type-unsatisfied-bound.rs:18:36
-   |
-LL | fn weird1() -> impl !Sized + Sized {}
-   |                ------------------- ^^ types differ
-   |                |
-   |                the expected opaque type
-   |
-   = note: expected opaque type `impl !Sized + Sized`
-                found unit type `()`
-
 error[E0271]: type mismatch resolving `() == impl !Sized + Sized`
-  --> $DIR/opaque-type-unsatisfied-bound.rs:18:16
+  --> $DIR/opaque-type-unsatisfied-bound.rs:17:16
    |
 LL | fn weird1() -> impl !Sized + Sized {}
    |                ^^^^^^^^^^^^^^^^^^^ types differ
 
-error[E0308]: mismatched types
-  --> $DIR/opaque-type-unsatisfied-bound.rs:21:28
-   |
-LL | fn weird2() -> impl !Sized {}
-   |                ----------- ^^ types differ
-   |                |
-   |                the expected opaque type
-   |
-   = note: expected opaque type `impl !Sized`
-                found unit type `()`
-
 error[E0271]: type mismatch resolving `() == impl !Sized`
-  --> $DIR/opaque-type-unsatisfied-bound.rs:21:16
+  --> $DIR/opaque-type-unsatisfied-bound.rs:19:16
    |
 LL | fn weird2() -> impl !Sized {}
    |                ^^^^^^^^^^^ types differ
@@ -63,7 +30,7 @@ note: required by a bound in `consume`
 LL | fn consume(_: impl Trait) {}
    |                    ^^^^^ required by this bound in `consume`
 
-error: aborting due to 7 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0271, E0277, E0308.
+Some errors have detailed explanations: E0271, E0277.
 For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs
index 72bca1a8910..bb2e861a1a7 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs
@@ -3,7 +3,6 @@
 #![feature(negative_bounds, unboxed_closures)]
 
 fn produce() -> impl !Fn<(u32,)> {}
-//~^ ERROR mismatched types
-//~| ERROR type mismatch resolving `() == impl !Fn<(u32,)>`
+//~^ ERROR type mismatch resolving `() == impl !Fn<(u32,)>`
 
 fn main() {}
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr
index a4fb4b2b5c4..1fd30410b00 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr
@@ -1,21 +1,9 @@
-error[E0308]: mismatched types
-  --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:34
-   |
-LL | fn produce() -> impl !Fn<(u32,)> {}
-   |                 ---------------- ^^ types differ
-   |                 |
-   |                 the expected opaque type
-   |
-   = note: expected opaque type `impl !Fn<(u32,)>`
-                found unit type `()`
-
 error[E0271]: type mismatch resolving `() == impl !Fn<(u32,)>`
   --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:17
    |
 LL | fn produce() -> impl !Fn<(u32,)> {}
    |                 ^^^^^^^^^^^^^^^^ types differ
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0271, E0308.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.rs b/tests/ui/traits/next-solver/alias-bound-unsound.rs
index 4e279a84a33..8fddbd7ecdc 100644
--- a/tests/ui/traits/next-solver/alias-bound-unsound.rs
+++ b/tests/ui/traits/next-solver/alias-bound-unsound.rs
@@ -23,10 +23,10 @@ fn main() {
     let x = String::from("hello, world");
     drop(<() as Foo>::copy_me(&x));
     //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized`
-    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
-    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
     //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
+    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
     //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
-    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
+    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
+    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
     println!("{x}");
 }
diff --git a/tests/ui/traits/next-solver/alias-bound-unsound.stderr b/tests/ui/traits/next-solver/alias-bound-unsound.stderr
index ac3f19b3fe6..874644317eb 100644
--- a/tests/ui/traits/next-solver/alias-bound-unsound.stderr
+++ b/tests/ui/traits/next-solver/alias-bound-unsound.stderr
@@ -52,13 +52,14 @@ LL |     drop(<() as Foo>::copy_me(&x));
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
 
-error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
+error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
   --> $DIR/alias-bound-unsound.rs:24:10
    |
 LL |     drop(<() as Foo>::copy_me(&x));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 7 previous errors
 
diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs
new file mode 100644
index 00000000000..424508dd9d9
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.rs
@@ -0,0 +1,39 @@
+// compile-flags: -Znext-solver
+#![feature(rustc_attrs)]
+
+// A test intended to check how we handle provisional results
+// for a goal computed with an inductive and a coinductive stack.
+//
+// Unfortunately this doesn't really detect whether we've done
+// something wrong but instead only showcases that we thought of
+// this.
+//
+// FIXME(-Znext-solver=coinductive): With the new coinduction approach
+// the same goal stack can be both inductive and coinductive, depending
+// on why we're proving a specific nested goal. Rewrite this test
+// at that point instead of relying on `BInd`.
+
+
+#[rustc_coinductive]
+trait A {}
+
+#[rustc_coinductive]
+trait B {}
+trait BInd {}
+impl<T: ?Sized + B> BInd for T {}
+
+#[rustc_coinductive]
+trait C {}
+trait CInd {}
+impl<T: ?Sized + C> CInd for T {}
+
+impl<T: ?Sized + BInd + C> A for T {}
+impl<T: ?Sized + CInd + C> B for T {}
+impl<T: ?Sized + B + A> C for T {}
+
+fn impls_a<T: A>() {}
+
+fn main() {
+    impls_a::<()>();
+    //~^ ERROR overflow evaluating the requirement `(): A`
+}
diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr
new file mode 100644
index 00000000000..e828bdeb16b
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-1.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `(): A`
+  --> $DIR/mixed-cycles-1.rs:37:15
+   |
+LL |     impls_a::<()>();
+   |               ^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mixed_cycles_1`)
+note: required by a bound in `impls_a`
+  --> $DIR/mixed-cycles-1.rs:34:15
+   |
+LL | fn impls_a<T: A>() {}
+   |               ^ required by this bound in `impls_a`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs
new file mode 100644
index 00000000000..300f30ecad2
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.rs
@@ -0,0 +1,32 @@
+// compile-flags: -Znext-solver
+#![feature(rustc_attrs)]
+
+// A test showcasing that the solver may need to
+// compute a goal which is already in the provisional
+// cache.
+//
+// However, given that `(): BInd` and `(): B` are currently distinct
+// goals, this is actually not possible right now.
+//
+// FIXME(-Znext-solver=coinductive): With the new coinduction approach
+// the same goal stack can be both inductive and coinductive, depending
+// on why we're proving a specific nested goal. Rewrite this test
+// at that point.
+
+#[rustc_coinductive]
+trait A {}
+
+#[rustc_coinductive]
+trait B {}
+trait BInd {}
+impl<T: ?Sized + B> BInd for T {}
+
+impl<T: ?Sized + BInd + B> A for T {}
+impl<T: ?Sized + BInd> B for T {}
+
+fn impls_a<T: A>() {}
+
+fn main() {
+    impls_a::<()>();
+    //~^ ERROR overflow evaluating the requirement `(): A`
+}
diff --git a/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr
new file mode 100644
index 00000000000..ec13093f707
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/mixed-cycles-2.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `(): A`
+  --> $DIR/mixed-cycles-2.rs:30:15
+   |
+LL |     impls_a::<()>();
+   |               ^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mixed_cycles_2`)
+note: required by a bound in `impls_a`
+  --> $DIR/mixed-cycles-2.rs:27:15
+   |
+LL | fn impls_a<T: A>() {}
+   |               ^ required by this bound in `impls_a`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/cycles/provisional-cache-impacts-behavior.rs b/tests/ui/traits/next-solver/cycles/provisional-cache-impacts-behavior.rs
new file mode 100644
index 00000000000..ab7c4c7601b
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/provisional-cache-impacts-behavior.rs
@@ -0,0 +1,70 @@
+// compile-flags: -Znext-solver
+// check-pass
+#![feature(rustc_attrs)]
+
+// A test showcasing that using a provisional cache can differ
+// from only tracking stack entries.
+//
+// Without a provisional cache, we have the following proof tree:
+//
+// - (): A
+//   - (): B
+//     - (): A (coinductive cycle)
+//     - (): C
+//       - (): B (coinductive cycle)
+//   - (): C
+//     - (): B
+//        - (): A (coinductive cycle)
+//        - (): C (coinductive cycle)
+//
+// While with the current provisional cache implementation we get:
+//
+// - (): A
+//   - (): B
+//     - (): A (coinductive cycle)
+//     - (): C
+//       - (): B (coinductive cycle)
+//   - (): C
+//     - (): B (provisional cache hit)
+//
+// Note that if even if we were to expand the provisional cache hit,
+// the proof tree would still be different:
+//
+// - (): A
+//   - (): B
+//     - (): A (coinductive cycle)
+//     - (): C
+//       - (): B (coinductive cycle)
+//   - (): C
+//     - (): B (provisional cache hit, expanded)
+//       - (): A (coinductive cycle)
+//       - (): C
+//         - (): B (coinductive cycle)
+//
+// Theoretically, this can result in observable behavior differences
+// due to incompleteness. However, this would require a very convoluted
+// example and would still be sound. The difference is determinstic
+// and can not be observed outside of the cycle itself as we don't move
+// non-root cycle participants into the global cache.
+//
+// For an example of how incompleteness could impact the observable behavior here, see
+//
+//   tests/ui/traits/next-solver/cycles/coinduction/incompleteness-unstable-result.rs
+#[rustc_coinductive]
+trait A {}
+
+#[rustc_coinductive]
+trait B {}
+
+#[rustc_coinductive]
+trait C {}
+
+impl<T: ?Sized + B + C> A for T {}
+impl<T: ?Sized + A + C> B for T {}
+impl<T: ?Sized + B> C for T {}
+
+fn impls_a<T: A>() {}
+
+fn main() {
+    impls_a::<()>();
+}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
index 327ef865de9..71b1502d775 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
@@ -13,8 +13,10 @@ fn needs_bar<S: Bar>() {}
 
 fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
     needs_bar::<T::Assoc1>();
-    //~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
-    //~| ERROR overflow evaluating the requirement `<T as Foo2>::Assoc2`
+    //~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
index eda62b99c44..bad6820f738 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
@@ -11,7 +11,7 @@ note: required by a bound in `needs_bar`
 LL | fn needs_bar<S: Bar>() {}
    |                 ^^^ required by this bound in `needs_bar`
 
-error[E0275]: overflow evaluating the requirement `<T as Foo2>::Assoc2`
+error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
   --> $DIR/recursive-self-normalization-2.rs:15:5
    |
 LL |     needs_bar::<T::Assoc1>();
@@ -19,6 +19,23 @@ LL |     needs_bar::<T::Assoc1>();
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
 
-error: aborting due to 2 previous errors
+error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+  --> $DIR/recursive-self-normalization-2.rs:15:5
+   |
+LL |     needs_bar::<T::Assoc1>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+  --> $DIR/recursive-self-normalization-2.rs:15:17
+   |
+LL |     needs_bar::<T::Assoc1>();
+   |                 ^^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
index f45d208e666..809a6a59ca6 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
@@ -9,8 +9,10 @@ fn needs_bar<S: Bar>() {}
 
 fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
     needs_bar::<T::Assoc>();
-    //~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc` [E0275]
+    //~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
+    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
+    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
+    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
index b0a0a69761a..80005d344ba 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
@@ -11,7 +11,7 @@ note: required by a bound in `needs_bar`
 LL | fn needs_bar<S: Bar>() {}
    |                 ^^^ required by this bound in `needs_bar`
 
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc`
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
   --> $DIR/recursive-self-normalization.rs:11:5
    |
 LL |     needs_bar::<T::Assoc>();
@@ -19,6 +19,23 @@ LL |     needs_bar::<T::Assoc>();
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
 
-error: aborting due to 2 previous errors
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
+  --> $DIR/recursive-self-normalization.rs:11:5
+   |
+LL |     needs_bar::<T::Assoc>();
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
+  --> $DIR/recursive-self-normalization.rs:11:17
+   |
+LL |     needs_bar::<T::Assoc>();
+   |                 ^^^^^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
+
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/treat-err-as-bug/eagerly-emit.rs b/tests/ui/treat-err-as-bug/eagerly-emit.rs
new file mode 100644
index 00000000000..5f32f5a1d94
--- /dev/null
+++ b/tests/ui/treat-err-as-bug/eagerly-emit.rs
@@ -0,0 +1,11 @@
+// compile-flags: -Zeagerly-emit-delayed-bugs
+
+trait Foo {}
+
+fn main() {}
+
+fn f() -> impl Foo {
+    //~^ ERROR the trait bound `i32: Foo` is not satisfied
+    //~| ERROR `report_selection_error` did not emit an error
+    1i32
+}
diff --git a/tests/ui/treat-err-as-bug/eagerly-emit.stderr b/tests/ui/treat-err-as-bug/eagerly-emit.stderr
new file mode 100644
index 00000000000..3d25741d52d
--- /dev/null
+++ b/tests/ui/treat-err-as-bug/eagerly-emit.stderr
@@ -0,0 +1,28 @@
+error: `report_selection_error` did not emit an error
+  --> $DIR/eagerly-emit.rs:7:11
+   |
+LL | fn f() -> impl Foo {
+   |           ^^^^^^^^
+
+error: trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging
+
+error[E0277]: the trait bound `i32: Foo` is not satisfied
+  --> $DIR/eagerly-emit.rs:7:11
+   |
+LL | fn f() -> impl Foo {
+   |           ^^^^^^^^ the trait `Foo` is not implemented for `i32`
+...
+LL |     1i32
+   |     ---- return type was inferred to be `i32` here
+   |
+help: this trait has no implementations, consider adding one
+  --> $DIR/eagerly-emit.rs:3:1
+   |
+LL | trait Foo {}
+   | ^^^^^^^^^
+
+error: expected fulfillment errors
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/treat-err-as-bug/err.stderr b/tests/ui/treat-err-as-bug/err.stderr
index 3a56445a26b..4c5d0e5ae79 100644
--- a/tests/ui/treat-err-as-bug/err.stderr
+++ b/tests/ui/treat-err-as-bug/err.stderr
@@ -1,4 +1,4 @@
-error[E0080]: could not evaluate static initializer
+error: internal compiler error[E0080]: could not evaluate static initializer
   --> $DIR/err.rs:11:21
    |
 LL | pub static C: u32 = 0 - 1;