about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml4
-rw-r--r--Cargo.lock74
-rw-r--r--compiler/rustc_ast/src/util/literal.rs96
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs20
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs38
-rw-r--r--compiler/rustc_attr/src/session_diagnostics.rs47
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml4
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/audit.yml2
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/main.yml18
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml8
-rw-r--r--compiler/rustc_codegen_cranelift/.vscode/settings.json3
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock140
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml12
-rw-r--r--compiler/rustc_codegen_cranelift/Readme.md23
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch22
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch2
-rw-r--r--compiler/rustc_codegen_cranelift/patches/rand-lock.toml23
-rw-r--r--compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml4
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs11
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs20
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs36
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs14
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs330
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs34
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs23
-rw-r--r--compiler/rustc_codegen_cranelift/src/unsize.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/vtable.rs2
-rw-r--r--compiler/rustc_codegen_llvm/messages.ftl3
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs38
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs80
-rw-r--r--compiler/rustc_const_eval/src/errors.rs52
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs21
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs14
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs23
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs58
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs658
-rw-r--r--compiler/rustc_error_codes/src/lib.rs678
-rw-r--r--compiler/rustc_errors/Cargo.toml2
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs7
-rw-r--r--compiler/rustc_errors/src/codes.rs39
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs17
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs13
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs50
-rw-r--r--compiler/rustc_errors/src/emitter.rs12
-rw-r--r--compiler/rustc_errors/src/json.rs4
-rw-r--r--compiler/rustc_errors/src/lib.rs31
-rw-r--r--compiler/rustc_errors/src/registry.rs9
-rw-r--r--compiler/rustc_expand/src/base.rs8
-rw-r--r--compiler/rustc_expand/src/config.rs4
-rw-r--r--compiler/rustc_expand/src/errors.rs11
-rw-r--r--compiler/rustc_feature/src/unstable.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/lint.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/object_safety.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/unsafety.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs140
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs34
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs56
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs35
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs14
-rw-r--r--compiler/rustc_index/src/interval.rs6
-rw-r--r--compiler/rustc_index/src/vec.rs7
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs66
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs4
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_lexer/src/unescape.rs170
-rw-r--r--compiler/rustc_lexer/src/unescape/tests.rs10
-rw-r--r--compiler/rustc_lint/src/errors.rs14
-rw-r--r--compiler/rustc_lint/src/lints.rs6
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs13
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs4
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs2
-rw-r--r--compiler/rustc_metadata/src/errors.rs28
-rw-r--r--compiler/rustc_middle/src/error.rs4
-rw-r--r--compiler/rustc_middle/src/middle/region.rs8
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs2
-rw-r--r--compiler/rustc_middle/src/values.rs2
-rw-r--r--compiler/rustc_mir_build/src/errors.rs64
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs13
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs4
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs7
-rw-r--r--compiler/rustc_mir_transform/src/errors.rs6
-rw-r--r--compiler/rustc_parse/messages.ftl14
-rw-r--r--compiler/rustc_parse/src/errors.rs30
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs40
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs4
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs44
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs23
-rw-r--r--compiler/rustc_parse/src/parser/item.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs1
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs155
-rw-r--r--compiler/rustc_parse_format/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/dead.rs2
-rw-r--r--compiler/rustc_passes/src/entry.rs6
-rw-r--r--compiler/rustc_passes/src/errors.rs94
-rw-r--r--compiler/rustc_passes/src/lib.rs1
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs7
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs26
-rw-r--r--compiler/rustc_privacy/src/errors.rs6
-rw-r--r--compiler/rustc_privacy/src/lib.rs59
-rw-r--r--compiler/rustc_query_system/src/error.rs3
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs4
-rw-r--r--compiler/rustc_resolve/src/errors.rs66
-rw-r--r--compiler/rustc_resolve/src/imports.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs83
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs14
-rw-r--r--compiler/rustc_resolve/src/lib.rs4
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_session/src/config.rs15
-rw-r--r--compiler/rustc_session/src/errors.rs6
-rw-r--r--compiler/rustc_session/src/options.rs6
-rw-r--r--compiler/rustc_session/src/session.rs6
-rw-r--r--compiler/rustc_span/src/symbol.rs13
-rw-r--r--compiler/rustc_symbol_mangling/src/hashed.rs43
-rw-r--r--compiler/rustc_symbol_mangling/src/lib.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs104
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs20
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs4
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs3
-rw-r--r--library/alloc/src/boxed.rs3
-rw-r--r--library/alloc/src/lib.rs2
-rw-r--r--library/alloc/src/rc.rs7
-rw-r--r--library/alloc/src/slice.rs4
-rw-r--r--library/alloc/src/str.rs2
-rw-r--r--library/alloc/src/sync.rs10
-rw-r--r--library/alloc/src/vec/cow.rs13
-rw-r--r--library/alloc/src/vec/mod.rs8
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/slice.rs16
-rw-r--r--library/alloc/tests/vec.rs24
-rw-r--r--library/core/src/array/mod.rs9
-rw-r--r--library/core/src/ascii/ascii_char.rs16
-rw-r--r--library/core/src/intrinsics.rs2
-rw-r--r--library/core/src/iter/adapters/intersperse.rs147
-rw-r--r--library/core/src/net/ip_addr.rs1
-rw-r--r--library/core/src/num/mod.rs10
-rw-r--r--library/core/src/num/nonzero.rs50
-rw-r--r--library/core/src/pin.rs46
-rw-r--r--library/core/src/primitive_docs.rs24
-rw-r--r--library/core/src/slice/iter.rs64
-rw-r--r--library/core/src/slice/mod.rs44
-rw-r--r--library/core/src/str/converts.rs40
-rw-r--r--library/core/src/str/iter.rs25
-rw-r--r--library/core/src/str/mod.rs3
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/std/src/io/error.rs36
-rw-r--r--library/std/src/io/error/tests.rs4
-rw-r--r--library/std/src/io/stdio.rs11
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/num.rs10
-rw-r--r--library/std/src/sys/pal/windows/alloc.rs24
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs5
-rwxr-xr-xsrc/ci/docker/run.sh116
-rw-r--r--src/ci/github-actions/ci.yml2
-rw-r--r--src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md1
-rw-r--r--src/etc/natvis/libcore.natvis39
-rw-r--r--src/librustdoc/clean/mod.rs5
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/tools/clippy/CHANGELOG.md2
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md21
-rw-r--r--src/tools/clippy/clippy_config/src/conf.rs80
-rw-r--r--src/tools/clippy/clippy_config/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_config/src/types.rs2
-rw-r--r--src/tools/clippy/clippy_dev/Cargo.toml4
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs5
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/mod.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_impl.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/open_options.rs230
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_or_err_ok.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/search_is_some.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/useless_asref.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs77
-rw-r--r--src/tools/clippy/clippy_lints/src/no_effect.rs179
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs55
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs118
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/single_call_fn.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unconditional_recursion.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs292
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/attrs.rs12
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs3
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.stderr6
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.toml14
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/src/main.rs3
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml10
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/src/main.rs3
-rw-r--r--src/tools/clippy/tests/ui-internal/check_formulation.stderr4
-rw-r--r--src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr6
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_underscore_fields/exported/clippy.toml2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/clippy.toml3
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs1
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr81
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs34
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.fixed14
-rw-r--r--src/tools/clippy/tests/ui/blocks_in_conditions.rs14
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs8
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr6
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs12
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr18
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9041.stderr2
-rw-r--r--src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.fixed28
-rw-r--r--src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.rs28
-rw-r--r--src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.stderr17
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed40
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs40
-rw-r--r--src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed32
-rw-r--r--src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs32
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.fixed8
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.rs8
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.stderr16
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else.rs28
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else.stderr69
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else2.rs18
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else2.stderr37
-rw-r--r--src/tools/clippy/tests/ui/ineffective_open_options.fixed9
-rw-r--r--src/tools/clippy/tests/ui/ineffective_open_options.rs9
-rw-r--r--src/tools/clippy/tests/ui/join_absolute_paths.stderr8
-rw-r--r--src/tools/clippy/tests/ui/manual_ok_or.stderr2
-rw-r--r--src/tools/clippy/tests/ui/manual_saturating_arithmetic.stderr48
-rw-r--r--src/tools/clippy/tests/ui/map_clone.fixed33
-rw-r--r--src/tools/clippy/tests/ui/map_clone.rs35
-rw-r--r--src/tools/clippy/tests/ui/map_clone.stderr36
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.rs4
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.stderr5
-rw-r--r--src/tools/clippy/tests/ui/mem_replace_no_std.fixed82
-rw-r--r--src/tools/clippy/tests/ui/mem_replace_no_std.rs82
-rw-r--r--src/tools/clippy/tests/ui/mem_replace_no_std.stderr50
-rw-r--r--src/tools/clippy/tests/ui/no_effect.rs2
-rw-r--r--src/tools/clippy/tests/ui/no_effect.stderr16
-rw-r--r--src/tools/clippy/tests/ui/open_options.rs38
-rw-r--r--src/tools/clippy/tests/ui/open_options.stderr34
-rw-r--r--src/tools/clippy/tests/ui/open_options_fixable.fixed7
-rw-r--r--src/tools/clippy/tests/ui/open_options_fixable.rs7
-rw-r--r--src/tools/clippy/tests/ui/open_options_fixable.stderr14
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_deref.stderr36
-rw-r--r--src/tools/clippy/tests/ui/option_map_or_err_ok.stderr2
-rw-r--r--src/tools/clippy/tests/ui/option_map_or_none.stderr10
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq_no_std.fixed49
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq_no_std.rs49
-rw-r--r--src/tools/clippy/tests/ui/ptr_eq_no_std.stderr17
-rw-r--r--src/tools/clippy/tests/ui/read_zero_byte_vec.rs29
-rw-r--r--src/tools/clippy/tests/ui/read_zero_byte_vec.stderr34
-rw-r--r--src/tools/clippy/tests/ui/result_map_or_into_option.stderr6
-rw-r--r--src/tools/clippy/tests/ui/same_item_push.stderr10
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.stderr4
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr86
-rw-r--r--src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr94
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed3
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs3
-rw-r--r--src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr2
-rw-r--r--src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed34
-rw-r--r--src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs34
-rw-r--r--src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr10
-rw-r--r--src/tools/clippy/tests/ui/single_call_fn.rs11
-rw-r--r--src/tools/clippy/tests/ui/single_char_pattern.stderr80
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed31
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs31
-rw-r--r--src/tools/clippy/tests/ui/transmute.rs13
-rw-r--r--src/tools/clippy/tests/ui/transmute.stderr61
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char.fixed15
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char.rs15
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char.stderr17
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed27
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs27
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_char_no_std.stderr17
-rw-r--r--src/tools/clippy/tests/ui/transmute_ref_to_ref.rs2
-rw-r--r--src/tools/clippy/tests/ui/transmute_ref_to_ref.stderr4
-rw-r--r--src/tools/clippy/tests/ui/transmute_ref_to_ref_no_std.rs30
-rw-r--r--src/tools/clippy/tests/ui/transmute_ref_to_ref_no_std.stderr26
-rw-r--r--src/tools/clippy/tests/ui/unconditional_recursion.rs26
-rw-r--r--src/tools/clippy/tests/ui/unconditional_recursion.stderr19
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_join.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_sort_by.stderr24
-rw-r--r--src/tools/clippy/tests/ui/unused_io_amount.rs87
-rw-r--r--src/tools/clippy/tests/ui/unused_io_amount.stderr141
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.fixed36
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.rs36
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.stderr26
-rw-r--r--src/tools/clippy/triagebot.toml1
-rw-r--r--src/tools/error_index_generator/Cargo.toml1
-rw-r--r--src/tools/error_index_generator/main.rs8
-rw-r--r--src/tools/miri/.github/workflows/sysroots.yml6
-rw-r--r--src/tools/miri/Cargo.lock4
-rw-r--r--src/tools/miri/README.md1
-rw-r--r--src/tools/miri/cargo-miri/src/phases.rs9
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/helpers.rs19
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/machine.rs95
-rw-r--r--src/tools/miri/src/operator.rs2
-rw-r--r--src/tools/miri/src/shims/extern_static.rs79
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs3
-rw-r--r--src/tools/miri/src/shims/mod.rs42
-rw-r--r--src/tools/miri/src/shims/unix/foreign_items.rs11
-rw-r--r--src/tools/miri/src/shims/unix/freebsd/foreign_items.rs28
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs89
-rw-r--r--src/tools/miri/src/shims/unix/macos/foreign_items.rs15
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs1
-rw-r--r--src/tools/miri/tests/pass/issues/issue-120337-irrefutable-let-ice.rs16
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/lexed_str.rs4
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs19
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/validation.rs12
-rw-r--r--src/tools/tidy/src/deps.rs2
-rw-r--r--src/tools/tidy/src/error_codes.rs34
-rw-r--r--src/tools/tidy/src/ui_tests.rs7
-rw-r--r--tests/assembly/targets/targets-elf.rs65
-rw-r--r--tests/assembly/targets/targets-macho.rs81
-rw-r--r--tests/debuginfo/msvc-pretty-enums.rs8
-rw-r--r--tests/debuginfo/numeric-types.rs46
-rw-r--r--tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff34
-rw-r--r--tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff34
-rw-r--r--tests/mir-opt/gvn_uninhabited.rs24
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff2
-rw-r--r--tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff2
-rw-r--r--tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff4
-rw-r--r--tests/run-make/symbol-mangling-hashed/Makefile48
-rw-r--r--tests/run-make/symbol-mangling-hashed/a_dylib.rs4
-rw-r--r--tests/run-make/symbol-mangling-hashed/a_rlib.rs5
-rw-r--r--tests/run-make/symbol-mangling-hashed/b_bin.rs9
-rw-r--r--tests/run-make/symbol-mangling-hashed/b_dylib.rs9
-rw-r--r--tests/run-make/target-specs/Makefile2
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs166
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr268
-rw-r--r--tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs2
-rw-r--r--tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr2
-rw-r--r--tests/ui/async-await/async-closures/higher-ranked.rs12
-rw-r--r--tests/ui/async-await/async-closures/higher-ranked.stderr17
-rw-r--r--tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs18
-rw-r--r--tests/ui/codegen/mismatched-data-layout.json13
-rw-r--r--tests/ui/codegen/mismatched-data-layouts.rs14
-rw-r--r--tests/ui/codegen/mismatched-data-layouts.stderr4
-rw-r--r--tests/ui/consts/let-irrefutable-pattern-ice-120337.rs10
-rw-r--r--tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs2
-rw-r--r--tests/ui/for/issue-20605.next.stderr20
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions1.rs8
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions1.stderr73
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions2.rs8
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions2.stderr75
-rw-r--r--tests/ui/internal/internal-unstable.rs10
-rw-r--r--tests/ui/internal/internal-unstable.stderr8
-rw-r--r--tests/ui/layout/zero-sized-array-enum-niche.stderr2
-rw-r--r--tests/ui/lint/clashing-extern-fn.rs2
-rw-r--r--tests/ui/lint/clashing-extern-fn.stderr6
-rw-r--r--tests/ui/lint/invalid_value.stderr16
-rw-r--r--tests/ui/lint/lint-ctypes-enum.stderr6
-rw-r--r--tests/ui/mismatched_types/non_zero_assigned_something.stderr8
-rw-r--r--tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr2
-rw-r--r--tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs9
-rw-r--r--tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr27
-rw-r--r--tests/ui/parser/issues/issue-24197.rs2
-rw-r--r--tests/ui/parser/issues/issue-24197.stderr6
-rw-r--r--tests/ui/parser/issues/issue-24375.rs2
-rw-r--r--tests/ui/parser/issues/issue-24375.stderr6
-rw-r--r--tests/ui/parser/pat-lt-bracket-5.rs4
-rw-r--r--tests/ui/parser/pat-lt-bracket-5.stderr15
-rw-r--r--tests/ui/parser/pat-lt-bracket-6.rs3
-rw-r--r--tests/ui/parser/pat-lt-bracket-6.stderr30
-rw-r--r--tests/ui/parser/pat-ranges-3.rs6
-rw-r--r--tests/ui/parser/pat-ranges-3.stderr14
-rw-r--r--tests/ui/parser/pat-ranges-4.rs6
-rw-r--r--tests/ui/parser/pat-ranges-4.stderr8
-rw-r--r--tests/ui/parser/pat-recover-exprs.rs28
-rw-r--r--tests/ui/parser/pat-recover-exprs.stderr76
-rw-r--r--tests/ui/parser/pat-recover-methodcalls.rs37
-rw-r--r--tests/ui/parser/pat-recover-methodcalls.stderr35
-rw-r--r--tests/ui/parser/pat-recover-ranges.rs16
-rw-r--r--tests/ui/parser/pat-recover-ranges.stderr84
-rw-r--r--tests/ui/parser/pat-recover-wildcards.rs61
-rw-r--r--tests/ui/parser/pat-recover-wildcards.stderr77
-rw-r--r--tests/ui/parser/range-exclusive-dotdotlt.rs43
-rw-r--r--tests/ui/parser/range-exclusive-dotdotlt.stderr46
-rw-r--r--tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr100
-rw-r--r--tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr630
-rw-r--r--tests/ui/pattern/usefulness/empty-types.normal.stderr98
-rw-r--r--tests/ui/pattern/usefulness/empty-types.rs84
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs2
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr2
-rw-r--r--tests/ui/pin-macro/cant_access_internals.rs2
-rw-r--r--tests/ui/pin-macro/cant_access_internals.stderr4
-rw-r--r--tests/ui/print_type_sizes/niche-filling.stdout16
-rw-r--r--tests/ui/str/str-escape.rs9
-rw-r--r--tests/ui/str/str-escape.stderr14
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.fixed29
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.rs29
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.stderr60
-rw-r--r--tests/ui/symbol-mangling-version/bad-value.bad.stderr2
-rw-r--r--tests/ui/symbol-mangling-version/bad-value.blank.stderr2
-rw-r--r--tests/ui/symbol-mangling-version/bad-value.no-value.stderr2
-rw-r--r--tests/ui/symbol-mangling-version/unstable.hashed.stderr2
-rw-r--r--tests/ui/symbol-mangling-version/unstable.rs5
-rw-r--r--tests/ui/traits/issue-77982.stderr3
-rw-r--r--tests/ui/traits/next-solver/alias-relate/alias_eq_cant_be_furthur_normalized.rs (renamed from tests/ui/traits/next-solver/alias_eq_cant_be_furthur_normalized.rs)0
-rw-r--r--tests/ui/traits/next-solver/alias-relate/alias_eq_dont_use_normalizes_to_if_substs_eq.rs (renamed from tests/ui/traits/next-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs)0
-rw-r--r--tests/ui/traits/next-solver/alias-relate/alias_eq_simple.rs (renamed from tests/ui/traits/next-solver/alias_eq_simple.rs)0
-rw-r--r--tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.rs (renamed from tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.rs)0
-rw-r--r--tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.stderr (renamed from tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.stderr)0
-rw-r--r--tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs (renamed from tests/ui/traits/next-solver/tait-eq-proj-2.rs)2
-rw-r--r--tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs (renamed from tests/ui/traits/next-solver/tait-eq-proj.rs)0
-rw-r--r--tests/ui/traits/next-solver/alias-relate/tait-eq-tait.rs (renamed from tests/ui/traits/next-solver/tait-eq-tait.rs)0
-rw-r--r--tests/ui/traits/next-solver/normalize-path-for-method.rs18
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs1
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr11
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs1
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr11
-rw-r--r--tests/ui/traits/next-solver/temporary-ambiguity.rs22
-rw-r--r--tests/ui/try-trait/bad-interconversion.stderr3
-rw-r--r--tests/ui/type-alias-impl-trait/struct-assignment-validity.rs31
-rw-r--r--triagebot.toml6
493 files changed, 8652 insertions, 4352 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index caf97abf78d..853f43e15e3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -28,6 +28,7 @@ name: CI
       - "**"
 permissions:
   contents: read
+  packages: write
 defaults:
   run:
     shell: bash
@@ -42,6 +43,7 @@ jobs:
       CI_JOB_NAME: "${{ matrix.name }}"
       CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
       HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
+      DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
       SCCACHE_BUCKET: rust-lang-ci-sccache2
       TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
       CACHE_DOMAIN: ci-caches.rust-lang.org
@@ -172,6 +174,7 @@ jobs:
       CI_JOB_NAME: "${{ matrix.name }}"
       CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
       HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
+      DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
       SCCACHE_BUCKET: rust-lang-ci-sccache2
       DEPLOY_BUCKET: rust-lang-ci2
       TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
@@ -554,6 +557,7 @@ jobs:
       CI_JOB_NAME: "${{ matrix.name }}"
       CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
       HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}"
+      DOCKER_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
       SCCACHE_BUCKET: rust-lang-ci-sccache2
       DEPLOY_BUCKET: rust-lang-ci2
       TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
diff --git a/Cargo.lock b/Cargo.lock
index 74f96983b31..d645957da96 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -382,9 +382,9 @@ dependencies = [
 
 [[package]]
 name = "byteorder"
-version = "1.4.3"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "bytes"
@@ -596,11 +596,11 @@ dependencies = [
 name = "clippy_dev"
 version = "0.0.1"
 dependencies = [
- "aho-corasick 0.7.20",
+ "aho-corasick 1.0.2",
  "clap",
  "indoc",
  "itertools",
- "opener 0.5.2",
+ "opener",
  "shell-escape",
  "walkdir",
 ]
@@ -610,7 +610,7 @@ name = "clippy_lints"
 version = "0.1.77"
 dependencies = [
  "arrayvec",
- "cargo_metadata 0.15.4",
+ "cargo_metadata 0.18.0",
  "clippy_config",
  "clippy_utils",
  "declare_clippy_lint",
@@ -1268,7 +1268,6 @@ name = "error_index_generator"
 version = "0.0.0"
 dependencies = [
  "mdbook",
- "rustc_error_codes",
 ]
 
 [[package]]
@@ -2351,7 +2350,7 @@ dependencies = [
  "log",
  "memchr",
  "once_cell",
- "opener 0.6.1",
+ "opener",
  "pathdiff",
  "pulldown-cmark",
  "regex",
@@ -2596,9 +2595,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
 
 [[package]]
 name = "object"
-version = "0.32.1"
+version = "0.32.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
 dependencies = [
  "compiler_builtins",
  "crc32fast",
@@ -2628,16 +2627,6 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
 
 [[package]]
 name = "opener"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005"
-dependencies = [
- "bstr",
- "winapi",
-]
-
-[[package]]
-name = "opener"
 version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6c62dcb6174f9cb326eac248f07e955d5d559c272730b6c03e396b443b562788"
@@ -3711,7 +3700,6 @@ dependencies = [
  "rustc_codegen_ssa",
  "rustc_const_eval",
  "rustc_data_structures",
- "rustc_error_codes",
  "rustc_errors",
  "rustc_expand",
  "rustc_feature",
@@ -3784,9 +3772,11 @@ dependencies = [
  "rustc_ast",
  "rustc_ast_pretty",
  "rustc_data_structures",
+ "rustc_error_codes",
  "rustc_error_messages",
  "rustc_fluent_macro",
  "rustc_hir",
+ "rustc_index",
  "rustc_lint_defs",
  "rustc_macros",
  "rustc_serialize",
@@ -4797,12 +4787,12 @@ checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
 
 [[package]]
 name = "ruzstd"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3ffab8f9715a0d455df4bbb9d21e91135aab3cd3ca187af0cd0c3c3f868fdc"
+checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d"
 dependencies = [
  "byteorder",
- "thiserror-core",
+ "derive_more",
  "twox-hash",
 ]
 
@@ -5366,26 +5356,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "thiserror-core"
-version = "1.0.38"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d97345f6437bb2004cd58819d8a9ef8e36cdd7661c2abc4bbde0a7c40d9f497"
-dependencies = [
- "thiserror-core-impl",
-]
-
-[[package]]
-name = "thiserror-core-impl"
-version = "1.0.38"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10ac1c5050e43014d16b2f94d0d2ce79e65ffdd8b38d8048f9c8f6a8a6da62ac"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
 name = "thiserror-impl"
 version = "1.0.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5757,9 +5727,9 @@ dependencies = [
 
 [[package]]
 name = "unic-langid"
-version = "0.9.1"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f"
+checksum = "238722e6d794ed130f91f4ea33e01fcff4f188d92337a21297892521c72df516"
 dependencies = [
  "unic-langid-impl",
  "unic-langid-macros",
@@ -5767,18 +5737,18 @@ dependencies = [
 
 [[package]]
 name = "unic-langid-impl"
-version = "0.9.1"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff"
+checksum = "4bd55a2063fdea4ef1f8633243a7b0524cbeef1905ae04c31a1c9b9775c55bc6"
 dependencies = [
  "tinystr",
 ]
 
 [[package]]
 name = "unic-langid-macros"
-version = "0.9.1"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "055e618bf694161ffff0466d95cef3e1a5edc59f6ba1888e97801f2b4ebdc4fe"
+checksum = "5c854cefb82ff2816410ce606acbad1b3af065140907b29be9229040752b83ec"
 dependencies = [
  "proc-macro-hack",
  "tinystr",
@@ -5788,13 +5758,13 @@ dependencies = [
 
 [[package]]
 name = "unic-langid-macros-impl"
-version = "0.9.1"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f5cdec05b907f4e2f6843f4354f4ce6a5bebe1a56df320a49134944477ce4d8"
+checksum = "fea2a4c80deb4fb3ca51f66b5e2dd91e3642bbce52234bcf22e41668281208e4"
 dependencies = [
  "proc-macro-hack",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.32",
  "unic-langid-impl",
 ]
 
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index 7b781ba1e11..aaeb1bb9bff 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -3,8 +3,7 @@
 use crate::ast::{self, LitKind, MetaItemLit, StrStyle};
 use crate::token::{self, Token};
 use rustc_lexer::unescape::{
-    byte_from_char, unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit,
-    Mode,
+    byte_from_char, unescape_byte, unescape_char, unescape_mixed, unescape_unicode, MixedUnit, Mode,
 };
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
@@ -48,6 +47,9 @@ impl LitKind {
             return Err(LitError::InvalidSuffix);
         }
 
+        // For byte/char/string literals, chars and escapes have already been
+        // checked in the lexer (in `cook_lexer_literal`). So we can assume all
+        // chars and escapes are valid here.
         Ok(match kind {
             token::Bool => {
                 assert!(symbol.is_bool_lit());
@@ -56,12 +58,12 @@ impl LitKind {
             token::Byte => {
                 return unescape_byte(symbol.as_str())
                     .map(LitKind::Byte)
-                    .map_err(|_| LitError::LexerError);
+                    .map_err(|_| panic!("failed to unescape byte literal"));
             }
             token::Char => {
                 return unescape_char(symbol.as_str())
                     .map(LitKind::Char)
-                    .map_err(|_| LitError::LexerError);
+                    .map_err(|_| panic!("failed to unescape char literal"));
             }
 
             // There are some valid suffixes for integer and float literals,
@@ -77,26 +79,22 @@ impl LitKind {
                 let s = symbol.as_str();
                 // Vanilla strings are so common we optimize for the common case where no chars
                 // requiring special behaviour are present.
-                let symbol = if s.contains(['\\', '\r']) {
+                let symbol = if s.contains('\\') {
                     let mut buf = String::with_capacity(s.len());
-                    let mut error = Ok(());
                     // Force-inlining here is aggressive but the closure is
-                    // called on every char in the string, so it can be
-                    // hot in programs with many long strings.
-                    unescape_literal(
+                    // called on every char in the string, so it can be hot in
+                    // programs with many long strings containing escapes.
+                    unescape_unicode(
                         s,
                         Mode::Str,
                         &mut #[inline(always)]
-                        |_, unescaped_char| match unescaped_char {
+                        |_, c| match c {
                             Ok(c) => buf.push(c),
                             Err(err) => {
-                                if err.is_fatal() {
-                                    error = Err(LitError::LexerError);
-                                }
+                                assert!(!err.is_fatal(), "failed to unescape string literal")
                             }
                         },
                     );
-                    error?;
                     Symbol::intern(&buf)
                 } else {
                     symbol
@@ -104,86 +102,46 @@ impl LitKind {
                 LitKind::Str(symbol, ast::StrStyle::Cooked)
             }
             token::StrRaw(n) => {
-                // Raw strings have no escapes, so we only need to check for invalid chars, and we
-                // can reuse the symbol on success.
-                let mut error = Ok(());
-                unescape_literal(symbol.as_str(), Mode::RawStr, &mut |_, unescaped_char| {
-                    match unescaped_char {
-                        Ok(_) => {}
-                        Err(err) => {
-                            if err.is_fatal() {
-                                error = Err(LitError::LexerError);
-                            }
-                        }
-                    }
-                });
-                error?;
+                // Raw strings have no escapes so no work is needed here.
                 LitKind::Str(symbol, ast::StrStyle::Raw(n))
             }
             token::ByteStr => {
                 let s = symbol.as_str();
                 let mut buf = Vec::with_capacity(s.len());
-                let mut error = Ok(());
-                unescape_literal(s, Mode::ByteStr, &mut |_, c| match c {
+                unescape_unicode(s, Mode::ByteStr, &mut |_, c| match c {
                     Ok(c) => buf.push(byte_from_char(c)),
                     Err(err) => {
-                        if err.is_fatal() {
-                            error = Err(LitError::LexerError);
-                        }
+                        assert!(!err.is_fatal(), "failed to unescape string literal")
                     }
                 });
-                error?;
                 LitKind::ByteStr(buf.into(), StrStyle::Cooked)
             }
             token::ByteStrRaw(n) => {
-                // Raw strings have no escapes, so we only need to check for invalid chars, and we
-                // can convert the symbol directly to a `Lrc<u8>` on success.
-                let s = symbol.as_str();
-                let mut error = Ok(());
-                unescape_literal(s, Mode::RawByteStr, &mut |_, c| match c {
-                    Ok(_) => {}
-                    Err(err) => {
-                        if err.is_fatal() {
-                            error = Err(LitError::LexerError);
-                        }
-                    }
-                });
-                LitKind::ByteStr(s.to_owned().into_bytes().into(), StrStyle::Raw(n))
+                // Raw strings have no escapes so we can convert the symbol
+                // directly to a `Lrc<u8>`.
+                let buf = symbol.as_str().to_owned().into_bytes();
+                LitKind::ByteStr(buf.into(), StrStyle::Raw(n))
             }
             token::CStr => {
                 let s = symbol.as_str();
                 let mut buf = Vec::with_capacity(s.len());
-                let mut error = Ok(());
-                unescape_c_string(s, Mode::CStr, &mut |_span, c| match c {
-                    Ok(CStrUnit::Byte(b)) => buf.push(b),
-                    Ok(CStrUnit::Char(c)) => {
+                unescape_mixed(s, Mode::CStr, &mut |_span, c| match c {
+                    Ok(MixedUnit::Char(c)) => {
                         buf.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
                     }
+                    Ok(MixedUnit::HighByte(b)) => buf.push(b),
                     Err(err) => {
-                        if err.is_fatal() {
-                            error = Err(LitError::LexerError);
-                        }
+                        assert!(!err.is_fatal(), "failed to unescape C string literal")
                     }
                 });
-                error?;
                 buf.push(0);
                 LitKind::CStr(buf.into(), StrStyle::Cooked)
             }
             token::CStrRaw(n) => {
-                // Raw strings have no escapes, so we only need to check for invalid chars, and we
-                // can convert the symbol directly to a `Lrc<u8>` on success.
-                let s = symbol.as_str();
-                let mut error = Ok(());
-                unescape_c_string(s, Mode::RawCStr, &mut |_, c| match c {
-                    Ok(_) => {}
-                    Err(err) => {
-                        if err.is_fatal() {
-                            error = Err(LitError::LexerError);
-                        }
-                    }
-                });
-                error?;
-                let mut buf = s.to_owned().into_bytes();
+                // Raw strings have no escapes so we can convert the symbol
+                // directly to a `Lrc<u8>` after appending the terminating NUL
+                // char.
+                let mut buf = symbol.as_str().to_owned().into_bytes();
                 buf.push(0);
                 LitKind::CStr(buf.into(), StrStyle::Raw(n))
             }
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 4843d36372d..51bb8a96fad 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -1,9 +1,9 @@
-use rustc_errors::DiagnosticArgFromDisplay;
+use rustc_errors::{codes::*, DiagnosticArgFromDisplay};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_generic_type_with_parentheses, code = "E0214")]
+#[diag(ast_lowering_generic_type_with_parentheses, code = E0214)]
 pub struct GenericTypeWithParentheses {
     #[primary_span]
     #[label]
@@ -22,7 +22,7 @@ pub struct UseAngleBrackets {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering_invalid_abi, code = "E0703")]
+#[diag(ast_lowering_invalid_abi, code = E0703)]
 #[note]
 pub struct InvalidAbi {
     #[primary_span]
@@ -89,7 +89,7 @@ pub enum AssocTyParenthesesSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_lowering_misplaced_impl_trait, code = "E0562")]
+#[diag(ast_lowering_misplaced_impl_trait, code = E0562)]
 #[note]
 pub struct MisplacedImplTrait<'a> {
     #[primary_span]
@@ -114,7 +114,7 @@ pub struct UnderscoreExprLhsAssign {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_base_expression_double_dot, code = "E0797")]
+#[diag(ast_lowering_base_expression_double_dot, code = E0797)]
 pub struct BaseExpressionDoubleDot {
     #[primary_span]
     #[suggestion(code = "/* expr */", applicability = "has-placeholders", style = "verbose")]
@@ -122,7 +122,7 @@ pub struct BaseExpressionDoubleDot {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = "E0728")]
+#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = E0728)]
 pub struct AwaitOnlyInAsyncFnAndBlocks {
     #[primary_span]
     #[label]
@@ -132,14 +132,14 @@ pub struct AwaitOnlyInAsyncFnAndBlocks {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_coroutine_too_many_parameters, code = "E0628")]
+#[diag(ast_lowering_coroutine_too_many_parameters, code = E0628)]
 pub struct CoroutineTooManyParameters {
     #[primary_span]
     pub fn_decl_span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_closure_cannot_be_static, code = "E0697")]
+#[diag(ast_lowering_closure_cannot_be_static, code = E0697)]
 pub struct ClosureCannotBeStatic {
     #[primary_span]
     pub fn_decl_span: Span,
@@ -154,14 +154,14 @@ pub struct FunctionalRecordUpdateDestructuringAssignment {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_async_coroutines_not_supported, code = "E0727")]
+#[diag(ast_lowering_async_coroutines_not_supported, code = E0727)]
 pub struct AsyncCoroutinesNotSupported {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_inline_asm_unsupported_target, code = "E0472")]
+#[diag(ast_lowering_inline_asm_unsupported_target, code = E0472)]
 pub struct InlineAsmUnsupportedTarget {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index e2b8e64b115..5f54a0ddf8c 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -1,7 +1,7 @@
 //! Errors emitted by ast_passes.
 
 use rustc_ast::ParamKindOrd;
-use rustc_errors::{AddToDiagnostic, Applicability};
+use rustc_errors::{codes::*, AddToDiagnostic, Applicability};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
@@ -23,7 +23,7 @@ pub struct InvalidLabel {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_visibility_not_permitted, code = "E0449")]
+#[diag(ast_passes_visibility_not_permitted, code = E0449)]
 pub struct VisibilityNotPermitted {
     #[primary_span]
     pub span: Span,
@@ -44,7 +44,7 @@ pub enum VisibilityNotPermittedNote {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_trait_fn_const, code = "E0379")]
+#[diag(ast_passes_trait_fn_const, code = E0379)]
 pub struct TraitFnConst {
     #[primary_span]
     #[label]
@@ -302,14 +302,14 @@ pub struct ItemUnderscore<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_nomangle_ascii, code = "E0754")]
+#[diag(ast_passes_nomangle_ascii, code = E0754)]
 pub struct NoMangleAscii {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_module_nonascii, code = "E0754")]
+#[diag(ast_passes_module_nonascii, code = E0754)]
 #[help]
 pub struct ModuleNonAscii {
     #[primary_span]
@@ -318,7 +318,7 @@ pub struct ModuleNonAscii {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_auto_generic, code = "E0567")]
+#[diag(ast_passes_auto_generic, code = E0567)]
 pub struct AutoTraitGeneric {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -328,7 +328,7 @@ pub struct AutoTraitGeneric {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_auto_super_lifetime, code = "E0568")]
+#[diag(ast_passes_auto_super_lifetime, code = E0568)]
 pub struct AutoTraitBounds {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -338,7 +338,7 @@ pub struct AutoTraitBounds {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_auto_items, code = "E0380")]
+#[diag(ast_passes_auto_items, code = E0380)]
 pub struct AutoTraitItems {
     #[primary_span]
     pub spans: Vec<Span>,
@@ -384,28 +384,28 @@ impl AddToDiagnostic for EmptyLabelManySpans {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_pattern_in_fn_pointer, code = "E0561")]
+#[diag(ast_passes_pattern_in_fn_pointer, code = E0561)]
 pub struct PatternFnPointer {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_trait_object_single_bound, code = "E0226")]
+#[diag(ast_passes_trait_object_single_bound, code = E0226)]
 pub struct TraitObjectBound {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_impl_trait_path, code = "E0667")]
+#[diag(ast_passes_impl_trait_path, code = E0667)]
 pub struct ImplTraitPath {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_nested_impl_trait, code = "E0666")]
+#[diag(ast_passes_nested_impl_trait, code = E0666)]
 pub struct NestedImplTrait {
     #[primary_span]
     pub span: Span,
@@ -443,7 +443,7 @@ pub struct ObsoleteAuto {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_unsafe_negative_impl, code = "E0198")]
+#[diag(ast_passes_unsafe_negative_impl, code = E0198)]
 pub struct UnsafeNegativeImpl {
     #[primary_span]
     pub span: Span,
@@ -468,7 +468,7 @@ pub struct InherentImplCannot<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_inherent_cannot_be, code = "E0197")]
+#[diag(ast_passes_inherent_cannot_be, code = E0197)]
 pub struct InherentImplCannotUnsafe<'a> {
     #[primary_span]
     pub span: Span,
@@ -536,7 +536,7 @@ pub struct GenericDefaultTrailing {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_nested_lifetimes, code = "E0316")]
+#[diag(ast_passes_nested_lifetimes, code = E0316)]
 pub struct NestedLifetimes {
     #[primary_span]
     pub span: Span,
@@ -655,7 +655,7 @@ pub struct ConstAndCVariadic {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_pattern_in_foreign, code = "E0130")]
+#[diag(ast_passes_pattern_in_foreign, code = E0130)]
 pub struct PatternInForeign {
     #[primary_span]
     #[label]
@@ -663,7 +663,7 @@ pub struct PatternInForeign {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_pattern_in_bodiless, code = "E0642")]
+#[diag(ast_passes_pattern_in_bodiless, code = E0642)]
 pub struct PatternInBodiless {
     #[primary_span]
     #[label]
@@ -711,14 +711,14 @@ pub struct AssociatedSuggestion2 {
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_stability_outside_std, code = "E0734")]
+#[diag(ast_passes_stability_outside_std, code = E0734)]
 pub struct StabilityOutsideStd {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(ast_passes_feature_on_non_nightly, code = "E0554")]
+#[diag(ast_passes_feature_on_non_nightly, code = E0554)]
 pub struct FeatureOnNonNightly {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index 315a00c8d2f..79370602842 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -2,8 +2,7 @@ use std::num::IntErrorKind;
 
 use rustc_ast as ast;
 use rustc_errors::{
-    error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
-    Level,
+    codes::*, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
@@ -12,14 +11,14 @@ use crate::fluent_generated as fluent;
 use crate::UnsupportedLiteralReason;
 
 #[derive(Diagnostic)]
-#[diag(attr_expected_one_cfg_pattern, code = "E0536")]
+#[diag(attr_expected_one_cfg_pattern, code = E0536)]
 pub(crate) struct ExpectedOneCfgPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_predicate, code = "E0537")]
+#[diag(attr_invalid_predicate, code = E0537)]
 pub(crate) struct InvalidPredicate {
     #[primary_span]
     pub span: Span,
@@ -28,7 +27,7 @@ pub(crate) struct InvalidPredicate {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_multiple_item, code = "E0538")]
+#[diag(attr_multiple_item, code = E0538)]
 pub(crate) struct MultipleItem {
     #[primary_span]
     pub span: Span,
@@ -37,7 +36,7 @@ pub(crate) struct MultipleItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_incorrect_meta_item, code = "E0539")]
+#[diag(attr_incorrect_meta_item, code = E0539)]
 pub(crate) struct IncorrectMetaItem {
     #[primary_span]
     pub span: Span,
@@ -56,7 +55,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> {
         let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
         DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item)
             .with_span(self.span)
-            .with_code(error_code!(E0541))
+            .with_code(E0541)
             .with_arg("item", self.item)
             .with_arg("expected", expected.join(", "))
             .with_span_label(self.span, fluent::attr_label)
@@ -64,28 +63,28 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_missing_since, code = "E0542")]
+#[diag(attr_missing_since, code = E0542)]
 pub(crate) struct MissingSince {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_missing_note, code = "E0543")]
+#[diag(attr_missing_note, code = E0543)]
 pub(crate) struct MissingNote {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_multiple_stability_levels, code = "E0544")]
+#[diag(attr_multiple_stability_levels, code = E0544)]
 pub(crate) struct MultipleStabilityLevels {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_issue_string, code = "E0545")]
+#[diag(attr_invalid_issue_string, code = E0545)]
 pub(crate) struct InvalidIssueString {
     #[primary_span]
     pub span: Span,
@@ -143,21 +142,21 @@ impl InvalidIssueStringCause {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_missing_feature, code = "E0546")]
+#[diag(attr_missing_feature, code = E0546)]
 pub(crate) struct MissingFeature {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_non_ident_feature, code = "E0546")]
+#[diag(attr_non_ident_feature, code = E0546)]
 pub(crate) struct NonIdentFeature {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_missing_issue, code = "E0547")]
+#[diag(attr_missing_issue, code = E0547)]
 pub(crate) struct MissingIssue {
     #[primary_span]
     pub span: Span,
@@ -166,14 +165,14 @@ pub(crate) struct MissingIssue {
 // FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
 // It is more similar to `IncorrectReprFormatGeneric`.
 #[derive(Diagnostic)]
-#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
+#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)]
 pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_repr_hint_no_paren, code = "E0552")]
+#[diag(attr_invalid_repr_hint_no_paren, code = E0552)]
 pub(crate) struct InvalidReprHintNoParen {
     #[primary_span]
     pub span: Span,
@@ -182,7 +181,7 @@ pub(crate) struct InvalidReprHintNoParen {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_repr_hint_no_value, code = "E0552")]
+#[diag(attr_invalid_repr_hint_no_value, code = E0552)]
 pub(crate) struct InvalidReprHintNoValue {
     #[primary_span]
     pub span: Span,
@@ -215,7 +214,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral {
             },
         );
         diag.span(self.span);
-        diag.code(error_code!(E0565));
+        diag.code(E0565);
         if self.is_bytestr {
             diag.span_suggestion(
                 self.start_point_span,
@@ -229,7 +228,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_repr_align_need_arg, code = "E0589")]
+#[diag(attr_invalid_repr_align_need_arg, code = E0589)]
 pub(crate) struct InvalidReprAlignNeedArg {
     #[primary_span]
     #[suggestion(code = "align(...)", applicability = "has-placeholders")]
@@ -237,7 +236,7 @@ pub(crate) struct InvalidReprAlignNeedArg {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_invalid_repr_generic, code = "E0589")]
+#[diag(attr_invalid_repr_generic, code = E0589)]
 pub(crate) struct InvalidReprGeneric<'a> {
     #[primary_span]
     pub span: Span,
@@ -247,14 +246,14 @@ pub(crate) struct InvalidReprGeneric<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_incorrect_repr_format_align_one_arg, code = "E0693")]
+#[diag(attr_incorrect_repr_format_align_one_arg, code = E0693)]
 pub(crate) struct IncorrectReprFormatAlignOneArg {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_incorrect_repr_format_generic, code = "E0693")]
+#[diag(attr_incorrect_repr_format_generic, code = E0693)]
 pub(crate) struct IncorrectReprFormatGeneric<'a> {
     #[primary_span]
     pub span: Span,
@@ -305,14 +304,14 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_rustc_promotable_pairing, code = "E0717")]
+#[diag(attr_rustc_promotable_pairing, code = E0717)]
 pub(crate) struct RustcPromotablePairing {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(attr_rustc_allowed_unstable_pairing, code = "E0789")]
+#[diag(attr_rustc_allowed_unstable_pairing, code = E0789)]
 pub(crate) struct RustcAllowedUnstablePairing {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 351976cdaea..8a275a83630 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{struct_span_code_err, DiagCtxt, DiagnosticBuilder};
+use rustc_errors::{codes::*, struct_span_code_err, DiagCtxt, DiagnosticBuilder};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index da67862a48d..2e83072b8d1 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -3,7 +3,9 @@
 use either::Either;
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
+use rustc_errors::{
+    codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index e321b92603d..1685624f247 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -1,4 +1,4 @@
-use rustc_errors::MultiSpan;
+use rustc_errors::{codes::*, MultiSpan};
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{GenericArg, Ty};
 use rustc_span::Span;
@@ -6,7 +6,7 @@ use rustc_span::Span;
 use crate::diagnostics::RegionName;
 
 #[derive(Diagnostic)]
-#[diag(borrowck_move_unsized, code = "E0161")]
+#[diag(borrowck_move_unsized, code = E0161)]
 pub(crate) struct MoveUnsized<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -281,7 +281,7 @@ pub(crate) enum CaptureVarCause {
 }
 
 #[derive(Diagnostic)]
-#[diag(borrowck_cannot_move_when_borrowed, code = "E0505")]
+#[diag(borrowck_cannot_move_when_borrowed, code = E0505)]
 pub(crate) struct MoveBorrow<'a> {
     pub place: &'a str,
     pub borrow_place: &'a str,
@@ -294,7 +294,7 @@ pub(crate) struct MoveBorrow<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(borrowck_opaque_type_non_generic_param, code = "E0792")]
+#[diag(borrowck_opaque_type_non_generic_param, code = E0792)]
 pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> {
     pub ty: GenericArg<'tcx>,
     pub kind: &'a str,
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index d6dfd0efaf9..eadb48ddd36 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -1,6 +1,6 @@
 use rustc_errors::{
-    AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
-    MultiSpan, SingleLabelManySpans,
+    codes::*, AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
+    Level, MultiSpan, SingleLabelManySpans,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
@@ -269,7 +269,7 @@ pub(crate) struct ConcatIdentsIdentArgs {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_bad_derive_target, code = "E0774")]
+#[diag(builtin_macros_bad_derive_target, code = E0774)]
 pub(crate) struct BadDeriveTarget {
     #[primary_span]
     #[label]
@@ -283,7 +283,7 @@ pub(crate) struct BadDeriveTarget {
 pub(crate) struct TestsNotSupport {}
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_unexpected_lit, code = "E0777")]
+#[diag(builtin_macros_unexpected_lit, code = E0777)]
 pub(crate) struct BadDeriveLit {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
index bd3b051185b..e6bf944f552 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/abi-cafe.yml
@@ -33,14 +33,14 @@ jobs:
               TARGET_TRIPLE: x86_64-pc-windows-gnu
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: CPU features
       if: matrix.os == 'ubuntu-latest'
       run: cat /proc/cpuinfo
 
     - name: Cache cargo target dir
-      uses: actions/cache@v3
+      uses: actions/cache@v4
       with:
         path: build/cg_clif
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml b/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml
index 3efdec41559..b4f8ce0f532 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/audit.yml
@@ -10,7 +10,7 @@ jobs:
   audit:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - run: |
           sed -i 's/components.*/components = []/' rust-toolchain
           echo 'profile = "minimal"' >> rust-toolchain
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index 9bbb18fc37f..cf9a105538d 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -10,7 +10,7 @@ jobs:
     timeout-minutes: 10
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: Avoid installing rustc-dev
       run: |
@@ -64,14 +64,14 @@ jobs:
               TARGET_TRIPLE: x86_64-pc-windows-gnu
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: CPU features
       if: matrix.os == 'ubuntu-latest'
       run: cat /proc/cpuinfo
 
     - name: Cache cargo target dir
-      uses: actions/cache@v3
+      uses: actions/cache@v4
       with:
         path: build/cg_clif
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
@@ -138,7 +138,7 @@ jobs:
         shell: bash
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: CPU features
       run: cat /proc/cpuinfo
@@ -164,13 +164,13 @@ jobs:
         shell: bash
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: CPU features
       run: cat /proc/cpuinfo
 
     - name: Cache cargo target dir
-      uses: actions/cache@v3
+      uses: actions/cache@v4
       with:
         path: build/cg_clif
         key: ${{ runner.os }}-x86_64-unknown-linux-gnu-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
@@ -221,10 +221,10 @@ jobs:
               TARGET_TRIPLE: x86_64-pc-windows-gnu
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: Cache cargo target dir
-      uses: actions/cache@v3
+      uses: actions/cache@v4
       with:
         path: build/cg_clif
         key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-dist-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
@@ -276,7 +276,7 @@ jobs:
       cancel-in-progress: true
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - name: Download all built artifacts
         uses: actions/download-artifact@v4
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
index 8085dc58263..930d025b73e 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
@@ -9,13 +9,13 @@ jobs:
     timeout-minutes: 60
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: CPU features
       run: cat /proc/cpuinfo
 
     - name: Cache cargo target dir
-      uses: actions/cache@v3
+      uses: actions/cache@v4
       with:
         path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
@@ -32,13 +32,13 @@ jobs:
     timeout-minutes: 60
 
     steps:
-    - uses: actions/checkout@v3
+    - uses: actions/checkout@v4
 
     - name: CPU features
       run: cat /proc/cpuinfo
 
     - name: Cache cargo target dir
-      uses: actions/cache@v3
+      uses: actions/cache@v4
       with:
         path: build/cg_clif
         key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json
index 834a1362caf..491646ce59b 100644
--- a/compiler/rustc_codegen_cranelift/.vscode/settings.json
+++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json
@@ -1,8 +1,9 @@
 {
     "editor.formatOnSave": true,
 
-    // source for rustc_* is not included in the rust-src component; disable the errors about this
+    // in case rustc.source is disabled for performance reasons; disable the errors about this
     "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "unresolved-macro-call"],
+    "rust-analyzer.rustc.source": "discover",
     "rust-analyzer.imports.granularity.enforce": true,
     "rust-analyzer.imports.granularity.group": "module",
     "rust-analyzer.imports.prefix": "crate",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index 6d6a1200f50..86bc7d0f067 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "cranelift-bforest"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c22542c0b95bd3302f7ed6839869c561f2324bac2fd5e7e99f5cfa65fdc8b92"
+checksum = "d819feeda4c420a18f1e28236ca0ce1177b22bf7c8a44ddee92dfe40de15bcf0"
 dependencies = [
  "cranelift-entity",
 ]
 
 [[package]]
 name = "cranelift-codegen"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b3db903ef2e9c8a4de2ea6db5db052c7857282952f9df604aa55d169e6000d8"
+checksum = "e9b8d03d5bdbca7e5f72b0e0a0f69933ed1f09e24be6c075aa6fe3f802b0cc0c"
 dependencies = [
  "bumpalo",
  "cranelift-bforest",
@@ -75,39 +75,39 @@ dependencies = [
 
 [[package]]
 name = "cranelift-codegen-meta"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6590feb5a1d6438f974bf6a5ac4dddf69fca14e1f07f3265d880f69e61a94463"
+checksum = "a3fd3664e38e51649b17dc30cfdd561273fe2f590dcd013fb75d9eabc6272dfb"
 dependencies = [
  "cranelift-codegen-shared",
 ]
 
 [[package]]
 name = "cranelift-codegen-shared"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7239038c56fafe77fddc8788fc8533dd6c474dc5bdc5637216404f41ba807330"
+checksum = "4b031ec5e605828975952622b5a77d49126f20ffe88d33719a0af66b23a0fc36"
 
 [[package]]
 name = "cranelift-control"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7dc9c595341404d381d27a3d950160856b35b402275f0c3990cd1ad683c8053"
+checksum = "fada054d017cf2ed8f7ed2336e0517fc1b19e6825be1790de9eb00c94788362b"
 dependencies = [
  "arbitrary",
 ]
 
 [[package]]
 name = "cranelift-entity"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44e3ee532fc4776c69bcedf7e62f9632cbb3f35776fa9a525cdade3195baa3f7"
+checksum = "177b6f94ae8de6348eb45bf977c79ab9e3c40fc3ac8cb7ed8109560ea39bee7d"
 
 [[package]]
 name = "cranelift-frontend"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a612c94d09e653662ec37681dc2d6fd2b9856e6df7147be0afc9aabb0abf19df"
+checksum = "ebebd23a69a23e3ddea78e98ff3a2de222e88c8e045d81ef4a72f042e0d79dbd"
 dependencies = [
  "cranelift-codegen",
  "log",
@@ -117,15 +117,15 @@ dependencies = [
 
 [[package]]
 name = "cranelift-isle"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85db9830abeb1170b7d29b536ffd55af1d4d26ac8a77570b5d1aca003bf225cc"
+checksum = "1571bfc14df8966d12c6121b5325026591a4b4009e22fea0fe3765ab7cd33b96"
 
 [[package]]
 name = "cranelift-jit"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4946271f1055e26544ef8c90fa24776f201566419dfac4b3962c39d5a804ff67"
+checksum = "2f61e236d7622c3c43016e8b0f3ba27136e21ac7de328c7fda902e61db1de851"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -138,14 +138,14 @@ dependencies = [
  "region",
  "target-lexicon",
  "wasmtime-jit-icache-coherence",
- "windows-sys",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "cranelift-module"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb7e3bdae2597556e59edeb8ecb62eb32c7e054c4f042d393732902979db69c3"
+checksum = "f30c6820342015c5009070e3e48d1da7b13521399de904663f1c84f5ee839657"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -154,9 +154,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-native"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301ef0edafeaeda5771a5d2db64ac53e1818ae3111220a185677025fe91db4a1"
+checksum = "35a69c37e0c10b46fe5527f2397ac821046efbf5f7ec112c8b84df25712f465b"
 dependencies = [
  "cranelift-codegen",
  "libc",
@@ -165,9 +165,9 @@ dependencies = [
 
 [[package]]
 name = "cranelift-object"
-version = "0.103.0"
+version = "0.104.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59e0ee3d013728903e0c513c31afa389b559bfd4fe8a44f80335c799e3132a41"
+checksum = "24425a329b4343177d5f1852243841dcec17f929d72c0e7f41262140155e55e7"
 dependencies = [
  "anyhow",
  "cranelift-codegen",
@@ -251,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
 dependencies = [
  "cfg-if",
- "windows-sys",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -374,13 +374,13 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "wasmtime-jit-icache-coherence"
-version = "16.0.0"
+version = "17.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b6d197fcc34ad32ed440e1f9552fd57d1f377d9699d31dee1b5b457322c1f8a"
+checksum = "bdc26415bb89e9ccd3bdc498fef63aabf665c4c0dd710c107691deb9694955da"
 dependencies = [
  "cfg-if",
  "libc",
- "windows-sys",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -411,7 +411,16 @@ version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.0",
 ]
 
 [[package]]
@@ -420,13 +429,28 @@ version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
 dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
 ]
 
 [[package]]
@@ -436,37 +460,79 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+
+[[package]]
 name = "windows_aarch64_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+
+[[package]]
 name = "windows_i686_gnu"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+
+[[package]]
 name = "windows_i686_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+
+[[package]]
 name = "windows_x86_64_gnu"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+
+[[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+
+[[package]]
 name = "windows_x86_64_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index c57e964168f..586ce2286f9 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,12 +8,12 @@ crate-type = ["dylib"]
 
 [dependencies]
 # These have to be in sync with each other
-cranelift-codegen = { version = "0.103", default-features = false, features = ["std", "unwind", "all-arch"] }
-cranelift-frontend = { version = "0.103" }
-cranelift-module = { version = "0.103" }
-cranelift-native = { version = "0.103" }
-cranelift-jit = { version = "0.103", optional = true }
-cranelift-object = { version = "0.103" }
+cranelift-codegen = { version = "0.104", default-features = false, features = ["std", "unwind", "all-arch"] }
+cranelift-frontend = { version = "0.104" }
+cranelift-module = { version = "0.104" }
+cranelift-native = { version = "0.104" }
+cranelift-jit = { version = "0.104", optional = true }
+cranelift-object = { version = "0.104" }
 target-lexicon = "0.12.0"
 gimli = { version = "0.28", default-features = false, features = ["write"]}
 object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
diff --git a/compiler/rustc_codegen_cranelift/Readme.md b/compiler/rustc_codegen_cranelift/Readme.md
index ca6ecdf1d0e..4f455261963 100644
--- a/compiler/rustc_codegen_cranelift/Readme.md
+++ b/compiler/rustc_codegen_cranelift/Readme.md
@@ -62,6 +62,27 @@ $ ./test.sh
 
 For more docs on how to build and test see [build_system/usage.txt](build_system/usage.txt) or the help message of `./y.sh`.
 
+## Platform support
+
+|OS \ architecture|x86\_64|AArch64|Riscv64|s390x (System-Z)|
+|---|---|---|---|---|
+|Linux|✅|✅|✅[^no-rustup]|✅[^no-rustup]|
+|FreeBSD|✅[^no-rustup]|❓|❓|❓|
+|AIX|❌[^xcoff]|N/A|N/A|❌[^xcoff]|
+|Other unixes|❓|❓|❓|❓|
+|macOS|✅|❌[^apple-silicon]|N/A|N/A|
+|Windows|✅[^no-rustup]|❌|N/A|N/A|
+
+✅: Fully supported and tested
+❓: Maybe supported, not tested
+❌: Not supported at all
+
+Not all targets are available as rustup component for nightly. See notes in the platform support matrix.
+
+[^xcoff]: XCOFF object file format is not supported.
+[^apple-silicon]: Tracked in [#1248](https://github.com/rust-lang/rustc_codegen_cranelift/issues/1248).
+[^no-rustup]: Not available as rustup component for nightly. You can build it yourself.
+
 ## Usage
 
 rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects.
@@ -100,6 +121,8 @@ You need to do this steps to successfully compile and use the cranelift backend
   * (Optional) run tests: `rustup run stage2 ./y.sh test`
 8. Now you can use your cg_clif build to compile other Rust programs, e.g. you can open any Rust crate and run commands like `$RustCheckoutDir/compiler/rustc_codegen_cranelift/dist/cargo-clif build --release`.
 
+You can also set `rust-analyzer.rustc.source` to your rust workspace to get rust-analyzer to understand your changes.
+
 ## Configuration
 
 See the documentation on the `BackendConfig` struct in [config.rs](src/config.rs) for all
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index cb7b2454cd5..818f3d6f08d 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -113,8 +113,8 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
 pub(crate) static RAND_REPO: GitRepo = GitRepo::github(
     "rust-random",
     "rand",
-    "9a02c819cc1e4ec6959ae25eafbb5cf6acb68234",
-    "4934f0afb1d1c2ca",
+    "1f4507a8e1cf8050e4ceef95eeda8f64645b6719",
+    "981f8bf489338978",
     "rand",
 );
 
@@ -133,8 +133,8 @@ pub(crate) static REGEX: CargoProject = CargoProject::new(&REGEX_REPO.source_dir
 pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github(
     "rust-lang",
     "portable-simd",
-    "4825b2a64d765317066948867e8714674419359b",
-    "9e67d07c00f5fb0b",
+    "97007cc2e70df8c97326ce896a79e2f0ce4dd98b",
+    "e54a16035cedf205",
     "portable-simd",
 );
 
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch b/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch
deleted file mode 100644
index b8c0783f524..00000000000
--- a/compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Enable-the-exposed_provenance-feature.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From a101a43b795431ce617e7782afb451f4853afc00 Mon Sep 17 00:00:00 2001
-From: bjorn3 <17426603+bjorn3@users.noreply.github.com>
-Date: Thu, 7 Dec 2023 14:51:35 +0000
-Subject: [PATCH] Enable the exposed_provenance feature
-
----
- crates/core_simd/tests/pointers.rs | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/crates/core_simd/tests/pointers.rs b/crates/core_simd/tests/pointers.rs
-index 0ae8f83..06620d6 100644
---- a/crates/core_simd/tests/pointers.rs
-+++ b/crates/core_simd/tests/pointers.rs
-@@ -1,4 +1,4 @@
--#![feature(portable_simd, strict_provenance)]
-+#![feature(exposed_provenance, portable_simd, strict_provenance)]
- 
- use core_simd::simd::{Simd, SimdConstPtr, SimdMutPtr};
- 
--- 
-2.34.1
-
diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
index be29ae09bcf..271ca12eabb 100644
--- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch
@@ -21,7 +21,7 @@ index 897a5e9..331f66f 100644
 -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
  #![cfg_attr(test, feature(cfg_match))]
  #![feature(int_roundings)]
- #![feature(slice_group_by)]
+ #![feature(split_array)]
 diff --git a/atomic.rs b/atomic.rs
 index b735957..ea728b6 100644
 --- a/atomic.rs
diff --git a/compiler/rustc_codegen_cranelift/patches/rand-lock.toml b/compiler/rustc_codegen_cranelift/patches/rand-lock.toml
index aacf3653c16..815b828a68b 100644
--- a/compiler/rustc_codegen_cranelift/patches/rand-lock.toml
+++ b/compiler/rustc_codegen_cranelift/patches/rand-lock.toml
@@ -487,6 +487,7 @@ dependencies = [
  "rand_pcg",
  "rayon",
  "serde",
+ "zerocopy",
 ]
 
 [[package]]
@@ -505,6 +506,7 @@ version = "0.7.0"
 dependencies = [
  "getrandom",
  "serde",
+ "zerocopy",
 ]
 
 [[package]]
@@ -525,6 +527,7 @@ name = "rand_pcg"
 version = "0.4.0"
 dependencies = [
  "bincode",
+ "rand",
  "rand_core",
  "serde",
 ]
@@ -823,3 +826,23 @@ name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "zerocopy"
+version = "0.7.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
+dependencies = [
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.7.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.37",
+]
diff --git a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
index 8e213f71c3f..ad63b0768d3 100644
--- a/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
+++ b/compiler/rustc_codegen_cranelift/patches/stdlib-lock.toml
@@ -61,9 +61,9 @@ dependencies = [
 
 [[package]]
 name = "compiler_builtins"
-version = "0.1.104"
+version = "0.1.106"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99c3f9035afc33f4358773239573f7d121099856753e1bbd2a6a5207098fc741"
+checksum = "f4ab134a739bafec76aa91ccb15d519a54e569350644a1fea6528d5a0d407e22"
 dependencies = [
  "cc",
  "rustc-std-workspace-core",
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index a086c029360..ccd7edbc2a9 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-12-31"
+channel = "nightly-2024-01-26"
 components = ["rust-src", "rustc-dev", "llvm-tools"]
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
index e6edc452cfb..2d9c2ecdbc2 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/mod.rs
@@ -13,17 +13,14 @@ use gimli::write::{
 };
 use gimli::{Encoding, Format, LineEncoding, RunTimeEndian};
 use indexmap::IndexSet;
+use rustc_session::Session;
 
 pub(crate) use self::emit::{DebugReloc, DebugRelocName};
 pub(crate) use self::unwind::UnwindContext;
 use crate::prelude::*;
 
-pub(crate) fn producer() -> String {
-    format!(
-        "rustc version {} with cranelift {}",
-        rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
-        cranelift_codegen::VERSION,
-    )
+pub(crate) fn producer(sess: &Session) -> String {
+    format!("rustc version {} with cranelift {}", sess.cfg_version, cranelift_codegen::VERSION)
 }
 
 pub(crate) struct DebugContext {
@@ -67,7 +64,7 @@ impl DebugContext {
 
         let should_remap_filepaths = tcx.sess.should_prefer_remapped_for_codegen();
 
-        let producer = producer();
+        let producer = producer(tcx.sess);
         let comp_dir = tcx
             .sess
             .opts
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index e77b0cd0721..757082a5fed 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -143,6 +143,7 @@ fn emit_cgu(
     debug: Option<DebugContext>,
     unwind_context: UnwindContext,
     global_asm_object_file: Option<PathBuf>,
+    producer: &str,
 ) -> Result<ModuleCodegenResult, String> {
     let mut product = module.finish();
 
@@ -152,8 +153,14 @@ fn emit_cgu(
 
     unwind_context.emit(&mut product);
 
-    let module_regular =
-        emit_module(output_filenames, prof, product.object, ModuleKind::Regular, name.clone())?;
+    let module_regular = emit_module(
+        output_filenames,
+        prof,
+        product.object,
+        ModuleKind::Regular,
+        name.clone(),
+        producer,
+    )?;
 
     Ok(ModuleCodegenResult {
         module_regular,
@@ -174,6 +181,7 @@ fn emit_module(
     mut object: cranelift_object::object::write::Object<'_>,
     kind: ModuleKind,
     name: String,
+    producer_str: &str,
 ) -> Result<CompiledModule, String> {
     if object.format() == cranelift_object::object::BinaryFormat::Elf {
         let comment_section = object.add_section(
@@ -182,7 +190,7 @@ fn emit_module(
             cranelift_object::object::SectionKind::OtherString,
         );
         let mut producer = vec![0];
-        producer.extend(crate::debuginfo::producer().as_bytes());
+        producer.extend(producer_str.as_bytes());
         producer.push(0);
         object.set_section_data(comment_section, producer, 1);
     }
@@ -321,6 +329,8 @@ fn module_codegen(
             (cgu_name, cx, module, codegened_functions)
         });
 
+    let producer = crate::debuginfo::producer(tcx.sess);
+
     OngoingModuleCodegen::Async(std::thread::spawn(move || {
         cx.profiler.clone().generic_activity_with_arg("compile functions", &*cgu_name).run(|| {
             cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler(
@@ -348,6 +358,7 @@ fn module_codegen(
                     cx.debug_context,
                     cx.unwind_context,
                     global_asm_object_file,
+                    &producer,
                 )
             });
         std::mem::drop(token);
@@ -453,6 +464,7 @@ pub(crate) fn run_aot(
             product.object,
             ModuleKind::Allocator,
             "allocator_shim".to_owned(),
+            &crate::debuginfo::producer(tcx.sess),
         ) {
             Ok(allocator_module) => Some(allocator_module),
             Err(err) => tcx.dcx().fatal(err),
@@ -467,7 +479,7 @@ pub(crate) fn run_aot(
 
             let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
             let metadata_cgu_name = cgu_name_builder
-                .build_cgu_name(LOCAL_CRATE, &["crate"], Some("metadata"))
+                .build_cgu_name(LOCAL_CRATE, ["crate"], Some("metadata"))
                 .as_str()
                 .to_string();
 
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 50d9f287e74..6b2b946db02 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -321,10 +321,9 @@ fn dep_symbol_lookup_fn(
             Linkage::NotLinked | Linkage::IncludedFromDylib => {}
             Linkage::Static => {
                 let name = crate_info.crate_name[&cnum];
-                sess.dcx()
-                    .struct_err(format!("Can't load static lib {}", name))
-                    .note("rustc_codegen_cranelift can only load dylibs in JIT mode.")
-                    .emit();
+                let mut diag = sess.dcx().struct_err(format!("Can't load static lib {}", name));
+                diag.note("rustc_codegen_cranelift can only load dylibs in JIT mode.");
+                diag.emit();
             }
             Linkage::Dynamic => {
                 dylib_paths.push(src.dylib.as_ref().unwrap().0.clone());
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 6b9cec39d70..7793b1b7092 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -52,7 +52,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
     }
 
     let operands = operands
-        .into_iter()
+        .iter()
         .map(|operand| match *operand {
             InlineAsmOperand::In { reg, ref value } => CInlineAsmOperand::In {
                 reg,
@@ -506,10 +506,34 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
                             if self.options.contains(InlineAsmOptions::ATT_SYNTAX) {
                                 generated_asm.push('%');
                             }
-                            self.registers[*operand_idx]
-                                .unwrap()
-                                .emit(&mut generated_asm, self.arch, *modifier)
-                                .unwrap();
+
+                            let reg = self.registers[*operand_idx].unwrap();
+                            match self.arch {
+                                InlineAsmArch::X86_64 => match reg {
+                                    InlineAsmReg::X86(reg)
+                                        if reg as u32 >= X86InlineAsmReg::xmm0 as u32
+                                            && reg as u32 <= X86InlineAsmReg::xmm15 as u32 =>
+                                    {
+                                        // rustc emits x0 rather than xmm0
+                                        let class = match *modifier {
+                                            None | Some('x') => "xmm",
+                                            Some('y') => "ymm",
+                                            Some('z') => "zmm",
+                                            _ => unreachable!(),
+                                        };
+                                        write!(
+                                            generated_asm,
+                                            "{class}{}",
+                                            reg as u32 - X86InlineAsmReg::xmm0 as u32
+                                        )
+                                        .unwrap();
+                                    }
+                                    _ => reg
+                                        .emit(&mut generated_asm, InlineAsmArch::X86_64, *modifier)
+                                        .unwrap(),
+                                },
+                                _ => reg.emit(&mut generated_asm, self.arch, *modifier).unwrap(),
+                            }
                         }
                         CInlineAsmOperand::Const { ref value } => {
                             generated_asm.push_str(value);
@@ -739,7 +763,7 @@ fn call_inline_asm<'tcx>(
             },
         )
         .unwrap();
-    let inline_asm_func = fx.module.declare_func_in_func(inline_asm_func, &mut fx.bcx.func);
+    let inline_asm_func = fx.module.declare_func_in_func(inline_asm_func, fx.bcx.func);
     if fx.clif_comments.enabled() {
         fx.add_comment(inline_asm_func, asm_name);
     }
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index 1345c4614e2..e50c74b87f6 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -35,6 +35,10 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
     }
 
     match intrinsic {
+        "llvm.prefetch" => {
+            // Nothing to do. This is merely a perf hint.
+        }
+
         _ if intrinsic.starts_with("llvm.ctlz.v") => {
             intrinsic_args!(fx, args => (a); intrinsic);
 
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
index f6f3b85d3ef..e66bcbf4e40 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
@@ -243,6 +243,20 @@ pub(crate) fn codegen_aarch64_llvm_intrinsic_call<'tcx>(
         }
 
         // FIXME generalize vector types
+        "llvm.aarch64.neon.tbl1.v8i8" => {
+            intrinsic_args!(fx, args => (t, idx); intrinsic);
+
+            let zero = fx.bcx.ins().iconst(types::I8, 0);
+            for i in 0..8 {
+                let idx_lane = idx.value_lane(fx, i).load_scalar(fx);
+                let is_zero =
+                    fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThanOrEqual, idx_lane, 16);
+                let t_idx = fx.bcx.ins().uextend(fx.pointer_type, idx_lane);
+                let t_lane = t.value_lane_dyn(fx, t_idx).load_scalar(fx);
+                let res = fx.bcx.ins().select(is_zero, zero, t_lane);
+                ret.place_lane(fx, i).to_ptr().store(fx, res, MemFlags::trusted());
+            }
+        }
         "llvm.aarch64.neon.tbl1.v16i8" => {
             intrinsic_args!(fx, args => (t, idx); intrinsic);
 
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index 994dc66835c..2e3e7ce986b 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -610,230 +610,56 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>(
             // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi16&ig_expand=4903
             intrinsic_args!(fx, args => (a, b); intrinsic);
 
-            assert_eq!(a.layout(), b.layout());
-            let layout = a.layout();
-
-            let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
-            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
-            assert_eq!(lane_ty, fx.tcx.types.i16);
-            assert_eq!(ret_lane_ty, fx.tcx.types.u8);
-            assert_eq!(lane_count * 2, ret_lane_count);
-
-            let zero = fx.bcx.ins().iconst(types::I16, 0);
-            let max_u8 = fx.bcx.ins().iconst(types::I16, 255);
-            let ret_lane_layout = fx.layout_of(fx.tcx.types.u8);
-
-            for idx in 0..lane_count {
-                let lane = a.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, zero);
-                let sat = fx.bcx.ins().umin(sat, max_u8);
-                let res = fx.bcx.ins().ireduce(types::I8, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, idx).write_cvalue(fx, res_lane);
-            }
+            pack_instruction(fx, a, b, ret, PackSize::U8, PackWidth::Sse);
+        }
 
-            for idx in 0..lane_count {
-                let lane = b.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, zero);
-                let sat = fx.bcx.ins().umin(sat, max_u8);
-                let res = fx.bcx.ins().ireduce(types::I8, sat);
+        "llvm.x86.sse2.packsswb.128" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi16&ig_expand=4848
+            intrinsic_args!(fx, args => (a, b); intrinsic);
 
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane);
-            }
+            pack_instruction(fx, a, b, ret, PackSize::S8, PackWidth::Sse);
         }
 
         "llvm.x86.avx2.packuswb" => {
             // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi16&ig_expand=4906
             intrinsic_args!(fx, args => (a, b); intrinsic);
 
-            assert_eq!(a.layout(), b.layout());
-            let layout = a.layout();
-
-            let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
-            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
-            assert_eq!(lane_ty, fx.tcx.types.i16);
-            assert_eq!(ret_lane_ty, fx.tcx.types.u8);
-            assert_eq!(lane_count * 2, ret_lane_count);
-
-            let zero = fx.bcx.ins().iconst(types::I16, 0);
-            let max_u8 = fx.bcx.ins().iconst(types::I16, 255);
-            let ret_lane_layout = fx.layout_of(fx.tcx.types.u8);
-
-            for idx in 0..lane_count / 2 {
-                let lane = a.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, zero);
-                let sat = fx.bcx.ins().umin(sat, max_u8);
-                let res = fx.bcx.ins().ireduce(types::I8, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, idx).write_cvalue(fx, res_lane);
-            }
-
-            for idx in 0..lane_count / 2 {
-                let lane = b.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, zero);
-                let sat = fx.bcx.ins().umin(sat, max_u8);
-                let res = fx.bcx.ins().ireduce(types::I8, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane);
-            }
-
-            for idx in 0..lane_count / 2 {
-                let lane = a.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, zero);
-                let sat = fx.bcx.ins().umin(sat, max_u8);
-                let res = fx.bcx.ins().ireduce(types::I8, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane);
-            }
-
-            for idx in 0..lane_count / 2 {
-                let lane = b.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, zero);
-                let sat = fx.bcx.ins().umin(sat, max_u8);
-                let res = fx.bcx.ins().ireduce(types::I8, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane);
-            }
+            pack_instruction(fx, a, b, ret, PackSize::U8, PackWidth::Avx);
         }
 
-        "llvm.x86.sse2.packssdw.128" => {
-            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32&ig_expand=4889
+        "llvm.x86.avx2.packsswb" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi16&ig_expand=4851
             intrinsic_args!(fx, args => (a, b); intrinsic);
 
-            assert_eq!(a.layout(), b.layout());
-            let layout = a.layout();
-
-            let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
-            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
-            assert_eq!(lane_ty, fx.tcx.types.i32);
-            assert_eq!(ret_lane_ty, fx.tcx.types.i16);
-            assert_eq!(lane_count * 2, ret_lane_count);
-
-            let min_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MIN) as u32 as i64);
-            let max_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MAX) as u32 as i64);
-            let ret_lane_layout = fx.layout_of(fx.tcx.types.i16);
-
-            for idx in 0..lane_count {
-                let lane = a.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, min_i16);
-                let sat = fx.bcx.ins().smin(sat, max_i16);
-                let res = fx.bcx.ins().ireduce(types::I16, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, idx).write_cvalue(fx, res_lane);
-            }
-
-            for idx in 0..lane_count {
-                let lane = b.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, min_i16);
-                let sat = fx.bcx.ins().smin(sat, max_i16);
-                let res = fx.bcx.ins().ireduce(types::I16, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane);
-            }
+            pack_instruction(fx, a, b, ret, PackSize::S8, PackWidth::Avx);
         }
 
         "llvm.x86.sse41.packusdw" => {
             // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packus_epi32&ig_expand=4912
             intrinsic_args!(fx, args => (a, b); intrinsic);
 
-            assert_eq!(a.layout(), b.layout());
-            let layout = a.layout();
-
-            let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
-            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
-            assert_eq!(lane_ty, fx.tcx.types.i32);
-            assert_eq!(ret_lane_ty, fx.tcx.types.u16);
-            assert_eq!(lane_count * 2, ret_lane_count);
-
-            let min_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MIN));
-            let max_u16 = fx.bcx.ins().iconst(types::I32, i64::from(u16::MAX));
-            let ret_lane_layout = fx.layout_of(fx.tcx.types.u16);
+            pack_instruction(fx, a, b, ret, PackSize::U16, PackWidth::Sse);
+        }
 
-            for idx in 0..lane_count {
-                let lane = a.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, min_u16);
-                let sat = fx.bcx.ins().smin(sat, max_u16);
-                let res = fx.bcx.ins().ireduce(types::I16, sat);
+        "llvm.x86.sse2.packssdw.128" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_packs_epi32&ig_expand=4889
+            intrinsic_args!(fx, args => (a, b); intrinsic);
 
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, idx).write_cvalue(fx, res_lane);
-            }
+            pack_instruction(fx, a, b, ret, PackSize::S16, PackWidth::Sse);
+        }
 
-            for idx in 0..lane_count {
-                let lane = b.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, min_u16);
-                let sat = fx.bcx.ins().smin(sat, max_u16);
-                let res = fx.bcx.ins().ireduce(types::I16, sat);
+        "llvm.x86.avx2.packusdw" => {
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packus_epi32&ig_expand=4883
+            intrinsic_args!(fx, args => (a, b); intrinsic);
 
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, lane_count + idx).write_cvalue(fx, res_lane);
-            }
+            pack_instruction(fx, a, b, ret, PackSize::U16, PackWidth::Avx);
         }
 
         "llvm.x86.avx2.packssdw" => {
             // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm256_packs_epi32&ig_expand=4892
             intrinsic_args!(fx, args => (a, b); intrinsic);
 
-            assert_eq!(a.layout(), b.layout());
-            let layout = a.layout();
-
-            let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
-            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
-            assert_eq!(lane_ty, fx.tcx.types.i32);
-            assert_eq!(ret_lane_ty, fx.tcx.types.i16);
-            assert_eq!(lane_count * 2, ret_lane_count);
-
-            let min_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MIN) as u32 as i64);
-            let max_i16 = fx.bcx.ins().iconst(types::I32, i32::from(i16::MAX) as u32 as i64);
-            let ret_lane_layout = fx.layout_of(fx.tcx.types.i16);
-
-            for idx in 0..lane_count / 2 {
-                let lane = a.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, min_i16);
-                let sat = fx.bcx.ins().smin(sat, max_i16);
-                let res = fx.bcx.ins().ireduce(types::I16, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, idx).write_cvalue(fx, res_lane);
-            }
-
-            for idx in 0..lane_count / 2 {
-                let lane = b.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, min_i16);
-                let sat = fx.bcx.ins().smin(sat, max_i16);
-                let res = fx.bcx.ins().ireduce(types::I16, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, lane_count / 2 + idx).write_cvalue(fx, res_lane);
-            }
-
-            for idx in 0..lane_count / 2 {
-                let lane = a.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, min_i16);
-                let sat = fx.bcx.ins().smin(sat, max_i16);
-                let res = fx.bcx.ins().ireduce(types::I16, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, lane_count / 2 * 2 + idx).write_cvalue(fx, res_lane);
-            }
-
-            for idx in 0..lane_count / 2 {
-                let lane = b.value_lane(fx, idx).load_scalar(fx);
-                let sat = fx.bcx.ins().smax(lane, min_i16);
-                let sat = fx.bcx.ins().smin(sat, max_i16);
-                let res = fx.bcx.ins().ireduce(types::I16, sat);
-
-                let res_lane = CValue::by_val(res, ret_lane_layout);
-                ret.place_lane(fx, lane_count / 2 * 3 + idx).write_cvalue(fx, res_lane);
-            }
+            pack_instruction(fx, a, b, ret, PackSize::S16, PackWidth::Avx);
         }
 
         "llvm.x86.fma.vfmaddsub.ps"
@@ -1407,3 +1233,115 @@ fn llvm_add_sub<'tcx>(
 
     (cb_out, c)
 }
+
+enum PackSize {
+    U8,
+    U16,
+    S8,
+    S16,
+}
+
+impl PackSize {
+    fn ret_clif_type(&self) -> Type {
+        match self {
+            Self::U8 | Self::S8 => types::I8,
+            Self::U16 | Self::S16 => types::I16,
+        }
+    }
+    fn src_clif_type(&self) -> Type {
+        match self {
+            Self::U8 | Self::S8 => types::I16,
+            Self::U16 | Self::S16 => types::I32,
+        }
+    }
+    fn src_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+        match self {
+            Self::U8 | Self::S8 => tcx.types.i16,
+            Self::U16 | Self::S16 => tcx.types.i32,
+        }
+    }
+    fn ret_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+        match self {
+            Self::U8 => tcx.types.u8,
+            Self::S8 => tcx.types.i8,
+            Self::U16 => tcx.types.u16,
+            Self::S16 => tcx.types.i16,
+        }
+    }
+    fn max(&self) -> i64 {
+        match self {
+            Self::U8 => u8::MAX as u64 as i64,
+            Self::S8 => i8::MAX as u8 as u64 as i64,
+            Self::U16 => u16::MAX as u64 as i64,
+            Self::S16 => i16::MAX as u64 as u64 as i64,
+        }
+    }
+    fn min(&self) -> i64 {
+        match self {
+            Self::U8 | Self::U16 => 0,
+            Self::S8 => i16::from(i8::MIN) as u16 as i64,
+            Self::S16 => i32::from(i16::MIN) as u32 as i64,
+        }
+    }
+}
+
+enum PackWidth {
+    Sse = 1,
+    Avx = 2,
+}
+impl PackWidth {
+    fn divisor(&self) -> u64 {
+        match self {
+            Self::Sse => 1,
+            Self::Avx => 2,
+        }
+    }
+}
+
+/// Implement an x86 pack instruction with the intrinsic `_mm{,256}pack{us,s}_epi{16,32}`.
+/// Validated for correctness against LLVM, see commit `c8f5d35508e062bd2d95e6c03429bfec831db6d3`.
+fn pack_instruction<'tcx>(
+    fx: &mut FunctionCx<'_, '_, 'tcx>,
+    a: CValue<'tcx>,
+    b: CValue<'tcx>,
+    ret: CPlace<'tcx>,
+    ret_size: PackSize,
+    width: PackWidth,
+) {
+    assert_eq!(a.layout(), b.layout());
+    let layout = a.layout();
+
+    let (src_lane_count, src_lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
+    let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
+    assert_eq!(src_lane_ty, ret_size.src_ty(fx.tcx));
+    assert_eq!(ret_lane_ty, ret_size.ret_ty(fx.tcx));
+    assert_eq!(src_lane_count * 2, ret_lane_count);
+
+    let min = fx.bcx.ins().iconst(ret_size.src_clif_type(), ret_size.min());
+    let max = fx.bcx.ins().iconst(ret_size.src_clif_type(), ret_size.max());
+    let ret_lane_layout = fx.layout_of(ret_size.ret_ty(fx.tcx));
+
+    let mut round = |source: CValue<'tcx>, source_offset: u64, dest_offset: u64| {
+        let step_amount = src_lane_count / width.divisor();
+        let dest_offset = step_amount * dest_offset;
+        for idx in 0..step_amount {
+            let lane = source.value_lane(fx, step_amount * source_offset + idx).load_scalar(fx);
+            let sat = fx.bcx.ins().smax(lane, min);
+            let sat = match ret_size {
+                PackSize::U8 | PackSize::U16 => fx.bcx.ins().umin(sat, max),
+                PackSize::S8 | PackSize::S16 => fx.bcx.ins().smin(sat, max),
+            };
+            let res = fx.bcx.ins().ireduce(ret_size.ret_clif_type(), sat);
+            let res_lane = CValue::by_val(res, ret_lane_layout);
+            ret.place_lane(fx, dest_offset + idx).write_cvalue(fx, res_lane);
+        }
+    };
+
+    round(a, 0, 0);
+    round(b, 0, 1);
+
+    if let PackWidth::Avx = width {
+        round(a, 1, 2);
+        round(b, 1, 3);
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index d56d17892d5..ebdc744bcd8 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -293,7 +293,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             }
 
             ret.write_cvalue(fx, base);
-            let ret_lane = ret.place_lane(fx, idx.try_into().unwrap());
+            let ret_lane = ret.place_lane(fx, idx.into());
             ret_lane.write_cvalue(fx, val);
         }
 
@@ -340,7 +340,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
                 );
             }
 
-            let ret_lane = v.value_lane(fx, idx.try_into().unwrap());
+            let ret_lane = v.value_lane(fx, idx.into());
             ret.write_cvalue(fx, ret_lane);
         }
 
@@ -822,7 +822,35 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
             let lane_layout = fx.layout_of(lane_ty);
 
-            let m = m.load_scalar(fx);
+            let expected_int_bits = lane_count.max(8);
+            let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64);
+
+            let m = match m.layout().ty.kind() {
+                ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => m.load_scalar(fx),
+                ty::Array(elem, len)
+                    if matches!(elem.kind(), ty::Uint(ty::UintTy::U8))
+                        && len.try_eval_target_usize(fx.tcx, ty::ParamEnv::reveal_all())
+                            == Some(expected_bytes) =>
+                {
+                    m.force_stack(fx).0.load(
+                        fx,
+                        Type::int(expected_int_bits as u16).unwrap(),
+                        MemFlags::trusted(),
+                    )
+                }
+                _ => {
+                    fx.tcx.dcx().span_fatal(
+                        span,
+                        format!(
+                            "invalid monomorphization of `simd_select_bitmask` intrinsic: \
+                            cannot accept `{}` as mask, expected `u{}` or `[u8; {}]`",
+                            ret.layout().ty,
+                            expected_int_bits,
+                            expected_bytes
+                        ),
+                    );
+                }
+            };
 
             for lane in 0..lane_count {
                 let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64);
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index b482f0dd2f0..416f87fcc87 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -18,7 +18,6 @@ extern crate rustc_fs_util;
 extern crate rustc_hir;
 extern crate rustc_incremental;
 extern crate rustc_index;
-extern crate rustc_interface;
 extern crate rustc_metadata;
 extern crate rustc_session;
 extern crate rustc_span;
@@ -42,7 +41,7 @@ use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_session::config::OutputFilenames;
 use rustc_session::Session;
-use rustc_span::Symbol;
+use rustc_span::{sym, Symbol};
 
 pub use crate::config::*;
 use crate::prelude::*;
@@ -190,8 +189,17 @@ impl CodegenBackend for CraneliftCodegenBackend {
         }
     }
 
-    fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec<rustc_span::Symbol> {
-        vec![] // FIXME necessary for #[cfg(target_feature]
+    fn target_features(&self, sess: &Session, _allow_unstable: bool) -> Vec<rustc_span::Symbol> {
+        // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
+        if sess.target.arch == "x86_64" && sess.target.os != "none" {
+            // x86_64 mandates SSE2 support
+            vec![Symbol::intern("fxsr"), sym::sse, Symbol::intern("sse2")]
+        } else if sess.target.arch == "aarch64" && sess.target.os != "none" {
+            // AArch64 mandates Neon support
+            vec![sym::neon]
+        } else {
+            vec![]
+        }
     }
 
     fn print_version(&self) {
@@ -305,16 +313,13 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc<dyn isa::Tar
     let flags = settings::Flags::new(flags_builder);
 
     let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
-        Some("native") => {
-            let builder = cranelift_native::builder_with_options(true).unwrap();
-            builder
-        }
+        Some("native") => cranelift_native::builder_with_options(true).unwrap(),
         Some(value) => {
             let mut builder =
                 cranelift_codegen::isa::lookup(target_triple.clone()).unwrap_or_else(|err| {
                     sess.dcx().fatal(format!("can't compile for {}: {}", target_triple, err));
                 });
-            if let Err(_) = builder.enable(value) {
+            if builder.enable(value).is_err() {
                 sess.dcx()
                     .fatal("the specified target cpu isn't currently supported by Cranelift.");
             }
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index f777e11371f..acfa461a6f3 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -28,10 +28,9 @@ pub(crate) fn unsized_info<'tcx>(
             .bcx
             .ins()
             .iconst(fx.pointer_type, len.eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
-        (
-            &ty::Dynamic(ref data_a, _, src_dyn_kind),
-            &ty::Dynamic(ref data_b, _, target_dyn_kind),
-        ) if src_dyn_kind == target_dyn_kind => {
+        (&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind))
+            if src_dyn_kind == target_dyn_kind =>
+        {
             let old_info =
                 old_info.expect("unsized_info: missing old info for trait upcasting coercion");
             if data_a.principal_def_id() == data_b.principal_def_id() {
diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs
index 41ea0b122de..d2254d4c15e 100644
--- a/compiler/rustc_codegen_cranelift/src/vtable.rs
+++ b/compiler/rustc_codegen_cranelift/src/vtable.rs
@@ -95,7 +95,7 @@ pub(crate) fn get_vtable<'tcx>(
     let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref));
     let data_id =
         data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not);
-    let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
+    let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
     if fx.clif_comments.enabled() {
         fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id));
     }
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index 7a86ddc7556..d5bc04f594d 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -39,6 +39,9 @@ codegen_llvm_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdy
 
 codegen_llvm_lto_proc_macro = lto cannot be used for `proc-macro` crate type without `-Zdylib-lto`
 
+codegen_llvm_mismatch_data_layout =
+    data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`
+
 codegen_llvm_missing_features =
     add the missing features in a `target_feature` attribute
 
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 5ef05dfbe4c..6cb62280a59 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -34,6 +34,7 @@ use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
 use smallvec::SmallVec;
 
 use libc::c_uint;
+use std::borrow::Borrow;
 use std::cell::{Cell, RefCell};
 use std::ffi::CStr;
 use std::str;
@@ -155,8 +156,7 @@ pub unsafe fn create_module<'ll>(
     }
 
     // Ensure the data-layout values hardcoded remain the defaults.
-    if sess.target.is_builtin {
-        // tm is disposed by its drop impl
+    {
         let tm = crate::back::write::create_informational_target_machine(tcx.sess);
         llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
 
@@ -164,33 +164,13 @@ pub unsafe fn create_module<'ll>(
         let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
             .expect("got a non-UTF8 data-layout from LLVM");
 
-        // Unfortunately LLVM target specs change over time, and right now we
-        // don't have proper support to work with any more than one
-        // `data_layout` than the one that is in the rust-lang/rust repo. If
-        // this compiler is configured against a custom LLVM, we may have a
-        // differing data layout, even though we should update our own to use
-        // that one.
-        //
-        // As an interim hack, if CFG_LLVM_ROOT is not an empty string then we
-        // disable this check entirely as we may be configured with something
-        // that has a different target layout.
-        //
-        // Unsure if this will actually cause breakage when rustc is configured
-        // as such.
-        //
-        // FIXME(#34960)
-        let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
-        let custom_llvm_used = !cfg_llvm_root.trim().is_empty();
-
-        if !custom_llvm_used && target_data_layout != llvm_data_layout {
-            bug!(
-                "data-layout for target `{rustc_target}`, `{rustc_layout}`, \
-                  differs from LLVM target's `{llvm_target}` default layout, `{llvm_layout}`",
-                rustc_target = sess.opts.target_triple,
-                rustc_layout = target_data_layout,
-                llvm_target = sess.target.llvm_target,
-                llvm_layout = llvm_data_layout
-            );
+        if target_data_layout != llvm_data_layout {
+            tcx.dcx().emit_err(crate::errors::MismatchedDataLayout {
+                rustc_target: sess.opts.target_triple.to_string().as_str(),
+                rustc_layout: target_data_layout.as_str(),
+                llvm_target: sess.target.llvm_target.borrow(),
+                llvm_layout: llvm_data_layout,
+            });
         }
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 697ce602298..d82ff6656f4 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -244,3 +244,12 @@ pub(crate) struct CopyBitcode {
 pub struct UnknownCompression {
     pub algorithm: &'static str,
 }
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_mismatch_data_layout)]
+pub struct MismatchedDataLayout<'a> {
+    pub rustc_target: &'a str,
+    pub rustc_layout: &'a str,
+    pub llvm_target: &'a str,
+    pub llvm_layout: &'a str,
+}
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 5d497d4a188..b13d566b40b 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::Emitter;
 use rustc_errors::{translation::Translate, DiagCtxt, FatalError, Level};
-use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, Style};
+use rustc_errors::{DiagnosticBuilder, DiagnosticMessage, ErrCode, Style};
 use rustc_fs_util::link_or_copy;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_incremental::{
@@ -1000,7 +1000,7 @@ type DiagnosticArgName<'source> = Cow<'source, str>;
 struct Diagnostic {
     msgs: Vec<(DiagnosticMessage, Style)>,
     args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
-    code: Option<String>,
+    code: Option<ErrCode>,
     lvl: Level,
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index cca239a43b3..47b1b080119 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,6 +1,6 @@
 use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
 use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index f90e1906caf..ef291ead190 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -4,7 +4,7 @@ use crate::assert_module_sources::CguReuse;
 use crate::back::command::Command;
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
+    codes::*, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
     IntoDiagnosticArg, Level,
 };
 use rustc_macros::Diagnostic;
@@ -612,7 +612,7 @@ pub struct UnknownAtomicOperation;
 
 #[derive(Diagnostic)]
 pub enum InvalidMonomorphization<'tcx> {
-    #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = E0511)]
     BasicIntegerType {
         #[primary_span]
         span: Span,
@@ -620,7 +620,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = E0511)]
     BasicFloatType {
         #[primary_span]
         span: Span,
@@ -628,14 +628,14 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = E0511)]
     FloatToIntUnchecked {
         #[primary_span]
         span: Span,
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = E0511)]
     FloatingPointVector {
         #[primary_span]
         span: Span,
@@ -644,7 +644,7 @@ pub enum InvalidMonomorphization<'tcx> {
         in_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = E0511)]
     FloatingPointType {
         #[primary_span]
         span: Span,
@@ -652,14 +652,14 @@ pub enum InvalidMonomorphization<'tcx> {
         in_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = E0511)]
     UnrecognizedIntrinsic {
         #[primary_span]
         span: Span,
         name: Symbol,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = E0511)]
     SimdArgument {
         #[primary_span]
         span: Span,
@@ -667,7 +667,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = E0511)]
     SimdInput {
         #[primary_span]
         span: Span,
@@ -675,7 +675,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = E0511)]
     SimdFirst {
         #[primary_span]
         span: Span,
@@ -683,7 +683,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = E0511)]
     SimdSecond {
         #[primary_span]
         span: Span,
@@ -691,7 +691,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = E0511)]
     SimdThird {
         #[primary_span]
         span: Span,
@@ -699,7 +699,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = E0511)]
     SimdReturn {
         #[primary_span]
         span: Span,
@@ -707,7 +707,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = E0511)]
     InvalidBitmask {
         #[primary_span]
         span: Span,
@@ -717,7 +717,7 @@ pub enum InvalidMonomorphization<'tcx> {
         expected_bytes: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = E0511)]
     ReturnLengthInputType {
         #[primary_span]
         span: Span,
@@ -728,7 +728,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = E0511)]
     SecondArgumentLength {
         #[primary_span]
         span: Span,
@@ -739,7 +739,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = E0511)]
     ThirdArgumentLength {
         #[primary_span]
         span: Span,
@@ -750,7 +750,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = E0511)]
     ReturnIntegerType {
         #[primary_span]
         span: Span,
@@ -759,7 +759,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = E0511)]
     SimdShuffle {
         #[primary_span]
         span: Span,
@@ -767,7 +767,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_length, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_length, code = E0511)]
     ReturnLength {
         #[primary_span]
         span: Span,
@@ -777,7 +777,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_element, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_element, code = E0511)]
     ReturnElement {
         #[primary_span]
         span: Span,
@@ -788,7 +788,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = E0511)]
     ShuffleIndexNotConstant {
         #[primary_span]
         span: Span,
@@ -796,7 +796,7 @@ pub enum InvalidMonomorphization<'tcx> {
         arg_idx: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = E0511)]
     ShuffleIndexOutOfBounds {
         #[primary_span]
         span: Span,
@@ -805,7 +805,7 @@ pub enum InvalidMonomorphization<'tcx> {
         total_len: u128,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = E0511)]
     InsertedType {
         #[primary_span]
         span: Span,
@@ -815,7 +815,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_return_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_return_type, code = E0511)]
     ReturnType {
         #[primary_span]
         span: Span,
@@ -825,7 +825,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ret_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = E0511)]
     ExpectedReturnType {
         #[primary_span]
         span: Span,
@@ -834,7 +834,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ret_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = E0511)]
     MismatchedLengths {
         #[primary_span]
         span: Span,
@@ -843,7 +843,7 @@ pub enum InvalidMonomorphization<'tcx> {
         v_len: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = E0511)]
     MaskType {
         #[primary_span]
         span: Span,
@@ -851,7 +851,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = E0511)]
     VectorArgument {
         #[primary_span]
         span: Span,
@@ -860,7 +860,7 @@ pub enum InvalidMonomorphization<'tcx> {
         in_elem: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = E0511)]
     CannotReturn {
         #[primary_span]
         span: Span,
@@ -870,7 +870,7 @@ pub enum InvalidMonomorphization<'tcx> {
         expected_bytes: u64,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = E0511)]
     ExpectedElementType {
         #[primary_span]
         span: Span,
@@ -882,7 +882,7 @@ pub enum InvalidMonomorphization<'tcx> {
         mutability: ExpectedPointerMutability,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = E0511)]
     ThirdArgElementType {
         #[primary_span]
         span: Span,
@@ -891,7 +891,7 @@ pub enum InvalidMonomorphization<'tcx> {
         third_arg: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = E0511)]
     UnsupportedSymbolOfSize {
         #[primary_span]
         span: Span,
@@ -903,7 +903,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ret_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = E0511)]
     UnsupportedSymbol {
         #[primary_span]
         span: Span,
@@ -914,7 +914,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ret_ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = E0511)]
     CastFatPointer {
         #[primary_span]
         span: Span,
@@ -922,7 +922,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = E0511)]
     ExpectedPointer {
         #[primary_span]
         span: Span,
@@ -930,7 +930,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = E0511)]
     ExpectedUsize {
         #[primary_span]
         span: Span,
@@ -938,7 +938,7 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = E0511)]
     UnsupportedCast {
         #[primary_span]
         span: Span,
@@ -949,7 +949,7 @@ pub enum InvalidMonomorphization<'tcx> {
         out_elem: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = E0511)]
     UnsupportedOperation {
         #[primary_span]
         span: Span,
@@ -958,7 +958,7 @@ pub enum InvalidMonomorphization<'tcx> {
         in_elem: Ty<'tcx>,
     },
 
-    #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = "E0511")]
+    #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = E0511)]
     ExpectedVectorElementType {
         #[primary_span]
         span: Span,
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 064d97a49d7..9e27c19e94c 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -1,8 +1,8 @@
 use std::borrow::Cow;
 
 use rustc_errors::{
-    DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee,
-    IntoDiagnostic, Level,
+    codes::*, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage,
+    EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_hir::ConstContext;
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -55,14 +55,14 @@ pub(crate) struct UnstableInStable {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_thread_local_access, code = "E0625")]
+#[diag(const_eval_thread_local_access, code = E0625)]
 pub(crate) struct NonConstOpErr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_static_access, code = "E0013")]
+#[diag(const_eval_static_access, code = E0013)]
 #[help]
 pub(crate) struct StaticAccessErr {
     #[primary_span]
@@ -98,7 +98,7 @@ pub(crate) struct PanicNonStrErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_mut_deref, code = "E0658")]
+#[diag(const_eval_mut_deref, code = E0658)]
 pub(crate) struct MutDerefErr {
     #[primary_span]
     pub span: Span,
@@ -106,7 +106,7 @@ pub(crate) struct MutDerefErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_transient_mut_borrow, code = "E0658")]
+#[diag(const_eval_transient_mut_borrow, code = E0658)]
 pub(crate) struct TransientMutBorrowErr {
     #[primary_span]
     pub span: Span,
@@ -114,7 +114,7 @@ pub(crate) struct TransientMutBorrowErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_transient_mut_raw, code = "E0658")]
+#[diag(const_eval_transient_mut_raw, code = E0658)]
 pub(crate) struct TransientMutRawErr {
     #[primary_span]
     pub span: Span,
@@ -146,7 +146,7 @@ pub(crate) struct UnstableConstFn {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_unallowed_mutable_refs, code = "E0764")]
+#[diag(const_eval_unallowed_mutable_refs, code = E0764)]
 pub(crate) struct UnallowedMutableRefs {
     #[primary_span]
     pub span: Span,
@@ -156,7 +156,7 @@ pub(crate) struct UnallowedMutableRefs {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_unallowed_mutable_raw, code = "E0764")]
+#[diag(const_eval_unallowed_mutable_raw, code = E0764)]
 pub(crate) struct UnallowedMutableRaw {
     #[primary_span]
     pub span: Span,
@@ -165,7 +165,7 @@ pub(crate) struct UnallowedMutableRaw {
     pub teach: Option<()>,
 }
 #[derive(Diagnostic)]
-#[diag(const_eval_non_const_fmt_macro_call, code = "E0015")]
+#[diag(const_eval_non_const_fmt_macro_call, code = E0015)]
 pub(crate) struct NonConstFmtMacroCall {
     #[primary_span]
     pub span: Span,
@@ -173,7 +173,7 @@ pub(crate) struct NonConstFmtMacroCall {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_non_const_fn_call, code = "E0015")]
+#[diag(const_eval_non_const_fn_call, code = E0015)]
 pub(crate) struct NonConstFnCall {
     #[primary_span]
     pub span: Span,
@@ -190,7 +190,7 @@ pub(crate) struct UnallowedOpInConstContext {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_unallowed_heap_allocations, code = "E0010")]
+#[diag(const_eval_unallowed_heap_allocations, code = E0010)]
 pub(crate) struct UnallowedHeapAllocations {
     #[primary_span]
     #[label]
@@ -201,7 +201,7 @@ pub(crate) struct UnallowedHeapAllocations {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_unallowed_inline_asm, code = "E0015")]
+#[diag(const_eval_unallowed_inline_asm, code = E0015)]
 pub(crate) struct UnallowedInlineAsm {
     #[primary_span]
     pub span: Span,
@@ -209,7 +209,7 @@ pub(crate) struct UnallowedInlineAsm {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_interior_mutable_data_refer, code = "E0492")]
+#[diag(const_eval_interior_mutable_data_refer, code = E0492)]
 pub(crate) struct InteriorMutableDataRefer {
     #[primary_span]
     #[label]
@@ -274,7 +274,7 @@ pub struct RawBytesNote {
 // FIXME(fee1-dead) do not use stringly typed `ConstContext`
 
 #[derive(Diagnostic)]
-#[diag(const_eval_match_eq_non_const, code = "E0015")]
+#[diag(const_eval_match_eq_non_const, code = E0015)]
 #[note]
 pub struct NonConstMatchEq<'tcx> {
     #[primary_span]
@@ -284,7 +284,7 @@ pub struct NonConstMatchEq<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_for_loop_into_iter_non_const, code = "E0015")]
+#[diag(const_eval_for_loop_into_iter_non_const, code = E0015)]
 pub struct NonConstForLoopIntoIter<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -293,7 +293,7 @@ pub struct NonConstForLoopIntoIter<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_question_branch_non_const, code = "E0015")]
+#[diag(const_eval_question_branch_non_const, code = E0015)]
 pub struct NonConstQuestionBranch<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -302,7 +302,7 @@ pub struct NonConstQuestionBranch<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_question_from_residual_non_const, code = "E0015")]
+#[diag(const_eval_question_from_residual_non_const, code = E0015)]
 pub struct NonConstQuestionFromResidual<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -311,7 +311,7 @@ pub struct NonConstQuestionFromResidual<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_try_block_from_output_non_const, code = "E0015")]
+#[diag(const_eval_try_block_from_output_non_const, code = E0015)]
 pub struct NonConstTryBlockFromOutput<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -320,7 +320,7 @@ pub struct NonConstTryBlockFromOutput<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_await_non_const, code = "E0015")]
+#[diag(const_eval_await_non_const, code = E0015)]
 pub struct NonConstAwait<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -329,7 +329,7 @@ pub struct NonConstAwait<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_closure_non_const, code = "E0015")]
+#[diag(const_eval_closure_non_const, code = E0015)]
 pub struct NonConstClosure {
     #[primary_span]
     pub span: Span,
@@ -362,7 +362,7 @@ pub struct ConsiderDereferencing {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_operator_non_const, code = "E0015")]
+#[diag(const_eval_operator_non_const, code = E0015)]
 pub struct NonConstOperator {
     #[primary_span]
     pub span: Span,
@@ -372,7 +372,7 @@ pub struct NonConstOperator {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_deref_coercion_non_const, code = "E0015")]
+#[diag(const_eval_deref_coercion_non_const, code = E0015)]
 #[note]
 pub struct NonConstDerefCoercion<'tcx> {
     #[primary_span]
@@ -385,7 +385,7 @@ pub struct NonConstDerefCoercion<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_live_drop, code = "E0493")]
+#[diag(const_eval_live_drop, code = E0493)]
 pub struct LiveDrop<'tcx> {
     #[primary_span]
     #[label]
@@ -397,7 +397,7 @@ pub struct LiveDrop<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_error, code = "E0080")]
+#[diag(const_eval_error, code = E0080)]
 pub struct ConstEvalError {
     #[primary_span]
     pub span: Span,
@@ -423,7 +423,7 @@ pub struct NullaryIntrinsicError {
 }
 
 #[derive(Diagnostic)]
-#[diag(const_eval_undefined_behavior, code = "E0080")]
+#[diag(const_eval_undefined_behavior, code = E0080)]
 pub struct UndefinedBehavior {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 80d4bda4827..4653c9016c6 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -260,8 +260,12 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
         // This makes several assumptions about what layouts we will encounter; we match what
         // codegen does as good as we can (see `extract_field` in `rustc_codegen_ssa/src/mir/operand.rs`).
         let inner_val: Immediate<_> = match (**self, self.layout.abi) {
-            // if the entire value is uninit, then so is the field (can happen in ConstProp)
+            // If the entire value is uninit, then so is the field (can happen in ConstProp).
             (Immediate::Uninit, _) => Immediate::Uninit,
+            // If the field is uninhabited, we can forget the data (can happen in ConstProp).
+            // `enum S { A(!), B, C }` is an example of an enum with Scalar layout that
+            // has an `Uninhabited` variant, which means this case is possible.
+            _ if layout.abi.is_uninhabited() => Immediate::Uninit,
             // the field contains no information, can be left uninit
             // (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST)
             _ if layout.is_zst() => Immediate::Uninit,
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index bd60e066f72..3a441c1d649 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -201,25 +201,8 @@ where
         // see https://github.com/rust-lang/rust/issues/93688#issuecomment-1032929496.)
         // So we just "offset" by 0.
         let layout = base.layout().for_variant(self, variant);
-        // In the future we might want to allow this to permit code like this:
-        // (this is a Rust/MIR pseudocode mix)
-        // ```
-        // enum Option2 {
-        //   Some(i32, !),
-        //   None,
-        // }
-        //
-        // fn panic() -> ! { panic!() }
-        //
-        // let x: Option2;
-        // x.Some.0 = 42;
-        // x.Some.1 = panic();
-        // SetDiscriminant(x, Some);
-        // ```
-        // However, for now we don't generate such MIR, and this check here *has* found real
-        // bugs (see https://github.com/rust-lang/rust/issues/115145), so we will keep rejecting
-        // it.
-        assert!(!layout.abi.is_uninhabited());
+        // This variant may in fact be uninhabited.
+        // See <https://github.com/rust-lang/rust/issues/120337>.
 
         // This cannot be `transmute` as variants *can* have a smaller size than the entire enum.
         base.offset(Size::ZERO, layout, self)
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 39bc2b960e9..fb705d91977 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -2,7 +2,7 @@
 
 use hir::def_id::LocalDefId;
 use hir::{ConstContext, LangItem};
-use rustc_errors::{error_code, DiagnosticBuilder};
+use rustc_errors::{codes::*, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
@@ -372,7 +372,7 @@ impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
         ccx.dcx().create_err(errors::UnallowedHeapAllocations {
             span,
             kind: ccx.const_kind(),
-            teach: ccx.tcx.sess.teach(&error_code!(E0010)).then_some(()),
+            teach: ccx.tcx.sess.teach(E0010).then_some(()),
         })
     }
 }
@@ -434,14 +434,14 @@ impl<'tcx> NonConstOp<'tcx> for CellBorrow {
                 span,
                 opt_help: Some(()),
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
+                teach: ccx.tcx.sess.teach(E0492).then_some(()),
             })
         } else {
             ccx.dcx().create_err(errors::InteriorMutableDataRefer {
                 span,
                 opt_help: None,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(&error_code!(E0492)).then_some(()),
+                teach: ccx.tcx.sess.teach(E0492).then_some(()),
             })
         }
     }
@@ -469,12 +469,12 @@ impl<'tcx> NonConstOp<'tcx> for MutBorrow {
             hir::BorrowKind::Raw => ccx.tcx.dcx().create_err(errors::UnallowedMutableRaw {
                 span,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
+                teach: ccx.tcx.sess.teach(E0764).then_some(()),
             }),
             hir::BorrowKind::Ref => ccx.dcx().create_err(errors::UnallowedMutableRefs {
                 span,
                 kind: ccx.const_kind(),
-                teach: ccx.tcx.sess.teach(&error_code!(E0764)).then_some(()),
+                teach: ccx.tcx.sess.teach(E0764).then_some(()),
             }),
         }
     }
@@ -588,7 +588,7 @@ impl<'tcx> NonConstOp<'tcx> for StaticAccess {
         ccx.dcx().create_err(errors::StaticAccessErr {
             span,
             kind: ccx.const_kind(),
-            teach: ccx.tcx.sess.teach(&error_code!(E0013)).then_some(()),
+            teach: ccx.tcx.sess.teach(E0013).then_some(()),
         })
     }
 }
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 5564902396e..21bdb66a276 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -810,13 +810,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     let adt_def = self.tcx.adt_def(def_id);
                     assert!(adt_def.is_union());
                     assert_eq!(idx, FIRST_VARIANT);
-                    let dest = adt_def.non_enum_variant().fields[field].ty(self.tcx, args);
-                    if fields.len() != 1 {
+                    let dest_ty = self.tcx.normalize_erasing_regions(
+                        self.param_env,
+                        adt_def.non_enum_variant().fields[field].ty(self.tcx, args),
+                    );
+                    if fields.len() == 1 {
+                        let src_ty = fields.raw[0].ty(self.body, self.tcx);
+                        if !self.mir_assign_valid_types(src_ty, dest_ty) {
+                            self.fail(location, "union field has the wrong type");
+                        }
+                    } else {
                         self.fail(location, "unions should have one initialized field");
                     }
-                    if !self.mir_assign_valid_types(fields.raw[0].ty(self.body, self.tcx), dest) {
-                        self.fail(location, "union field has the wrong type");
-                    }
                 }
                 AggregateKind::Adt(def_id, idx, args, _, None) => {
                     let adt_def = self.tcx.adt_def(def_id);
@@ -826,10 +831,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                         self.fail(location, "adt has the wrong number of initialized fields");
                     }
                     for (src, dest) in std::iter::zip(fields, &variant.fields) {
-                        if !self.mir_assign_valid_types(
-                            src.ty(self.body, self.tcx),
-                            dest.ty(self.tcx, args),
-                        ) {
+                        let dest_ty = self
+                            .tcx
+                            .normalize_erasing_regions(self.param_env, dest.ty(self.tcx, args));
+                        if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest_ty) {
                             self.fail(location, "adt field has the wrong type");
                         }
                     }
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 97a7dfef3b3..bfdd871455c 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -15,7 +15,6 @@ rustc_builtin_macros = { path = "../rustc_builtin_macros" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_const_eval = { path = "../rustc_const_eval" }
 rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_error_codes = { path = "../rustc_error_codes" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_expand = { path = "../rustc_expand" }
 rustc_feature = { path = "../rustc_feature" }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 09e627fa7a3..5903c43ae98 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -23,9 +23,8 @@ use rustc_codegen_ssa::{traits::CodegenBackend, CodegenErrors, CodegenResults};
 use rustc_data_structures::profiling::{
     get_resident_set_size, print_time_passes_entry, TimePassesFormat,
 };
-use rustc_errors::registry::{InvalidErrorCode, Registry};
-use rustc_errors::{markdown, ColorConfig};
-use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult};
+use rustc_errors::registry::Registry;
+use rustc_errors::{markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, PResult};
 use rustc_feature::find_gated_cfg;
 use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
 use rustc_interface::{interface, Queries};
@@ -207,7 +206,7 @@ impl Callbacks for TimePassesCallbacks {
 }
 
 pub fn diagnostics_registry() -> Registry {
-    Registry::new(rustc_error_codes::DIAGNOSTICS)
+    Registry::new(rustc_errors::codes::DIAGNOSTICS)
 }
 
 /// This is the primary entry point for rustc.
@@ -535,37 +534,36 @@ pub enum Compilation {
 }
 
 fn handle_explain(early_dcx: &EarlyDiagCtxt, registry: Registry, code: &str, color: ColorConfig) {
+    // Allow "E0123" or "0123" form.
     let upper_cased_code = code.to_ascii_uppercase();
-    let normalised =
-        if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
-    match registry.try_find_description(&normalised) {
-        Ok(description) => {
-            let mut is_in_code_block = false;
-            let mut text = String::new();
-            // Slice off the leading newline and print.
-            for line in description.lines() {
-                let indent_level =
-                    line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
-                let dedented_line = &line[indent_level..];
-                if dedented_line.starts_with("```") {
-                    is_in_code_block = !is_in_code_block;
-                    text.push_str(&line[..(indent_level + 3)]);
-                } else if is_in_code_block && dedented_line.starts_with("# ") {
-                    continue;
-                } else {
-                    text.push_str(line);
-                }
-                text.push('\n');
-            }
-            if io::stdout().is_terminal() {
-                show_md_content_with_pager(&text, color);
+    let start = if upper_cased_code.starts_with('E') { 1 } else { 0 };
+    if let Ok(code) = upper_cased_code[start..].parse::<u32>()
+        && let Ok(description) = registry.try_find_description(ErrCode::from_u32(code))
+    {
+        let mut is_in_code_block = false;
+        let mut text = String::new();
+        // Slice off the leading newline and print.
+        for line in description.lines() {
+            let indent_level =
+                line.find(|c: char| !c.is_whitespace()).unwrap_or_else(|| line.len());
+            let dedented_line = &line[indent_level..];
+            if dedented_line.starts_with("```") {
+                is_in_code_block = !is_in_code_block;
+                text.push_str(&line[..(indent_level + 3)]);
+            } else if is_in_code_block && dedented_line.starts_with("# ") {
+                continue;
             } else {
-                safe_print!("{text}");
+                text.push_str(line);
             }
+            text.push('\n');
         }
-        Err(InvalidErrorCode) => {
-            early_dcx.early_fatal(format!("{code} is not a valid error code"));
+        if io::stdout().is_terminal() {
+            show_md_content_with_pager(&text, color);
+        } else {
+            safe_print!("{text}");
         }
+    } else {
+        early_dcx.early_fatal(format!("{code} is not a valid error code"));
     }
 }
 
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
deleted file mode 100644
index 9cd9ed54d41..00000000000
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ /dev/null
@@ -1,658 +0,0 @@
-// Error messages for EXXXX errors. Each message should start and end with a
-// new line, and be wrapped to 80 characters. In vim you can `:set tw=80` and
-// use `gq` to wrap paragraphs. Use `:set tw=0` to disable.
-//
-// /!\ IMPORTANT /!\
-//
-// Error messages' format must follow the RFC 1567 available here:
-// https://rust-lang.github.io/rfcs/1567-long-error-codes-explanation-normalization.html
-
-register_diagnostics! {
-E0001: include_str!("./error_codes/E0001.md"),
-E0002: include_str!("./error_codes/E0002.md"),
-E0004: include_str!("./error_codes/E0004.md"),
-E0005: include_str!("./error_codes/E0005.md"),
-E0007: include_str!("./error_codes/E0007.md"),
-E0009: include_str!("./error_codes/E0009.md"),
-E0010: include_str!("./error_codes/E0010.md"),
-E0013: include_str!("./error_codes/E0013.md"),
-E0014: include_str!("./error_codes/E0014.md"),
-E0015: include_str!("./error_codes/E0015.md"),
-E0023: include_str!("./error_codes/E0023.md"),
-E0025: include_str!("./error_codes/E0025.md"),
-E0026: include_str!("./error_codes/E0026.md"),
-E0027: include_str!("./error_codes/E0027.md"),
-E0029: include_str!("./error_codes/E0029.md"),
-E0030: include_str!("./error_codes/E0030.md"),
-E0033: include_str!("./error_codes/E0033.md"),
-E0034: include_str!("./error_codes/E0034.md"),
-E0038: include_str!("./error_codes/E0038.md"),
-E0040: include_str!("./error_codes/E0040.md"),
-E0044: include_str!("./error_codes/E0044.md"),
-E0045: include_str!("./error_codes/E0045.md"),
-E0046: include_str!("./error_codes/E0046.md"),
-E0049: include_str!("./error_codes/E0049.md"),
-E0050: include_str!("./error_codes/E0050.md"),
-E0053: include_str!("./error_codes/E0053.md"),
-E0054: include_str!("./error_codes/E0054.md"),
-E0055: include_str!("./error_codes/E0055.md"),
-E0057: include_str!("./error_codes/E0057.md"),
-E0059: include_str!("./error_codes/E0059.md"),
-E0060: include_str!("./error_codes/E0060.md"),
-E0061: include_str!("./error_codes/E0061.md"),
-E0062: include_str!("./error_codes/E0062.md"),
-E0063: include_str!("./error_codes/E0063.md"),
-E0067: include_str!("./error_codes/E0067.md"),
-E0069: include_str!("./error_codes/E0069.md"),
-E0070: include_str!("./error_codes/E0070.md"),
-E0071: include_str!("./error_codes/E0071.md"),
-E0072: include_str!("./error_codes/E0072.md"),
-E0073: include_str!("./error_codes/E0073.md"),
-E0074: include_str!("./error_codes/E0074.md"),
-E0075: include_str!("./error_codes/E0075.md"),
-E0076: include_str!("./error_codes/E0076.md"),
-E0077: include_str!("./error_codes/E0077.md"),
-E0080: include_str!("./error_codes/E0080.md"),
-E0081: include_str!("./error_codes/E0081.md"),
-E0084: include_str!("./error_codes/E0084.md"),
-E0087: include_str!("./error_codes/E0087.md"),
-E0088: include_str!("./error_codes/E0088.md"),
-E0089: include_str!("./error_codes/E0089.md"),
-E0090: include_str!("./error_codes/E0090.md"),
-E0091: include_str!("./error_codes/E0091.md"),
-E0092: include_str!("./error_codes/E0092.md"),
-E0093: include_str!("./error_codes/E0093.md"),
-E0094: include_str!("./error_codes/E0094.md"),
-E0106: include_str!("./error_codes/E0106.md"),
-E0107: include_str!("./error_codes/E0107.md"),
-E0109: include_str!("./error_codes/E0109.md"),
-E0110: include_str!("./error_codes/E0110.md"),
-E0116: include_str!("./error_codes/E0116.md"),
-E0117: include_str!("./error_codes/E0117.md"),
-E0118: include_str!("./error_codes/E0118.md"),
-E0119: include_str!("./error_codes/E0119.md"),
-E0120: include_str!("./error_codes/E0120.md"),
-E0121: include_str!("./error_codes/E0121.md"),
-E0124: include_str!("./error_codes/E0124.md"),
-E0128: include_str!("./error_codes/E0128.md"),
-E0130: include_str!("./error_codes/E0130.md"),
-E0131: include_str!("./error_codes/E0131.md"),
-E0132: include_str!("./error_codes/E0132.md"),
-E0133: include_str!("./error_codes/E0133.md"),
-E0136: include_str!("./error_codes/E0136.md"),
-E0137: include_str!("./error_codes/E0137.md"),
-E0138: include_str!("./error_codes/E0138.md"),
-E0139: include_str!("./error_codes/E0139.md"),
-E0152: include_str!("./error_codes/E0152.md"),
-E0154: include_str!("./error_codes/E0154.md"),
-E0158: include_str!("./error_codes/E0158.md"),
-E0161: include_str!("./error_codes/E0161.md"),
-E0162: include_str!("./error_codes/E0162.md"),
-E0164: include_str!("./error_codes/E0164.md"),
-E0165: include_str!("./error_codes/E0165.md"),
-E0170: include_str!("./error_codes/E0170.md"),
-E0178: include_str!("./error_codes/E0178.md"),
-E0183: include_str!("./error_codes/E0183.md"),
-E0184: include_str!("./error_codes/E0184.md"),
-E0185: include_str!("./error_codes/E0185.md"),
-E0186: include_str!("./error_codes/E0186.md"),
-E0191: include_str!("./error_codes/E0191.md"),
-E0192: include_str!("./error_codes/E0192.md"),
-E0193: include_str!("./error_codes/E0193.md"),
-E0195: include_str!("./error_codes/E0195.md"),
-E0197: include_str!("./error_codes/E0197.md"),
-E0198: include_str!("./error_codes/E0198.md"),
-E0199: include_str!("./error_codes/E0199.md"),
-E0200: include_str!("./error_codes/E0200.md"),
-E0201: include_str!("./error_codes/E0201.md"),
-E0203: include_str!("./error_codes/E0203.md"),
-E0204: include_str!("./error_codes/E0204.md"),
-E0205: include_str!("./error_codes/E0205.md"),
-E0206: include_str!("./error_codes/E0206.md"),
-E0207: include_str!("./error_codes/E0207.md"),
-E0208: include_str!("./error_codes/E0208.md"),
-E0210: include_str!("./error_codes/E0210.md"),
-E0211: include_str!("./error_codes/E0211.md"),
-E0212: include_str!("./error_codes/E0212.md"),
-E0214: include_str!("./error_codes/E0214.md"),
-E0220: include_str!("./error_codes/E0220.md"),
-E0221: include_str!("./error_codes/E0221.md"),
-E0222: include_str!("./error_codes/E0222.md"),
-E0223: include_str!("./error_codes/E0223.md"),
-E0224: include_str!("./error_codes/E0224.md"),
-E0225: include_str!("./error_codes/E0225.md"),
-E0226: include_str!("./error_codes/E0226.md"),
-E0227: include_str!("./error_codes/E0227.md"),
-E0228: include_str!("./error_codes/E0228.md"),
-E0229: include_str!("./error_codes/E0229.md"),
-E0230: include_str!("./error_codes/E0230.md"),
-E0231: include_str!("./error_codes/E0231.md"),
-E0232: include_str!("./error_codes/E0232.md"),
-E0243: include_str!("./error_codes/E0243.md"),
-E0244: include_str!("./error_codes/E0244.md"),
-E0251: include_str!("./error_codes/E0251.md"),
-E0252: include_str!("./error_codes/E0252.md"),
-E0253: include_str!("./error_codes/E0253.md"),
-E0254: include_str!("./error_codes/E0254.md"),
-E0255: include_str!("./error_codes/E0255.md"),
-E0256: include_str!("./error_codes/E0256.md"),
-E0259: include_str!("./error_codes/E0259.md"),
-E0260: include_str!("./error_codes/E0260.md"),
-E0261: include_str!("./error_codes/E0261.md"),
-E0262: include_str!("./error_codes/E0262.md"),
-E0263: include_str!("./error_codes/E0263.md"),
-E0264: include_str!("./error_codes/E0264.md"),
-E0267: include_str!("./error_codes/E0267.md"),
-E0268: include_str!("./error_codes/E0268.md"),
-E0271: include_str!("./error_codes/E0271.md"),
-E0275: include_str!("./error_codes/E0275.md"),
-E0276: include_str!("./error_codes/E0276.md"),
-E0277: include_str!("./error_codes/E0277.md"),
-E0281: include_str!("./error_codes/E0281.md"),
-E0282: include_str!("./error_codes/E0282.md"),
-E0283: include_str!("./error_codes/E0283.md"),
-E0284: include_str!("./error_codes/E0284.md"),
-E0297: include_str!("./error_codes/E0297.md"),
-E0301: include_str!("./error_codes/E0301.md"),
-E0302: include_str!("./error_codes/E0302.md"),
-E0303: include_str!("./error_codes/E0303.md"),
-E0307: include_str!("./error_codes/E0307.md"),
-E0308: include_str!("./error_codes/E0308.md"),
-E0309: include_str!("./error_codes/E0309.md"),
-E0310: include_str!("./error_codes/E0310.md"),
-E0311: include_str!("./error_codes/E0311.md"),
-E0312: include_str!("./error_codes/E0312.md"),
-E0316: include_str!("./error_codes/E0316.md"),
-E0317: include_str!("./error_codes/E0317.md"),
-E0320: include_str!("./error_codes/E0320.md"),
-E0321: include_str!("./error_codes/E0321.md"),
-E0322: include_str!("./error_codes/E0322.md"),
-E0323: include_str!("./error_codes/E0323.md"),
-E0324: include_str!("./error_codes/E0324.md"),
-E0325: include_str!("./error_codes/E0325.md"),
-E0326: include_str!("./error_codes/E0326.md"),
-E0328: include_str!("./error_codes/E0328.md"),
-E0329: include_str!("./error_codes/E0329.md"),
-E0364: include_str!("./error_codes/E0364.md"),
-E0365: include_str!("./error_codes/E0365.md"),
-E0366: include_str!("./error_codes/E0366.md"),
-E0367: include_str!("./error_codes/E0367.md"),
-E0368: include_str!("./error_codes/E0368.md"),
-E0369: include_str!("./error_codes/E0369.md"),
-E0370: include_str!("./error_codes/E0370.md"),
-E0371: include_str!("./error_codes/E0371.md"),
-E0373: include_str!("./error_codes/E0373.md"),
-E0374: include_str!("./error_codes/E0374.md"),
-E0375: include_str!("./error_codes/E0375.md"),
-E0376: include_str!("./error_codes/E0376.md"),
-E0377: include_str!("./error_codes/E0377.md"),
-E0378: include_str!("./error_codes/E0378.md"),
-E0379: include_str!("./error_codes/E0379.md"),
-E0380: include_str!("./error_codes/E0380.md"),
-E0381: include_str!("./error_codes/E0381.md"),
-E0382: include_str!("./error_codes/E0382.md"),
-E0383: include_str!("./error_codes/E0383.md"),
-E0384: include_str!("./error_codes/E0384.md"),
-E0386: include_str!("./error_codes/E0386.md"),
-E0387: include_str!("./error_codes/E0387.md"),
-E0388: include_str!("./error_codes/E0388.md"),
-E0389: include_str!("./error_codes/E0389.md"),
-E0390: include_str!("./error_codes/E0390.md"),
-E0391: include_str!("./error_codes/E0391.md"),
-E0392: include_str!("./error_codes/E0392.md"),
-E0393: include_str!("./error_codes/E0393.md"),
-E0398: include_str!("./error_codes/E0398.md"),
-E0399: include_str!("./error_codes/E0399.md"),
-E0401: include_str!("./error_codes/E0401.md"),
-E0403: include_str!("./error_codes/E0403.md"),
-E0404: include_str!("./error_codes/E0404.md"),
-E0405: include_str!("./error_codes/E0405.md"),
-E0407: include_str!("./error_codes/E0407.md"),
-E0408: include_str!("./error_codes/E0408.md"),
-E0409: include_str!("./error_codes/E0409.md"),
-E0411: include_str!("./error_codes/E0411.md"),
-E0412: include_str!("./error_codes/E0412.md"),
-E0415: include_str!("./error_codes/E0415.md"),
-E0416: include_str!("./error_codes/E0416.md"),
-E0422: include_str!("./error_codes/E0422.md"),
-E0423: include_str!("./error_codes/E0423.md"),
-E0424: include_str!("./error_codes/E0424.md"),
-E0425: include_str!("./error_codes/E0425.md"),
-E0426: include_str!("./error_codes/E0426.md"),
-E0428: include_str!("./error_codes/E0428.md"),
-E0429: include_str!("./error_codes/E0429.md"),
-E0430: include_str!("./error_codes/E0430.md"),
-E0431: include_str!("./error_codes/E0431.md"),
-E0432: include_str!("./error_codes/E0432.md"),
-E0433: include_str!("./error_codes/E0433.md"),
-E0434: include_str!("./error_codes/E0434.md"),
-E0435: include_str!("./error_codes/E0435.md"),
-E0436: include_str!("./error_codes/E0436.md"),
-E0437: include_str!("./error_codes/E0437.md"),
-E0438: include_str!("./error_codes/E0438.md"),
-E0439: include_str!("./error_codes/E0439.md"),
-E0445: include_str!("./error_codes/E0445.md"),
-E0446: include_str!("./error_codes/E0446.md"),
-E0447: include_str!("./error_codes/E0447.md"),
-E0448: include_str!("./error_codes/E0448.md"),
-E0449: include_str!("./error_codes/E0449.md"),
-E0451: include_str!("./error_codes/E0451.md"),
-E0452: include_str!("./error_codes/E0452.md"),
-E0453: include_str!("./error_codes/E0453.md"),
-E0454: include_str!("./error_codes/E0454.md"),
-E0455: include_str!("./error_codes/E0455.md"),
-E0457: include_str!("./error_codes/E0457.md"),
-E0458: include_str!("./error_codes/E0458.md"),
-E0459: include_str!("./error_codes/E0459.md"),
-E0460: include_str!("./error_codes/E0460.md"),
-E0461: include_str!("./error_codes/E0461.md"),
-E0462: include_str!("./error_codes/E0462.md"),
-E0463: include_str!("./error_codes/E0463.md"),
-E0464: include_str!("./error_codes/E0464.md"),
-E0466: include_str!("./error_codes/E0466.md"),
-E0468: include_str!("./error_codes/E0468.md"),
-E0469: include_str!("./error_codes/E0469.md"),
-E0472: include_str!("./error_codes/E0472.md"),
-E0476: include_str!("./error_codes/E0476.md"),
-E0477: include_str!("./error_codes/E0477.md"),
-E0478: include_str!("./error_codes/E0478.md"),
-E0482: include_str!("./error_codes/E0482.md"),
-E0491: include_str!("./error_codes/E0491.md"),
-E0492: include_str!("./error_codes/E0492.md"),
-E0493: include_str!("./error_codes/E0493.md"),
-E0495: include_str!("./error_codes/E0495.md"),
-E0496: include_str!("./error_codes/E0496.md"),
-E0497: include_str!("./error_codes/E0497.md"),
-E0498: include_str!("./error_codes/E0498.md"),
-E0499: include_str!("./error_codes/E0499.md"),
-E0500: include_str!("./error_codes/E0500.md"),
-E0501: include_str!("./error_codes/E0501.md"),
-E0502: include_str!("./error_codes/E0502.md"),
-E0503: include_str!("./error_codes/E0503.md"),
-E0504: include_str!("./error_codes/E0504.md"),
-E0505: include_str!("./error_codes/E0505.md"),
-E0506: include_str!("./error_codes/E0506.md"),
-E0507: include_str!("./error_codes/E0507.md"),
-E0508: include_str!("./error_codes/E0508.md"),
-E0509: include_str!("./error_codes/E0509.md"),
-E0510: include_str!("./error_codes/E0510.md"),
-E0511: include_str!("./error_codes/E0511.md"),
-E0512: include_str!("./error_codes/E0512.md"),
-E0514: include_str!("./error_codes/E0514.md"),
-E0515: include_str!("./error_codes/E0515.md"),
-E0516: include_str!("./error_codes/E0516.md"),
-E0517: include_str!("./error_codes/E0517.md"),
-E0518: include_str!("./error_codes/E0518.md"),
-E0519: include_str!("./error_codes/E0519.md"),
-E0520: include_str!("./error_codes/E0520.md"),
-E0521: include_str!("./error_codes/E0521.md"),
-E0522: include_str!("./error_codes/E0522.md"),
-E0523: include_str!("./error_codes/E0523.md"),
-E0524: include_str!("./error_codes/E0524.md"),
-E0525: include_str!("./error_codes/E0525.md"),
-E0527: include_str!("./error_codes/E0527.md"),
-E0528: include_str!("./error_codes/E0528.md"),
-E0529: include_str!("./error_codes/E0529.md"),
-E0530: include_str!("./error_codes/E0530.md"),
-E0531: include_str!("./error_codes/E0531.md"),
-E0532: include_str!("./error_codes/E0532.md"),
-E0533: include_str!("./error_codes/E0533.md"),
-E0534: include_str!("./error_codes/E0534.md"),
-E0535: include_str!("./error_codes/E0535.md"),
-E0536: include_str!("./error_codes/E0536.md"),
-E0537: include_str!("./error_codes/E0537.md"),
-E0538: include_str!("./error_codes/E0538.md"),
-E0539: include_str!("./error_codes/E0539.md"),
-E0541: include_str!("./error_codes/E0541.md"),
-E0542: include_str!("./error_codes/E0542.md"),
-E0543: include_str!("./error_codes/E0543.md"),
-E0544: include_str!("./error_codes/E0544.md"),
-E0545: include_str!("./error_codes/E0545.md"),
-E0546: include_str!("./error_codes/E0546.md"),
-E0547: include_str!("./error_codes/E0547.md"),
-E0549: include_str!("./error_codes/E0549.md"),
-E0550: include_str!("./error_codes/E0550.md"),
-E0551: include_str!("./error_codes/E0551.md"),
-E0552: include_str!("./error_codes/E0552.md"),
-E0554: include_str!("./error_codes/E0554.md"),
-E0556: include_str!("./error_codes/E0556.md"),
-E0557: include_str!("./error_codes/E0557.md"),
-E0559: include_str!("./error_codes/E0559.md"),
-E0560: include_str!("./error_codes/E0560.md"),
-E0561: include_str!("./error_codes/E0561.md"),
-E0562: include_str!("./error_codes/E0562.md"),
-E0565: include_str!("./error_codes/E0565.md"),
-E0566: include_str!("./error_codes/E0566.md"),
-E0567: include_str!("./error_codes/E0567.md"),
-E0568: include_str!("./error_codes/E0568.md"),
-E0569: include_str!("./error_codes/E0569.md"),
-E0570: include_str!("./error_codes/E0570.md"),
-E0571: include_str!("./error_codes/E0571.md"),
-E0572: include_str!("./error_codes/E0572.md"),
-E0573: include_str!("./error_codes/E0573.md"),
-E0574: include_str!("./error_codes/E0574.md"),
-E0575: include_str!("./error_codes/E0575.md"),
-E0576: include_str!("./error_codes/E0576.md"),
-E0577: include_str!("./error_codes/E0577.md"),
-E0578: include_str!("./error_codes/E0578.md"),
-E0579: include_str!("./error_codes/E0579.md"),
-E0580: include_str!("./error_codes/E0580.md"),
-E0581: include_str!("./error_codes/E0581.md"),
-E0582: include_str!("./error_codes/E0582.md"),
-E0583: include_str!("./error_codes/E0583.md"),
-E0584: include_str!("./error_codes/E0584.md"),
-E0585: include_str!("./error_codes/E0585.md"),
-E0586: include_str!("./error_codes/E0586.md"),
-E0587: include_str!("./error_codes/E0587.md"),
-E0588: include_str!("./error_codes/E0588.md"),
-E0589: include_str!("./error_codes/E0589.md"),
-E0590: include_str!("./error_codes/E0590.md"),
-E0591: include_str!("./error_codes/E0591.md"),
-E0592: include_str!("./error_codes/E0592.md"),
-E0593: include_str!("./error_codes/E0593.md"),
-E0594: include_str!("./error_codes/E0594.md"),
-E0595: include_str!("./error_codes/E0595.md"),
-E0596: include_str!("./error_codes/E0596.md"),
-E0597: include_str!("./error_codes/E0597.md"),
-E0599: include_str!("./error_codes/E0599.md"),
-E0600: include_str!("./error_codes/E0600.md"),
-E0601: include_str!("./error_codes/E0601.md"),
-E0602: include_str!("./error_codes/E0602.md"),
-E0603: include_str!("./error_codes/E0603.md"),
-E0604: include_str!("./error_codes/E0604.md"),
-E0605: include_str!("./error_codes/E0605.md"),
-E0606: include_str!("./error_codes/E0606.md"),
-E0607: include_str!("./error_codes/E0607.md"),
-E0608: include_str!("./error_codes/E0608.md"),
-E0609: include_str!("./error_codes/E0609.md"),
-E0610: include_str!("./error_codes/E0610.md"),
-E0614: include_str!("./error_codes/E0614.md"),
-E0615: include_str!("./error_codes/E0615.md"),
-E0616: include_str!("./error_codes/E0616.md"),
-E0617: include_str!("./error_codes/E0617.md"),
-E0618: include_str!("./error_codes/E0618.md"),
-E0619: include_str!("./error_codes/E0619.md"),
-E0620: include_str!("./error_codes/E0620.md"),
-E0621: include_str!("./error_codes/E0621.md"),
-E0622: include_str!("./error_codes/E0622.md"),
-E0623: include_str!("./error_codes/E0623.md"),
-E0624: include_str!("./error_codes/E0624.md"),
-E0625: include_str!("./error_codes/E0625.md"),
-E0626: include_str!("./error_codes/E0626.md"),
-E0627: include_str!("./error_codes/E0627.md"),
-E0628: include_str!("./error_codes/E0628.md"),
-E0631: include_str!("./error_codes/E0631.md"),
-E0632: include_str!("./error_codes/E0632.md"),
-E0633: include_str!("./error_codes/E0633.md"),
-E0634: include_str!("./error_codes/E0634.md"),
-E0635: include_str!("./error_codes/E0635.md"),
-E0636: include_str!("./error_codes/E0636.md"),
-E0637: include_str!("./error_codes/E0637.md"),
-E0638: include_str!("./error_codes/E0638.md"),
-E0639: include_str!("./error_codes/E0639.md"),
-E0640: include_str!("./error_codes/E0640.md"),
-E0641: include_str!("./error_codes/E0641.md"),
-E0642: include_str!("./error_codes/E0642.md"),
-E0643: include_str!("./error_codes/E0643.md"),
-E0644: include_str!("./error_codes/E0644.md"),
-E0646: include_str!("./error_codes/E0646.md"),
-E0647: include_str!("./error_codes/E0647.md"),
-E0648: include_str!("./error_codes/E0648.md"),
-E0657: include_str!("./error_codes/E0657.md"),
-E0658: include_str!("./error_codes/E0658.md"),
-E0659: include_str!("./error_codes/E0659.md"),
-E0660: include_str!("./error_codes/E0660.md"),
-E0661: include_str!("./error_codes/E0661.md"),
-E0662: include_str!("./error_codes/E0662.md"),
-E0663: include_str!("./error_codes/E0663.md"),
-E0664: include_str!("./error_codes/E0664.md"),
-E0665: include_str!("./error_codes/E0665.md"),
-E0666: include_str!("./error_codes/E0666.md"),
-E0667: include_str!("./error_codes/E0667.md"),
-E0668: include_str!("./error_codes/E0668.md"),
-E0669: include_str!("./error_codes/E0669.md"),
-E0670: include_str!("./error_codes/E0670.md"),
-E0671: include_str!("./error_codes/E0671.md"),
-E0687: include_str!("./error_codes/E0687.md"),
-E0688: include_str!("./error_codes/E0688.md"),
-E0689: include_str!("./error_codes/E0689.md"),
-E0690: include_str!("./error_codes/E0690.md"),
-E0691: include_str!("./error_codes/E0691.md"),
-E0692: include_str!("./error_codes/E0692.md"),
-E0693: include_str!("./error_codes/E0693.md"),
-E0695: include_str!("./error_codes/E0695.md"),
-E0696: include_str!("./error_codes/E0696.md"),
-E0697: include_str!("./error_codes/E0697.md"),
-E0698: include_str!("./error_codes/E0698.md"),
-E0699: include_str!("./error_codes/E0699.md"),
-E0700: include_str!("./error_codes/E0700.md"),
-E0701: include_str!("./error_codes/E0701.md"),
-E0703: include_str!("./error_codes/E0703.md"),
-E0704: include_str!("./error_codes/E0704.md"),
-E0705: include_str!("./error_codes/E0705.md"),
-E0706: include_str!("./error_codes/E0706.md"),
-E0708: include_str!("./error_codes/E0708.md"),
-E0710: include_str!("./error_codes/E0710.md"),
-E0712: include_str!("./error_codes/E0712.md"),
-E0713: include_str!("./error_codes/E0713.md"),
-E0714: include_str!("./error_codes/E0714.md"),
-E0715: include_str!("./error_codes/E0715.md"),
-E0716: include_str!("./error_codes/E0716.md"),
-E0711: include_str!("./error_codes/E0711.md"),
-E0717: include_str!("./error_codes/E0717.md"),
-E0718: include_str!("./error_codes/E0718.md"),
-E0719: include_str!("./error_codes/E0719.md"),
-E0720: include_str!("./error_codes/E0720.md"),
-E0722: include_str!("./error_codes/E0722.md"),
-E0724: include_str!("./error_codes/E0724.md"),
-E0725: include_str!("./error_codes/E0725.md"),
-E0726: include_str!("./error_codes/E0726.md"),
-E0727: include_str!("./error_codes/E0727.md"),
-E0728: include_str!("./error_codes/E0728.md"),
-E0729: include_str!("./error_codes/E0729.md"),
-E0730: include_str!("./error_codes/E0730.md"),
-E0731: include_str!("./error_codes/E0731.md"),
-E0732: include_str!("./error_codes/E0732.md"),
-E0733: include_str!("./error_codes/E0733.md"),
-E0734: include_str!("./error_codes/E0734.md"),
-E0735: include_str!("./error_codes/E0735.md"),
-E0736: include_str!("./error_codes/E0736.md"),
-E0737: include_str!("./error_codes/E0737.md"),
-E0739: include_str!("./error_codes/E0739.md"),
-E0740: include_str!("./error_codes/E0740.md"),
-E0741: include_str!("./error_codes/E0741.md"),
-E0742: include_str!("./error_codes/E0742.md"),
-E0743: include_str!("./error_codes/E0743.md"),
-E0744: include_str!("./error_codes/E0744.md"),
-E0745: include_str!("./error_codes/E0745.md"),
-E0746: include_str!("./error_codes/E0746.md"),
-E0747: include_str!("./error_codes/E0747.md"),
-E0748: include_str!("./error_codes/E0748.md"),
-E0749: include_str!("./error_codes/E0749.md"),
-E0750: include_str!("./error_codes/E0750.md"),
-E0751: include_str!("./error_codes/E0751.md"),
-E0752: include_str!("./error_codes/E0752.md"),
-E0753: include_str!("./error_codes/E0753.md"),
-E0754: include_str!("./error_codes/E0754.md"),
-E0755: include_str!("./error_codes/E0755.md"),
-E0756: include_str!("./error_codes/E0756.md"),
-E0757: include_str!("./error_codes/E0757.md"),
-E0758: include_str!("./error_codes/E0758.md"),
-E0759: include_str!("./error_codes/E0759.md"),
-E0760: include_str!("./error_codes/E0760.md"),
-E0761: include_str!("./error_codes/E0761.md"),
-E0762: include_str!("./error_codes/E0762.md"),
-E0763: include_str!("./error_codes/E0763.md"),
-E0764: include_str!("./error_codes/E0764.md"),
-E0765: include_str!("./error_codes/E0765.md"),
-E0766: include_str!("./error_codes/E0766.md"),
-E0767: include_str!("./error_codes/E0767.md"),
-E0768: include_str!("./error_codes/E0768.md"),
-E0769: include_str!("./error_codes/E0769.md"),
-E0770: include_str!("./error_codes/E0770.md"),
-E0771: include_str!("./error_codes/E0771.md"),
-E0772: include_str!("./error_codes/E0772.md"),
-E0773: include_str!("./error_codes/E0773.md"),
-E0774: include_str!("./error_codes/E0774.md"),
-E0775: include_str!("./error_codes/E0775.md"),
-E0776: include_str!("./error_codes/E0776.md"),
-E0777: include_str!("./error_codes/E0777.md"),
-E0778: include_str!("./error_codes/E0778.md"),
-E0779: include_str!("./error_codes/E0779.md"),
-E0780: include_str!("./error_codes/E0780.md"),
-E0781: include_str!("./error_codes/E0781.md"),
-E0782: include_str!("./error_codes/E0782.md"),
-E0783: include_str!("./error_codes/E0783.md"),
-E0784: include_str!("./error_codes/E0784.md"),
-E0785: include_str!("./error_codes/E0785.md"),
-E0786: include_str!("./error_codes/E0786.md"),
-E0787: include_str!("./error_codes/E0787.md"),
-E0788: include_str!("./error_codes/E0788.md"),
-E0789: include_str!("./error_codes/E0789.md"),
-E0790: include_str!("./error_codes/E0790.md"),
-E0791: include_str!("./error_codes/E0791.md"),
-E0792: include_str!("./error_codes/E0792.md"),
-E0793: include_str!("./error_codes/E0793.md"),
-E0794: include_str!("./error_codes/E0794.md"),
-E0795: include_str!("./error_codes/E0795.md"),
-E0796: include_str!("./error_codes/E0796.md"),
-E0797: include_str!("./error_codes/E0797.md"),
-}
-
-// Undocumented removed error codes. Note that many removed error codes are kept in the list above
-// and marked as no-longer emitted with a note in the markdown file (see E0001 for an example).
-//  E0006, // merged with E0005
-//  E0008, // cannot bind by-move into a pattern guard
-//  E0019, // merged into E0015
-//  E0035, // merged into E0087/E0089
-//  E0036, // merged into E0087/E0089
-//  E0068,
-//  E0085,
-//  E0086,
-//  E0101, // replaced with E0282
-//  E0102, // replaced with E0282
-//  E0103,
-//  E0104,
-//  E0122, // bounds in type aliases are ignored, turned into proper lint
-//  E0123,
-//  E0127,
-//  E0129,
-//  E0134,
-//  E0135,
-//  E0141,
-//  E0153, // unused error code
-//  E0157, // unused error code
-//  E0159, // use of trait `{}` as struct constructor
-//  E0163, // merged into E0071
-//  E0167,
-//  E0168,
-//  E0172, // non-trait found in a type sum, moved to resolve
-//  E0173, // manual implementations of unboxed closure traits are experimental
-//  E0174,
-//  E0182, // merged into E0229
-//  E0187, // cannot infer the kind of the closure
-//  E0188, // can not cast an immutable reference to a mutable pointer
-//  E0189, // deprecated: can only cast a boxed pointer to a boxed object
-//  E0190, // deprecated: can only cast a &-pointer to an &-object
-//  E0194, // merged into E0403
-//  E0196, // cannot determine a type for this closure
-//  E0209, // builtin traits can only be implemented on structs or enums
-//  E0213, // associated types are not accepted in this context
-//  E0215, // angle-bracket notation is not stable with `Fn`
-//  E0216, // parenthetical notation is only stable with `Fn`
-//  E0217, // ambiguous associated type, defined in multiple supertraits
-//  E0218, // no associated type defined
-//  E0219, // associated type defined in higher-ranked supertrait
-//  E0233,
-//  E0234,
-//  E0235, // structure constructor specifies a structure of type but
-//  E0236, // no lang item for range syntax
-//  E0237, // no lang item for range syntax
-//  E0238, // parenthesized parameters may only be used with a trait
-//  E0239, // `next` method of `Iterator` trait has unexpected type
-//  E0240,
-//  E0241,
-//  E0242,
-//  E0245, // not a trait
-//  E0246, // invalid recursive type
-//  E0247,
-//  E0248, // value used as a type, now reported earlier during resolution
-//         // as E0412
-//  E0249,
-//  E0257,
-//  E0258,
-//  E0272, // on_unimplemented #0
-//  E0273, // on_unimplemented #1
-//  E0274, // on_unimplemented #2
-//  E0278, // requirement is not satisfied
-//  E0279,
-//  E0280, // changed to ICE
-//  E0285, // overflow evaluation builtin bounds
-//  E0296, // replaced with a generic attribute input check
-//  E0298, // cannot compare constants
-//  E0299, // mismatched types between arms
-//  E0300, // unexpanded macro
-//  E0304, // expected signed integer constant
-//  E0305, // expected constant
-//  E0313, // removed: found unreachable
-//  E0314, // closure outlives stack frame
-//  E0315, // cannot invoke closure outside of its lifetime
-//  E0319, // trait impls for defaulted traits allowed just for structs/enums
-//  E0372, // coherence not object safe
-//  E0385, // {} in an aliasable location
-//  E0402, // cannot use an outer type parameter in this context
-//  E0406, // merged into 420
-//  E0410, // merged into 408
-//  E0413, // merged into 530
-//  E0414, // merged into 530
-//  E0417, // merged into 532
-//  E0418, // merged into 532
-//  E0419, // merged into 531
-//  E0420, // merged into 532
-//  E0421, // merged into 531
-//  E0427, // merged into 530
-//  E0445, // merged into 446 and type privacy lints
-//  E0456, // plugin `..` is not available for triple `..`
-//  E0465, // removed: merged with E0464
-//  E0467, // removed
-//  E0470, // removed
-//  E0471, // constant evaluation error (in pattern)
-//  E0473, // dereference of reference outside its lifetime
-//  E0474, // captured variable `..` does not outlive the enclosing closure
-//  E0475, // index of slice outside its lifetime
-//  E0479, // the type `..` (provided as the value of a type parameter) is...
-//  E0480, // lifetime of method receiver does not outlive the method call
-//  E0481, // lifetime of function argument does not outlive the function call
-//  E0483, // lifetime of operand does not outlive the operation
-//  E0484, // reference is not valid at the time of borrow
-//  E0485, // automatically reference is not valid at the time of borrow
-//  E0486, // type of expression contains references that are not valid during..
-//  E0487, // unsafe use of destructor: destructor might be called while...
-//  E0488, // lifetime of variable does not enclose its declaration
-//  E0489, // type/lifetime parameter not in scope here
-//  E0490, // removed: unreachable
-//  E0526, // shuffle indices are not constant
-//  E0540, // multiple rustc_deprecated attributes
-//  E0548, // replaced with a generic attribute input check
-//  E0553, // multiple rustc_const_unstable attributes
-//  E0555, // replaced with a generic attribute input check
-//  E0558, // replaced with a generic attribute input check
-//  E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
-//  E0564, // only named lifetimes are allowed in `impl Trait`,
-//         // but `{}` was found in the type `{}`
-//  E0598, // lifetime of {} is too short to guarantee its contents can be...
-//  E0611, // merged into E0616
-//  E0612, // merged into E0609
-//  E0613, // Removed (merged with E0609)
-//  E0629, // missing 'feature' (rustc_const_unstable)
-//  E0630, // rustc_const_unstable attribute must be paired with stable/unstable
-//         // attribute
-//  E0645, // trait aliases not finished
-//  E0694, // an unknown tool name found in scoped attributes
-//  E0702, // replaced with a generic attribute input check
-//  E0707, // multiple elided lifetimes used in arguments of `async fn`
-//  E0709, // multiple different lifetimes used in arguments of `async fn`
-//  E0721, // `await` keyword
-//  E0723, // unstable feature in `const` context
-//  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
-//  E0744, // merged into E0728
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index dd281811636..5b2766618fc 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -1,19 +1,679 @@
+//! This library is used to gather all error codes into one place, to make
+//! their maintenance easier.
+
 #![allow(internal_features)]
 #![feature(rustdoc_internals)]
 #![doc(rust_logo)]
 #![deny(rustdoc::invalid_codeblock_attributes)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-//! This library is used to gather all error codes into one place,
-//! the goal being to make their maintenance easier.
 
-macro_rules! register_diagnostics {
-    ($($ecode:ident: $message:expr,)*) => (
-        pub static DIAGNOSTICS: &[(&str, &str)] = &[
-            $( (stringify!($ecode), $message), )*
-        ];
+// This higher-order macro defines the error codes that are in use. It is used
+// in the `rustc_errors` crate. Removed error codes are listed in the comment
+// below.
+//
+// /!\ IMPORTANT /!\
+//
+// Error code explanation are defined in `error_codes/EXXXX.md` files. They must follow the RFC
+// 1567 available here:
+// https://rust-lang.github.io/rfcs/1567-long-error-codes-explanation-normalization.html
+//
+// Also, the contents of this macro is checked by tidy (in `check_error_codes_docs`). If you change
+// the macro syntax you will need to change tidy as well.
+//
+// Both columns are necessary because it's not possible in Rust to create a new identifier such as
+// `E0123` from an integer literal such as `0123`, unfortunately.
+#[macro_export]
+macro_rules! error_codes {
+    ($macro:path) => (
+        $macro!(
+E0001: 0001,
+E0002: 0002,
+E0004: 0004,
+E0005: 0005,
+E0007: 0007,
+E0009: 0009,
+E0010: 0010,
+E0013: 0013,
+E0014: 0014,
+E0015: 0015,
+E0023: 0023,
+E0025: 0025,
+E0026: 0026,
+E0027: 0027,
+E0029: 0029,
+E0030: 0030,
+E0033: 0033,
+E0034: 0034,
+E0038: 0038,
+E0040: 0040,
+E0044: 0044,
+E0045: 0045,
+E0046: 0046,
+E0049: 0049,
+E0050: 0050,
+E0053: 0053,
+E0054: 0054,
+E0055: 0055,
+E0057: 0057,
+E0059: 0059,
+E0060: 0060,
+E0061: 0061,
+E0062: 0062,
+E0063: 0063,
+E0067: 0067,
+E0069: 0069,
+E0070: 0070,
+E0071: 0071,
+E0072: 0072,
+E0073: 0073,
+E0074: 0074,
+E0075: 0075,
+E0076: 0076,
+E0077: 0077,
+E0080: 0080,
+E0081: 0081,
+E0084: 0084,
+E0087: 0087,
+E0088: 0088,
+E0089: 0089,
+E0090: 0090,
+E0091: 0091,
+E0092: 0092,
+E0093: 0093,
+E0094: 0094,
+E0106: 0106,
+E0107: 0107,
+E0109: 0109,
+E0110: 0110,
+E0116: 0116,
+E0117: 0117,
+E0118: 0118,
+E0119: 0119,
+E0120: 0120,
+E0121: 0121,
+E0124: 0124,
+E0128: 0128,
+E0130: 0130,
+E0131: 0131,
+E0132: 0132,
+E0133: 0133,
+E0136: 0136,
+E0137: 0137,
+E0138: 0138,
+E0139: 0139,
+E0152: 0152,
+E0154: 0154,
+E0158: 0158,
+E0161: 0161,
+E0162: 0162,
+E0164: 0164,
+E0165: 0165,
+E0170: 0170,
+E0178: 0178,
+E0183: 0183,
+E0184: 0184,
+E0185: 0185,
+E0186: 0186,
+E0191: 0191,
+E0192: 0192,
+E0193: 0193,
+E0195: 0195,
+E0197: 0197,
+E0198: 0198,
+E0199: 0199,
+E0200: 0200,
+E0201: 0201,
+E0203: 0203,
+E0204: 0204,
+E0205: 0205,
+E0206: 0206,
+E0207: 0207,
+E0208: 0208,
+E0210: 0210,
+E0211: 0211,
+E0212: 0212,
+E0214: 0214,
+E0220: 0220,
+E0221: 0221,
+E0222: 0222,
+E0223: 0223,
+E0224: 0224,
+E0225: 0225,
+E0226: 0226,
+E0227: 0227,
+E0228: 0228,
+E0229: 0229,
+E0230: 0230,
+E0231: 0231,
+E0232: 0232,
+E0243: 0243,
+E0244: 0244,
+E0251: 0251,
+E0252: 0252,
+E0253: 0253,
+E0254: 0254,
+E0255: 0255,
+E0256: 0256,
+E0259: 0259,
+E0260: 0260,
+E0261: 0261,
+E0262: 0262,
+E0263: 0263,
+E0264: 0264,
+E0267: 0267,
+E0268: 0268,
+E0271: 0271,
+E0275: 0275,
+E0276: 0276,
+E0277: 0277,
+E0281: 0281,
+E0282: 0282,
+E0283: 0283,
+E0284: 0284,
+E0297: 0297,
+E0301: 0301,
+E0302: 0302,
+E0303: 0303,
+E0307: 0307,
+E0308: 0308,
+E0309: 0309,
+E0310: 0310,
+E0311: 0311,
+E0312: 0312,
+E0316: 0316,
+E0317: 0317,
+E0320: 0320,
+E0321: 0321,
+E0322: 0322,
+E0323: 0323,
+E0324: 0324,
+E0325: 0325,
+E0326: 0326,
+E0328: 0328,
+E0329: 0329,
+E0364: 0364,
+E0365: 0365,
+E0366: 0366,
+E0367: 0367,
+E0368: 0368,
+E0369: 0369,
+E0370: 0370,
+E0371: 0371,
+E0373: 0373,
+E0374: 0374,
+E0375: 0375,
+E0376: 0376,
+E0377: 0377,
+E0378: 0378,
+E0379: 0379,
+E0380: 0380,
+E0381: 0381,
+E0382: 0382,
+E0383: 0383,
+E0384: 0384,
+E0386: 0386,
+E0387: 0387,
+E0388: 0388,
+E0389: 0389,
+E0390: 0390,
+E0391: 0391,
+E0392: 0392,
+E0393: 0393,
+E0398: 0398,
+E0399: 0399,
+E0401: 0401,
+E0403: 0403,
+E0404: 0404,
+E0405: 0405,
+E0407: 0407,
+E0408: 0408,
+E0409: 0409,
+E0411: 0411,
+E0412: 0412,
+E0415: 0415,
+E0416: 0416,
+E0422: 0422,
+E0423: 0423,
+E0424: 0424,
+E0425: 0425,
+E0426: 0426,
+E0428: 0428,
+E0429: 0429,
+E0430: 0430,
+E0431: 0431,
+E0432: 0432,
+E0433: 0433,
+E0434: 0434,
+E0435: 0435,
+E0436: 0436,
+E0437: 0437,
+E0438: 0438,
+E0439: 0439,
+E0445: 0445,
+E0446: 0446,
+E0447: 0447,
+E0448: 0448,
+E0449: 0449,
+E0451: 0451,
+E0452: 0452,
+E0453: 0453,
+E0454: 0454,
+E0455: 0455,
+E0457: 0457,
+E0458: 0458,
+E0459: 0459,
+E0460: 0460,
+E0461: 0461,
+E0462: 0462,
+E0463: 0463,
+E0464: 0464,
+E0466: 0466,
+E0468: 0468,
+E0469: 0469,
+E0472: 0472,
+E0476: 0476,
+E0477: 0477,
+E0478: 0478,
+E0482: 0482,
+E0491: 0491,
+E0492: 0492,
+E0493: 0493,
+E0495: 0495,
+E0496: 0496,
+E0497: 0497,
+E0498: 0498,
+E0499: 0499,
+E0500: 0500,
+E0501: 0501,
+E0502: 0502,
+E0503: 0503,
+E0504: 0504,
+E0505: 0505,
+E0506: 0506,
+E0507: 0507,
+E0508: 0508,
+E0509: 0509,
+E0510: 0510,
+E0511: 0511,
+E0512: 0512,
+E0514: 0514,
+E0515: 0515,
+E0516: 0516,
+E0517: 0517,
+E0518: 0518,
+E0519: 0519,
+E0520: 0520,
+E0521: 0521,
+E0522: 0522,
+E0523: 0523,
+E0524: 0524,
+E0525: 0525,
+E0527: 0527,
+E0528: 0528,
+E0529: 0529,
+E0530: 0530,
+E0531: 0531,
+E0532: 0532,
+E0533: 0533,
+E0534: 0534,
+E0535: 0535,
+E0536: 0536,
+E0537: 0537,
+E0538: 0538,
+E0539: 0539,
+E0541: 0541,
+E0542: 0542,
+E0543: 0543,
+E0544: 0544,
+E0545: 0545,
+E0546: 0546,
+E0547: 0547,
+E0549: 0549,
+E0550: 0550,
+E0551: 0551,
+E0552: 0552,
+E0554: 0554,
+E0556: 0556,
+E0557: 0557,
+E0559: 0559,
+E0560: 0560,
+E0561: 0561,
+E0562: 0562,
+E0565: 0565,
+E0566: 0566,
+E0567: 0567,
+E0568: 0568,
+E0569: 0569,
+E0570: 0570,
+E0571: 0571,
+E0572: 0572,
+E0573: 0573,
+E0574: 0574,
+E0575: 0575,
+E0576: 0576,
+E0577: 0577,
+E0578: 0578,
+E0579: 0579,
+E0580: 0580,
+E0581: 0581,
+E0582: 0582,
+E0583: 0583,
+E0584: 0584,
+E0585: 0585,
+E0586: 0586,
+E0587: 0587,
+E0588: 0588,
+E0589: 0589,
+E0590: 0590,
+E0591: 0591,
+E0592: 0592,
+E0593: 0593,
+E0594: 0594,
+E0595: 0595,
+E0596: 0596,
+E0597: 0597,
+E0599: 0599,
+E0600: 0600,
+E0601: 0601,
+E0602: 0602,
+E0603: 0603,
+E0604: 0604,
+E0605: 0605,
+E0606: 0606,
+E0607: 0607,
+E0608: 0608,
+E0609: 0609,
+E0610: 0610,
+E0614: 0614,
+E0615: 0615,
+E0616: 0616,
+E0617: 0617,
+E0618: 0618,
+E0619: 0619,
+E0620: 0620,
+E0621: 0621,
+E0622: 0622,
+E0623: 0623,
+E0624: 0624,
+E0625: 0625,
+E0626: 0626,
+E0627: 0627,
+E0628: 0628,
+E0631: 0631,
+E0632: 0632,
+E0633: 0633,
+E0634: 0634,
+E0635: 0635,
+E0636: 0636,
+E0637: 0637,
+E0638: 0638,
+E0639: 0639,
+E0640: 0640,
+E0641: 0641,
+E0642: 0642,
+E0643: 0643,
+E0644: 0644,
+E0646: 0646,
+E0647: 0647,
+E0648: 0648,
+E0657: 0657,
+E0658: 0658,
+E0659: 0659,
+E0660: 0660,
+E0661: 0661,
+E0662: 0662,
+E0663: 0663,
+E0664: 0664,
+E0665: 0665,
+E0666: 0666,
+E0667: 0667,
+E0668: 0668,
+E0669: 0669,
+E0670: 0670,
+E0671: 0671,
+E0687: 0687,
+E0688: 0688,
+E0689: 0689,
+E0690: 0690,
+E0691: 0691,
+E0692: 0692,
+E0693: 0693,
+E0695: 0695,
+E0696: 0696,
+E0697: 0697,
+E0698: 0698,
+E0699: 0699,
+E0700: 0700,
+E0701: 0701,
+E0703: 0703,
+E0704: 0704,
+E0705: 0705,
+E0706: 0706,
+E0708: 0708,
+E0710: 0710,
+E0712: 0712,
+E0713: 0713,
+E0714: 0714,
+E0715: 0715,
+E0716: 0716,
+E0711: 0711,
+E0717: 0717,
+E0718: 0718,
+E0719: 0719,
+E0720: 0720,
+E0722: 0722,
+E0724: 0724,
+E0725: 0725,
+E0726: 0726,
+E0727: 0727,
+E0728: 0728,
+E0729: 0729,
+E0730: 0730,
+E0731: 0731,
+E0732: 0732,
+E0733: 0733,
+E0734: 0734,
+E0735: 0735,
+E0736: 0736,
+E0737: 0737,
+E0739: 0739,
+E0740: 0740,
+E0741: 0741,
+E0742: 0742,
+E0743: 0743,
+E0744: 0744,
+E0745: 0745,
+E0746: 0746,
+E0747: 0747,
+E0748: 0748,
+E0749: 0749,
+E0750: 0750,
+E0751: 0751,
+E0752: 0752,
+E0753: 0753,
+E0754: 0754,
+E0755: 0755,
+E0756: 0756,
+E0757: 0757,
+E0758: 0758,
+E0759: 0759,
+E0760: 0760,
+E0761: 0761,
+E0762: 0762,
+E0763: 0763,
+E0764: 0764,
+E0765: 0765,
+E0766: 0766,
+E0767: 0767,
+E0768: 0768,
+E0769: 0769,
+E0770: 0770,
+E0771: 0771,
+E0772: 0772,
+E0773: 0773,
+E0774: 0774,
+E0775: 0775,
+E0776: 0776,
+E0777: 0777,
+E0778: 0778,
+E0779: 0779,
+E0780: 0780,
+E0781: 0781,
+E0782: 0782,
+E0783: 0783,
+E0784: 0784,
+E0785: 0785,
+E0786: 0786,
+E0787: 0787,
+E0788: 0788,
+E0789: 0789,
+E0790: 0790,
+E0791: 0791,
+E0792: 0792,
+E0793: 0793,
+E0794: 0794,
+E0795: 0795,
+E0796: 0796,
+E0797: 0797,
+        );
     )
 }
 
-mod error_codes;
-pub use error_codes::DIAGNOSTICS;
+// Undocumented removed error codes. Note that many removed error codes are kept in the list above
+// and marked as no-longer emitted with a note in the markdown file (see E0001 for an example).
+//  E0006, // merged with E0005
+//  E0008, // cannot bind by-move into a pattern guard
+//  E0019, // merged into E0015
+//  E0035, // merged into E0087/E0089
+//  E0036, // merged into E0087/E0089
+//  E0068,
+//  E0085,
+//  E0086,
+//  E0101, // replaced with E0282
+//  E0102, // replaced with E0282
+//  E0103,
+//  E0104,
+//  E0122, // bounds in type aliases are ignored, turned into proper lint
+//  E0123,
+//  E0127,
+//  E0129,
+//  E0134,
+//  E0135,
+//  E0141,
+//  E0153, // unused error code
+//  E0157, // unused error code
+//  E0159, // use of trait `{}` as struct constructor
+//  E0163, // merged into E0071
+//  E0167,
+//  E0168,
+//  E0172, // non-trait found in a type sum, moved to resolve
+//  E0173, // manual implementations of unboxed closure traits are experimental
+//  E0174,
+//  E0182, // merged into E0229
+//  E0187, // cannot infer the kind of the closure
+//  E0188, // can not cast an immutable reference to a mutable pointer
+//  E0189, // deprecated: can only cast a boxed pointer to a boxed object
+//  E0190, // deprecated: can only cast a &-pointer to an &-object
+//  E0194, // merged into E0403
+//  E0196, // cannot determine a type for this closure
+//  E0209, // builtin traits can only be implemented on structs or enums
+//  E0213, // associated types are not accepted in this context
+//  E0215, // angle-bracket notation is not stable with `Fn`
+//  E0216, // parenthetical notation is only stable with `Fn`
+//  E0217, // ambiguous associated type, defined in multiple supertraits
+//  E0218, // no associated type defined
+//  E0219, // associated type defined in higher-ranked supertrait
+//  E0233,
+//  E0234,
+//  E0235, // structure constructor specifies a structure of type but
+//  E0236, // no lang item for range syntax
+//  E0237, // no lang item for range syntax
+//  E0238, // parenthesized parameters may only be used with a trait
+//  E0239, // `next` method of `Iterator` trait has unexpected type
+//  E0240,
+//  E0241,
+//  E0242,
+//  E0245, // not a trait
+//  E0246, // invalid recursive type
+//  E0247,
+//  E0248, // value used as a type, now reported earlier during resolution
+//         // as E0412
+//  E0249,
+//  E0257,
+//  E0258,
+//  E0272, // on_unimplemented #0
+//  E0273, // on_unimplemented #1
+//  E0274, // on_unimplemented #2
+//  E0278, // requirement is not satisfied
+//  E0279,
+//  E0280, // changed to ICE
+//  E0285, // overflow evaluation builtin bounds
+//  E0296, // replaced with a generic attribute input check
+//  E0298, // cannot compare constants
+//  E0299, // mismatched types between arms
+//  E0300, // unexpanded macro
+//  E0304, // expected signed integer constant
+//  E0305, // expected constant
+//  E0313, // removed: found unreachable
+//  E0314, // closure outlives stack frame
+//  E0315, // cannot invoke closure outside of its lifetime
+//  E0319, // trait impls for defaulted traits allowed just for structs/enums
+//  E0372, // coherence not object safe
+//  E0385, // {} in an aliasable location
+//  E0402, // cannot use an outer type parameter in this context
+//  E0406, // merged into 420
+//  E0410, // merged into 408
+//  E0413, // merged into 530
+//  E0414, // merged into 530
+//  E0417, // merged into 532
+//  E0418, // merged into 532
+//  E0419, // merged into 531
+//  E0420, // merged into 532
+//  E0421, // merged into 531
+//  E0427, // merged into 530
+//  E0445, // merged into 446 and type privacy lints
+//  E0456, // plugin `..` is not available for triple `..`
+//  E0465, // removed: merged with E0464
+//  E0467, // removed
+//  E0470, // removed
+//  E0471, // constant evaluation error (in pattern)
+//  E0473, // dereference of reference outside its lifetime
+//  E0474, // captured variable `..` does not outlive the enclosing closure
+//  E0475, // index of slice outside its lifetime
+//  E0479, // the type `..` (provided as the value of a type parameter) is...
+//  E0480, // lifetime of method receiver does not outlive the method call
+//  E0481, // lifetime of function argument does not outlive the function call
+//  E0483, // lifetime of operand does not outlive the operation
+//  E0484, // reference is not valid at the time of borrow
+//  E0485, // automatically reference is not valid at the time of borrow
+//  E0486, // type of expression contains references that are not valid during..
+//  E0487, // unsafe use of destructor: destructor might be called while...
+//  E0488, // lifetime of variable does not enclose its declaration
+//  E0489, // type/lifetime parameter not in scope here
+//  E0490, // removed: unreachable
+//  E0526, // shuffle indices are not constant
+//  E0540, // multiple rustc_deprecated attributes
+//  E0548, // replaced with a generic attribute input check
+//  E0553, // multiple rustc_const_unstable attributes
+//  E0555, // replaced with a generic attribute input check
+//  E0558, // replaced with a generic attribute input check
+//  E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
+//  E0564, // only named lifetimes are allowed in `impl Trait`,
+//         // but `{}` was found in the type `{}`
+//  E0598, // lifetime of {} is too short to guarantee its contents can be...
+//  E0611, // merged into E0616
+//  E0612, // merged into E0609
+//  E0613, // Removed (merged with E0609)
+//  E0629, // missing 'feature' (rustc_const_unstable)
+//  E0630, // rustc_const_unstable attribute must be paired with stable/unstable
+//         // attribute
+//  E0645, // trait aliases not finished
+//  E0694, // an unknown tool name found in scoped attributes
+//  E0702, // replaced with a generic attribute input check
+//  E0707, // multiple elided lifetimes used in arguments of `async fn`
+//  E0709, // multiple different lifetimes used in arguments of `async fn`
+//  E0721, // `await` keyword
+//  E0723, // unstable feature in `const` context
+//  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
+//  E0744, // merged into E0728
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index 0c1fcecb571..a2d1fd2a924 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -10,9 +10,11 @@ derive_setters = "0.1.6"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_error_codes = { path = "../rustc_error_codes" }
 rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
+rustc_index = { path = "../rustc_index" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index f0699a56f98..949f52ef6b5 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -9,8 +9,8 @@ use crate::emitter::FileWithAnnotatedLines;
 use crate::snippet::Line;
 use crate::translation::{to_fluent_args, Translate};
 use crate::{
-    CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, FluentBundle, LazyFallbackBundle,
-    Level, MultiSpan, Style, SubDiagnostic,
+    CodeSuggestion, Diagnostic, DiagnosticMessage, Emitter, ErrCode, FluentBundle,
+    LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
 };
 use annotate_snippets::{Annotation, AnnotationType, Renderer, Slice, Snippet, SourceAnnotation};
 use rustc_data_structures::sync::Lrc;
@@ -127,7 +127,7 @@ impl AnnotateSnippetEmitter {
         level: &Level,
         messages: &[(DiagnosticMessage, Style)],
         args: &FluentArgs<'_>,
-        code: &Option<String>,
+        code: &Option<ErrCode>,
         msp: &MultiSpan,
         _children: &[SubDiagnostic],
         _suggestions: &[CodeSuggestion],
@@ -178,6 +178,7 @@ impl AnnotateSnippetEmitter {
                         .collect::<Vec<Owned>>()
                 })
                 .collect();
+            let code = code.map(|code| code.to_string());
             let snippet = Snippet {
                 title: Some(Annotation {
                     label: Some(&message),
diff --git a/compiler/rustc_errors/src/codes.rs b/compiler/rustc_errors/src/codes.rs
new file mode 100644
index 00000000000..947cf27ca79
--- /dev/null
+++ b/compiler/rustc_errors/src/codes.rs
@@ -0,0 +1,39 @@
+//! This module defines the following.
+//! - The `ErrCode` type.
+//! - A constant for every error code, with a name like `E0123`.
+//! - A static table `DIAGNOSTICS` pairing every error code constant with its
+//!   long description text.
+
+use std::fmt;
+
+rustc_index::newtype_index! {
+    #[max = 9999] // Because all error codes have four digits.
+    #[orderable]
+    #[encodable]
+    #[debug_format = "ErrCode({})"]
+    pub struct ErrCode {}
+}
+
+impl fmt::Display for ErrCode {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "E{:04}", self.as_u32())
+    }
+}
+
+macro_rules! define_error_code_constants_and_diagnostics_table {
+    ($($name:ident: $num:literal,)*) => (
+        $(
+            pub const $name: $crate::ErrCode = $crate::ErrCode::from_u32($num);
+        )*
+        pub static DIAGNOSTICS: &[($crate::ErrCode, &str)] = &[
+            $( (
+                $name,
+                include_str!(
+                    concat!("../../rustc_error_codes/src/error_codes/", stringify!($name), ".md")
+                )
+            ), )*
+        ];
+    )
+}
+
+rustc_error_codes::error_codes!(define_error_code_constants_and_diagnostics_table);
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 4934bc2450c..8a32e29ddc9 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1,7 +1,8 @@
 use crate::snippet::Style;
 use crate::{
-    CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level,
-    MultiSpan, SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
+    CodeSuggestion, DelayedBugKind, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee,
+    ErrCode, 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;
@@ -104,7 +105,7 @@ pub struct Diagnostic {
     pub(crate) level: Level,
 
     pub messages: Vec<(DiagnosticMessage, Style)>,
-    pub code: Option<String>,
+    pub code: Option<ErrCode>,
     pub span: MultiSpan,
     pub children: Vec<SubDiagnostic>,
     pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
@@ -893,8 +894,8 @@ impl Diagnostic {
         self
     }
 
-    pub fn code(&mut self, s: String) -> &mut Self {
-        self.code = Some(s);
+    pub fn code(&mut self, code: ErrCode) -> &mut Self {
+        self.code = Some(code);
         self
     }
 
@@ -903,8 +904,8 @@ impl Diagnostic {
         self
     }
 
-    pub fn get_code(&self) -> Option<&str> {
-        self.code.as_deref()
+    pub fn get_code(&self) -> Option<ErrCode> {
+        self.code
     }
 
     pub fn primary_message(&mut self, msg: impl Into<DiagnosticMessage>) -> &mut Self {
@@ -990,7 +991,7 @@ impl Diagnostic {
         &Level,
         &[(DiagnosticMessage, Style)],
         Vec<(&Cow<'static, str>, &DiagnosticArgValue<'static>)>,
-        &Option<String>,
+        &Option<ErrCode>,
         &Option<IsLint>,
         &MultiSpan,
         &Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 87e2d295c7f..8bfb1816486 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -1,7 +1,7 @@
 use crate::diagnostic::IntoDiagnosticArg;
 use crate::{DiagCtxt, Level, MultiSpan, StashKey};
 use crate::{
-    Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, ExplicitBug,
+    Diagnostic, DiagnosticMessage, DiagnosticStyledString, ErrCode, ErrorGuaranteed, ExplicitBug,
     SubdiagnosticMessage,
 };
 use rustc_lint_defs::Applicability;
@@ -399,7 +399,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
         name: String, has_future_breakage: bool,
     ));
     forward!((code, with_code)(
-        s: String,
+        code: ErrCode,
     ));
     forward!((arg, with_arg)(
         name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
@@ -439,12 +439,7 @@ impl<G: EmissionGuarantee> Drop for DiagnosticBuilder<'_, G> {
 
 #[macro_export]
 macro_rules! struct_span_code_err {
-    ($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({
-        $dcx.struct_span_err($span, format!($($message)*)).with_code($crate::error_code!($code))
+    ($dcx:expr, $span:expr, $code:expr, $($message:tt)*) => ({
+        $dcx.struct_span_err($span, format!($($message)*)).with_code($code)
     })
 }
-
-#[macro_export]
-macro_rules! error_code {
-    ($code:ident) => {{ stringify!($code).to_owned() }};
-}
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index f6679ae9bb3..df3fd4af4b4 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -1,7 +1,7 @@
 use crate::diagnostic::DiagnosticLocation;
 use crate::{fluent_generated as fluent, AddToDiagnostic};
 use crate::{
-    DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
+    DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, ErrCode, IntoDiagnostic,
     IntoDiagnosticArg, Level,
 };
 use rustc_ast as ast;
@@ -58,16 +58,29 @@ macro_rules! into_diagnostic_arg_using_display {
     }
 }
 
+macro_rules! into_diagnostic_arg_for_number {
+    ($( $ty:ty ),+ $(,)?) => {
+        $(
+            impl IntoDiagnosticArg for $ty {
+                fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+                    // HACK: `FluentNumber` the underline backing struct represent
+                    // numbers using a f64 which can't represent all the i128 numbers
+                    // So in order to be able to use fluent selectors and still
+                    // have all the numbers representable we only convert numbers
+                    // below a certain threshold.
+                    if let Ok(n) = TryInto::<i128>::try_into(self) && n >= -100 && n <= 100 {
+                        DiagnosticArgValue::Number(n)
+                    } else {
+                        self.to_string().into_diagnostic_arg()
+                    }
+                }
+            }
+        )+
+    }
+}
+
 into_diagnostic_arg_using_display!(
     ast::ParamKindOrd,
-    i8,
-    u8,
-    i16,
-    u16,
-    u32,
-    i64,
-    i128,
-    u128,
     std::io::Error,
     Box<dyn std::error::Error>,
     std::num::NonZeroU32,
@@ -80,19 +93,10 @@ into_diagnostic_arg_using_display!(
     &TargetTriple,
     SplitDebuginfo,
     ExitStatus,
+    ErrCode,
 );
 
-impl IntoDiagnosticArg for i32 {
-    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
-        DiagnosticArgValue::Number(self.into())
-    }
-}
-
-impl IntoDiagnosticArg for u64 {
-    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
-        DiagnosticArgValue::Number(self.into())
-    }
-}
+into_diagnostic_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
 
 impl IntoDiagnosticArg for bool {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
@@ -154,12 +158,6 @@ impl IntoDiagnosticArg for PathBuf {
     }
 }
 
-impl IntoDiagnosticArg for usize {
-    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
-        DiagnosticArgValue::Number(self as i128)
-    }
-}
-
 impl IntoDiagnosticArg for PanicStrategy {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
         DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 23efdaea0eb..9f76c1dd248 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -17,8 +17,8 @@ use crate::styled_buffer::StyledBuffer;
 use crate::translation::{to_fluent_args, Translate};
 use crate::{
     diagnostic::DiagnosticLocation, CodeSuggestion, DiagCtxt, Diagnostic, DiagnosticMessage,
-    FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight,
-    SuggestionStyle, TerminalUrl,
+    ErrCode, FluentBundle, LazyFallbackBundle, Level, MultiSpan, SubDiagnostic,
+    SubstitutionHighlight, SuggestionStyle, TerminalUrl,
 };
 use rustc_lint_defs::pluralize;
 
@@ -1309,7 +1309,7 @@ impl HumanEmitter {
         msp: &MultiSpan,
         msgs: &[(DiagnosticMessage, Style)],
         args: &FluentArgs<'_>,
-        code: &Option<String>,
+        code: &Option<ErrCode>,
         level: &Level,
         max_line_num_len: usize,
         is_secondary: bool,
@@ -1340,9 +1340,9 @@ impl HumanEmitter {
                 buffer.append(0, "[", Style::Level(*level));
                 let code = if let TerminalUrl::Yes = self.terminal_url {
                     let path = "https://doc.rust-lang.org/error_codes";
-                    Cow::Owned(format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07"))
+                    format!("\x1b]8;;{path}/{code}.html\x07{code}\x1b]8;;\x07")
                 } else {
-                    Cow::Borrowed(code)
+                    code.to_string()
                 };
                 buffer.append(0, &code, Style::Level(*level));
                 buffer.append(0, "]", Style::Level(*level));
@@ -2076,7 +2076,7 @@ impl HumanEmitter {
         level: &Level,
         messages: &[(DiagnosticMessage, Style)],
         args: &FluentArgs<'_>,
-        code: &Option<String>,
+        code: &Option<ErrCode>,
         span: &MultiSpan,
         children: &[SubDiagnostic],
         suggestions: &[CodeSuggestion],
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 51b064f4c61..6f922998279 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -400,10 +400,10 @@ impl Diagnostic {
 
         let translated_message = je.translate_messages(&diag.messages, &args);
 
-        let code = if let Some(code) = &diag.code {
+        let code = if let Some(code) = diag.code {
             Some(DiagnosticCode {
                 code: code.to_string(),
-                explanation: je.registry.as_ref().unwrap().try_find_description(&code).ok(),
+                explanation: je.registry.as_ref().unwrap().try_find_description(code).ok(),
             })
         } else if let Some(IsLint { name, .. }) = &diag.is_lint {
             Some(DiagnosticCode { code: name.to_string(), explanation: None })
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index ee831c4f560..6d9208341a5 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -2,23 +2,26 @@
 //!
 //! This module contains the code for creating and emitting diagnostics.
 
+// tidy-alphabetical-start
+#![allow(incomplete_features)]
+#![allow(internal_features)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
-#![feature(rustdoc_internals)]
 #![feature(array_windows)]
 #![feature(associated_type_defaults)]
 #![feature(box_into_inner)]
 #![feature(box_patterns)]
+#![feature(error_reporter)]
 #![feature(extract_if)]
 #![feature(let_chains)]
+#![feature(min_specialization)]
 #![feature(negative_impls)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
-#![feature(yeet_expr)]
+#![feature(rustdoc_internals)]
 #![feature(try_blocks)]
-#![feature(error_reporter)]
-#![allow(incomplete_features)]
-#![allow(internal_features)]
+#![feature(yeet_expr)]
+// tidy-alphabetical-end
 
 #[macro_use]
 extern crate rustc_macros;
@@ -28,6 +31,7 @@ extern crate tracing;
 
 extern crate self as rustc_errors;
 
+pub use codes::*;
 pub use diagnostic::{
     AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue,
     DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
@@ -76,6 +80,7 @@ use std::path::{Path, PathBuf};
 use Level::*;
 
 pub mod annotate_snippet_emitter_writer;
+pub mod codes;
 mod diagnostic;
 mod diagnostic_builder;
 mod diagnostic_impls;
@@ -444,10 +449,10 @@ struct DiagCtxtInner {
     /// This set contains the code of all emitted diagnostics to avoid
     /// emitting the same diagnostic with extended help (`--teach`) twice, which
     /// would be unnecessary repetition.
-    taught_diagnostics: FxHashSet<String>,
+    taught_diagnostics: FxHashSet<ErrCode>,
 
     /// Used to suggest rustc --explain `<error code>`
-    emitted_diagnostic_codes: FxIndexSet<String>,
+    emitted_diagnostic_codes: FxIndexSet<ErrCode>,
 
     /// This set contains a hash of every diagnostic that has been emitted by
     /// this `DiagCtxt`. These hashes is used to avoid emitting the same error
@@ -1002,9 +1007,9 @@ impl DiagCtxt {
             let mut error_codes = inner
                 .emitted_diagnostic_codes
                 .iter()
-                .filter_map(|code| {
+                .filter_map(|&code| {
                     if registry.try_find_description(code).is_ok().clone() {
-                        Some(code.clone())
+                        Some(code.to_string())
                     } else {
                         None
                     }
@@ -1050,8 +1055,8 @@ impl DiagCtxt {
     ///
     /// Used to suppress emitting the same error multiple times with extended explanation when
     /// calling `-Zteach`.
-    pub fn must_teach(&self, code: &str) -> bool {
-        self.inner.borrow_mut().taught_diagnostics.insert(code.to_string())
+    pub fn must_teach(&self, code: ErrCode) -> bool {
+        self.inner.borrow_mut().taught_diagnostics.insert(code)
     }
 
     pub fn force_print_diagnostic(&self, db: Diagnostic) {
@@ -1311,8 +1316,8 @@ impl DiagCtxtInner {
 
         let mut guaranteed = None;
         (*TRACK_DIAGNOSTIC)(diagnostic, &mut |mut diagnostic| {
-            if let Some(ref code) = diagnostic.code {
-                self.emitted_diagnostic_codes.insert(code.clone());
+            if let Some(code) = diagnostic.code {
+                self.emitted_diagnostic_codes.insert(code);
             }
 
             let already_emitted = {
diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs
index f26d8e7ebdc..8834d04d971 100644
--- a/compiler/rustc_errors/src/registry.rs
+++ b/compiler/rustc_errors/src/registry.rs
@@ -1,3 +1,4 @@
+use crate::ErrCode;
 use rustc_data_structures::fx::FxHashMap;
 
 #[derive(Debug)]
@@ -5,17 +6,17 @@ pub struct InvalidErrorCode;
 
 #[derive(Clone)]
 pub struct Registry {
-    long_descriptions: FxHashMap<&'static str, &'static str>,
+    long_descriptions: FxHashMap<ErrCode, &'static str>,
 }
 
 impl Registry {
-    pub fn new(long_descriptions: &[(&'static str, &'static str)]) -> Registry {
+    pub fn new(long_descriptions: &[(ErrCode, &'static str)]) -> Registry {
         Registry { long_descriptions: long_descriptions.iter().copied().collect() }
     }
 
     /// Returns `InvalidErrorCode` if the code requested does not exist in the
     /// registry.
-    pub fn try_find_description(&self, code: &str) -> Result<&'static str, InvalidErrorCode> {
-        self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode)
+    pub fn try_find_description(&self, code: ErrCode) -> Result<&'static str, InvalidErrorCode> {
+        self.long_descriptions.get(&code).copied().ok_or(InvalidErrorCode)
     }
 }
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 29b70f33a6c..657e19277a7 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -796,9 +796,15 @@ impl SyntaxExtension {
     /// | external      | no  | if-ext        | if-ext   | yes |
     /// | yes           | yes | yes           | yes      | yes |
     fn get_collapse_debuginfo(sess: &Session, attrs: &[ast::Attribute], is_local: bool) -> bool {
-        let collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
+        let mut collapse_debuginfo_attr = attr::find_by_name(attrs, sym::collapse_debuginfo)
             .map(|v| Self::collapse_debuginfo_by_name(sess, v))
             .unwrap_or(CollapseMacroDebuginfo::Unspecified);
+        if collapse_debuginfo_attr == CollapseMacroDebuginfo::Unspecified
+            && attr::contains_name(attrs, sym::rustc_builtin_macro)
+        {
+            collapse_debuginfo_attr = CollapseMacroDebuginfo::Yes;
+        }
+
         let flag = sess.opts.unstable_opts.collapse_macro_debuginfo;
         let attr = collapse_debuginfo_attr;
         let ext = !is_local;
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index f574e81e905..781186764fa 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -373,7 +373,9 @@ impl<'a> StripUnconfigured<'a> {
     /// If attributes are not allowed on expressions, emit an error for `attr`
     #[instrument(level = "trace", skip(self))]
     pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
-        if self.features.is_some_and(|features| !features.stmt_expr_attributes) {
+        if self.features.is_some_and(|features| !features.stmt_expr_attributes)
+            && !attr.span.allows_unstable(sym::stmt_expr_attributes)
+        {
             let mut err = feature_err(
                 &self.sess,
                 sym::stmt_expr_attributes,
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 4a1c00f0104..2584ff62e98 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -1,4 +1,5 @@
 use rustc_ast::ast;
+use rustc_errors::codes::*;
 use rustc_macros::Diagnostic;
 use rustc_session::Limit;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
@@ -175,7 +176,7 @@ pub(crate) struct TakesNoArguments<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_feature_removed, code = "E0557")]
+#[diag(expand_feature_removed, code = E0557)]
 pub(crate) struct FeatureRemoved<'a> {
     #[primary_span]
     #[label]
@@ -191,7 +192,7 @@ pub(crate) struct FeatureRemovedReason<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_feature_not_allowed, code = "E0725")]
+#[diag(expand_feature_not_allowed, code = E0725)]
 pub(crate) struct FeatureNotAllowed {
     #[primary_span]
     pub span: Span,
@@ -210,7 +211,7 @@ pub(crate) struct RecursionLimitReached<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_malformed_feature_attribute, code = "E0556")]
+#[diag(expand_malformed_feature_attribute, code = E0556)]
 pub(crate) struct MalformedFeatureAttribute {
     #[primary_span]
     pub span: Span,
@@ -347,7 +348,7 @@ pub(crate) struct ModuleInBlockName {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_module_file_not_found, code = "E0583")]
+#[diag(expand_module_file_not_found, code = E0583)]
 #[help]
 #[note]
 pub(crate) struct ModuleFileNotFound {
@@ -359,7 +360,7 @@ pub(crate) struct ModuleFileNotFound {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_module_multiple_candidates, code = "E0761")]
+#[diag(expand_module_multiple_candidates, code = E0761)]
 #[help]
 pub(crate) struct ModuleMultipleCandidates {
     #[primary_span]
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 6eed2178ead..e66a66e23dc 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -516,6 +516,9 @@ declare_features! (
     (unstable, macro_metavar_expr, "1.61.0", Some(83527)),
     /// Allows `#[marker]` on certain traits allowing overlapping implementations.
     (unstable, marker_trait_attr, "1.30.0", Some(29864)),
+    /// Allows exhaustive pattern matching on types that contain uninhabited types in cases that are
+    /// unambiguously sound.
+    (incomplete, min_exhaustive_patterns, "CURRENT_RUSTC_VERSION", Some(119612)),
     /// A minimal, sound subset of specialization intended to be used by the
     /// standard library until the soundness issues with specialization
     /// are fixed.
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index 3aad510f366..c22daad334f 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index bfe88df4e1a..5e9076243f8 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -7,7 +7,9 @@ use crate::fluent_generated as fluent;
 use crate::traits::error_reporting::report_object_safety_error;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
 use rustc_data_structures::unord::UnordMap;
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed};
+use rustc_errors::{
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed,
+};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::traits::FulfillmentError;
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index 4284758b117..30b10446afc 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -5,7 +5,9 @@ use crate::astconv::{
 };
 use crate::structured_errors::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs};
 use rustc_ast::ast::ParamKindOrd;
-use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{
+    codes::*, struct_span_code_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
index 33e782abc68..98cd8a085ba 100644
--- a/compiler/rustc_hir_analysis/src/astconv/lint.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -1,5 +1,5 @@
 use rustc_ast::TraitObjectSyntax;
-use rustc_errors::{Diagnostic, StashKey};
+use rustc_errors::{codes::*, Diagnostic, StashKey};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 7c97c2a1a6f..2dec0ab4355 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -18,8 +18,8 @@ use crate::require_c_abi_if_c_variadic;
 use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{
-    error_code, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
-    ErrorGuaranteed, FatalError, MultiSpan,
+    codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+    FatalError, MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
@@ -1072,9 +1072,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 if let Some(binding) = binding
                     && let ConvertedBindingKind::Equality(_) = binding.kind
                 {
-                    error_code!(E0222)
+                    E0222
                 } else {
-                    error_code!(E0221)
+                    E0221
                 },
             );
 
@@ -1630,7 +1630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             let reported = tcx
                 .dcx()
                 .struct_span_err(span, msg)
-                .with_code(rustc_errors::error_code!(E0624))
+                .with_code(E0624)
                 .with_span_label(span, format!("private {kind}"))
                 .with_span_label(def_span, format!("{kind} defined here"))
                 .emit();
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index 5f35f75c77b..2d85ad5789e 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -2,7 +2,7 @@ use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBou
 use crate::bounds::Bounds;
 use crate::errors::TraitObjectDeclaredWithNoTraits;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index c63bafcdcd4..2fe3499e8e6 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -5,7 +5,7 @@ use super::compare_impl_item::check_type_bounds;
 use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
 use super::*;
 use rustc_attr as attr;
-use rustc_errors::{ErrorGuaranteed, MultiSpan};
+use rustc_errors::{codes::*, ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{DefId, LocalDefId};
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 57829d9d418..479421af77f 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -2,7 +2,7 @@ use super::potentially_plural_count;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
 use hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
+use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit;
@@ -1382,7 +1382,7 @@ fn compare_number_of_generics<'tcx>(
                     kind = kind,
                 ),
             );
-            err.code("E0049".into());
+            err.code(E0049);
 
             let msg =
                 format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),);
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index 3275a81c3dd..9fe95487bb9 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -2,7 +2,7 @@
 //
 // We don't do any drop checking during hir typeck.
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
+use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
 use rustc_middle::ty::util::CheckRegions;
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 60e4403c1c7..2d0d6611444 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -8,7 +8,7 @@ use crate::errors::{
 };
 
 use hir::def_id::DefId;
-use rustc_errors::{struct_span_code_err, DiagnosticMessage};
+use rustc_errors::{codes::*, struct_span_code_err, DiagnosticMessage};
 use rustc_hir as hir;
 use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
 use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 70213ee0614..0978a5e6596 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -4,7 +4,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
+    codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
 };
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index 63ea0272014..951440d6a2d 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index dafa899ef24..8cf1f2c9407 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -6,7 +6,7 @@
 // mappings. That mapping code resides here.
 
 use crate::errors;
-use rustc_errors::{error_code, struct_span_code_err};
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
@@ -61,7 +61,7 @@ fn enforce_trait_manually_implementable(
         // Maintain explicit error code for `Unsize`, since it has a useful
         // explanation about using `CoerceUnsized` instead.
         if Some(trait_def_id) == tcx.lang_items().unsize_trait() {
-            err.code(error_code!(E0328));
+            err.code(E0328);
         }
 
         return Err(err.emit());
diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index e4c407af53f..e3b5c724cde 100644
--- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -1,7 +1,7 @@
 //! Unsafety checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::Unsafety;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index a857e01f4fa..97d792e49ae 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -8,7 +8,7 @@
 
 use rustc_ast::walk_list;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index f14390b77c6..e5871276d64 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -2,8 +2,8 @@
 
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic,
-    Level, MultiSpan,
+    codes::*, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
+    MultiSpan,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
@@ -52,7 +52,7 @@ pub struct AssocKindMismatchWrapInBracesSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_assoc_item_not_found, code = "E0220")]
+#[diag(hir_analysis_assoc_item_not_found, code = E0220)]
 pub struct AssocItemNotFound<'a> {
     #[primary_span]
     pub span: Span,
@@ -122,7 +122,7 @@ pub enum AssocItemNotFoundSugg<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_unrecognized_atomic_operation, code = "E0092")]
+#[diag(hir_analysis_unrecognized_atomic_operation, code = E0092)]
 pub struct UnrecognizedAtomicOperation<'a> {
     #[primary_span]
     #[label]
@@ -131,7 +131,7 @@ pub struct UnrecognizedAtomicOperation<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
+#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = E0094)]
 pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
     #[primary_span]
     #[label]
@@ -142,7 +142,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_unrecognized_intrinsic_function, code = "E0093")]
+#[diag(hir_analysis_unrecognized_intrinsic_function, code = E0093)]
 pub struct UnrecognizedIntrinsicFunction {
     #[primary_span]
     #[label]
@@ -151,7 +151,7 @@ pub struct UnrecognizedIntrinsicFunction {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
+#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = E0195)]
 pub struct LifetimesOrBoundsMismatchOnTrait {
     #[primary_span]
     #[label]
@@ -178,7 +178,7 @@ pub struct AsyncTraitImplShouldBeAsync {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
+#[diag(hir_analysis_drop_impl_on_wrong_item, code = E0120)]
 pub struct DropImplOnWrongItem {
     #[primary_span]
     #[label]
@@ -186,7 +186,7 @@ pub struct DropImplOnWrongItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_field_already_declared, code = "E0124")]
+#[diag(hir_analysis_field_already_declared, code = E0124)]
 pub struct FieldAlreadyDeclared {
     pub field_name: Ident,
     #[primary_span]
@@ -197,7 +197,7 @@ pub struct FieldAlreadyDeclared {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = "E0184")]
+#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = E0184)]
 pub struct CopyImplOnTypeWithDtor {
     #[primary_span]
     #[label]
@@ -205,14 +205,14 @@ pub struct CopyImplOnTypeWithDtor {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")]
+#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)]
 pub struct MultipleRelaxedDefaultBounds {
     #[primary_span]
     pub spans: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_copy_impl_on_non_adt, code = "E0206")]
+#[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)]
 pub struct CopyImplOnNonAdt {
     #[primary_span]
     #[label]
@@ -228,7 +228,7 @@ pub struct ConstParamTyImplOnNonAdt {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")]
+#[diag(hir_analysis_trait_object_declared_with_no_traits, code = E0224)]
 pub struct TraitObjectDeclaredWithNoTraits {
     #[primary_span]
     pub span: Span,
@@ -237,14 +237,14 @@ pub struct TraitObjectDeclaredWithNoTraits {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_ambiguous_lifetime_bound, code = "E0227")]
+#[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)]
 pub struct AmbiguousLifetimeBound {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_assoc_type_binding_not_allowed, code = "E0229")]
+#[diag(hir_analysis_assoc_type_binding_not_allowed, code = E0229)]
 pub struct AssocTypeBindingNotAllowed {
     #[primary_span]
     #[label]
@@ -264,7 +264,7 @@ pub struct ParenthesizedFnTraitExpansion {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_typeof_reserved_keyword_used, code = "E0516")]
+#[diag(hir_analysis_typeof_reserved_keyword_used, code = E0516)]
 pub struct TypeofReservedKeywordUsed<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -275,7 +275,7 @@ pub struct TypeofReservedKeywordUsed<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_value_of_associated_struct_already_specified, code = "E0719")]
+#[diag(hir_analysis_value_of_associated_struct_already_specified, code = E0719)]
 pub struct ValueOfAssociatedStructAlreadySpecified {
     #[primary_span]
     #[label]
@@ -320,7 +320,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams {
     fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
         let mut err = DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_missing_type_params);
         err.span(self.span);
-        err.code(error_code!(E0393));
+        err.code(E0393);
         err.arg("parameterCount", self.missing_type_params.len());
         err.arg(
             "parameters",
@@ -373,7 +373,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_manual_implementation, code = "E0183")]
+#[diag(hir_analysis_manual_implementation, code = E0183)]
 #[help]
 pub struct ManualImplementation {
     #[primary_span]
@@ -421,7 +421,7 @@ pub struct SelfInImplSelf {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_linkage_type, code = "E0791")]
+#[diag(hir_analysis_linkage_type, code = E0791)]
 pub(crate) struct LinkageType {
     #[primary_span]
     pub span: Span,
@@ -429,7 +429,7 @@ pub(crate) struct LinkageType {
 
 #[derive(Diagnostic)]
 #[help]
-#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = "E0055")]
+#[diag(hir_analysis_auto_deref_reached_recursion_limit, code = E0055)]
 pub struct AutoDerefReachedRecursionLimit<'a> {
     #[primary_span]
     #[label]
@@ -440,7 +440,7 @@ pub struct AutoDerefReachedRecursionLimit<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_where_clause_on_main, code = "E0646")]
+#[diag(hir_analysis_where_clause_on_main, code = E0646)]
 pub(crate) struct WhereClauseOnMain {
     #[primary_span]
     pub span: Span,
@@ -485,7 +485,7 @@ pub(crate) struct StartTargetFeature {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_start_not_async, code = "E0752")]
+#[diag(hir_analysis_start_not_async, code = E0752)]
 pub(crate) struct StartAsync {
     #[primary_span]
     #[label]
@@ -493,7 +493,7 @@ pub(crate) struct StartAsync {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_start_function_where, code = "E0647")]
+#[diag(hir_analysis_start_function_where, code = E0647)]
 pub(crate) struct StartFunctionWhere {
     #[primary_span]
     #[label]
@@ -501,7 +501,7 @@ pub(crate) struct StartFunctionWhere {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_start_function_parameters, code = "E0132")]
+#[diag(hir_analysis_start_function_parameters, code = E0132)]
 pub(crate) struct StartFunctionParameters {
     #[primary_span]
     #[label]
@@ -509,14 +509,14 @@ pub(crate) struct StartFunctionParameters {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_main_function_return_type_generic, code = "E0131")]
+#[diag(hir_analysis_main_function_return_type_generic, code = E0131)]
 pub(crate) struct MainFunctionReturnTypeGeneric {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_main_function_async, code = "E0752")]
+#[diag(hir_analysis_main_function_async, code = E0752)]
 pub(crate) struct MainFunctionAsync {
     #[primary_span]
     pub span: Span,
@@ -525,7 +525,7 @@ pub(crate) struct MainFunctionAsync {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_main_function_generic_parameters, code = "E0131")]
+#[diag(hir_analysis_main_function_generic_parameters, code = E0131)]
 pub(crate) struct MainFunctionGenericParameters {
     #[primary_span]
     pub span: Span,
@@ -534,7 +534,7 @@ pub(crate) struct MainFunctionGenericParameters {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_variadic_function_compatible_convention, code = "E0045")]
+#[diag(hir_analysis_variadic_function_compatible_convention, code = E0045)]
 pub(crate) struct VariadicFunctionCompatibleConvention<'a> {
     #[primary_span]
     #[label]
@@ -587,7 +587,7 @@ pub(crate) struct TypeOf<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_pass_to_variadic_function, code = "E0617")]
+#[diag(hir_analysis_pass_to_variadic_function, code = E0617)]
 pub(crate) struct PassToVariadicFunction<'tcx, 'a> {
     #[primary_span]
     pub span: Span,
@@ -601,7 +601,7 @@ pub(crate) struct PassToVariadicFunction<'tcx, 'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_cast_thin_pointer_to_fat_pointer, code = "E0607")]
+#[diag(hir_analysis_cast_thin_pointer_to_fat_pointer, code = E0607)]
 pub(crate) struct CastThinPointerToFatPointer<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -610,7 +610,7 @@ pub(crate) struct CastThinPointerToFatPointer<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_invalid_union_field, code = "E0740")]
+#[diag(hir_analysis_invalid_union_field, code = E0740)]
 pub(crate) struct InvalidUnionField {
     #[primary_span]
     pub field_span: Span,
@@ -649,7 +649,7 @@ pub(crate) struct ReturnTypeNotationEqualityBound {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")]
+#[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = E0121)]
 pub(crate) struct PlaceholderNotAllowedItemSignatures {
     #[primary_span]
     #[label]
@@ -658,7 +658,7 @@ pub(crate) struct PlaceholderNotAllowedItemSignatures {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = "E0212")]
+#[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = E0212)]
 pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
     #[primary_span]
     pub span: Span,
@@ -684,7 +684,7 @@ pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_enum_discriminant_overflowed, code = "E0370")]
+#[diag(hir_analysis_enum_discriminant_overflowed, code = E0370)]
 #[note]
 pub(crate) struct EnumDiscriminantOverflowed {
     #[primary_span]
@@ -774,7 +774,7 @@ pub(crate) struct SIMDFFIHighlyExperimental {
 
 #[derive(Diagnostic)]
 pub enum ImplNotMarkedDefault {
-    #[diag(hir_analysis_impl_not_marked_default, code = "E0520")]
+    #[diag(hir_analysis_impl_not_marked_default, code = E0520)]
     #[note]
     Ok {
         #[primary_span]
@@ -784,7 +784,7 @@ pub enum ImplNotMarkedDefault {
         ok_label: Span,
         ident: Symbol,
     },
-    #[diag(hir_analysis_impl_not_marked_default_err, code = "E0520")]
+    #[diag(hir_analysis_impl_not_marked_default_err, code = E0520)]
     #[note]
     Err {
         #[primary_span]
@@ -795,7 +795,7 @@ pub enum ImplNotMarkedDefault {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_missing_trait_item, code = "E0046")]
+#[diag(hir_analysis_missing_trait_item, code = E0046)]
 pub(crate) struct MissingTraitItem {
     #[primary_span]
     #[label]
@@ -846,7 +846,7 @@ pub(crate) struct MissingTraitItemSuggestionNone {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_missing_one_of_trait_item, code = "E0046")]
+#[diag(hir_analysis_missing_one_of_trait_item, code = E0046)]
 pub(crate) struct MissingOneOfTraitItem {
     #[primary_span]
     #[label]
@@ -857,7 +857,7 @@ pub(crate) struct MissingOneOfTraitItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_missing_trait_item_unstable, code = "E0046")]
+#[diag(hir_analysis_missing_trait_item_unstable, code = E0046)]
 #[note]
 pub(crate) struct MissingTraitItemUnstable {
     #[primary_span]
@@ -872,7 +872,7 @@ pub(crate) struct MissingTraitItemUnstable {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_transparent_enum_variant, code = "E0731")]
+#[diag(hir_analysis_transparent_enum_variant, code = E0731)]
 pub(crate) struct TransparentEnumVariant {
     #[primary_span]
     #[label]
@@ -886,7 +886,7 @@ pub(crate) struct TransparentEnumVariant {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_transparent_non_zero_sized_enum, code = "E0690")]
+#[diag(hir_analysis_transparent_non_zero_sized_enum, code = E0690)]
 pub(crate) struct TransparentNonZeroSizedEnum<'a> {
     #[primary_span]
     #[label]
@@ -898,7 +898,7 @@ pub(crate) struct TransparentNonZeroSizedEnum<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_transparent_non_zero_sized, code = "E0690")]
+#[diag(hir_analysis_transparent_non_zero_sized, code = E0690)]
 pub(crate) struct TransparentNonZeroSized<'a> {
     #[primary_span]
     #[label]
@@ -1045,7 +1045,7 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_ty_outside, code = "E0390")]
+#[diag(hir_analysis_inherent_ty_outside, code = E0390)]
 #[help]
 pub struct InherentTyOutside {
     #[primary_span]
@@ -1054,7 +1054,7 @@ pub struct InherentTyOutside {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0378")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
 pub struct DispatchFromDynCoercion<'a> {
     #[primary_span]
     pub span: Span,
@@ -1066,14 +1066,14 @@ pub struct DispatchFromDynCoercion<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_dispatch_from_dyn_repr, code = "E0378")]
+#[diag(hir_analysis_dispatch_from_dyn_repr, code = E0378)]
 pub struct DispatchFromDynRepr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_ty_outside_relevant, code = "E0390")]
+#[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)]
 #[help]
 pub struct InherentTyOutsideRelevant {
     #[primary_span]
@@ -1083,7 +1083,7 @@ pub struct InherentTyOutsideRelevant {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_ty_outside_new, code = "E0116")]
+#[diag(hir_analysis_inherent_ty_outside_new, code = E0116)]
 #[note]
 pub struct InherentTyOutsideNew {
     #[primary_span]
@@ -1092,7 +1092,7 @@ pub struct InherentTyOutsideNew {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_ty_outside_primitive, code = "E0390")]
+#[diag(hir_analysis_inherent_ty_outside_primitive, code = E0390)]
 #[help]
 pub struct InherentTyOutsidePrimitive {
     #[primary_span]
@@ -1102,7 +1102,7 @@ pub struct InherentTyOutsidePrimitive {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_primitive_ty, code = "E0390")]
+#[diag(hir_analysis_inherent_primitive_ty, code = E0390)]
 #[help]
 pub struct InherentPrimitiveTy<'a> {
     #[primary_span]
@@ -1118,7 +1118,7 @@ pub struct InherentPrimitiveTyNote<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_dyn, code = "E0785")]
+#[diag(hir_analysis_inherent_dyn, code = E0785)]
 #[note]
 pub struct InherentDyn {
     #[primary_span]
@@ -1127,7 +1127,7 @@ pub struct InherentDyn {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_inherent_nominal, code = "E0118")]
+#[diag(hir_analysis_inherent_nominal, code = E0118)]
 #[note]
 pub struct InherentNominal {
     #[primary_span]
@@ -1136,7 +1136,7 @@ pub struct InherentNominal {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_dispatch_from_dyn_zst, code = "E0378")]
+#[diag(hir_analysis_dispatch_from_dyn_zst, code = E0378)]
 #[note]
 pub struct DispatchFromDynZST<'a> {
     #[primary_span]
@@ -1146,7 +1146,7 @@ pub struct DispatchFromDynZST<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0378")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
 pub struct DispatchFromDynSingle<'a> {
     #[primary_span]
     pub span: Span,
@@ -1156,7 +1156,7 @@ pub struct DispatchFromDynSingle<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_dispatch_from_dyn_multi, code = "E0378")]
+#[diag(hir_analysis_dispatch_from_dyn_multi, code = E0378)]
 #[note]
 pub struct DispatchFromDynMulti {
     #[primary_span]
@@ -1168,7 +1168,7 @@ pub struct DispatchFromDynMulti {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0376")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0376)]
 pub struct DispatchFromDynStruct<'a> {
     #[primary_span]
     pub span: Span,
@@ -1176,7 +1176,7 @@ pub struct DispatchFromDynStruct<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0377")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0377)]
 pub struct DispatchFromDynSame<'a> {
     #[primary_span]
     pub span: Span,
@@ -1188,7 +1188,7 @@ pub struct DispatchFromDynSame<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0374")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0374)]
 pub struct CoerceUnsizedOneField<'a> {
     #[primary_span]
     pub span: Span,
@@ -1198,7 +1198,7 @@ pub struct CoerceUnsizedOneField<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_multi, code = "E0375")]
+#[diag(hir_analysis_coerce_unsized_multi, code = E0375)]
 #[note]
 pub struct CoerceUnsizedMulti {
     #[primary_span]
@@ -1211,7 +1211,7 @@ pub struct CoerceUnsizedMulti {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_coerce_unsized_may, code = "E0378")]
+#[diag(hir_analysis_coerce_unsized_may, code = E0378)]
 pub struct CoerceUnsizedMay<'a> {
     #[primary_span]
     pub span: Span,
@@ -1219,7 +1219,7 @@ pub struct CoerceUnsizedMay<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_trait_cannot_impl_for_ty, code = "E0204")]
+#[diag(hir_analysis_trait_cannot_impl_for_ty, code = E0204)]
 pub struct TraitCannotImplForTy {
     #[primary_span]
     pub span: Span,
@@ -1241,7 +1241,7 @@ pub struct ImplForTyRequires {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_traits_with_defualt_impl, code = "E0321")]
+#[diag(hir_analysis_traits_with_defualt_impl, code = E0321)]
 #[note]
 pub struct TraitsWithDefaultImpl<'a> {
     #[primary_span]
@@ -1252,7 +1252,7 @@ pub struct TraitsWithDefaultImpl<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_cross_crate_traits, code = "E0321")]
+#[diag(hir_analysis_cross_crate_traits, code = E0321)]
 pub struct CrossCrateTraits<'a> {
     #[primary_span]
     #[label]
@@ -1262,7 +1262,7 @@ pub struct CrossCrateTraits<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_cross_crate_traits_defined, code = "E0321")]
+#[diag(hir_analysis_cross_crate_traits_defined, code = E0321)]
 pub struct CrossCrateTraitsDefined {
     #[primary_span]
     #[label]
@@ -1271,7 +1271,7 @@ pub struct CrossCrateTraitsDefined {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_ty_param_first_local, code = "E0210")]
+#[diag(hir_analysis_ty_param_first_local, code = E0210)]
 #[note]
 pub struct TyParamFirstLocal<'a> {
     #[primary_span]
@@ -1284,7 +1284,7 @@ pub struct TyParamFirstLocal<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_ty_param_some, code = "E0210")]
+#[diag(hir_analysis_ty_param_some, code = E0210)]
 #[note]
 pub struct TyParamSome<'a> {
     #[primary_span]
@@ -1297,7 +1297,7 @@ pub struct TyParamSome<'a> {
 
 #[derive(Diagnostic)]
 pub enum OnlyCurrentTraits<'a> {
-    #[diag(hir_analysis_only_current_traits_outside, code = "E0117")]
+    #[diag(hir_analysis_only_current_traits_outside, code = E0117)]
     Outside {
         #[primary_span]
         #[label(hir_analysis_only_current_traits_label)]
@@ -1317,7 +1317,7 @@ pub enum OnlyCurrentTraits<'a> {
         #[subdiagnostic]
         sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
-    #[diag(hir_analysis_only_current_traits_primitive, code = "E0117")]
+    #[diag(hir_analysis_only_current_traits_primitive, code = E0117)]
     Primitive {
         #[primary_span]
         #[label(hir_analysis_only_current_traits_label)]
@@ -1337,7 +1337,7 @@ pub enum OnlyCurrentTraits<'a> {
         #[subdiagnostic]
         sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>,
     },
-    #[diag(hir_analysis_only_current_traits_arbitrary, code = "E0117")]
+    #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)]
     Arbitrary {
         #[primary_span]
         #[label(hir_analysis_only_current_traits_label)]
@@ -1412,7 +1412,7 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_static_mut_ref, code = "E0796")]
+#[diag(hir_analysis_static_mut_ref, code = E0796)]
 #[note]
 pub struct StaticMutRef {
     #[primary_span]
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 2fe08ead72b..c072891e295 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -12,7 +12,7 @@ use crate::constrained_generic_params as cgp;
 use min_specialization::check_min_specialization;
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{LocalDefId, LocalModDefId};
 use rustc_middle::query::Providers;
diff --git a/compiler/rustc_hir_analysis/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs
index b061d637138..6846e4defe5 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors.rs
@@ -6,18 +6,18 @@ pub use self::{
     missing_cast_for_variadic_arg::*, sized_unsized_cast::*, wrong_number_of_generic_args::*,
 };
 
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{DiagnosticBuilder, ErrCode};
 use rustc_session::Session;
 
 pub trait StructuredDiagnostic<'tcx> {
     fn session(&self) -> &Session;
 
-    fn code(&self) -> String;
+    fn code(&self) -> ErrCode;
 
     fn diagnostic(&self) -> DiagnosticBuilder<'tcx> {
         let err = self.diagnostic_common();
 
-        if self.session().teach(&self.code()) {
+        if self.session().teach(self.code()) {
             self.diagnostic_extended(err)
         } else {
             self.diagnostic_regular(err)
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
index 6f4435db411..50b4ef623ac 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -1,5 +1,5 @@
 use crate::{errors, structured_errors::StructuredDiagnostic};
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{codes::*, DiagnosticBuilder, ErrCode};
 use rustc_middle::ty::{Ty, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::Span;
@@ -16,8 +16,8 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx, '_> {
         self.sess
     }
 
-    fn code(&self) -> String {
-        rustc_errors::error_code!(E0617)
+    fn code(&self) -> ErrCode {
+        E0617
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
index 19cac4a38aa..54d54a2af93 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
@@ -1,5 +1,5 @@
 use crate::{errors, structured_errors::StructuredDiagnostic};
-use rustc_errors::DiagnosticBuilder;
+use rustc_errors::{codes::*, DiagnosticBuilder, ErrCode};
 use rustc_middle::ty::{Ty, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::Span;
@@ -16,8 +16,8 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
         self.sess
     }
 
-    fn code(&self) -> String {
-        rustc_errors::error_code!(E0607)
+    fn code(&self) -> ErrCode {
+        E0607
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index ba81e7f1f81..501915d2e7e 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -1,5 +1,7 @@
 use crate::structured_errors::StructuredDiagnostic;
-use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
+use rustc_errors::{
+    codes::*, pluralize, Applicability, Diagnostic, DiagnosticBuilder, ErrCode, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_middle::ty::{self as ty, AssocItems, AssocKind, TyCtxt};
 use rustc_session::Session;
@@ -1105,8 +1107,8 @@ impl<'tcx> StructuredDiagnostic<'tcx> for WrongNumberOfGenericArgs<'_, 'tcx> {
         self.tcx.sess
     }
 
-    fn code(&self) -> String {
-        rustc_errors::error_code!(E0107)
+    fn code(&self) -> ErrCode {
+        E0107
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index bd8a2024caa..a0ac839f3dd 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -33,7 +33,7 @@ use super::FnCtxt;
 use crate::errors;
 use crate::type_error_struct;
 use hir::ExprKind;
-use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{codes::*, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_macros::{TypeFoldable, TypeVisitable};
 use rustc_middle::mir::Mutability;
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 858faf161f6..ca636ebcade 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -36,7 +36,9 @@
 //! ```
 
 use crate::FnCtxt;
-use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan};
+use rustc_errors::{
+    codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
+};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{self, Visitor};
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 4f929068887..b75cf4b4e8b 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -3,8 +3,8 @@ use std::borrow::Cow;
 
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg, MultiSpan,
-    SubdiagnosticMessage,
+    codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticArgValue, IntoDiagnosticArg,
+    MultiSpan, SubdiagnosticMessage,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
@@ -15,7 +15,7 @@ use rustc_span::{
 };
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_field_multiply_specified_in_initializer, code = "E0062")]
+#[diag(hir_typeck_field_multiply_specified_in_initializer, code = E0062)]
 pub struct FieldMultiplySpecifiedInInitializer {
     #[primary_span]
     #[label]
@@ -26,7 +26,7 @@ pub struct FieldMultiplySpecifiedInInitializer {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_return_stmt_outside_of_fn_body, code = "E0572")]
+#[diag(hir_typeck_return_stmt_outside_of_fn_body, code = E0572)]
 pub struct ReturnStmtOutsideOfFnBody {
     #[primary_span]
     pub span: Span,
@@ -62,14 +62,14 @@ pub struct RustCallIncorrectArgs {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = "E0627")]
+#[diag(hir_typeck_yield_expr_outside_of_coroutine, code = E0627)]
 pub struct YieldExprOutsideOfCoroutine {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_struct_expr_non_exhaustive, code = "E0639")]
+#[diag(hir_typeck_struct_expr_non_exhaustive, code = E0639)]
 pub struct StructExprNonExhaustive {
     #[primary_span]
     pub span: Span,
@@ -77,7 +77,7 @@ pub struct StructExprNonExhaustive {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_method_call_on_unknown_raw_pointee, code = "E0699")]
+#[diag(hir_typeck_method_call_on_unknown_raw_pointee, code = E0699)]
 pub struct MethodCallOnUnknownRawPointee {
     #[primary_span]
     pub span: Span,
@@ -92,14 +92,14 @@ pub struct MissingFnLangItems {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_functional_record_update_on_non_struct, code = "E0436")]
+#[diag(hir_typeck_functional_record_update_on_non_struct, code = E0436)]
 pub struct FunctionalRecordUpdateOnNonStruct {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_address_of_temporary_taken, code = "E0745")]
+#[diag(hir_typeck_address_of_temporary_taken, code = E0745)]
 pub struct AddressOfTemporaryTaken {
     #[primary_span]
     #[label]
@@ -145,7 +145,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_explicit_destructor, code = "E0040")]
+#[diag(hir_typeck_explicit_destructor, code = E0040)]
 pub struct ExplicitDestructorCall {
     #[primary_span]
     #[label]
@@ -168,7 +168,7 @@ pub enum ExplicitDestructorCallSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_missing_parentheses_in_range, code = "E0689")]
+#[diag(hir_typeck_missing_parentheses_in_range, code = E0689)]
 pub struct MissingParenthesesInRange {
     #[primary_span]
     #[label(hir_typeck_missing_parentheses_in_range)]
@@ -321,7 +321,7 @@ impl HelpUseLatestEdition {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_invalid_callee, code = "E0618")]
+#[diag(hir_typeck_invalid_callee, code = E0618)]
 pub struct InvalidCallee {
     #[primary_span]
     pub span: Span,
@@ -329,7 +329,7 @@ pub struct InvalidCallee {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_int_to_fat, code = "E0606")]
+#[diag(hir_typeck_int_to_fat, code = E0606)]
 pub struct IntToWide<'tcx> {
     #[primary_span]
     #[label(hir_typeck_int_to_fat_label)]
@@ -510,7 +510,7 @@ pub struct TrivialCast<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_no_associated_item, code = "E0599")]
+#[diag(hir_typeck_no_associated_item, code = E0599)]
 pub struct NoAssociatedItem {
     #[primary_span]
     pub span: Span,
@@ -532,7 +532,7 @@ pub struct CandidateTraitNote {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_cannot_cast_to_bool, code = "E0054")]
+#[diag(hir_typeck_cannot_cast_to_bool, code = E0054)]
 pub struct CannotCastToBool<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -549,7 +549,7 @@ pub struct CastEnumDrop<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_cast_unknown_pointer, code = "E0641")]
+#[diag(hir_typeck_cast_unknown_pointer, code = E0641)]
 pub struct CastUnknownPointer {
     #[primary_span]
     pub span: Span,
@@ -600,7 +600,7 @@ pub enum CannotCastToBoolHelp {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_typeck_ctor_is_private, code = "E0603")]
+#[diag(hir_typeck_ctor_is_private, code = E0603)]
 pub struct CtorIsPrivate {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 3bc259c17b7..fafed5be8c5 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -25,8 +25,8 @@ use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
-    pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder,
-    ErrorGuaranteed, StashKey,
+    codes::*, pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diagnostic,
+    DiagnosticBuilder, ErrCode, ErrorGuaranteed, StashKey,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -527,7 +527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Ty::new_error(tcx, e)
             }
             Res::Def(DefKind::Variant, _) => {
-                let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, "E0533", "value");
+                let e = report_unexpected_variant_res(tcx, res, qpath, expr.span, E0533, "value");
                 Ty::new_error(tcx, e)
             }
             _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
@@ -939,7 +939,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(crate) fn check_lhs_assignable(
         &self,
         lhs: &'tcx hir::Expr<'tcx>,
-        err_code: &'static str,
+        code: ErrCode,
         op_span: Span,
         adjust_err: impl FnOnce(&mut Diagnostic),
     ) {
@@ -948,7 +948,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment");
-        err.code(err_code.into());
+        err.code(code);
         err.span_label(lhs.span, "cannot assign to this expression");
 
         self.comes_from_while_condition(lhs.hir_id, |expr| {
@@ -1244,7 +1244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             diag.emit();
         }
 
-        self.check_lhs_assignable(lhs, "E0070", span, |err| {
+        self.check_lhs_assignable(lhs, E0070, span, |err| {
             if let Some(rhs_ty) = self.typeck_results.borrow().expr_ty_opt(rhs) {
                 suggest_deref_binop(err, rhs_ty);
             }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 6a77450f075..2494feee1ff 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -12,7 +12,9 @@ use crate::{
 use itertools::Itertools;
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{pluralize, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan, StashKey};
+use rustc_errors::{
+    codes::*, pluralize, Applicability, Diagnostic, ErrCode, ErrorGuaranteed, MultiSpan, StashKey,
+};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
@@ -177,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.register_wf_obligation(fn_input_ty.into(), arg_expr.span, traits::MiscObligation);
         }
 
-        let mut err_code = "E0061";
+        let mut err_code = E0061;
 
         // If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
         let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
@@ -187,7 +189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 ty::Tuple(arg_types) => {
                     // Argument length differs
                     if arg_types.len() != provided_args.len() {
-                        err_code = "E0057";
+                        err_code = E0057;
                     }
                     let expected_input_tys = match expected_input_tys {
                         Some(expected_input_tys) => match expected_input_tys.get(0) {
@@ -358,7 +360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if c_variadic && provided_arg_count < minimum_input_count {
-            err_code = "E0060";
+            err_code = E0060;
         }
 
         for arg in provided_args.iter().skip(minimum_input_count) {
@@ -443,7 +445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         formal_and_expected_inputs: IndexVec<ExpectedIdx, (Ty<'tcx>, Ty<'tcx>)>,
         provided_args: IndexVec<ProvidedIdx, &'tcx hir::Expr<'tcx>>,
         c_variadic: bool,
-        err_code: &str,
+        err_code: ErrCode,
         fn_def_id: Option<DefId>,
         call_span: Span,
         call_expr: &'tcx hir::Expr<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 18f547be2a7..449de631f5a 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -369,6 +369,14 @@ pub struct LoweredTy<'tcx> {
 
 impl<'tcx> LoweredTy<'tcx> {
     pub fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> {
-        LoweredTy { raw, normalized: fcx.normalize(span, raw) }
+        // FIXME(-Znext-solver): We're still figuring out how to best handle
+        // normalization and this doesn't feel too great. We should look at this
+        // code again before stabilizing it.
+        let normalized = if fcx.next_trait_solver() {
+            fcx.try_structurally_resolve_type(span, raw)
+        } else {
+            fcx.normalize(span, raw)
+        };
+        LoweredTy { raw, normalized }
     }
 }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 7780ceda1c1..95c1139e43e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -2040,7 +2040,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let field_is_local = sole_field.did.is_local();
                     let field_is_accessible =
                         sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
-                        // Skip suggestions for unstable public fields (for example `Pin::pointer`)
+                        // Skip suggestions for unstable public fields (for example `Pin::__pointer`)
                         && matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked);
 
                     if !field_is_local && !field_is_accessible {
@@ -2140,46 +2140,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr_ty: Ty<'tcx>,
     ) -> bool {
         let tcx = self.tcx;
-        let (adt, unwrap) = match expected.kind() {
+        let (adt, substs, unwrap) = match expected.kind() {
             // In case Option<NonZero*> is wanted, but * is provided, suggest calling new
-            ty::Adt(adt, args) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
-                // Unwrap option
-                let ty::Adt(adt, _) = args.type_at(0).kind() else {
+            ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
+                let nonzero_type = substs.type_at(0); // Unwrap option type.
+                let ty::Adt(adt, substs) = nonzero_type.kind() else {
                     return false;
                 };
-
-                (adt, "")
+                (adt, substs, "")
             }
-            // In case NonZero* is wanted, but * is provided also add `.unwrap()` to satisfy types
-            ty::Adt(adt, _) => (adt, ".unwrap()"),
+            // In case `NonZero<*>` is wanted but `*` is provided, also add `.unwrap()` to satisfy types.
+            ty::Adt(adt, substs) => (adt, substs, ".unwrap()"),
             _ => return false,
         };
 
-        let map = [
-            (sym::NonZeroU8, tcx.types.u8),
-            (sym::NonZeroU16, tcx.types.u16),
-            (sym::NonZeroU32, tcx.types.u32),
-            (sym::NonZeroU64, tcx.types.u64),
-            (sym::NonZeroU128, tcx.types.u128),
-            (sym::NonZeroI8, tcx.types.i8),
-            (sym::NonZeroI16, tcx.types.i16),
-            (sym::NonZeroI32, tcx.types.i32),
-            (sym::NonZeroI64, tcx.types.i64),
-            (sym::NonZeroI128, tcx.types.i128),
+        if !self.tcx.is_diagnostic_item(sym::NonZero, adt.did()) {
+            return false;
+        }
+
+        // FIXME: This can be simplified once `NonZero<T>` is stable.
+        let coercable_types = [
+            ("NonZeroU8", tcx.types.u8),
+            ("NonZeroU16", tcx.types.u16),
+            ("NonZeroU32", tcx.types.u32),
+            ("NonZeroU64", tcx.types.u64),
+            ("NonZeroU128", tcx.types.u128),
+            ("NonZeroI8", tcx.types.i8),
+            ("NonZeroI16", tcx.types.i16),
+            ("NonZeroI32", tcx.types.i32),
+            ("NonZeroI64", tcx.types.i64),
+            ("NonZeroI128", tcx.types.i128),
         ];
 
-        let Some((s, _)) = map.iter().find(|&&(s, t)| {
-            self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t)
+        let int_type = substs.type_at(0);
+
+        let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| {
+            if *t == int_type && self.can_coerce(expr_ty, *t) { Some(nonzero_alias) } else { None }
         }) else {
             return false;
         };
 
-        let path = self.tcx.def_path_str(adt.non_enum_variant().def_id);
-
         err.multipart_suggestion(
-            format!("consider calling `{s}::new`"),
+            format!("consider calling `{nonzero_alias}::new`"),
             vec![
-                (expr.span.shrink_to_lo(), format!("{path}::new(")),
+                (expr.span.shrink_to_lo(), format!("{nonzero_alias}::new(")),
                 (expr.span.shrink_to_hi(), format!("){unwrap}")),
             ],
             Applicability::MaybeIncorrect,
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index e087733130e..2dee5093e87 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -1,5 +1,5 @@
 use hir::HirId;
-use rustc_errors::struct_span_code_err;
+use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_index::Idx;
 use rustc_middle::ty::layout::{LayoutError, SizeSkeleton};
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 36cd6583147..36aa949668f 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -51,7 +51,7 @@ use crate::expectation::Expectation;
 use crate::fn_ctxt::LoweredTy;
 use crate::gather_locals::GatherLocalsVisitor;
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
+use rustc_errors::{codes::*, struct_span_code_err, ErrCode, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::Visitor;
@@ -71,7 +71,7 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
 #[macro_export]
 macro_rules! type_error_struct {
-    ($dcx:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
+    ($dcx:expr, $span:expr, $typ:expr, $code:expr, $($message:tt)*) => ({
         let mut err = rustc_errors::struct_span_code_err!($dcx, $span, $code, $($message)*);
 
         if $typ.references_error() {
@@ -375,7 +375,7 @@ fn report_unexpected_variant_res(
     res: Res,
     qpath: &hir::QPath<'_>,
     span: Span,
-    err_code: &str,
+    err_code: ErrCode,
     expected: &str,
 ) -> ErrorGuaranteed {
     let res_descr = match res {
@@ -386,9 +386,9 @@ fn report_unexpected_variant_res(
     let err = tcx
         .dcx()
         .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`"))
-        .with_code(err_code.into());
+        .with_code(err_code);
     match res {
-        Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => {
+        Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == E0164 => {
             let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html";
             err.with_span_label(span, "`fn` calls are not allowed in patterns")
                 .with_help(format!("for more information, visit {patterns_url}"))
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 0b8a25eedaf..314d28e6e04 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -3,17 +3,16 @@
 
 // ignore-tidy-filelength
 
-use crate::errors;
-use crate::errors::{CandidateTraitNote, NoAssociatedItem};
+use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
 use crate::Expectation;
 use crate::FnCtxt;
 use rustc_ast::ast::Mutability;
 use rustc_attr::parse_confusables;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::StashKey;
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    MultiSpan, StashKey,
 };
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -1601,23 +1600,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.ty_to_value_string(rcvr_ty.peel_refs())
         };
         if let SelfSource::MethodCall(_) = source {
-            let first_arg = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0)
-                && let Some(assoc) = self.associated_value(*impl_did, item_name)
-                && assoc.kind == ty::AssocKind::Fn
-            {
+            let first_arg = static_candidates.get(0).and_then(|candidate_source| {
+                let (assoc_did, self_ty) = match candidate_source {
+                    CandidateSource::Impl(impl_did) => {
+                        (*impl_did, self.tcx.type_of(*impl_did).instantiate_identity())
+                    }
+                    CandidateSource::Trait(trait_did) => (*trait_did, rcvr_ty),
+                };
+
+                let assoc = self.associated_value(assoc_did, item_name)?;
+                if assoc.kind != ty::AssocKind::Fn {
+                    return None;
+                }
+
+                // for CandidateSource::Impl, `Self` will be instantiated to a concrete type
+                // but for CandidateSource::Trait, `Self` is still `Self`
                 let sig = self.tcx.fn_sig(assoc.def_id).instantiate_identity();
                 sig.inputs().skip_binder().get(0).and_then(|first| {
-                    let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
                     // if the type of first arg is the same as the current impl type, we should take the first arg into assoc function
-                    if first.peel_refs() == impl_ty {
+                    let first_ty = first.peel_refs();
+                    if first_ty == self_ty || first_ty == self.tcx.types.self_param {
                         Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
                     } else {
                         None
                     }
                 })
-            } else {
-                None
-            };
+            });
+
             let mut applicability = Applicability::MachineApplicable;
             let args = if let SelfSource::MethodCall(receiver) = source
                 && let Some(args) = args
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index ff82e2d653c..bbe6d9e9670 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -5,7 +5,7 @@ use super::{has_expected_num_generic_args, FnCtxt};
 use crate::Expectation;
 use rustc_ast as ast;
 use rustc_data_structures::packed::Pu128;
-use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::traits::ObligationCauseCode;
@@ -44,7 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 return_ty
             };
 
-        self.check_lhs_assignable(lhs, "E0067", op.span, |err| {
+        self.check_lhs_assignable(lhs, E0067, op.span, |err| {
             if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
                 if self
                     .lookup_op_method(
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index e31eeab4c4a..a611d0eda85 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -3,8 +3,8 @@ use crate::{errors, FnCtxt, LoweredTy};
 use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-    MultiSpan,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -576,7 +576,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         if (lhs, rhs).references_error() {
             err.downgrade_to_delayed_bug();
         }
-        if self.tcx.sess.teach(&err.get_code().unwrap()) {
+        if self.tcx.sess.teach(err.get_code().unwrap()) {
             err.note(
                 "In a match expression, only numbers and characters can be matched \
                     against a range. This is because the compiler checks that the range \
@@ -847,7 +847,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 type_str
             );
             err.span_label(span, format!("type `{type_str}` cannot be dereferenced"));
-            if self.tcx.sess.teach(&err.get_code().unwrap()) {
+            if self.tcx.sess.teach(err.get_code().unwrap()) {
                 err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ);
             }
             return Err(err.emit());
@@ -907,7 +907,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
                 let expected = "unit struct, unit variant or constant";
-                let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0533", expected);
+                let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0533, expected);
                 return Ty::new_error(tcx, e);
             }
             Res::SelfCtor(..)
@@ -1061,7 +1061,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         let report_unexpected_res = |res: Res| {
             let expected = "tuple struct or tuple variant";
-            let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, "E0164", expected);
+            let e = report_unexpected_variant_res(tcx, res, qpath, pat.span, E0164, expected);
             on_error(e);
             e
         };
@@ -1669,7 +1669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
         }
-        if tcx.sess.teach(&err.get_code().unwrap()) {
+        if tcx.sess.teach(err.get_code().unwrap()) {
             err.note(
                 "This error indicates that a struct pattern attempted to \
                  extract a nonexistent field from a struct. Struct fields \
diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs
index d3cf267dc9d..0c1180b3e98 100644
--- a/compiler/rustc_index/src/interval.rs
+++ b/compiler/rustc_index/src/interval.rs
@@ -236,6 +236,12 @@ impl<I: Idx> IntervalSet<I> {
         I: Step,
     {
         assert_eq!(self.domain, other.domain);
+        if self.map.len() < other.map.len() {
+            let backup = self.clone();
+            self.map.clone_from(&other.map);
+            return self.union(&backup);
+        }
+
         let mut did_insert = false;
         for range in other.iter_intervals() {
             did_insert |= self.insert_range(range);
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index 66c5cc774b2..d876174e620 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -12,10 +12,13 @@ use std::vec;
 use crate::{Idx, IndexSlice};
 
 /// An owned contiguous collection of `T`s, indexed by `I` rather than by `usize`.
+/// Its purpose is to avoid mixing indexes.
 ///
 /// While it's possible to use `u32` or `usize` directly for `I`,
 /// you almost certainly want to use a [`newtype_index!`]-generated type instead.
 ///
+/// This allows to index the IndexVec with the new index type.
+///
 /// [`newtype_index!`]: ../macro.newtype_index.html
 #[derive(Clone, PartialEq, Eq, Hash)]
 #[repr(transparent)]
@@ -25,11 +28,13 @@ pub struct IndexVec<I: Idx, T> {
 }
 
 impl<I: Idx, T> IndexVec<I, T> {
+    /// Constructs a new, empty `IndexVec<I, T>`.
     #[inline]
     pub const fn new() -> Self {
         IndexVec::from_raw(Vec::new())
     }
 
+    /// Constructs a new `IndexVec<I, T>` from a `Vec<T>`.
     #[inline]
     pub const fn from_raw(raw: Vec<T>) -> Self {
         IndexVec { raw, _marker: PhantomData }
@@ -59,6 +64,7 @@ impl<I: Idx, T> IndexVec<I, T> {
         IndexVec::from_raw(vec![elem; universe.len()])
     }
 
+    /// Creates a new IndexVec with n copies of the `elem`.
     #[inline]
     pub fn from_elem_n(elem: T, n: usize) -> Self
     where
@@ -85,6 +91,7 @@ impl<I: Idx, T> IndexVec<I, T> {
         IndexSlice::from_raw_mut(&mut self.raw)
     }
 
+    /// Pushes an element to the array returning the index where it was pushed to.
     #[inline]
     pub fn push(&mut self, d: T) -> I {
         let idx = self.next_index();
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index aee99063e03..4e9f573091b 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,7 +1,7 @@
 use hir::GenericParamKind;
 use rustc_errors::{
-    AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
-    IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
+    codes::*, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage,
+    DiagnosticStyledString, IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage,
 };
 use rustc_hir as hir;
 use rustc_hir::FnRetTy;
@@ -33,7 +33,7 @@ pub struct OpaqueHiddenTypeDiag {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = "E0282")]
+#[diag(infer_type_annotations_needed, code = E0282)]
 pub struct AnnotationRequired<'a> {
     #[primary_span]
     pub span: Span,
@@ -51,7 +51,7 @@ pub struct AnnotationRequired<'a> {
 
 // Copy of `AnnotationRequired` for E0283
 #[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = "E0283")]
+#[diag(infer_type_annotations_needed, code = E0283)]
 pub struct AmbiguousImpl<'a> {
     #[primary_span]
     pub span: Span,
@@ -69,7 +69,7 @@ pub struct AmbiguousImpl<'a> {
 
 // Copy of `AnnotationRequired` for E0284
 #[derive(Diagnostic)]
-#[diag(infer_type_annotations_needed, code = "E0284")]
+#[diag(infer_type_annotations_needed, code = E0284)]
 pub struct AmbiguousReturn<'a> {
     #[primary_span]
     pub span: Span,
@@ -421,7 +421,7 @@ impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_lifetime_mismatch, code = "E0623")]
+#[diag(infer_lifetime_mismatch, code = E0623)]
 pub struct LifetimeMismatch<'a> {
     #[primary_span]
     pub span: Span,
@@ -495,7 +495,7 @@ pub struct MismatchedStaticLifetime<'a> {
 
 #[derive(Diagnostic)]
 pub enum ExplicitLifetimeRequired<'a> {
-    #[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")]
+    #[diag(infer_explicit_lifetime_required_with_ident, code = E0621)]
     WithIdent {
         #[primary_span]
         #[label]
@@ -511,7 +511,7 @@ pub enum ExplicitLifetimeRequired<'a> {
         #[skip_arg]
         new_ty: Ty<'a>,
     },
-    #[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")]
+    #[diag(infer_explicit_lifetime_required_with_param_type, code = E0621)]
     WithParamType {
         #[primary_span]
         #[label]
@@ -819,7 +819,7 @@ impl AddToDiagnostic for DynTraitConstraintSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_but_calling_introduces, code = "E0772")]
+#[diag(infer_but_calling_introduces, code = E0772)]
 pub struct ButCallingIntroduces {
     #[label(infer_label1)]
     pub param_ty_span: Span,
@@ -871,14 +871,14 @@ impl AddToDiagnostic for MoreTargeted {
     where
         F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
     {
-        diag.code(rustc_errors::error_code!(E0772));
+        diag.code(E0772);
         diag.primary_message(fluent::infer_more_targeted);
         diag.arg("ident", self.ident);
     }
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_but_needs_to_satisfy, code = "E0759")]
+#[diag(infer_but_needs_to_satisfy, code = E0759)]
 pub struct ButNeedsToSatisfy {
     #[primary_span]
     pub sp: Span,
@@ -904,7 +904,7 @@ pub struct ButNeedsToSatisfy {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_outlives_content, code = "E0312")]
+#[diag(infer_outlives_content, code = E0312)]
 pub struct OutlivesContent<'a> {
     #[primary_span]
     pub span: Span,
@@ -913,7 +913,7 @@ pub struct OutlivesContent<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_outlives_bound, code = "E0476")]
+#[diag(infer_outlives_bound, code = E0476)]
 pub struct OutlivesBound<'a> {
     #[primary_span]
     pub span: Span,
@@ -922,7 +922,7 @@ pub struct OutlivesBound<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_fulfill_req_lifetime, code = "E0477")]
+#[diag(infer_fulfill_req_lifetime, code = E0477)]
 pub struct FulfillReqLifetime<'a> {
     #[primary_span]
     pub span: Span,
@@ -932,7 +932,7 @@ pub struct FulfillReqLifetime<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_lf_bound_not_satisfied, code = "E0478")]
+#[diag(infer_lf_bound_not_satisfied, code = E0478)]
 pub struct LfBoundNotSatisfied<'a> {
     #[primary_span]
     pub span: Span,
@@ -941,7 +941,7 @@ pub struct LfBoundNotSatisfied<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_ref_longer_than_data, code = "E0491")]
+#[diag(infer_ref_longer_than_data, code = E0491)]
 pub struct RefLongerThanData<'a> {
     #[primary_span]
     pub span: Span,
@@ -1117,7 +1117,7 @@ pub enum PlaceholderRelationLfNotSatisfied {
 }
 
 #[derive(Diagnostic)]
-#[diag(infer_opaque_captures_lifetime, code = "E0700")]
+#[diag(infer_opaque_captures_lifetime, code = E0700)]
 pub struct OpaqueCapturesLifetime<'tcx> {
     #[primary_span]
     pub span: Span,
@@ -1378,73 +1378,73 @@ pub enum TypeErrorAdditionalDiags {
 
 #[derive(Diagnostic)]
 pub enum ObligationCauseFailureCode {
-    #[diag(infer_oc_method_compat, code = "E0308")]
+    #[diag(infer_oc_method_compat, code = E0308)]
     MethodCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_type_compat, code = "E0308")]
+    #[diag(infer_oc_type_compat, code = E0308)]
     TypeCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_const_compat, code = "E0308")]
+    #[diag(infer_oc_const_compat, code = E0308)]
     ConstCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_try_compat, code = "E0308")]
+    #[diag(infer_oc_try_compat, code = E0308)]
     TryCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_match_compat, code = "E0308")]
+    #[diag(infer_oc_match_compat, code = E0308)]
     MatchCompat {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_if_else_different, code = "E0308")]
+    #[diag(infer_oc_if_else_different, code = E0308)]
     IfElseDifferent {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_no_else, code = "E0317")]
+    #[diag(infer_oc_no_else, code = E0317)]
     NoElse {
         #[primary_span]
         span: Span,
     },
-    #[diag(infer_oc_no_diverge, code = "E0308")]
+    #[diag(infer_oc_no_diverge, code = E0308)]
     NoDiverge {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_fn_main_correct_type, code = "E0580")]
+    #[diag(infer_oc_fn_main_correct_type, code = E0580)]
     FnMainCorrectType {
         #[primary_span]
         span: Span,
     },
-    #[diag(infer_oc_fn_start_correct_type, code = "E0308")]
+    #[diag(infer_oc_fn_start_correct_type, code = E0308)]
     FnStartCorrectType {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_fn_lang_correct_type, code = "E0308")]
+    #[diag(infer_oc_fn_lang_correct_type, code = E0308)]
     FnLangCorrectType {
         #[primary_span]
         span: Span,
@@ -1452,33 +1452,33 @@ pub enum ObligationCauseFailureCode {
         subdiags: Vec<TypeErrorAdditionalDiags>,
         lang_item_name: Symbol,
     },
-    #[diag(infer_oc_intrinsic_correct_type, code = "E0308")]
+    #[diag(infer_oc_intrinsic_correct_type, code = E0308)]
     IntrinsicCorrectType {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_method_correct_type, code = "E0308")]
+    #[diag(infer_oc_method_correct_type, code = E0308)]
     MethodCorrectType {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_closure_selfref, code = "E0644")]
+    #[diag(infer_oc_closure_selfref, code = E0644)]
     ClosureSelfref {
         #[primary_span]
         span: Span,
     },
-    #[diag(infer_oc_cant_coerce, code = "E0308")]
+    #[diag(infer_oc_cant_coerce, code = E0308)]
     CantCoerce {
         #[primary_span]
         span: Span,
         #[subdiagnostic]
         subdiags: Vec<TypeErrorAdditionalDiags>,
     },
-    #[diag(infer_oc_generic, code = "E0308")]
+    #[diag(infer_oc_generic, code = E0308)]
     Generic {
         #[primary_span]
         span: Span,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 7882e761a0c..e19177fccef 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -60,7 +60,7 @@ use crate::traits::{
 
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{
-    error_code, pluralize, struct_span_code_err, Applicability, DiagCtxt, Diagnostic,
+    codes::*, pluralize, struct_span_code_err, Applicability, DiagCtxt, Diagnostic,
     DiagnosticBuilder, DiagnosticStyledString, ErrorGuaranteed, IntoDiagnosticArg,
 };
 use rustc_hir as hir;
@@ -2362,9 +2362,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             .dcx()
             .struct_span_err(span, format!("{labeled_user_string} may not live long enough"));
         err.code(match sub.kind() {
-            ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309),
-            ty::ReStatic => error_code!(E0310),
-            _ => error_code!(E0311),
+            ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => E0309,
+            ty::ReStatic => E0310,
+            _ => E0311,
         });
 
         '_explain: {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 03c8e08aa01..cf1e042c529 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -5,7 +5,7 @@ use crate::errors::{
 use crate::infer::error_reporting::TypeErrCtxt;
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::InferCtxt;
-use rustc_errors::{DiagnosticBuilder, IntoDiagnosticArg};
+use rustc_errors::{codes::*, DiagnosticBuilder, ErrCode, IntoDiagnosticArg};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
@@ -43,12 +43,12 @@ pub enum TypeAnnotationNeeded {
     E0284,
 }
 
-impl Into<String> for TypeAnnotationNeeded {
-    fn into(self) -> String {
+impl Into<ErrCode> for TypeAnnotationNeeded {
+    fn into(self) -> ErrCode {
         match self {
-            Self::E0282 => rustc_errors::error_code!(E0282),
-            Self::E0283 => rustc_errors::error_code!(E0283),
-            Self::E0284 => rustc_errors::error_code!(E0284),
+            Self::E0282 => E0282,
+            Self::E0283 => E0283,
+            Self::E0284 => E0284,
         }
     }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index 21ea48c6c83..0e7c641e0e0 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -195,7 +195,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             }
                         }
                         diag.help("type parameters must be constrained to match other types");
-                        if tcx.sess.teach(&diag.get_code().unwrap()) {
+                        if tcx.sess.teach(diag.get_code().unwrap()) {
                             diag.help(
                                 "given a type parameter `T` and a method `foo`:
 ```
@@ -678,7 +678,7 @@ impl<T> Trait<T> for X {
                  https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
             );
         }
-        if tcx.sess.teach(&diag.get_code().unwrap()) {
+        if tcx.sess.teach(diag.get_code().unwrap()) {
             diag.help(
                 "given an associated type `T` and a method `foo`:
 ```
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index 6f218019dee..eabc1b953af 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -2,7 +2,7 @@ use super::ObjectSafetyViolation;
 
 use crate::infer::InferCtxt;
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::Map;
diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs
index 0a632c4d12a..03d178eb266 100644
--- a/compiler/rustc_lexer/src/unescape.rs
+++ b/compiler/rustc_lexer/src/unescape.rs
@@ -80,12 +80,12 @@ impl EscapeError {
     }
 }
 
-/// Takes a contents of a literal (without quotes) and produces a sequence of
-/// escaped characters or errors.
+/// Takes the contents of a unicode-only (non-mixed-utf8) literal (without
+/// quotes) and produces a sequence of escaped characters or errors.
 ///
 /// Values are returned by invoking `callback`. For `Char` and `Byte` modes,
 /// the callback will be called exactly once.
-pub fn unescape_literal<F>(src: &str, mode: Mode, callback: &mut F)
+pub fn unescape_unicode<F>(src: &str, mode: Mode, callback: &mut F)
 where
     F: FnMut(Range<usize>, Result<char, EscapeError>),
 {
@@ -97,50 +97,63 @@ where
         }
         Str | ByteStr => unescape_non_raw_common(src, mode, callback),
         RawStr | RawByteStr => check_raw_common(src, mode, callback),
-        CStr | RawCStr => unreachable!(),
+        RawCStr => check_raw_common(src, mode, &mut |r, mut result| {
+            if let Ok('\0') = result {
+                result = Err(EscapeError::NulInCStr);
+            }
+            callback(r, result)
+        }),
+        CStr => unreachable!(),
     }
 }
 
-/// A unit within CStr. Must not be a nul character.
-pub enum CStrUnit {
-    Byte(u8),
+/// Used for mixed utf8 string literals, i.e. those that allow both unicode
+/// chars and high bytes.
+pub enum MixedUnit {
+    /// Used for ASCII chars (written directly or via `\x00`..`\x7f` escapes)
+    /// and Unicode chars (written directly or via `\u` escapes).
+    ///
+    /// For example, if '¥' appears in a string it is represented here as
+    /// `MixedUnit::Char('¥')`, and it will be appended to the relevant byte
+    /// string as the two-byte UTF-8 sequence `[0xc2, 0xa5]`
     Char(char),
+
+    /// Used for high bytes (`\x80`..`\xff`).
+    ///
+    /// For example, if `\xa5` appears in a string it is represented here as
+    /// `MixedUnit::HighByte(0xa5)`, and it will be appended to the relevant
+    /// byte string as the single byte `0xa5`.
+    HighByte(u8),
 }
 
-impl From<u8> for CStrUnit {
-    fn from(value: u8) -> Self {
-        CStrUnit::Byte(value)
+impl From<char> for MixedUnit {
+    fn from(c: char) -> Self {
+        MixedUnit::Char(c)
     }
 }
 
-impl From<char> for CStrUnit {
-    fn from(value: char) -> Self {
-        CStrUnit::Char(value)
+impl From<u8> for MixedUnit {
+    fn from(n: u8) -> Self {
+        if n.is_ascii() { MixedUnit::Char(n as char) } else { MixedUnit::HighByte(n) }
     }
 }
 
-pub fn unescape_c_string<F>(src: &str, mode: Mode, callback: &mut F)
+/// Takes the contents of a mixed-utf8 literal (without quotes) and produces
+/// a sequence of escaped characters or errors.
+///
+/// Values are returned by invoking `callback`.
+pub fn unescape_mixed<F>(src: &str, mode: Mode, callback: &mut F)
 where
-    F: FnMut(Range<usize>, Result<CStrUnit, EscapeError>),
+    F: FnMut(Range<usize>, Result<MixedUnit, EscapeError>),
 {
     match mode {
-        CStr => {
-            unescape_non_raw_common(src, mode, &mut |r, mut result| {
-                if let Ok(CStrUnit::Byte(0) | CStrUnit::Char('\0')) = result {
-                    result = Err(EscapeError::NulInCStr);
-                }
-                callback(r, result)
-            });
-        }
-        RawCStr => {
-            check_raw_common(src, mode, &mut |r, mut result| {
-                if let Ok('\0') = result {
-                    result = Err(EscapeError::NulInCStr);
-                }
-                callback(r, result.map(CStrUnit::Char))
-            });
-        }
-        Char | Byte | Str | RawStr | ByteStr | RawByteStr => unreachable!(),
+        CStr => unescape_non_raw_common(src, mode, &mut |r, mut result| {
+            if let Ok(MixedUnit::Char('\0')) = result {
+                result = Err(EscapeError::NulInCStr);
+            }
+            callback(r, result)
+        }),
+        Char | Byte | Str | RawStr | ByteStr | RawByteStr | RawCStr => unreachable!(),
     }
 }
 
@@ -181,29 +194,29 @@ impl Mode {
         }
     }
 
-    /// Non-byte literals should have `\xXX` escapes that are within the ASCII range.
-    fn ascii_escapes_should_be_ascii(self) -> bool {
+    /// Are `\x80`..`\xff` allowed?
+    fn allow_high_bytes(self) -> bool {
         match self {
-            Char | Str => true,
-            Byte | ByteStr | CStr => false,
+            Char | Str => false,
+            Byte | ByteStr | CStr => true,
             RawStr | RawByteStr | RawCStr => unreachable!(),
         }
     }
 
-    /// Whether characters within the literal must be within the ASCII range.
+    /// Are unicode (non-ASCII) chars allowed?
     #[inline]
-    fn chars_should_be_ascii(self) -> bool {
+    fn allow_unicode_chars(self) -> bool {
         match self {
-            Byte | ByteStr | RawByteStr => true,
-            Char | Str | RawStr | CStr | RawCStr => false,
+            Byte | ByteStr | RawByteStr => false,
+            Char | Str | RawStr | CStr | RawCStr => true,
         }
     }
 
-    /// Byte literals do not allow unicode escape.
-    fn is_unicode_escape_disallowed(self) -> bool {
+    /// Are unicode escapes (`\u`) allowed?
+    fn allow_unicode_escapes(self) -> bool {
         match self {
-            Byte | ByteStr => true,
-            Char | Str | CStr => false,
+            Byte | ByteStr => false,
+            Char | Str | CStr => true,
             RawByteStr | RawStr | RawCStr => unreachable!(),
         }
     }
@@ -217,20 +230,19 @@ impl Mode {
     }
 }
 
-fn scan_escape<T: From<u8> + From<char>>(
+fn scan_escape<T: From<char> + From<u8>>(
     chars: &mut Chars<'_>,
     mode: Mode,
 ) -> Result<T, EscapeError> {
     // Previous character was '\\', unescape what follows.
-    let res = match chars.next().ok_or(EscapeError::LoneSlash)? {
-        '"' => b'"',
-        'n' => b'\n',
-        'r' => b'\r',
-        't' => b'\t',
-        '\\' => b'\\',
-        '\'' => b'\'',
-        '0' => b'\0',
-
+    let res: char = match chars.next().ok_or(EscapeError::LoneSlash)? {
+        '"' => '"',
+        'n' => '\n',
+        'r' => '\r',
+        't' => '\t',
+        '\\' => '\\',
+        '\'' => '\'',
+        '0' => '\0',
         'x' => {
             // Parse hexadecimal character code.
 
@@ -240,25 +252,23 @@ fn scan_escape<T: From<u8> + From<char>>(
             let lo = chars.next().ok_or(EscapeError::TooShortHexEscape)?;
             let lo = lo.to_digit(16).ok_or(EscapeError::InvalidCharInHexEscape)?;
 
-            let value = hi * 16 + lo;
-
-            if mode.ascii_escapes_should_be_ascii() && !is_ascii(value) {
-                return Err(EscapeError::OutOfRangeHexEscape);
-            }
+            let value = (hi * 16 + lo) as u8;
 
-            value as u8
+            return if !mode.allow_high_bytes() && !value.is_ascii() {
+                Err(EscapeError::OutOfRangeHexEscape)
+            } else {
+                // This may be a high byte, but that will only happen if `T` is
+                // `MixedUnit`, because of the `allow_high_bytes` check above.
+                Ok(T::from(value as u8))
+            };
         }
-
-        'u' => return scan_unicode(chars, mode.is_unicode_escape_disallowed()).map(Into::into),
+        'u' => return scan_unicode(chars, mode.allow_unicode_escapes()).map(T::from),
         _ => return Err(EscapeError::InvalidEscape),
     };
-    Ok(res.into())
+    Ok(T::from(res))
 }
 
-fn scan_unicode(
-    chars: &mut Chars<'_>,
-    is_unicode_escape_disallowed: bool,
-) -> Result<char, EscapeError> {
+fn scan_unicode(chars: &mut Chars<'_>, allow_unicode_escapes: bool) -> Result<char, EscapeError> {
     // We've parsed '\u', now we have to parse '{..}'.
 
     if chars.next() != Some('{') {
@@ -286,7 +296,7 @@ fn scan_unicode(
 
                 // Incorrect syntax has higher priority for error reporting
                 // than unallowed value for a literal.
-                if is_unicode_escape_disallowed {
+                if !allow_unicode_escapes {
                     return Err(EscapeError::UnicodeEscapeInByte);
                 }
 
@@ -312,12 +322,8 @@ fn scan_unicode(
 }
 
 #[inline]
-fn ascii_check(c: char, chars_should_be_ascii: bool) -> Result<char, EscapeError> {
-    if chars_should_be_ascii && !c.is_ascii() {
-        Err(EscapeError::NonAsciiCharInByte)
-    } else {
-        Ok(c)
-    }
+fn ascii_check(c: char, allow_unicode_chars: bool) -> Result<char, EscapeError> {
+    if allow_unicode_chars || c.is_ascii() { Ok(c) } else { Err(EscapeError::NonAsciiCharInByte) }
 }
 
 fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
@@ -326,7 +332,7 @@ fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, Esca
         '\\' => scan_escape(chars, mode),
         '\n' | '\t' | '\'' => Err(EscapeError::EscapeOnlyChar),
         '\r' => Err(EscapeError::BareCarriageReturn),
-        _ => ascii_check(c, mode.chars_should_be_ascii()),
+        _ => ascii_check(c, mode.allow_unicode_chars()),
     }?;
     if chars.next().is_some() {
         return Err(EscapeError::MoreThanOneChar);
@@ -336,12 +342,12 @@ fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, Esca
 
 /// Takes a contents of a string literal (without quotes) and produces a
 /// sequence of escaped characters or errors.
-fn unescape_non_raw_common<F, T: From<u8> + From<char>>(src: &str, mode: Mode, callback: &mut F)
+fn unescape_non_raw_common<F, T: From<char> + From<u8>>(src: &str, mode: Mode, callback: &mut F)
 where
     F: FnMut(Range<usize>, Result<T, EscapeError>),
 {
     let mut chars = src.chars();
-    let chars_should_be_ascii = mode.chars_should_be_ascii(); // get this outside the loop
+    let allow_unicode_chars = mode.allow_unicode_chars(); // get this outside the loop
 
     // The `start` and `end` computation here is complicated because
     // `skip_ascii_whitespace` makes us to skip over chars without counting
@@ -366,7 +372,7 @@ where
             }
             '"' => Err(EscapeError::EscapeOnlyChar),
             '\r' => Err(EscapeError::BareCarriageReturn),
-            _ => ascii_check(c, chars_should_be_ascii).map(Into::into),
+            _ => ascii_check(c, allow_unicode_chars).map(T::from),
         };
         let end = src.len() - chars.as_str().len();
         callback(start..end, res);
@@ -408,7 +414,7 @@ where
     F: FnMut(Range<usize>, Result<char, EscapeError>),
 {
     let mut chars = src.chars();
-    let chars_should_be_ascii = mode.chars_should_be_ascii(); // get this outside the loop
+    let allow_unicode_chars = mode.allow_unicode_chars(); // get this outside the loop
 
     // The `start` and `end` computation here matches the one in
     // `unescape_non_raw_common` for consistency, even though this function
@@ -417,7 +423,7 @@ where
         let start = src.len() - chars.as_str().len() - c.len_utf8();
         let res = match c {
             '\r' => Err(EscapeError::BareCarriageReturnInRawString),
-            _ => ascii_check(c, chars_should_be_ascii),
+            _ => ascii_check(c, allow_unicode_chars),
         };
         let end = src.len() - chars.as_str().len();
         callback(start..end, res);
@@ -430,7 +436,3 @@ pub fn byte_from_char(c: char) -> u8 {
     debug_assert!(res <= u8::MAX as u32, "guaranteed because of ByteStr");
     res as u8
 }
-
-fn is_ascii(x: u32) -> bool {
-    x <= 0x7F
-}
diff --git a/compiler/rustc_lexer/src/unescape/tests.rs b/compiler/rustc_lexer/src/unescape/tests.rs
index 1c25b03fdb2..5b99495f475 100644
--- a/compiler/rustc_lexer/src/unescape/tests.rs
+++ b/compiler/rustc_lexer/src/unescape/tests.rs
@@ -100,7 +100,7 @@ fn test_unescape_char_good() {
 fn test_unescape_str_warn() {
     fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
         let mut unescaped = Vec::with_capacity(literal.len());
-        unescape_literal(literal, Mode::Str, &mut |range, res| unescaped.push((range, res)));
+        unescape_unicode(literal, Mode::Str, &mut |range, res| unescaped.push((range, res)));
         assert_eq!(unescaped, expected);
     }
 
@@ -124,7 +124,7 @@ fn test_unescape_str_warn() {
 fn test_unescape_str_good() {
     fn check(literal_text: &str, expected: &str) {
         let mut buf = Ok(String::with_capacity(literal_text.len()));
-        unescape_literal(literal_text, Mode::Str, &mut |range, c| {
+        unescape_unicode(literal_text, Mode::Str, &mut |range, c| {
             if let Ok(b) = &mut buf {
                 match c {
                     Ok(c) => b.push(c),
@@ -241,7 +241,7 @@ fn test_unescape_byte_good() {
 fn test_unescape_byte_str_good() {
     fn check(literal_text: &str, expected: &[u8]) {
         let mut buf = Ok(Vec::with_capacity(literal_text.len()));
-        unescape_literal(literal_text, Mode::ByteStr, &mut |range, c| {
+        unescape_unicode(literal_text, Mode::ByteStr, &mut |range, c| {
             if let Ok(b) = &mut buf {
                 match c {
                     Ok(c) => b.push(byte_from_char(c)),
@@ -264,7 +264,7 @@ fn test_unescape_byte_str_good() {
 fn test_unescape_raw_str() {
     fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
         let mut unescaped = Vec::with_capacity(literal.len());
-        unescape_literal(literal, Mode::RawStr, &mut |range, res| unescaped.push((range, res)));
+        unescape_unicode(literal, Mode::RawStr, &mut |range, res| unescaped.push((range, res)));
         assert_eq!(unescaped, expected);
     }
 
@@ -276,7 +276,7 @@ fn test_unescape_raw_str() {
 fn test_unescape_raw_byte_str() {
     fn check(literal: &str, expected: &[(Range<usize>, Result<char, EscapeError>)]) {
         let mut unescaped = Vec::with_capacity(literal.len());
-        unescape_literal(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res)));
+        unescape_unicode(literal, Mode::RawByteStr, &mut |range, res| unescaped.push((range, res)));
         assert_eq!(unescaped, expected);
     }
 
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 841d282a099..3bd0c1b8031 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -1,11 +1,11 @@
 use crate::fluent_generated as fluent;
-use rustc_errors::{AddToDiagnostic, Diagnostic, SubdiagnosticMessage};
+use rustc_errors::{codes::*, AddToDiagnostic, Diagnostic, SubdiagnosticMessage};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_session::lint::Level;
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
-#[diag(lint_overruled_attribute, code = "E0453")]
+#[diag(lint_overruled_attribute, code = E0453)]
 pub struct OverruledAttribute<'a> {
     #[primary_span]
     pub span: Span,
@@ -48,7 +48,7 @@ impl AddToDiagnostic for OverruledAttributeSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_malformed_attribute, code = "E0452")]
+#[diag(lint_malformed_attribute, code = E0452)]
 pub struct MalformedAttribute {
     #[primary_span]
     pub span: Span,
@@ -67,7 +67,7 @@ pub enum MalformedAttributeSub {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_unknown_tool_in_scoped_lint, code = "E0710")]
+#[diag(lint_unknown_tool_in_scoped_lint, code = E0710)]
 pub struct UnknownToolInScopedLint {
     #[primary_span]
     pub span: Option<Span>,
@@ -78,7 +78,7 @@ pub struct UnknownToolInScopedLint {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
+#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = E0783)]
 pub struct BuiltinEllipsisInclusiveRangePatterns {
     #[primary_span]
     pub span: Span,
@@ -95,13 +95,13 @@ pub struct RequestedLevel<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_unsupported_group, code = "E0602")]
+#[diag(lint_unsupported_group, code = E0602)]
 pub struct UnsupportedGroup {
     pub lint_group: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(lint_check_name_unknown_tool, code = "E0602")]
+#[diag(lint_check_name_unknown_tool, code = E0602)]
 pub struct CheckNameUnknownTool<'a> {
     pub tool_name: Symbol,
     #[subdiagnostic]
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index e19bb1cb62f..f916deb4a46 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -5,8 +5,8 @@ use std::num::NonZeroU32;
 use crate::errors::RequestedLevel;
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
-    DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle,
+    codes::*, AddToDiagnostic, Applicability, DecorateLint, Diagnostic, DiagnosticBuilder,
+    DiagnosticMessage, DiagnosticStyledString, SubdiagnosticMessage, SuggestionStyle,
 };
 use rustc_hir::def_id::DefId;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
@@ -1065,7 +1065,7 @@ pub enum UnknownLintSuggestion {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(lint_unknown_lint, code = "E0602")]
+#[diag(lint_unknown_lint, code = E0602)]
 pub struct UnknownLintFromCommandLine<'a> {
     pub name: String,
     #[subdiagnostic]
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index f64509fe8bc..bed5d3c80c0 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -4,7 +4,7 @@ use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{
     self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable,
 };
-use rustc_span::Span;
+use rustc_span::{symbol::kw, Span};
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 
@@ -96,6 +96,17 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
                 continue;
             }
 
+            // HACK: `async fn() -> Self` in traits is "ok"...
+            // This is not really that great, but it's similar to why the `-> Self`
+            // return type is well-formed in traits even when `Self` isn't sized.
+            if let ty::Param(param_ty) = *proj_term.kind()
+                && param_ty.name == kw::SelfUpper
+                && matches!(opaque.origin, hir::OpaqueTyOrigin::AsyncFn(_))
+                && opaque.in_trait
+            {
+                continue;
+            }
+
             let proj_ty =
                 Ty::new_projection(cx.tcx, proj.projection_ty.def_id, proj.projection_ty.args);
             // For every instance of the projection type in the bounds,
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 0b7ecff8148..85bb9584a05 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -209,9 +209,9 @@ impl DiagnosticDeriveVariantBuilder {
                 if path.is_ident("code") {
                     self.code.set_once((), path.span().unwrap());
 
-                    let code = nested.parse::<syn::LitStr>()?;
+                    let code = nested.parse::<syn::Expr>()?;
                     tokens.extend(quote! {
-                        diag.code(#code.to_string());
+                        diag.code(#code);
                     });
                 } else {
                     span_err(path.span().unwrap(), "unknown argument")
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index 135b9e32fe7..33dffe6998a 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -20,7 +20,7 @@ use synstructure::Structure;
 /// # extern crate rust_middle;
 /// # use rustc_middle::ty::Ty;
 /// #[derive(Diagnostic)]
-/// #[diag(borrowck_move_out_of_borrow, code = "E0505")]
+/// #[diag(borrowck_move_out_of_borrow, code = E0505)]
 /// pub struct MoveOutOfBorrowError<'tcx> {
 ///     pub name: Ident,
 ///     pub ty: Ty<'tcx>,
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 27c26d31781..d17bf0cf708 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -4,7 +4,7 @@ use std::{
 };
 
 use rustc_errors::{
-    error_code, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
+    codes::*, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_macros::Diagnostic;
 use rustc_session::config;
@@ -122,7 +122,7 @@ pub struct WasmImportForm {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_empty_link_name, code = "E0454")]
+#[diag(metadata_empty_link_name, code = E0454)]
 pub struct EmptyLinkName {
     #[primary_span]
     #[label]
@@ -130,21 +130,21 @@ pub struct EmptyLinkName {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_link_framework_apple, code = "E0455")]
+#[diag(metadata_link_framework_apple, code = E0455)]
 pub struct LinkFrameworkApple {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_framework_only_windows, code = "E0455")]
+#[diag(metadata_framework_only_windows, code = E0455)]
 pub struct FrameworkOnlyWindows {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_unknown_link_kind, code = "E0458")]
+#[diag(metadata_unknown_link_kind, code = E0458)]
 pub struct UnknownLinkKind<'a> {
     #[primary_span]
     #[label]
@@ -239,7 +239,7 @@ pub struct IncompatibleWasmLink {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_link_requires_name, code = "E0459")]
+#[diag(metadata_link_requires_name, code = E0459)]
 pub struct LinkRequiresName {
     #[primary_span]
     #[label]
@@ -502,7 +502,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for MultipleCandidates {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_multiple_candidates);
         diag.arg("crate_name", self.crate_name);
         diag.arg("flavor", self.flavor);
-        diag.code(error_code!(E0464));
+        diag.code(E0464);
         diag.span(self.span);
         for (i, candidate) in self.candidates.iter().enumerate() {
             diag.note(format!("candidate #{}: {}", i + 1, candidate.display()));
@@ -512,7 +512,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for MultipleCandidates {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_symbol_conflicts_current, code = "E0519")]
+#[diag(metadata_symbol_conflicts_current, code = E0519)]
 pub struct SymbolConflictsCurrent {
     #[primary_span]
     pub span: Span,
@@ -537,7 +537,7 @@ pub struct DlError {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_newer_crate_version, code = "E0460")]
+#[diag(metadata_newer_crate_version, code = E0460)]
 #[note]
 #[note(metadata_found_crate_versions)]
 pub struct NewerCrateVersion {
@@ -549,7 +549,7 @@ pub struct NewerCrateVersion {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_no_crate_with_triple, code = "E0461")]
+#[diag(metadata_no_crate_with_triple, code = E0461)]
 #[note(metadata_found_crate_versions)]
 pub struct NoCrateWithTriple<'a> {
     #[primary_span]
@@ -561,7 +561,7 @@ pub struct NoCrateWithTriple<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_found_staticlib, code = "E0462")]
+#[diag(metadata_found_staticlib, code = E0462)]
 #[note(metadata_found_crate_versions)]
 #[help]
 pub struct FoundStaticlib {
@@ -573,7 +573,7 @@ pub struct FoundStaticlib {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_incompatible_rustc, code = "E0514")]
+#[diag(metadata_incompatible_rustc, code = E0514)]
 #[note(metadata_found_crate_versions)]
 #[help]
 pub struct IncompatibleRustc {
@@ -598,7 +598,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidMetadataFiles {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_invalid_meta_files);
         diag.arg("crate_name", self.crate_name);
         diag.arg("add_info", self.add_info);
-        diag.code(error_code!(E0786));
+        diag.code(E0786);
         diag.span(self.span);
         for crate_rejection in self.crate_rejections {
             diag.note(crate_rejection);
@@ -627,7 +627,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for CannotFindCrate {
         diag.arg("current_crate", self.current_crate);
         diag.arg("add_info", self.add_info);
         diag.arg("locator_triple", self.locator_triple.triple());
-        diag.code(error_code!(E0463));
+        diag.code(E0463);
         diag.span(self.span);
         if (self.crate_name == sym::std || self.crate_name == sym::core)
             && self.locator_triple != TargetTriple::from_triple(config::host_triple())
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 3c553657087..e0436b38c4b 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,14 +1,14 @@
 use std::borrow::Cow;
 use std::fmt;
 
-use rustc_errors::{DiagnosticArgValue, DiagnosticMessage};
+use rustc_errors::{codes::*, DiagnosticArgValue, DiagnosticMessage};
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
 
 use crate::ty::Ty;
 
 #[derive(Diagnostic)]
-#[diag(middle_drop_check_overflow, code = "E0320")]
+#[diag(middle_drop_check_overflow, code = E0320)]
 #[note]
 pub struct DropCheckOverflow<'tcx> {
     #[primary_span]
diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs
index 5d6a7f75df8..b9914f6cb7a 100644
--- a/compiler/rustc_middle/src/middle/region.rs
+++ b/compiler/rustc_middle/src/middle/region.rs
@@ -221,9 +221,6 @@ pub struct ScopeTree {
     /// variable is declared.
     var_map: FxIndexMap<hir::ItemLocalId, Scope>,
 
-    /// Maps from a `NodeId` to the associated destruction scope (if any).
-    destruction_scopes: FxIndexMap<hir::ItemLocalId, Scope>,
-
     /// Identifies expressions which, if captured into a temporary, ought to
     /// have a temporary whose lifetime extends to the end of the enclosing *block*,
     /// and not the enclosing *statement*. Expressions that are not present in this
@@ -336,11 +333,6 @@ impl ScopeTree {
             let prev = self.parent_map.insert(child, p);
             assert!(prev.is_none());
         }
-
-        // Record the destruction scopes for later so we can query them.
-        if let ScopeData::Destruction = child.data {
-            self.destruction_scopes.insert(child.item_local_id(), child);
-        }
     }
 
     pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index a5c229879a7..a4b6c4f9c3f 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1074,6 +1074,8 @@ pub enum ProjectionElem<V, T> {
     /// "Downcast" to a variant of an enum or a coroutine.
     ///
     /// The included Symbol is the name of the variant, used for printing MIR.
+    ///
+    /// This operation itself is never UB, all it does is change the type of the place.
     Downcast(Option<Symbol>, VariantIdx),
 
     /// Like an explicit cast from an opaque type to a concrete type, but without
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 6a03bf243eb..27b48f46e75 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -1,7 +1,7 @@
 use crate::dep_graph::dep_kinds;
 use crate::query::plumbing::CyclePlaceholder;
 use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan};
+use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_middle::ty::Representability;
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index e1b998b2471..6929c8040c5 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1,7 +1,7 @@
 use crate::fluent_generated as fluent;
 use rustc_errors::DiagnosticArgValue;
 use rustc_errors::{
-    error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
+    codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
     IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -138,7 +138,7 @@ pub struct UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = "E0133")]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe, code = E0133)]
 #[note]
 pub struct CallToUnsafeFunctionRequiresUnsafe<'a> {
     #[primary_span]
@@ -150,7 +150,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafe<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = "E0133")]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_nameless, code = E0133)]
 #[note]
 pub struct CallToUnsafeFunctionRequiresUnsafeNameless {
     #[primary_span]
@@ -161,7 +161,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNameless {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_call_to_unsafe_fn_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
     #[primary_span]
@@ -175,7 +175,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
 #[derive(Diagnostic)]
 #[diag(
     mir_build_call_to_unsafe_fn_requires_unsafe_nameless_unsafe_op_in_unsafe_fn_allowed,
-    code = "E0133"
+    code = E0133
 )]
 #[note]
 pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
@@ -187,7 +187,7 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_inline_assembly_requires_unsafe, code = "E0133")]
+#[diag(mir_build_inline_assembly_requires_unsafe, code = E0133)]
 #[note]
 pub struct UseOfInlineAssemblyRequiresUnsafe {
     #[primary_span]
@@ -198,7 +198,7 @@ pub struct UseOfInlineAssemblyRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_inline_assembly_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -209,7 +209,7 @@ pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_initializing_type_with_requires_unsafe, code = "E0133")]
+#[diag(mir_build_initializing_type_with_requires_unsafe, code = E0133)]
 #[note]
 pub struct InitializingTypeWithRequiresUnsafe {
     #[primary_span]
@@ -222,7 +222,7 @@ pub struct InitializingTypeWithRequiresUnsafe {
 #[derive(Diagnostic)]
 #[diag(
     mir_build_initializing_type_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
-    code = "E0133"
+    code = E0133
 )]
 #[note]
 pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
@@ -234,7 +234,7 @@ pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_mutable_static_requires_unsafe, code = "E0133")]
+#[diag(mir_build_mutable_static_requires_unsafe, code = E0133)]
 #[note]
 pub struct UseOfMutableStaticRequiresUnsafe {
     #[primary_span]
@@ -245,7 +245,7 @@ pub struct UseOfMutableStaticRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_mutable_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -256,7 +256,7 @@ pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_extern_static_requires_unsafe, code = "E0133")]
+#[diag(mir_build_extern_static_requires_unsafe, code = E0133)]
 #[note]
 pub struct UseOfExternStaticRequiresUnsafe {
     #[primary_span]
@@ -267,7 +267,7 @@ pub struct UseOfExternStaticRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -278,7 +278,7 @@ pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = "E0133")]
+#[diag(mir_build_deref_raw_pointer_requires_unsafe, code = E0133)]
 #[note]
 pub struct DerefOfRawPointerRequiresUnsafe {
     #[primary_span]
@@ -289,7 +289,7 @@ pub struct DerefOfRawPointerRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -300,7 +300,7 @@ pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_union_field_requires_unsafe, code = "E0133")]
+#[diag(mir_build_union_field_requires_unsafe, code = E0133)]
 #[note]
 pub struct AccessToUnionFieldRequiresUnsafe {
     #[primary_span]
@@ -311,7 +311,7 @@ pub struct AccessToUnionFieldRequiresUnsafe {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[note]
 pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
     #[primary_span]
@@ -322,7 +322,7 @@ pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = "E0133")]
+#[diag(mir_build_mutation_of_layout_constrained_field_requires_unsafe, code = E0133)]
 #[note]
 pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
     #[primary_span]
@@ -335,7 +335,7 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe {
 #[derive(Diagnostic)]
 #[diag(
     mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
-    code = "E0133"
+    code = E0133
 )]
 #[note]
 pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
@@ -347,7 +347,7 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllow
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = "E0133")]
+#[diag(mir_build_borrow_of_layout_constrained_field_requires_unsafe, code = E0133)]
 #[note]
 pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
     #[primary_span]
@@ -360,7 +360,7 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe {
 #[derive(Diagnostic)]
 #[diag(
     mir_build_borrow_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed,
-    code = "E0133"
+    code = E0133
 )]
 #[note]
 pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed {
@@ -372,7 +372,7 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_fn_with_requires_unsafe, code = "E0133")]
+#[diag(mir_build_call_to_fn_with_requires_unsafe, code = E0133)]
 #[help]
 pub struct CallToFunctionWithRequiresUnsafe<'a> {
     #[primary_span]
@@ -390,7 +390,7 @@ pub struct CallToFunctionWithRequiresUnsafe<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = "E0133")]
+#[diag(mir_build_call_to_fn_with_requires_unsafe_unsafe_op_in_unsafe_fn_allowed, code = E0133)]
 #[help]
 pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> {
     #[primary_span]
@@ -468,7 +468,7 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
             fluent::mir_build_non_exhaustive_patterns_type_not_empty,
         );
         diag.span(self.span);
-        diag.code(error_code!(E0004));
+        diag.code(E0004);
         let peeled_ty = self.ty.peel_refs();
         diag.arg("ty", self.ty);
         diag.arg("peeled_ty", peeled_ty);
@@ -539,28 +539,28 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
 pub struct NonExhaustiveMatchAllArmsGuarded;
 
 #[derive(Diagnostic)]
-#[diag(mir_build_static_in_pattern, code = "E0158")]
+#[diag(mir_build_static_in_pattern, code = E0158)]
 pub struct StaticInPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_assoc_const_in_pattern, code = "E0158")]
+#[diag(mir_build_assoc_const_in_pattern, code = E0158)]
 pub struct AssocConstInPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_const_param_in_pattern, code = "E0158")]
+#[diag(mir_build_const_param_in_pattern, code = E0158)]
 pub struct ConstParamInPattern {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_non_const_path, code = "E0080")]
+#[diag(mir_build_non_const_path, code = E0080)]
 pub struct NonConstPath {
     #[primary_span]
     pub span: Span,
@@ -590,7 +590,7 @@ pub struct CouldNotEvalConstPattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = "E0030")]
+#[diag(mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper, code = E0030)]
 pub struct LowerRangeBoundMustBeLessThanOrEqualToUpper {
     #[primary_span]
     #[label]
@@ -611,7 +611,7 @@ pub struct LiteralOutOfRange<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = "E0579")]
+#[diag(mir_build_lower_range_bound_must_be_less_than_upper, code = E0579)]
 pub struct LowerRangeBoundMustBeLessThanUpper {
     #[primary_span]
     pub span: Span,
@@ -634,7 +634,7 @@ pub struct TrailingIrrefutableLetPatterns {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(mir_build_bindings_with_variant_name, code = "E0170")]
+#[diag(mir_build_bindings_with_variant_name, code = E0170)]
 pub struct BindingsWithVariantName {
     #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")]
     pub suggestion: Option<Span>,
@@ -821,7 +821,7 @@ pub struct NonPartialEqMatch<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_build_pattern_not_covered, code = "E0005")]
+#[diag(mir_build_pattern_not_covered, code = E0005)]
 pub(crate) struct PatternNotCovered<'s, 'tcx> {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index ce75a2831a5..caf7f4227db 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -11,7 +11,7 @@ use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
-    struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
+    codes::*, struct_span_code_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::*;
@@ -47,9 +47,18 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), Err
     };
     visitor.visit_expr(&thir[expr]);
 
+    let origin = match tcx.def_kind(def_id) {
+        DefKind::AssocFn | DefKind::Fn => "function argument",
+        DefKind::Closure => "closure argument",
+        // other types of MIR don't have function parameters, and we don't need to
+        // categorize those for the irrefutable check.
+        _ if thir.params.is_empty() => "",
+        kind => bug!("unexpected function parameters in THIR: {kind:?} {def_id:?}"),
+    };
+
     for param in thir.params.iter() {
         if let Some(box ref pattern) = param.pat {
-            visitor.check_binding_is_irrefutable(pattern, "function argument", None, None);
+            visitor.check_binding_is_irrefutable(pattern, origin, None, None);
         }
     }
     visitor.error
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index ff7e985bdfd..2190ad14b55 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -8,7 +8,7 @@ pub(crate) use self::check_match::check_match;
 use crate::errors::*;
 use crate::thir::util::UserAnnotatedTyHelpers;
 
-use rustc_errors::error_code;
+use rustc_errors::codes::*;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
@@ -209,7 +209,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     RangeEnd::Included => {
                         self.tcx.dcx().emit_err(LowerRangeBoundMustBeLessThanOrEqualToUpper {
                             span,
-                            teach: self.tcx.sess.teach(&error_code!(E0030)).then_some(()),
+                            teach: self.tcx.sess.teach(E0030).then_some(()),
                         })
                     }
                     RangeEnd::Excluded => {
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index d5f22b2cdbc..ad12bce9b02 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -403,12 +403,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
             operand,
             &mut |elem, op| match elem {
                 TrackElem::Field(idx) => self.ecx.project_field(op, idx.as_usize()).ok(),
-                TrackElem::Variant(idx) => {
-                    if op.layout.for_variant(&self.ecx, idx).abi.is_uninhabited() {
-                        return None;
-                    }
-                    self.ecx.project_downcast(op, idx).ok()
-                }
+                TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).ok(),
                 TrackElem::Discriminant => {
                     let variant = self.ecx.read_discriminant(op).ok()?;
                     let discr_value =
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 4574cb4d28d..4ef3d47d6a6 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -1,7 +1,7 @@
 use std::borrow::Cow;
 
 use rustc_errors::{
-    Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder,
+    codes::*, Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder,
     DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, Level,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -33,7 +33,7 @@ pub(crate) enum ConstMutate {
 }
 
 #[derive(Diagnostic)]
-#[diag(mir_transform_unaligned_packed_ref, code = "E0793")]
+#[diag(mir_transform_unaligned_packed_ref, code = E0793)]
 #[note]
 #[note(mir_transform_note_ub)]
 #[help]
@@ -66,7 +66,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe {
     #[track_caller]
     fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe);
-        diag.code("E0133".to_string());
+        diag.code(E0133);
         diag.span(self.span);
         diag.span_label(self.span, self.details.label());
         let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter());
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index f904e0c44ea..aac8c0b3103 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -772,6 +772,20 @@ parse_unexpected_const_param_declaration = unexpected `const` parameter declarat
 parse_unexpected_default_value_for_lifetime_in_generic_parameters = unexpected default lifetime parameter
     .label = lifetime parameters cannot have default values
 
+parse_unexpected_expr_in_pat =
+    expected {$is_bound ->
+        [true] a pattern range bound
+       *[false] a pattern
+    }, found {$is_method_call ->
+        [true] a method call
+       *[false] an expression
+    }
+
+    .label = {$is_method_call ->
+        [true] method calls
+       *[false] arbitrary expressions
+    } are not allowed in patterns
+
 parse_unexpected_if_with_if = unexpected `if` in the condition expression
     .suggestion = remove the `if`
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 40852048293..4e4bf9bdad9 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -3,7 +3,7 @@ use std::borrow::Cow;
 use rustc_ast::token::Token;
 use rustc_ast::{Path, Visibility};
 use rustc_errors::{
-    AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level,
+    codes::*, AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, IntoDiagnostic, Level,
     SubdiagnosticMessage,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
@@ -25,7 +25,7 @@ pub(crate) struct AmbiguousPlus {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_maybe_recover_from_bad_type_plus, code = "E0178")]
+#[diag(parse_maybe_recover_from_bad_type_plus, code = E0178)]
 pub(crate) struct BadTypePlus {
     pub ty: String,
     #[primary_span]
@@ -807,7 +807,7 @@ pub(crate) struct InclusiveRangeMatchArrow {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_inclusive_range_no_end, code = "E0586")]
+#[diag(parse_inclusive_range_no_end, code = E0586)]
 #[note]
 pub(crate) struct InclusiveRangeNoEnd {
     #[primary_span]
@@ -901,7 +901,7 @@ pub(crate) struct MismatchedClosingDelimiter {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_incorrect_visibility_restriction, code = "E0704")]
+#[diag(parse_incorrect_visibility_restriction, code = E0704)]
 #[help]
 pub(crate) struct IncorrectVisibilityRestriction {
     #[primary_span]
@@ -925,7 +925,7 @@ pub(crate) struct ExpectedStatementAfterOuterAttr {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_doc_comment_does_not_document_anything, code = "E0585")]
+#[diag(parse_doc_comment_does_not_document_anything, code = E0585)]
 #[help]
 pub(crate) struct DocCommentDoesNotDocumentAnything {
     #[primary_span]
@@ -1357,7 +1357,7 @@ pub(crate) struct AttributeOnParamType {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_pattern_method_param_without_body, code = "E0642")]
+#[diag(parse_pattern_method_param_without_body, code = E0642)]
 pub(crate) struct PatternMethodParamWithoutBody {
     #[primary_span]
     #[suggestion(code = "_", applicability = "machine-applicable")]
@@ -1565,7 +1565,7 @@ pub(crate) struct WhereClauseBeforeTupleStructBodySugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_async_fn_in_2015, code = "E0670")]
+#[diag(parse_async_fn_in_2015, code = E0670)]
 pub(crate) struct AsyncFnIn2015 {
     #[primary_span]
     #[label]
@@ -1929,7 +1929,7 @@ pub struct CrDocComment {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_no_digits_literal, code = "E0768")]
+#[diag(parse_no_digits_literal, code = E0768)]
 pub struct NoDigitsLiteral {
     #[primary_span]
     pub span: Span,
@@ -2416,6 +2416,18 @@ pub(crate) struct ExpectedCommaAfterPatternField {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_unexpected_expr_in_pat)]
+pub(crate) struct UnexpectedExpressionInPattern {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    /// Was a `RangePatternBound` expected?
+    pub is_bound: bool,
+    /// Was the unexpected expression a `MethodCallExpression`?
+    pub is_method_call: bool,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_unexpected_paren_in_range_pat)]
 pub(crate) struct UnexpectedParenInRangePat {
     #[primary_span]
@@ -2499,7 +2511,7 @@ pub(crate) struct FnPointerCannotBeAsync {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_nested_c_variadic_type, code = "E0743")]
+#[diag(parse_nested_c_variadic_type, code = E0743)]
 pub(crate) struct NestedCVariadicType {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index d7ecf577ed6..31552452676 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, DiagnosticBuilder, StashKey};
+use rustc_errors::{codes::*, Applicability, DiagCtxt, DiagnosticBuilder, StashKey};
 use rustc_lexer::unescape::{self, EscapeError, Mode};
 use rustc_lexer::{Base, DocStyle, RawStrError};
 use rustc_lexer::{Cursor, LiteralKind};
@@ -397,10 +397,10 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                 if !terminated {
                     self.dcx()
                         .struct_span_fatal(self.mk_sp(start, end), "unterminated character literal")
-                        .with_code(error_code!(E0762))
+                        .with_code(E0762)
                         .emit()
                 }
-                self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' '
+                self.cook_unicode(token::Char, Mode::Char, start, end, 1, 1) // ' '
             }
             rustc_lexer::LiteralKind::Byte { terminated } => {
                 if !terminated {
@@ -409,10 +409,10 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                             self.mk_sp(start + BytePos(1), end),
                             "unterminated byte constant",
                         )
-                        .with_code(error_code!(E0763))
+                        .with_code(E0763)
                         .emit()
                 }
-                self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' '
+                self.cook_unicode(token::Byte, Mode::Byte, start, end, 2, 1) // b' '
             }
             rustc_lexer::LiteralKind::Str { terminated } => {
                 if !terminated {
@@ -421,10 +421,10 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                             self.mk_sp(start, end),
                             "unterminated double quote string",
                         )
-                        .with_code(error_code!(E0765))
+                        .with_code(E0765)
                         .emit()
                 }
-                self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " "
+                self.cook_unicode(token::Str, Mode::Str, start, end, 1, 1) // " "
             }
             rustc_lexer::LiteralKind::ByteStr { terminated } => {
                 if !terminated {
@@ -433,10 +433,10 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                             self.mk_sp(start + BytePos(1), end),
                             "unterminated double quote byte string",
                         )
-                        .with_code(error_code!(E0766))
+                        .with_code(E0766)
                         .emit()
                 }
-                self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" "
+                self.cook_unicode(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" "
             }
             rustc_lexer::LiteralKind::CStr { terminated } => {
                 if !terminated {
@@ -445,16 +445,16 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                             self.mk_sp(start + BytePos(1), end),
                             "unterminated C string",
                         )
-                        .with_code(error_code!(E0767))
+                        .with_code(E0767)
                         .emit()
                 }
-                self.cook_c_string(token::CStr, Mode::CStr, start, end, 2, 1) // c" "
+                self.cook_mixed(token::CStr, Mode::CStr, start, end, 2, 1) // c" "
             }
             rustc_lexer::LiteralKind::RawStr { n_hashes } => {
                 if let Some(n_hashes) = n_hashes {
                     let n = u32::from(n_hashes);
                     let kind = token::StrRaw(n_hashes);
-                    self.cook_quoted(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "##
+                    self.cook_unicode(kind, Mode::RawStr, start, end, 2 + n, 1 + n) // r##" "##
                 } else {
                     self.report_raw_str_error(start, 1);
                 }
@@ -463,7 +463,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                 if let Some(n_hashes) = n_hashes {
                     let n = u32::from(n_hashes);
                     let kind = token::ByteStrRaw(n_hashes);
-                    self.cook_quoted(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "##
+                    self.cook_unicode(kind, Mode::RawByteStr, start, end, 3 + n, 1 + n) // br##" "##
                 } else {
                     self.report_raw_str_error(start, 2);
                 }
@@ -472,7 +472,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
                 if let Some(n_hashes) = n_hashes {
                     let n = u32::from(n_hashes);
                     let kind = token::CStrRaw(n_hashes);
-                    self.cook_c_string(kind, Mode::RawCStr, start, end, 3 + n, 1 + n) // cr##" "##
+                    self.cook_unicode(kind, Mode::RawCStr, start, end, 3 + n, 1 + n) // cr##" "##
                 } else {
                     self.report_raw_str_error(start, 2);
                 }
@@ -582,7 +582,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
     ) -> ! {
         let mut err =
             self.dcx().struct_span_fatal(self.mk_sp(start, start), "unterminated raw string");
-        err.code(error_code!(E0748));
+        err.code(E0748);
         err.span_label(self.mk_sp(start, start), "unterminated raw string");
 
         if n_hashes > 0 {
@@ -614,7 +614,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
         };
         let last_bpos = self.pos;
         let mut err = self.dcx().struct_span_fatal(self.mk_sp(start, last_bpos), msg);
-        err.code(error_code!(E0758));
+        err.code(E0758);
         let mut nested_block_comment_open_idxs = vec![];
         let mut last_nested_block_comment_idxs = None;
         let mut content_chars = self.str_from(start).char_indices().peekable();
@@ -735,7 +735,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
         }
     }
 
-    fn cook_quoted(
+    fn cook_unicode(
         &self,
         kind: token::LitKind,
         mode: Mode,
@@ -745,13 +745,13 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
         postfix_len: u32,
     ) -> (token::LitKind, Symbol) {
         self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| {
-            unescape::unescape_literal(src, mode, &mut |span, result| {
+            unescape::unescape_unicode(src, mode, &mut |span, result| {
                 callback(span, result.map(drop))
             })
         })
     }
 
-    fn cook_c_string(
+    fn cook_mixed(
         &self,
         kind: token::LitKind,
         mode: Mode,
@@ -761,7 +761,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
         postfix_len: u32,
     ) -> (token::LitKind, Symbol) {
         self.cook_common(kind, mode, start, end, prefix_len, postfix_len, |src, mode, callback| {
-            unescape::unescape_c_string(src, mode, &mut |span, result| {
+            unescape::unescape_mixed(src, mode, &mut |span, result| {
                 callback(span, result.map(drop))
             })
         })
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index a92609c2c2f..98e062dd784 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -8,7 +8,7 @@ use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle
 use rustc_ast as ast;
 use rustc_ast::attr;
 use rustc_ast::token::{self, Delimiter, Nonterminal};
-use rustc_errors::{error_code, Diagnostic, PResult};
+use rustc_errors::{codes::*, Diagnostic, PResult};
 use rustc_span::{sym, BytePos, Span};
 use thin_vec::ThinVec;
 use tracing::debug;
@@ -61,7 +61,7 @@ impl<'a> Parser<'a> {
                     let mut err = self
                         .dcx()
                         .struct_span_err(span, fluent::parse_inner_doc_comment_not_permitted);
-                    err.code(error_code!(E0753));
+                    err.code(E0753);
                     if let Some(replacement_span) = self.annotate_following_item_if_applicable(
                         &mut err,
                         span,
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 720a610fdf5..7a24b819b5f 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -23,7 +23,7 @@ use crate::parser;
 use crate::parser::attr::InnerAttrPolicy;
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Lit, LitKind, TokenKind};
+use rustc_ast::token::{self, Delimiter, Lit, LitKind, Token, TokenKind};
 use rustc_ast::tokenstream::AttrTokenTree;
 use rustc_ast::util::parser::AssocOp;
 use rustc_ast::{
@@ -448,12 +448,11 @@ impl<'a> Parser<'a> {
             })
         }
 
-        let mut expected = edible
+        self.expected_tokens.extend(edible.iter().chain(inedible).cloned().map(TokenType::Token));
+        let mut expected = self
+            .expected_tokens
             .iter()
-            .chain(inedible)
             .cloned()
-            .map(TokenType::Token)
-            .chain(self.expected_tokens.iter().cloned())
             .filter(|token| {
                 // Filter out suggestions that suggest the same token which was found and deemed incorrect.
                 fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
@@ -792,13 +791,28 @@ impl<'a> Parser<'a> {
                 && let [segment] = &attr_kind.item.path.segments[..]
                 && segment.ident.name == sym::cfg
                 && let Some(args_span) = attr_kind.item.args.span()
-                && let Ok(next_attr) = snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None))
+                && let next_attr = match snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None))
+                {
+                    Ok(next_attr) => next_attr,
+                    Err(inner_err) => {
+                        err.cancel();
+                        inner_err.cancel();
+                        return;
+                    }
+                }
                 && let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind
                 && let Some(next_attr_args_span) = next_attr_kind.item.args.span()
                 && let [next_segment] = &next_attr_kind.item.path.segments[..]
                 && segment.ident.name == sym::cfg
-                && let Ok(next_expr) = snapshot.parse_expr()
             {
+                let next_expr = match snapshot.parse_expr() {
+                    Ok(next_expr) => next_expr,
+                    Err(inner_err) => {
+                        err.cancel();
+                        inner_err.cancel();
+                        return;
+                    }
+                };
                 // We have for sure
                 // #[cfg(..)]
                 // expr
@@ -2927,6 +2941,22 @@ impl<'a> Parser<'a> {
         Ok(())
     }
 
+    /// Check for exclusive ranges written as `..<`
+    pub(crate) fn maybe_err_dotdotlt_syntax(&self, maybe_lt: Token, mut err: PErr<'a>) -> PErr<'a> {
+        if maybe_lt == token::Lt
+            && (self.expected_tokens.contains(&TokenType::Token(token::Gt))
+                || matches!(self.token.kind, token::Literal(..)))
+        {
+            err.span_suggestion(
+                maybe_lt.span,
+                "remove the `<` to write an exclusive range",
+                "",
+                Applicability::MachineApplicable,
+            );
+        }
+        err
+    }
+
     pub fn is_diff_marker(&mut self, long_kind: &TokenKind, short_kind: &TokenKind) -> bool {
         (0..3).all(|i| self.look_ahead(i, |tok| tok == long_kind))
             && self.look_ahead(3, |tok| tok == short_kind)
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index ae3661a530b..c395decab12 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -444,6 +444,19 @@ impl<'a> Parser<'a> {
             ) if self.restrictions.contains(Restrictions::CONST_EXPR) => {
                 return None;
             }
+            // When recovering patterns as expressions, stop parsing when encountering an assignment `=`, an alternative `|`, or a range `..`.
+            (
+                Some(
+                    AssocOp::Assign
+                    | AssocOp::AssignOp(_)
+                    | AssocOp::BitOr
+                    | AssocOp::DotDot
+                    | AssocOp::DotDotEq,
+                ),
+                _,
+            ) if self.restrictions.contains(Restrictions::IS_PAT) => {
+                return None;
+            }
             (Some(op), _) => (op, self.token.span),
             (None, Some((Ident { name: sym::and, span }, false))) if self.may_recover() => {
                 self.dcx().emit_err(errors::InvalidLogicalOperator {
@@ -482,7 +495,11 @@ impl<'a> Parser<'a> {
         cur_op_span: Span,
     ) -> PResult<'a, P<Expr>> {
         let rhs = if self.is_at_start_of_range_notation_rhs() {
-            Some(self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)?)
+            let maybe_lt = self.token.clone();
+            Some(
+                self.parse_expr_assoc_with(prec + 1, LhsExpr::NotYetParsed)
+                    .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?,
+            )
         } else {
             None
         };
@@ -531,11 +548,13 @@ impl<'a> Parser<'a> {
         let attrs = self.parse_or_use_outer_attributes(attrs)?;
         self.collect_tokens_for_expr(attrs, |this, attrs| {
             let lo = this.token.span;
+            let maybe_lt = this.look_ahead(1, |t| t.clone());
             this.bump();
             let (span, opt_end) = if this.is_at_start_of_range_notation_rhs() {
                 // RHS must be parsed with more associativity than the dots.
                 this.parse_expr_assoc_with(op.unwrap().precedence() + 1, LhsExpr::NotYetParsed)
-                    .map(|x| (lo.to(x.span), Some(x)))?
+                    .map(|x| (lo.to(x.span), Some(x)))
+                    .map_err(|err| this.maybe_err_dotdotlt_syntax(maybe_lt, err))?
             } else {
                 (lo, None)
             };
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 3bd8ae02586..9a77643f951 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -10,7 +10,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast::util::case::Case;
 use rustc_ast::{self as ast};
 use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_code_err, Applicability, PResult, StashKey};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability, PResult, StashKey};
 use rustc_span::edit_distance::edit_distance;
 use rustc_span::edition::Edition;
 use rustc_span::source_map;
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index ff2fb6271a8..623407eb380 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -53,6 +53,7 @@ bitflags::bitflags! {
         const CONST_EXPR        = 1 << 2;
         const ALLOW_LET         = 1 << 3;
         const IN_IF_GUARD       = 1 << 4;
+        const IS_PAT            = 1 << 5;
     }
 }
 
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 7918e03750c..d04921dde54 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,4 +1,4 @@
-use super::{ForceCollect, Parser, PathStyle, TrailingToken};
+use super::{ForceCollect, Parser, PathStyle, Restrictions, TrailingToken};
 use crate::errors::{
     self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed,
     DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt,
@@ -6,14 +6,14 @@ use crate::errors::{
     InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
     PatternOnWrongSideOfAt, RefMutOrderIncorrect, RemoveLet, RepeatedMutInPattern,
     SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
-    TrailingVertNotAllowed, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat,
-    UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam,
-    UnexpectedVertVertInPattern,
+    TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern,
+    UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
+    UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern,
 };
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter};
+use rustc_ast::token::{self, BinOpToken, Delimiter, Token};
 use rustc_ast::{
     self as ast, AttrVec, BindingAnnotation, ByRef, Expr, ExprKind, MacCall, Mutability, Pat,
     PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
@@ -23,7 +23,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, PResult};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::Span;
+use rustc_span::{ErrorGuaranteed, Span};
 use thin_vec::{thin_vec, ThinVec};
 
 #[derive(PartialEq, Copy, Clone)]
@@ -336,6 +336,95 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Ensures that the last parsed pattern (or pattern range bound) is not followed by a method call or an operator.
+    ///
+    /// `is_end_bound` indicates whether the last parsed thing was the end bound of a range pattern (see [`parse_pat_range_end`](Self::parse_pat_range_end))
+    /// in order to say "expected a pattern range bound" instead of "expected a pattern";
+    /// ```text
+    /// 0..=1 + 2
+    ///     ^^^^^
+    /// ```
+    /// Only the end bound is spanned, and this function have no idea if there were a `..=` before `pat_span`, hence the parameter.
+    #[must_use = "the pattern must be discarded as `PatKind::Err` if this function returns Some"]
+    fn maybe_recover_trailing_expr(
+        &mut self,
+        pat_span: Span,
+        is_end_bound: bool,
+    ) -> Option<ErrorGuaranteed> {
+        if self.prev_token.is_keyword(kw::Underscore) || !self.may_recover() {
+            // Don't recover anything after an `_` or if recovery is disabled.
+            return None;
+        }
+
+        // Check for `.hello()`, but allow `.Hello()` to be recovered as `, Hello()` in `parse_seq_to_before_tokens()`.
+        let has_trailing_method = self.check_noexpect(&token::Dot)
+            && self.look_ahead(1, |tok| {
+                tok.ident()
+                    .and_then(|(ident, _)| ident.name.as_str().chars().next())
+                    .is_some_and(char::is_lowercase)
+            })
+            && self.look_ahead(2, |tok| tok.kind == token::OpenDelim(Delimiter::Parenthesis));
+
+        // Check for operators.
+        // `|` is excluded as it is used in pattern alternatives and lambdas,
+        // `?` is included for error propagation,
+        // `[` is included for indexing operations,
+        // `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`)
+        let has_trailing_operator = matches!(self.token.kind, token::BinOp(op) if op != BinOpToken::Or)
+            || self.token.kind == token::Question
+            || (self.token.kind == token::OpenDelim(Delimiter::Bracket)
+                && self.look_ahead(1, |tok| tok.kind != token::CloseDelim(Delimiter::Bracket)));
+
+        if !has_trailing_method && !has_trailing_operator {
+            // Nothing to recover here.
+            return None;
+        }
+
+        // Let's try to parse an expression to emit a better diagnostic.
+        let mut snapshot = self.create_snapshot_for_diagnostic();
+        snapshot.restrictions.insert(Restrictions::IS_PAT);
+
+        // Parse `?`, `.f`, `(arg0, arg1, ...)` or `[expr]` until they've all been eaten.
+        if let Ok(expr) = snapshot
+            .parse_expr_dot_or_call_with(
+                self.mk_expr_err(pat_span), // equivalent to transforming the parsed pattern into an `Expr`
+                pat_span,
+                AttrVec::new(),
+            )
+            .map_err(|err| err.cancel())
+        {
+            let non_assoc_span = expr.span;
+
+            // Parse an associative expression such as `+ expr`, `% expr`, ...
+            // Assignements, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
+            if let Ok(expr) =
+                snapshot.parse_expr_assoc_with(0, expr.into()).map_err(|err| err.cancel())
+            {
+                // We got a valid expression.
+                self.restore_snapshot(snapshot);
+                self.restrictions.remove(Restrictions::IS_PAT);
+
+                let is_bound = is_end_bound
+                    // is_start_bound: either `..` or `)..`
+                    || self.token.is_range_separator()
+                    || self.token.kind == token::CloseDelim(Delimiter::Parenthesis)
+                        && self.look_ahead(1, Token::is_range_separator);
+
+                // Check that `parse_expr_assoc_with` didn't eat a rhs.
+                let is_method_call = has_trailing_method && non_assoc_span == expr.span;
+
+                return Some(self.dcx().emit_err(UnexpectedExpressionInPattern {
+                    span: expr.span,
+                    is_bound,
+                    is_method_call,
+                }));
+            }
+        }
+
+        // We got a trailing method/operator, but we couldn't parse an expression.
+        None
+    }
+
     /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
     /// allowed).
     fn parse_pat_with_range_pat(
@@ -441,7 +530,10 @@ impl<'a> Parser<'a> {
             } else if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
                 self.parse_pat_tuple_struct(qself, path)?
             } else {
-                PatKind::Path(qself, path)
+                match self.maybe_recover_trailing_expr(span, false) {
+                    Some(guar) => PatKind::Err(guar),
+                    None => PatKind::Path(qself, path),
+                }
             }
         } else if matches!(self.token.kind, token::Lifetime(_))
             // In pattern position, we're totally fine with using "next token isn't colon"
@@ -470,10 +562,17 @@ impl<'a> Parser<'a> {
         } else {
             // Try to parse everything else as literal with optional minus
             match self.parse_literal_maybe_minus() {
-                Ok(begin) => match self.parse_range_end() {
-                    Some(form) => self.parse_pat_range_begin_with(begin, form)?,
-                    None => PatKind::Lit(begin),
-                },
+                Ok(begin) => {
+                    let begin = match self.maybe_recover_trailing_expr(begin.span, false) {
+                        Some(_) => self.mk_expr_err(begin.span),
+                        None => begin,
+                    };
+
+                    match self.parse_range_end() {
+                        Some(form) => self.parse_pat_range_begin_with(begin, form)?,
+                        None => PatKind::Lit(begin),
+                    }
+                }
                 Err(err) => return self.fatal_unexpected_non_pat(err, expected),
             }
         };
@@ -615,6 +714,21 @@ impl<'a> Parser<'a> {
 
                     self.parse_pat_range_begin_with(begin.clone(), form)?
                 }
+                // recover ranges with parentheses around the `(start)..`
+                PatKind::Err(_)
+                    if self.may_recover()
+                        && let Some(form) = self.parse_range_end() =>
+                {
+                    self.dcx().emit_err(UnexpectedParenInRangePat {
+                        span: vec![open_paren, close_paren],
+                        sugg: UnexpectedParenInRangePatSugg {
+                            start_span: open_paren,
+                            end_span: close_paren,
+                        },
+                    });
+
+                    self.parse_pat_range_begin_with(self.mk_expr(pat.span, ExprKind::Err), form)?
+                }
 
                 // (pat) with optional parentheses
                 _ => PatKind::Paren(pat),
@@ -853,6 +967,8 @@ impl<'a> Parser<'a> {
             self.parse_literal_maybe_minus()
         }?;
 
+        let recovered = self.maybe_recover_trailing_expr(bound.span, true);
+
         // recover trailing `)`
         if let Some(open_paren) = open_paren {
             self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
@@ -866,7 +982,10 @@ impl<'a> Parser<'a> {
             });
         }
 
-        Ok(bound)
+        Ok(match recovered {
+            Some(_) => self.mk_expr_err(bound.span),
+            None => bound,
+        })
     }
 
     /// Is this the start of a pattern beginning with a path?
@@ -929,7 +1048,17 @@ impl<'a> Parser<'a> {
                 .create_err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span }));
         }
 
-        Ok(PatKind::Ident(binding_annotation, ident, sub))
+        // Check for method calls after the `ident`,
+        // but not `ident @ subpat` as `subpat` was already checked and `ident` continues with `@`.
+
+        let pat = if sub.is_none()
+            && let Some(guar) = self.maybe_recover_trailing_expr(ident.span, false)
+        {
+            PatKind::Err(guar)
+        } else {
+            PatKind::Ident(binding_annotation, ident, sub)
+        };
+        Ok(pat)
     }
 
     /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 625764876a6..d76ee161da6 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -1056,7 +1056,7 @@ fn find_width_map_from_snippet(
 fn unescape_string(string: &str) -> Option<string::String> {
     let mut buf = string::String::new();
     let mut ok = true;
-    unescape::unescape_literal(string, unescape::Mode::Str, &mut |_, unescaped_char| {
+    unescape::unescape_unicode(string, unescape::Mode::Str, &mut |_, unescaped_char| {
         match unescaped_char {
             Ok(c) => buf.push(c),
             Err(_) => ok = false,
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index d3909ce3a1c..9be28674435 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -917,7 +917,7 @@ impl<'tcx> DeadVisitor<'tcx> {
             return;
         }
         dead_codes.sort_by_key(|v| v.level);
-        for group in dead_codes[..].group_by(|a, b| a.level == b.level) {
+        for group in dead_codes[..].chunk_by(|a, b| a.level == b.level) {
             self.lint_at_single_level(&group, participle, Some(def_id), report_on);
         }
     }
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 25ca685cbfa..97c70e327f0 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -1,6 +1,6 @@
 use rustc_ast::attr;
 use rustc_ast::entry::EntryPointType;
-use rustc_errors::error_code;
+use rustc_errors::codes::*;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
@@ -180,8 +180,8 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
         Default::default()
     });
     let main_def_opt = tcx.resolutions(()).main_def;
-    let code = error_code!(E0601);
-    let add_teach_note = tcx.sess.teach(&code);
+    let code = E0601;
+    let add_teach_note = tcx.sess.teach(code);
     // The file may be empty, which leads to the diagnostic machinery not emitting this
     // note. This is a relatively simple way to detect that case and emit a span-less
     // note instead.
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index cf3c7cc4ace..77bfe57e370 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -6,7 +6,7 @@ use std::{
 use crate::fluent_generated as fluent;
 use rustc_ast::Label;
 use rustc_errors::{
-    error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
+    codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
     DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan,
 };
 use rustc_hir::{self as hir, ExprKind, Target};
@@ -55,7 +55,7 @@ pub struct IgnoredInlineAttrFnProto;
 pub struct IgnoredInlineAttrConstants;
 
 #[derive(Diagnostic)]
-#[diag(passes_inline_not_fn_or_closure, code = "E0518")]
+#[diag(passes_inline_not_fn_or_closure, code = E0518)]
 pub struct InlineNotFnOrClosure {
     #[primary_span]
     pub attr_span: Span,
@@ -76,7 +76,7 @@ pub struct IgnoredCoveragePropagate;
 pub struct IgnoredCoverageFnDefn;
 
 #[derive(Diagnostic)]
-#[diag(passes_coverage_not_coverable, code = "E0788")]
+#[diag(passes_coverage_not_coverable, code = E0788)]
 pub struct IgnoredCoverageNotCoverable {
     #[primary_span]
     pub attr_span: Span,
@@ -95,14 +95,14 @@ pub struct AttrShouldBeAppliedToFn {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_naked_tracked_caller, code = "E0736")]
+#[diag(passes_naked_tracked_caller, code = E0736)]
 pub struct NakedTrackedCaller {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_should_be_applied_to_fn, code = "E0739")]
+#[diag(passes_should_be_applied_to_fn, code = E0739)]
 pub struct TrackedCallerWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -112,7 +112,7 @@ pub struct TrackedCallerWrongLocation {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_should_be_applied_to_struct_enum, code = "E0701")]
+#[diag(passes_should_be_applied_to_struct_enum, code = E0701)]
 pub struct NonExhaustiveWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -370,28 +370,28 @@ pub struct HasIncoherentInherentImpl {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_both_ffi_const_and_pure, code = "E0757")]
+#[diag(passes_both_ffi_const_and_pure, code = E0757)]
 pub struct BothFfiConstAndPure {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_ffi_pure_invalid_target, code = "E0755")]
+#[diag(passes_ffi_pure_invalid_target, code = E0755)]
 pub struct FfiPureInvalidTarget {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_ffi_const_invalid_target, code = "E0756")]
+#[diag(passes_ffi_const_invalid_target, code = E0756)]
 pub struct FfiConstInvalidTarget {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_ffi_returns_twice_invalid_target, code = "E0724")]
+#[diag(passes_ffi_returns_twice_invalid_target, code = E0724)]
 pub struct FfiReturnsTwiceInvalidTarget {
     #[primary_span]
     pub attr_span: Span,
@@ -552,21 +552,21 @@ pub struct NoMangle {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_repr_ident, code = "E0565")]
+#[diag(passes_repr_ident, code = E0565)]
 pub struct ReprIdent {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_repr_conflicting, code = "E0566")]
+#[diag(passes_repr_conflicting, code = E0566)]
 pub struct ReprConflicting {
     #[primary_span]
     pub hint_spans: Vec<Span>,
 }
 
 #[derive(LintDiagnostic)]
-#[diag(passes_repr_conflicting, code = "E0566")]
+#[diag(passes_repr_conflicting, code = E0566)]
 pub struct ReprConflictingLint;
 
 #[derive(Diagnostic)]
@@ -667,7 +667,7 @@ pub(crate) struct EmptyConfusables {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_incorrect_meta_item, code = "E0539")]
+#[diag(passes_incorrect_meta_item, code = E0539)]
 pub(crate) struct IncorrectMetaItem {
     #[primary_span]
     pub span: Span,
@@ -737,7 +737,7 @@ pub struct Unused {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_non_exported_macro_invalid_attrs, code = "E0518")]
+#[diag(passes_non_exported_macro_invalid_attrs, code = E0518)]
 pub struct NonExportedMacroInvalidAttrs {
     #[primary_span]
     #[label]
@@ -801,7 +801,7 @@ pub struct DeprecatedAnnotationHasNoEffect {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unknown_external_lang_item, code = "E0264")]
+#[diag(passes_unknown_external_lang_item, code = E0264)]
 pub struct UnknownExternLangItem {
     #[primary_span]
     pub span: Span,
@@ -837,7 +837,7 @@ pub struct LangItemWithTargetFeature {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_lang_item_on_incorrect_target, code = "E0718")]
+#[diag(passes_lang_item_on_incorrect_target, code = E0718)]
 pub struct LangItemOnIncorrectTarget {
     #[primary_span]
     #[label]
@@ -848,7 +848,7 @@ pub struct LangItemOnIncorrectTarget {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unknown_lang_item, code = "E0522")]
+#[diag(passes_unknown_lang_item, code = E0522)]
 pub struct UnknownLangItem {
     #[primary_span]
     #[label]
@@ -990,7 +990,7 @@ pub struct UnrecognizedField {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_feature_stable_twice, code = "E0711")]
+#[diag(passes_feature_stable_twice, code = E0711)]
 pub struct FeatureStableTwice {
     #[primary_span]
     pub span: Span,
@@ -1000,7 +1000,7 @@ pub struct FeatureStableTwice {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_feature_previously_declared, code = "E0711")]
+#[diag(passes_feature_previously_declared, code = E0711)]
 pub struct FeaturePreviouslyDeclared<'a, 'b> {
     #[primary_span]
     pub span: Span,
@@ -1025,7 +1025,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> {
     fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_break_non_loop);
         diag.span(self.span);
-        diag.code(error_code!(E0571));
+        diag.code(E0571);
         diag.arg("kind", self.kind);
         diag.span_label(self.span, fluent::passes_label);
         if let Some(head) = self.head {
@@ -1063,7 +1063,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_continue_labeled_block, code = "E0696")]
+#[diag(passes_continue_labeled_block, code = E0696)]
 pub struct ContinueLabeledBlock {
     #[primary_span]
     #[label]
@@ -1073,7 +1073,7 @@ pub struct ContinueLabeledBlock {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_break_inside_closure, code = "E0267")]
+#[diag(passes_break_inside_closure, code = E0267)]
 pub struct BreakInsideClosure<'a> {
     #[primary_span]
     #[label]
@@ -1084,7 +1084,7 @@ pub struct BreakInsideClosure<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_break_inside_async_block, code = "E0267")]
+#[diag(passes_break_inside_async_block, code = E0267)]
 pub struct BreakInsideAsyncBlock<'a> {
     #[primary_span]
     #[label]
@@ -1095,7 +1095,7 @@ pub struct BreakInsideAsyncBlock<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_outside_loop, code = "E0268")]
+#[diag(passes_outside_loop, code = E0268)]
 pub struct OutsideLoop<'a> {
     #[primary_span]
     #[label]
@@ -1115,7 +1115,7 @@ pub struct OutsideLoopSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unlabeled_in_labeled_block, code = "E0695")]
+#[diag(passes_unlabeled_in_labeled_block, code = E0695)]
 pub struct UnlabeledInLabeledBlock<'a> {
     #[primary_span]
     #[label]
@@ -1124,7 +1124,7 @@ pub struct UnlabeledInLabeledBlock<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unlabeled_cf_in_while_condition, code = "E0590")]
+#[diag(passes_unlabeled_cf_in_while_condition, code = E0590)]
 pub struct UnlabeledCfInWhileCondition<'a> {
     #[primary_span]
     #[label]
@@ -1169,7 +1169,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock {
     fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_naked_functions_asm_block);
         diag.span(self.span);
-        diag.code(error_code!(E0787));
+        diag.code(E0787);
         for span in self.multiple_asms.iter() {
             diag.span_label(*span, fluent::passes_label_multiple_asm);
         }
@@ -1181,14 +1181,14 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_naked_functions_operands, code = "E0787")]
+#[diag(passes_naked_functions_operands, code = E0787)]
 pub struct NakedFunctionsOperands {
     #[primary_span]
     pub unsupported_operands: Vec<Span>,
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_naked_functions_asm_options, code = "E0787")]
+#[diag(passes_naked_functions_asm_options, code = E0787)]
 pub struct NakedFunctionsAsmOptions {
     #[primary_span]
     pub span: Span,
@@ -1196,7 +1196,7 @@ pub struct NakedFunctionsAsmOptions {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_naked_functions_must_use_noreturn, code = "E0787")]
+#[diag(passes_naked_functions_must_use_noreturn, code = E0787)]
 pub struct NakedFunctionsMustUseNoreturn {
     #[primary_span]
     pub span: Span,
@@ -1229,7 +1229,7 @@ pub struct AttrOnlyInFunctions {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_multiple_rustc_main, code = "E0137")]
+#[diag(passes_multiple_rustc_main, code = E0137)]
 pub struct MultipleRustcMain {
     #[primary_span]
     pub span: Span,
@@ -1240,7 +1240,7 @@ pub struct MultipleRustcMain {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_multiple_start_functions, code = "E0138")]
+#[diag(passes_multiple_start_functions, code = E0138)]
 pub struct MultipleStartFunctions {
     #[primary_span]
     pub span: Span,
@@ -1280,7 +1280,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr {
     fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> {
         let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_no_main_function);
         diag.span(DUMMY_SP);
-        diag.code(error_code!(E0601));
+        diag.code(E0601);
         diag.arg("crate_name", self.crate_name);
         diag.arg("filename", self.filename);
         diag.arg("has_filename", self.has_filename);
@@ -1345,7 +1345,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for DuplicateLangItem {
                 Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends,
             },
         );
-        diag.code(error_code!(E0152));
+        diag.code(E0152);
         diag.arg("lang_item_name", self.lang_item_name);
         diag.arg("crate_name", self.crate_name);
         diag.arg("dependency_of", self.dependency_of);
@@ -1382,7 +1382,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for DuplicateLangItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_incorrect_target, code = "E0718")]
+#[diag(passes_incorrect_target, code = E0718)]
 pub struct IncorrectTarget<'a> {
     #[primary_span]
     pub span: Span,
@@ -1418,7 +1418,7 @@ pub struct ObjectLifetimeErr {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unrecognized_repr_hint, code = "E0552")]
+#[diag(passes_unrecognized_repr_hint, code = E0552)]
 #[help]
 pub struct UnrecognizedReprHint {
     #[primary_span]
@@ -1427,35 +1427,35 @@ pub struct UnrecognizedReprHint {
 
 #[derive(Diagnostic)]
 pub enum AttrApplication {
-    #[diag(passes_attr_application_enum, code = "E0517")]
+    #[diag(passes_attr_application_enum, code = E0517)]
     Enum {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes_attr_application_struct, code = "E0517")]
+    #[diag(passes_attr_application_struct, code = E0517)]
     Struct {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes_attr_application_struct_union, code = "E0517")]
+    #[diag(passes_attr_application_struct_union, code = E0517)]
     StructUnion {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes_attr_application_struct_enum_union, code = "E0517")]
+    #[diag(passes_attr_application_struct_enum_union, code = E0517)]
     StructEnumUnion {
         #[primary_span]
         hint_span: Span,
         #[label]
         span: Span,
     },
-    #[diag(passes_attr_application_struct_enum_function_method_union, code = "E0517")]
+    #[diag(passes_attr_application_struct_enum_function_method_union, code = E0517)]
     StructEnumFunctionMethodUnion {
         #[primary_span]
         hint_span: Span,
@@ -1465,7 +1465,7 @@ pub enum AttrApplication {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_transparent_incompatible, code = "E0692")]
+#[diag(passes_transparent_incompatible, code = E0692)]
 pub struct TransparentIncompatible {
     #[primary_span]
     pub hint_spans: Vec<Span>,
@@ -1473,7 +1473,7 @@ pub struct TransparentIncompatible {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_deprecated_attribute, code = "E0549")]
+#[diag(passes_deprecated_attribute, code = E0549)]
 pub struct DeprecatedAttribute {
     #[primary_span]
     pub span: Span,
@@ -1524,7 +1524,7 @@ pub struct TraitImplConstStable {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_feature_only_on_nightly, code = "E0554")]
+#[diag(passes_feature_only_on_nightly, code = E0554)]
 pub struct FeatureOnlyOnNightly {
     #[primary_span]
     pub span: Span,
@@ -1532,7 +1532,7 @@ pub struct FeatureOnlyOnNightly {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_unknown_feature, code = "E0635")]
+#[diag(passes_unknown_feature, code = E0635)]
 pub struct UnknownFeature {
     #[primary_span]
     pub span: Span,
@@ -1549,7 +1549,7 @@ pub struct ImpliedFeatureNotExist {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_duplicate_feature_err, code = "E0636")]
+#[diag(passes_duplicate_feature_err, code = E0636)]
 pub struct DuplicateFeatureErr {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 050a90efbdf..862b76b1f60 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -11,7 +11,6 @@
 #![feature(let_chains)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
-#![feature(slice_group_by)]
 #![feature(try_blocks)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index a55d53dfdac..6374874165f 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -95,6 +95,7 @@ pub trait TypeCx: Sized + fmt::Debug {
     type PatData: Clone;
 
     fn is_exhaustive_patterns_feature_on(&self) -> bool;
+    fn is_min_exhaustive_patterns_feature_on(&self) -> bool;
 
     /// The number of fields for this constructor.
     fn ctor_arity(&self, ctor: &Constructor<Self>, ty: &Self::Ty) -> usize;
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 23cab5f43ab..ef90d24b0bf 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -181,7 +181,9 @@ impl<'p, 'tcx> RustcMatchCheckCtxt<'p, 'tcx> {
             // `field.ty()` doesn't normalize after substituting.
             let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
             let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
-            let is_uninhabited = cx.tcx.features().exhaustive_patterns && cx.is_uninhabited(ty);
+            let is_uninhabited = (cx.tcx.features().exhaustive_patterns
+                || cx.tcx.features().min_exhaustive_patterns)
+                && cx.is_uninhabited(ty);
 
             if is_uninhabited && (!is_visible || is_non_exhaustive) {
                 None
@@ -863,6 +865,9 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
     fn is_exhaustive_patterns_feature_on(&self) -> bool {
         self.tcx.features().exhaustive_patterns
     }
+    fn is_min_exhaustive_patterns_feature_on(&self) -> bool {
+        self.tcx.features().min_exhaustive_patterns
+    }
 
     fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
         self.ctor_arity(ctor, *ty)
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index 0de48c9f3c0..a627bdeef81 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -548,11 +548,12 @@
 //! [`ValidityConstraint::specialize`].
 //!
 //! Having said all that, in practice we don't fully follow what's been presented in this section.
-//! Under `exhaustive_patterns`, we allow omitting empty arms even in `!known_valid` places, for
-//! backwards-compatibility until we have a better alternative. Without `exhaustive_patterns`, we
-//! mostly treat empty types as inhabited, except specifically a non-nested `!` or empty enum. In
-//! this specific case we also allow the empty match regardless of place validity, for
-//! backwards-compatibility. Hopefully we can eventually deprecate this.
+//! Let's call "toplevel exception" the case where the match scrutinee itself has type `!` or
+//! `EmptyEnum`. First, on stable rust, we require `_` patterns for empty types in all cases apart
+//! from the toplevel exception. The `exhaustive_patterns` and `min_exaustive_patterns` allow
+//! omitting patterns in the cases described above. There's a final detail: in the toplevel
+//! exception or with the `exhaustive_patterns` feature, we ignore place validity when checking
+//! whether a pattern is required for exhaustiveness. I (Nadrieril) hope to deprecate this behavior.
 //!
 //!
 //!
@@ -1442,10 +1443,17 @@ fn compute_exhaustiveness_and_usefulness<'a, 'p, Cx: TypeCx>(
     // We treat match scrutinees of type `!` or `EmptyEnum` differently.
     let is_toplevel_exception =
         is_top_level && matches!(ctors_for_ty, ConstructorSet::NoConstructors);
-    // Whether empty patterns can be omitted for exhaustiveness.
-    let can_omit_empty_arms = is_toplevel_exception || mcx.tycx.is_exhaustive_patterns_feature_on();
-    // Whether empty patterns are counted as useful or not.
-    let empty_arms_are_unreachable = place_validity.is_known_valid() && can_omit_empty_arms;
+    // Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if
+    // it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`).
+    let empty_arms_are_unreachable = place_validity.is_known_valid()
+        && (is_toplevel_exception
+            || mcx.tycx.is_exhaustive_patterns_feature_on()
+            || mcx.tycx.is_min_exhaustive_patterns_feature_on());
+    // Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the
+    // toplevel exception and `exhaustive_patterns` cases for backwards compatibility.
+    let can_omit_empty_arms = empty_arms_are_unreachable
+        || is_toplevel_exception
+        || mcx.tycx.is_exhaustive_patterns_feature_on();
 
     // Analyze the constructors present in this column.
     let ctors = matrix.heads().map(|p| p.ctor());
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index b1242f82f4f..01c6d18c0e1 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -1,9 +1,9 @@
-use rustc_errors::DiagnosticArgFromDisplay;
+use rustc_errors::{codes::*, DiagnosticArgFromDisplay};
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
-#[diag(privacy_field_is_private, code = "E0451")]
+#[diag(privacy_field_is_private, code = E0451)]
 pub struct FieldIsPrivate {
     #[primary_span]
     pub span: Span,
@@ -48,7 +48,7 @@ pub struct UnnamedItemIsPrivate {
 }
 
 #[derive(Diagnostic)]
-#[diag(privacy_in_public_interface, code = "E0446")]
+#[diag(privacy_in_public_interface, code = E0446)]
 pub struct InPublicInterface<'a> {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 9087ae00d11..a64b06e70d6 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -22,7 +22,6 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, CRATE_DEF_ID};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, PatKind};
-use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::GenericArgs;
@@ -34,9 +33,9 @@ use rustc_span::hygiene::Transparency;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Span;
 
+use std::fmt;
 use std::marker::PhantomData;
 use std::ops::ControlFlow;
-use std::{fmt, mem};
 
 use errors::{
     FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
@@ -933,7 +932,6 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
 struct NamePrivacyVisitor<'tcx> {
     tcx: TyCtxt<'tcx>,
     maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
-    current_item: LocalDefId,
 }
 
 impl<'tcx> NamePrivacyVisitor<'tcx> {
@@ -949,6 +947,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
     // Checks that a field in a struct constructor (expression or pattern) is accessible.
     fn check_field(
         &mut self,
+        hir_id: hir::HirId,    // ID of the field use
         use_ctxt: Span,        // syntax context of the field name at the use site
         span: Span,            // span of the field pattern, e.g., `x: 0`
         def: ty::AdtDef<'tcx>, // definition of the struct or enum
@@ -961,7 +960,6 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
 
         // definition of the field
         let ident = Ident::new(kw::Empty, use_ctxt);
-        let hir_id = self.tcx.local_def_id_to_hir_id(self.current_item);
         let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1;
         if !field.vis.is_accessible_from(def_id, self.tcx) {
             self.tcx.dcx().emit_err(FieldIsPrivate {
@@ -980,33 +978,13 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
 }
 
 impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
-    type NestedFilter = nested_filter::All;
-
-    /// We want to visit items in the context of their containing
-    /// module and so forth, so supply a crate for doing a deep walk.
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
-        // Don't visit nested modules, since we run a separate visitor walk
-        // for each module in `effective_visibilities`
-    }
-
-    fn visit_nested_body(&mut self, body: hir::BodyId) {
+    fn visit_nested_body(&mut self, body_id: hir::BodyId) {
         let old_maybe_typeck_results =
-            self.maybe_typeck_results.replace(self.tcx.typeck_body(body));
-        let body = self.tcx.hir().body(body);
-        self.visit_body(body);
+            self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
+        self.visit_body(self.tcx.hir().body(body_id));
         self.maybe_typeck_results = old_maybe_typeck_results;
     }
 
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id);
-        intravisit::walk_item(self, item);
-        self.current_item = orig_current_item;
-    }
-
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
         if let hir::ExprKind::Struct(qpath, fields, ref base) = expr.kind {
             let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
@@ -1020,17 +998,17 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
                     let field = fields
                         .iter()
                         .find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
-                    let (use_ctxt, span) = match field {
-                        Some(field) => (field.ident.span, field.span),
-                        None => (base.span, base.span),
+                    let (hir_id, use_ctxt, span) = match field {
+                        Some(field) => (field.hir_id, field.ident.span, field.span),
+                        None => (base.hir_id, base.span, base.span),
                     };
-                    self.check_field(use_ctxt, span, adt, variant_field, true);
+                    self.check_field(hir_id, use_ctxt, span, adt, variant_field, true);
                 }
             } else {
                 for field in fields {
-                    let use_ctxt = field.ident.span;
+                    let (hir_id, use_ctxt, span) = (field.hir_id, field.ident.span, field.span);
                     let index = self.typeck_results().field_index(field.hir_id);
-                    self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
+                    self.check_field(hir_id, use_ctxt, span, adt, &variant.fields[index], false);
                 }
             }
         }
@@ -1044,9 +1022,9 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
             let adt = self.typeck_results().pat_ty(pat).ty_adt_def().unwrap();
             let variant = adt.variant_of_res(res);
             for field in fields {
-                let use_ctxt = field.ident.span;
+                let (hir_id, use_ctxt, span) = (field.hir_id, field.ident.span, field.span);
                 let index = self.typeck_results().field_index(field.hir_id);
-                self.check_field(use_ctxt, field.span, adt, &variant.fields[index], false);
+                self.check_field(hir_id, use_ctxt, span, adt, &variant.fields[index], false);
             }
         }
 
@@ -1741,17 +1719,12 @@ pub fn provide(providers: &mut Providers) {
 
 fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
     // Check privacy of names not checked in previous compilation stages.
-    let mut visitor = NamePrivacyVisitor {
-        tcx,
-        maybe_typeck_results: None,
-        current_item: module_def_id.to_local_def_id(),
-    };
-    let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
-
-    intravisit::walk_mod(&mut visitor, module, hir_id);
+    let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None };
+    tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor);
 
     // Check privacy of explicitly written types and traits as well as
     // inferred types of expressions and patterns.
+    let span = tcx.def_span(module_def_id);
     let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span };
     tcx.hir().visit_item_likes_in_module(module_def_id, &mut visitor);
 }
diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs
index 5829e17ec16..9db6fac8036 100644
--- a/compiler/rustc_query_system/src/error.rs
+++ b/compiler/rustc_query_system/src/error.rs
@@ -1,3 +1,4 @@
+use rustc_errors::codes::*;
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_session::Limit;
 use rustc_span::{Span, Symbol};
@@ -45,7 +46,7 @@ pub struct CycleUsage {
 }
 
 #[derive(Diagnostic)]
-#[diag(query_system_cycle, code = "E0391")]
+#[diag(query_system_cycle, code = E0391)]
 pub struct Cycle {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index b855ec8f920..7eb7c8c2bca 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -19,7 +19,7 @@ use rustc_ast::{self as ast, AssocItem, AssocItemKind, MetaItemKind, StmtKind};
 use rustc_ast::{Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, NodeId};
 use rustc_attr as attr;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{struct_span_code_err, Applicability};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability};
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def::{self, *};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 66dfee6c062..f3a6eb65a72 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -6,8 +6,8 @@ use rustc_ast::{MetaItemKind, NestedMetaItem};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{
-    pluralize, report_ambiguity_error, struct_span_code_err, Applicability, DiagCtxt, Diagnostic,
-    DiagnosticBuilder, ErrorGuaranteed, MultiSpan, SuggestionStyle,
+    codes::*, pluralize, report_ambiguity_error, struct_span_code_err, Applicability, DiagCtxt,
+    Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, SuggestionStyle,
 };
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 821b1e946f3..50ff09feb4d 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -1,3 +1,4 @@
+use rustc_errors::codes::*;
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{
     symbol::{Ident, Symbol},
@@ -7,16 +8,16 @@ use rustc_span::{
 use crate::{late::PatternSource, Res};
 
 #[derive(Diagnostic)]
-#[diag(resolve_parent_module_reset_for_binding, code = "E0637")]
+#[diag(resolve_parent_module_reset_for_binding, code = E0637)]
 pub(crate) struct ParentModuleResetForBinding;
 
 #[derive(Diagnostic)]
-#[diag(resolve_ampersand_used_without_explicit_lifetime_name, code = "E0637")]
+#[diag(resolve_ampersand_used_without_explicit_lifetime_name, code = E0637)]
 #[note]
 pub(crate) struct AmpersandUsedWithoutExplicitLifetimeName(#[primary_span] pub(crate) Span);
 
 #[derive(Diagnostic)]
-#[diag(resolve_underscore_lifetime_name_cannot_be_used_here, code = "E0637")]
+#[diag(resolve_underscore_lifetime_name_cannot_be_used_here, code = E0637)]
 #[note]
 pub(crate) struct UnderscoreLifetimeNameCannotBeUsedHere(#[primary_span] pub(crate) Span);
 
@@ -33,7 +34,7 @@ pub(crate) struct CrateRootNamesMustBeNamedExplicitly(#[primary_span] pub(crate)
 pub(crate) struct ResolutionError(#[primary_span] pub(crate) Span);
 
 #[derive(Diagnostic)]
-#[diag(resolve_generic_params_from_outer_item, code = "E0401")]
+#[diag(resolve_generic_params_from_outer_item, code = E0401)]
 pub(crate) struct GenericParamsFromOuterItem {
     #[primary_span]
     #[label]
@@ -67,7 +68,7 @@ pub(crate) struct GenericParamsFromOuterItemSugg {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_name_is_already_used_as_generic_parameter, code = "E0403")]
+#[diag(resolve_name_is_already_used_as_generic_parameter, code = E0403)]
 pub(crate) struct NameAlreadyUsedInParameterList {
     #[primary_span]
     #[label]
@@ -78,7 +79,7 @@ pub(crate) struct NameAlreadyUsedInParameterList {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_method_not_member_of_trait, code = "E0407")]
+#[diag(resolve_method_not_member_of_trait, code = E0407)]
 pub(crate) struct MethodNotMemberOfTrait {
     #[primary_span]
     #[label]
@@ -102,7 +103,7 @@ pub(crate) struct AssociatedFnWithSimilarNameExists {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_type_not_member_of_trait, code = "E0437")]
+#[diag(resolve_type_not_member_of_trait, code = E0437)]
 pub(crate) struct TypeNotMemberOfTrait {
     #[primary_span]
     #[label]
@@ -126,7 +127,7 @@ pub(crate) struct AssociatedTypeWithSimilarNameExists {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_const_not_member_of_trait, code = "E0438")]
+#[diag(resolve_const_not_member_of_trait, code = E0438)]
 pub(crate) struct ConstNotMemberOfTrait {
     #[primary_span]
     #[label]
@@ -150,7 +151,7 @@ pub(crate) struct AssociatedConstWithSimilarNameExists {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_variable_bound_with_different_mode, code = "E0409")]
+#[diag(resolve_variable_bound_with_different_mode, code = E0409)]
 pub(crate) struct VariableBoundWithDifferentMode {
     #[primary_span]
     #[label]
@@ -161,7 +162,7 @@ pub(crate) struct VariableBoundWithDifferentMode {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = "E0415")]
+#[diag(resolve_ident_bound_more_than_once_in_parameter_list, code = E0415)]
 pub(crate) struct IdentifierBoundMoreThanOnceInParameterList {
     #[primary_span]
     #[label]
@@ -170,7 +171,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInParameterList {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = "E0416")]
+#[diag(resolve_ident_bound_more_than_once_in_same_pattern, code = E0416)]
 pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern {
     #[primary_span]
     #[label]
@@ -179,7 +180,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_undeclared_label, code = "E0426")]
+#[diag(resolve_undeclared_label, code = E0426)]
 pub(crate) struct UndeclaredLabel {
     #[primary_span]
     #[label]
@@ -217,7 +218,7 @@ pub(crate) struct UnreachableLabelWithSimilarNameExists {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = "E0430")]
+#[diag(resolve_self_import_can_only_appear_once_in_the_list, code = E0430)]
 pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
     #[primary_span]
     #[label]
@@ -225,7 +226,7 @@ pub(crate) struct SelfImportCanOnlyAppearOnceInTheList {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = "E0431")]
+#[diag(resolve_self_import_only_in_import_list_with_non_empty_prefix, code = E0431)]
 pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix {
     #[primary_span]
     #[label]
@@ -233,7 +234,7 @@ pub(crate) struct SelfImportOnlyInImportListWithNonEmptyPrefix {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = "E0434")]
+#[diag(resolve_cannot_capture_dynamic_environment_in_fn_item, code = E0434)]
 #[help]
 pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem {
     #[primary_span]
@@ -241,7 +242,7 @@ pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = "E0435")]
+#[diag(resolve_attempt_to_use_non_constant_value_in_constant, code = E0435)]
 pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> {
     #[primary_span]
     pub(crate) span: Span,
@@ -283,7 +284,7 @@ pub(crate) struct AttemptToUseNonConstantValueInConstantWithoutSuggestion<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_self_imports_only_allowed_within, code = "E0429")]
+#[diag(resolve_self_imports_only_allowed_within, code = E0429)]
 pub(crate) struct SelfImportsOnlyAllowedWithin {
     #[primary_span]
     pub(crate) span: Span,
@@ -317,7 +318,7 @@ pub(crate) struct SelfImportsOnlyAllowedWithinMultipartSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_binding_shadows_something_unacceptable, code = "E0530")]
+#[diag(resolve_binding_shadows_something_unacceptable, code = E0530)]
 pub(crate) struct BindingShadowsSomethingUnacceptable<'a> {
     #[primary_span]
     #[label]
@@ -346,7 +347,7 @@ pub(crate) struct BindingShadowsSomethingUnacceptableSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_forward_declared_generic_param, code = "E0128")]
+#[diag(resolve_forward_declared_generic_param, code = E0128)]
 pub(crate) struct ForwardDeclaredGenericParam {
     #[primary_span]
     #[label]
@@ -354,7 +355,7 @@ pub(crate) struct ForwardDeclaredGenericParam {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_param_in_ty_of_const_param, code = "E0770")]
+#[diag(resolve_param_in_ty_of_const_param, code = E0770)]
 pub(crate) struct ParamInTyOfConstParam {
     #[primary_span]
     #[label]
@@ -376,7 +377,7 @@ pub(crate) enum ParamKindInTyOfConstParam {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_self_in_generic_param_default, code = "E0735")]
+#[diag(resolve_self_in_generic_param_default, code = E0735)]
 pub(crate) struct SelfInGenericParamDefault {
     #[primary_span]
     #[label]
@@ -412,7 +413,7 @@ pub(crate) enum ParamKindInNonTrivialAnonConst {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_unreachable_label, code = "E0767")]
+#[diag(resolve_unreachable_label, code = E0767)]
 #[note]
 pub(crate) struct UnreachableLabel {
     #[primary_span]
@@ -456,7 +457,7 @@ pub(crate) struct UnreachableLabelSubLabelUnreachable {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_trait_impl_mismatch, code = "{code}")]
+#[diag(resolve_trait_impl_mismatch)]
 pub(crate) struct TraitImplMismatch {
     #[primary_span]
     #[label]
@@ -466,7 +467,6 @@ pub(crate) struct TraitImplMismatch {
     #[label(resolve_label_trait_item)]
     pub(crate) trait_item_span: Span,
     pub(crate) trait_path: String,
-    pub(crate) code: String,
 }
 
 #[derive(Diagnostic)]
@@ -496,7 +496,7 @@ pub(crate) struct BindingInNeverPattern {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_trait_impl_duplicate, code = "E0201")]
+#[diag(resolve_trait_impl_duplicate, code = E0201)]
 pub(crate) struct TraitImplDuplicate {
     #[primary_span]
     #[label]
@@ -519,11 +519,11 @@ pub(crate) struct Relative2018 {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_ancestor_only, code = "E0742")]
+#[diag(resolve_ancestor_only, code = E0742)]
 pub(crate) struct AncestorOnly(#[primary_span] pub(crate) Span);
 
 #[derive(Diagnostic)]
-#[diag(resolve_expected_found, code = "E0577")]
+#[diag(resolve_expected_found, code = E0577)]
 pub(crate) struct ExpectedFound {
     #[primary_span]
     #[label]
@@ -533,7 +533,7 @@ pub(crate) struct ExpectedFound {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_indeterminate, code = "E0578")]
+#[diag(resolve_indeterminate, code = E0578)]
 pub(crate) struct Indeterminate(#[primary_span] pub(crate) Span);
 
 #[derive(Diagnostic)]
@@ -715,7 +715,7 @@ pub(crate) struct CannotDetermineMacroResolution {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_be_reexported_private, code = "E0364")]
+#[diag(resolve_cannot_be_reexported_private, code = E0364)]
 pub(crate) struct CannotBeReexportedPrivate {
     #[primary_span]
     pub(crate) span: Span,
@@ -723,7 +723,7 @@ pub(crate) struct CannotBeReexportedPrivate {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_be_reexported_crate_public, code = "E0364")]
+#[diag(resolve_cannot_be_reexported_crate_public, code = E0364)]
 pub(crate) struct CannotBeReexportedCratePublic {
     #[primary_span]
     pub(crate) span: Span,
@@ -731,7 +731,7 @@ pub(crate) struct CannotBeReexportedCratePublic {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_be_reexported_private, code = "E0365")]
+#[diag(resolve_cannot_be_reexported_private, code = E0365)]
 #[note(resolve_consider_declaring_with_pub)]
 pub(crate) struct CannotBeReexportedPrivateNS {
     #[primary_span]
@@ -741,7 +741,7 @@ pub(crate) struct CannotBeReexportedPrivateNS {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_cannot_be_reexported_crate_public, code = "E0365")]
+#[diag(resolve_cannot_be_reexported_crate_public, code = E0365)]
 #[note(resolve_consider_declaring_with_pub)]
 pub(crate) struct CannotBeReexportedCratePublicNS {
     #[primary_span]
@@ -780,7 +780,7 @@ pub(crate) struct ItemsInTraitsAreNotImportable {
 }
 
 #[derive(Diagnostic)]
-#[diag(resolve_is_not_directly_importable, code = "E0253")]
+#[diag(resolve_is_not_directly_importable, code = E0253)]
 pub(crate) struct IsNotDirectlyImportable {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index ad60caed354..30fb35238c3 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -17,7 +17,7 @@ use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult};
 use rustc_ast::NodeId;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::intern::Interned;
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, MultiSpan};
+use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan};
 use rustc_hir::def::{self, DefKind, PartialRes};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::metadata::Reexport;
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index abd724a6cc2..0743ff03864 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -16,7 +16,9 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_errors::{Applicability, DiagnosticArgValue, IntoDiagnosticArg};
+use rustc_errors::{
+    codes::*, struct_span_code_err, Applicability, DiagnosticArgValue, ErrCode, IntoDiagnosticArg,
+};
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
@@ -533,21 +535,20 @@ impl<'a> PathSource<'a> {
         }
     }
 
-    fn error_code(self, has_unexpected_resolution: bool) -> String {
-        use rustc_errors::error_code;
+    fn error_code(self, has_unexpected_resolution: bool) -> ErrCode {
         match (self, has_unexpected_resolution) {
-            (PathSource::Trait(_), true) => error_code!(E0404),
-            (PathSource::Trait(_), false) => error_code!(E0405),
-            (PathSource::Type, true) => error_code!(E0573),
-            (PathSource::Type, false) => error_code!(E0412),
-            (PathSource::Struct, true) => error_code!(E0574),
-            (PathSource::Struct, false) => error_code!(E0422),
-            (PathSource::Expr(..), true) | (PathSource::Delegation, true) => error_code!(E0423),
-            (PathSource::Expr(..), false) | (PathSource::Delegation, false) => error_code!(E0425),
-            (PathSource::Pat | PathSource::TupleStruct(..), true) => error_code!(E0532),
-            (PathSource::Pat | PathSource::TupleStruct(..), false) => error_code!(E0531),
-            (PathSource::TraitItem(..), true) => error_code!(E0575),
-            (PathSource::TraitItem(..), false) => error_code!(E0576),
+            (PathSource::Trait(_), true) => E0404,
+            (PathSource::Trait(_), false) => E0405,
+            (PathSource::Type, true) => E0573,
+            (PathSource::Type, false) => E0412,
+            (PathSource::Struct, true) => E0574,
+            (PathSource::Struct, false) => E0422,
+            (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423,
+            (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
+            (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
+            (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
+            (PathSource::TraitItem(..), true) => E0575,
+            (PathSource::TraitItem(..), false) => E0576,
         }
     }
 }
@@ -1673,13 +1674,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     } else {
                         ("`'_` cannot be used here", "`'_` is a reserved lifetime name")
                     };
-                    let mut diag = rustc_errors::struct_span_code_err!(
-                        self.r.dcx(),
-                        lifetime.ident.span,
-                        E0637,
-                        "{}",
-                        msg,
-                    );
+                    let mut diag =
+                        struct_span_code_err!(self.r.dcx(), lifetime.ident.span, E0637, "{}", msg,);
                     diag.span_label(lifetime.ident.span, note);
                     if elided {
                         for rib in self.lifetime_ribs[i..].iter().rev() {
@@ -1863,7 +1859,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
                     | LifetimeRibKind::AnonymousWarn(_) => {
                         let sess = self.r.tcx.sess;
-                        let mut err = rustc_errors::struct_span_code_err!(
+                        let mut err = struct_span_code_err!(
                             sess.dcx(),
                             path_span,
                             E0726,
@@ -2608,7 +2604,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             }
 
             if param.ident.name == kw::UnderscoreLifetime {
-                rustc_errors::struct_span_code_err!(
+                struct_span_code_err!(
                     self.r.dcx(),
                     param.ident.span,
                     E0637,
@@ -2622,7 +2618,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             }
 
             if param.ident.name == kw::StaticLifetime {
-                rustc_errors::struct_span_code_err!(
+                struct_span_code_err!(
                     self.r.dcx(),
                     param.ident.span,
                     E0262,
@@ -3164,10 +3160,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         // The method kind does not correspond to what appeared in the trait, report.
         let path = &self.current_trait_ref.as_ref().unwrap().1.path;
         let (code, kind) = match kind {
-            AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"),
-            AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"),
-            AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"),
-            AssocItemKind::Delegation(..) => (rustc_errors::error_code!(E0324), "method"),
+            AssocItemKind::Const(..) => (E0323, "const"),
+            AssocItemKind::Fn(..) => (E0324, "method"),
+            AssocItemKind::Type(..) => (E0325, "type"),
+            AssocItemKind::Delegation(..) => (E0324, "method"),
             AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
         };
         let trait_path = path_names_to_string(path);
@@ -4424,35 +4420,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             ExprKind::Type(ref _type_expr, ref _ty) => {
                 visit::walk_expr(self, expr);
             }
-            // `async |x| ...` gets desugared to `|x| async {...}`, so we need to
-            // resolve the arguments within the proper scopes so that usages of them inside the
-            // closure are detected as upvars rather than normal closure arg usages.
-            //
-            // Similarly, `gen |x| ...` gets desugared to `|x| gen {...}`, so we handle that too.
-            ExprKind::Closure(box ast::Closure {
-                coroutine_kind: Some(_),
-                ref fn_decl,
-                ref body,
-                ..
-            }) => {
-                self.with_rib(ValueNS, RibKind::Normal, |this| {
-                    this.with_label_rib(RibKind::FnOrCoroutine, |this| {
-                        // Resolve arguments:
-                        this.resolve_params(&fn_decl.inputs);
-                        // No need to resolve return type --
-                        // the outer closure return type is `FnRetTy::Default`.
-
-                        // Now resolve the inner closure
-                        {
-                            // No need to resolve arguments: the inner closure has none.
-                            // Resolve the return type:
-                            visit::walk_fn_ret_ty(this, &fn_decl.output);
-                            // Resolve the body
-                            this.visit_expr(body);
-                        }
-                    })
-                });
-            }
             // For closures, RibKind::FnOrCoroutine is added in visit_fn
             ExprKind::Closure(box ast::Closure {
                 binder: ClosureBinder::For { ref generic_params, span },
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index abb0a7a465a..a4c041f1ff2 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -16,8 +16,8 @@ use rustc_ast::{
 use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-    MultiSpan, SuggestionStyle,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    ErrorGuaranteed, MultiSpan, SuggestionStyle,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
@@ -922,8 +922,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         path: &[Segment],
         span: Span,
     ) {
-        if let Some(err_code) = &err.code {
-            if err_code == &rustc_errors::error_code!(E0425) {
+        if let Some(err_code) = err.code {
+            if err_code == E0425 {
                 for label_rib in &self.label_ribs {
                     for (label_ident, node_id) in &label_rib.bindings {
                         let ident = path.last().unwrap().ident;
@@ -946,7 +946,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                         }
                     }
                 }
-            } else if err_code == &rustc_errors::error_code!(E0412) {
+            } else if err_code == E0412 {
                 if let Some(correct) = Self::likely_rust_type(path) {
                     err.span_suggestion(
                         span,
@@ -970,7 +970,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         if !is_self_type(path, source.namespace()) {
             return false;
         }
-        err.code(rustc_errors::error_code!(E0411));
+        err.code(E0411);
         err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
         if let Some(item_kind) = self.diagnostic_metadata.current_item {
             if !item_kind.ident.span.is_dummy() {
@@ -999,7 +999,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
 
         debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
-        err.code(rustc_errors::error_code!(E0424));
+        err.code(E0424);
         err.span_label(
             span,
             match source {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 925c3c0e27d..9d09d060b59 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -35,7 +35,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{FreezeReadGuard, Lrc};
-use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_errors::{Applicability, DiagnosticBuilder, ErrCode};
 use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
 use rustc_feature::BUILTIN_ATTRIBUTES;
 use rustc_hir::def::Namespace::{self, *};
@@ -256,7 +256,7 @@ enum ResolutionError<'a> {
         kind: &'static str,
         trait_path: String,
         trait_item_span: Span,
-        code: String,
+        code: ErrCode,
     },
     /// Error E0201: multiple impl items for the same trait item.
     TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span },
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 1c085ddf57b..a6bf289a76a 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -15,7 +15,7 @@ use rustc_ast_pretty::pprust;
 use rustc_attr::StabilityLevel;
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{struct_span_code_err, Applicability};
+use rustc_errors::{codes::*, struct_span_code_err, Applicability};
 use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand};
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::compile_declarative_macro;
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index e751ff13a34..2ec1a726cef 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -347,6 +347,7 @@ impl SwitchWithOptPath {
 pub enum SymbolManglingVersion {
     Legacy,
     V0,
+    Hashed,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Hash)]
@@ -2692,6 +2693,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
     match cg.symbol_mangling_version {
         // Stable values:
         None | Some(SymbolManglingVersion::V0) => {}
+
         // Unstable values:
         Some(SymbolManglingVersion::Legacy) => {
             if !unstable_opts.unstable_options {
@@ -2700,6 +2702,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
                 );
             }
         }
+        Some(SymbolManglingVersion::Hashed) => {
+            if !unstable_opts.unstable_options {
+                early_dcx.early_fatal(
+                    "`-C symbol-mangling-version=hashed` requires `-Z unstable-options`",
+                );
+            }
+        }
     }
 
     // Check for unstable values of `-C instrument-coverage`.
@@ -2741,6 +2750,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
                 );
             }
             Some(SymbolManglingVersion::V0) => {}
+            Some(SymbolManglingVersion::Hashed) => {
+                early_dcx.early_warn(
+                    "-C instrument-coverage requires symbol mangling version `v0`, \
+                    but `-C symbol-mangling-version=hashed` was specified",
+                );
+            }
         }
     }
 
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index e19f0fd84de..c36cec6f353 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -3,7 +3,7 @@ use std::num::NonZeroU32;
 use rustc_ast::token;
 use rustc_ast::util::literal::LitError;
 use rustc_errors::{
-    error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan,
+    codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan,
 };
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
@@ -19,9 +19,7 @@ pub struct FeatureGateError {
 impl<'a> IntoDiagnostic<'a> for FeatureGateError {
     #[track_caller]
     fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder::new(dcx, level, self.explain)
-            .with_span(self.span)
-            .with_code(error_code!(E0658))
+        DiagnosticBuilder::new(dcx, level, self.explain).with_span(self.span).with_code(E0658)
     }
 }
 
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 486b6d4bf2e..d8d201d5f24 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -407,7 +407,8 @@ mod desc {
     pub const parse_switch_with_opt_path: &str =
         "an optional path to the profiling data output directory";
     pub const parse_merge_functions: &str = "one of: `disabled`, `trampolines`, or `aliases`";
-    pub const parse_symbol_mangling_version: &str = "either `legacy` or `v0` (RFC 2603)";
+    pub const parse_symbol_mangling_version: &str =
+        "one of: `legacy`, `v0` (RFC 2603), or `hashed`";
     pub const parse_src_file_hash: &str = "either `md5` or `sha1`";
     pub const parse_relocation_model: &str =
         "one of supported relocation models (`rustc --print relocation-models`)";
@@ -1180,6 +1181,7 @@ mod parse {
         *slot = match v {
             Some("legacy") => Some(SymbolManglingVersion::Legacy),
             Some("v0") => Some(SymbolManglingVersion::V0),
+            Some("hashed") => Some(SymbolManglingVersion::Hashed),
             _ => return false,
         };
         true
@@ -1504,7 +1506,7 @@ options! {
         "tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
     symbol_mangling_version: Option<SymbolManglingVersion> = (None,
         parse_symbol_mangling_version, [TRACKED],
-        "which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
+        "which mangling version to use for symbol names ('legacy' (default), 'v0', or 'hashed')"),
     target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
         "select target processor (`rustc --print target-cpus` for details)"),
     target_feature: String = (String::new(), parse_target_feature, [TRACKED],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 891a83ce80c..7cd76ad7293 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -22,7 +22,7 @@ use rustc_errors::emitter::{DynEmitter, HumanEmitter, HumanReadableErrorType};
 use rustc_errors::json::JsonEmitter;
 use rustc_errors::registry::Registry;
 use rustc_errors::{
-    error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage,
+    codes::*, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrCode,
     ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl,
 };
 use rustc_macros::HashStable_Generic;
@@ -316,7 +316,7 @@ impl Session {
     ) -> DiagnosticBuilder<'a> {
         let mut err = self.dcx().create_err(err);
         if err.code.is_none() {
-            err.code(error_code!(E0658));
+            err.code(E0658);
         }
         add_feature_diagnostics(&mut err, self, feature);
         err
@@ -893,7 +893,7 @@ impl Session {
         CodegenUnits::Default(16)
     }
 
-    pub fn teach(&self, code: &str) -> bool {
+    pub fn teach(&self, code: ErrCode) -> bool {
         self.opts.unstable_opts.teach && self.dcx().must_teach(code)
     }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 4a1c222a528..a54b928b908 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -246,17 +246,7 @@ symbols! {
         MutexGuard,
         N,
         NonNull,
-        NonZeroI128,
-        NonZeroI16,
-        NonZeroI32,
-        NonZeroI64,
-        NonZeroI8,
-        NonZeroU128,
-        NonZeroU16,
-        NonZeroU32,
-        NonZeroU64,
-        NonZeroU8,
-        NonZeroUsize,
+        NonZero,
         None,
         Normal,
         Ok,
@@ -1029,6 +1019,7 @@ symbols! {
         min_const_fn,
         min_const_generics,
         min_const_unsafe_fn,
+        min_exhaustive_patterns,
         min_specialization,
         min_type_alias_impl_trait,
         minnumf32,
diff --git a/compiler/rustc_symbol_mangling/src/hashed.rs b/compiler/rustc_symbol_mangling/src/hashed.rs
new file mode 100644
index 00000000000..d4cd6161ac0
--- /dev/null
+++ b/compiler/rustc_symbol_mangling/src/hashed.rs
@@ -0,0 +1,43 @@
+use crate::v0;
+use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
+use rustc_hir::def_id::CrateNum;
+use rustc_middle::ty::{Instance, TyCtxt};
+
+use std::fmt::Write;
+
+pub(super) fn mangle<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+    instantiating_crate: Option<CrateNum>,
+    full_mangling_name: impl FnOnce() -> String,
+) -> String {
+    // The symbol of a generic function may be scattered in multiple downstream dylibs.
+    // If the symbol of a generic function still contains `crate name`, hash conflicts between the
+    // generic funcion and other symbols of the same `crate` cannot be detected in time during
+    // construction. This symbol conflict is left over until it occurs during run time.
+    // In this case, `instantiating-crate name` is used to replace `crate name` can completely
+    // eliminate the risk of the preceding potential hash conflict.
+    let crate_num =
+        if let Some(krate) = instantiating_crate { krate } else { instance.def_id().krate };
+
+    let mut symbol = "_RNxC".to_string();
+    v0::push_ident(tcx.crate_name(crate_num).as_str(), &mut symbol);
+
+    let hash = tcx.with_stable_hashing_context(|mut hcx| {
+        let mut hasher = StableHasher::new();
+        full_mangling_name().hash_stable(&mut hcx, &mut hasher);
+        hasher.finish::<Hash64>().as_u64()
+    });
+
+    push_hash64(hash, &mut symbol);
+
+    symbol
+}
+
+// The hash is encoded based on `base-62` and the final terminator `_` is removed because it does
+// not help prevent hash collisions
+fn push_hash64(hash: u64, output: &mut String) {
+    let hash = v0::encode_integer_62(hash);
+    let hash_len = hash.len();
+    let _ = write!(output, "{hash_len}H{}", &hash[..hash_len - 1]);
+}
diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs
index 1817cd72b23..362aaca6364 100644
--- a/compiler/rustc_symbol_mangling/src/lib.rs
+++ b/compiler/rustc_symbol_mangling/src/lib.rs
@@ -109,6 +109,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_session::config::SymbolManglingVersion;
 
+mod hashed;
 mod legacy;
 mod v0;
 
@@ -263,6 +264,9 @@ fn compute_symbol_name<'tcx>(
     let symbol = match mangling_version {
         SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate),
         SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate),
+        SymbolManglingVersion::Hashed => hashed::mangle(tcx, instance, instantiating_crate, || {
+            v0::mangle(tcx, instance, instantiating_crate)
+        }),
     };
 
     debug_assert!(
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index e89a640767f..16ebda55a7a 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -116,10 +116,7 @@ impl<'tcx> SymbolMangler<'tcx> {
     /// * `x > 0` is encoded as `x - 1` in base 62, followed by `"_"`,
     ///   e.g. `1` becomes `"0_"`, `62` becomes `"Z_"`, etc.
     fn push_integer_62(&mut self, x: u64) {
-        if let Some(x) = x.checked_sub(1) {
-            base_n::push_str(x as u128, 62, &mut self.out);
-        }
-        self.push("_");
+        push_integer_62(x, &mut self.out)
     }
 
     /// Push a `tag`-prefixed base 62 integer, when larger than `0`, that is:
@@ -138,45 +135,7 @@ impl<'tcx> SymbolMangler<'tcx> {
     }
 
     fn push_ident(&mut self, ident: &str) {
-        let mut use_punycode = false;
-        for b in ident.bytes() {
-            match b {
-                b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => {}
-                0x80..=0xff => use_punycode = true,
-                _ => bug!("symbol_names: bad byte {} in ident {:?}", b, ident),
-            }
-        }
-
-        let punycode_string;
-        let ident = if use_punycode {
-            self.push("u");
-
-            // FIXME(eddyb) we should probably roll our own punycode implementation.
-            let mut punycode_bytes = match punycode::encode(ident) {
-                Ok(s) => s.into_bytes(),
-                Err(()) => bug!("symbol_names: punycode encoding failed for ident {:?}", ident),
-            };
-
-            // Replace `-` with `_`.
-            if let Some(c) = punycode_bytes.iter_mut().rfind(|&&mut c| c == b'-') {
-                *c = b'_';
-            }
-
-            // FIXME(eddyb) avoid rechecking UTF-8 validity.
-            punycode_string = String::from_utf8(punycode_bytes).unwrap();
-            &punycode_string
-        } else {
-            ident
-        };
-
-        let _ = write!(self.out, "{}", ident.len());
-
-        // Write a separating `_` if necessary (leading digit or `_`).
-        if let Some('_' | '0'..='9') = ident.chars().next() {
-            self.push("_");
-        }
-
-        self.push(ident);
+        push_ident(ident, &mut self.out)
     }
 
     fn path_append_ns(
@@ -836,3 +795,62 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
         Ok(())
     }
 }
+/// Push a `_`-terminated base 62 integer, using the format
+/// specified in the RFC as `<base-62-number>`, that is:
+/// * `x = 0` is encoded as just the `"_"` terminator
+/// * `x > 0` is encoded as `x - 1` in base 62, followed by `"_"`,
+///   e.g. `1` becomes `"0_"`, `62` becomes `"Z_"`, etc.
+pub(crate) fn push_integer_62(x: u64, output: &mut String) {
+    if let Some(x) = x.checked_sub(1) {
+        base_n::push_str(x as u128, 62, output);
+    }
+    output.push('_');
+}
+
+pub(crate) fn encode_integer_62(x: u64) -> String {
+    let mut output = String::new();
+    push_integer_62(x, &mut output);
+    output
+}
+
+pub(crate) fn push_ident(ident: &str, output: &mut String) {
+    let mut use_punycode = false;
+    for b in ident.bytes() {
+        match b {
+            b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => {}
+            0x80..=0xff => use_punycode = true,
+            _ => bug!("symbol_names: bad byte {} in ident {:?}", b, ident),
+        }
+    }
+
+    let punycode_string;
+    let ident = if use_punycode {
+        output.push('u');
+
+        // FIXME(eddyb) we should probably roll our own punycode implementation.
+        let mut punycode_bytes = match punycode::encode(ident) {
+            Ok(s) => s.into_bytes(),
+            Err(()) => bug!("symbol_names: punycode encoding failed for ident {:?}", ident),
+        };
+
+        // Replace `-` with `_`.
+        if let Some(c) = punycode_bytes.iter_mut().rfind(|&&mut c| c == b'-') {
+            *c = b'_';
+        }
+
+        // FIXME(eddyb) avoid rechecking UTF-8 validity.
+        punycode_string = String::from_utf8(punycode_bytes).unwrap();
+        &punycode_string
+    } else {
+        ident
+    };
+
+    let _ = write!(output, "{}", ident.len());
+
+    // Write a separating `_` if necessary (leading digit or `_`).
+    if let Some('_' | '0'..='9') = ident.chars().next() {
+        output.push('_');
+    }
+
+    output.push_str(ident);
+}
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 5eff52afbca..7894f8dd98f 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,7 +1,7 @@
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee,
-    IntoDiagnostic, Level, SubdiagnosticMessage,
+    codes::*, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder,
+    EmissionGuarantee, IntoDiagnostic, Level, SubdiagnosticMessage,
 };
 use rustc_macros::Diagnostic;
 use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty};
@@ -25,7 +25,7 @@ pub struct UnableToConstructConstantValue<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = E0232)]
 pub struct EmptyOnClauseInOnUnimplemented {
     #[primary_span]
     #[label]
@@ -33,7 +33,7 @@ pub struct EmptyOnClauseInOnUnimplemented {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = E0232)]
 pub struct InvalidOnClauseInOnUnimplemented {
     #[primary_span]
     #[label]
@@ -41,7 +41,7 @@ pub struct InvalidOnClauseInOnUnimplemented {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = "E0232")]
+#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = E0232)]
 #[note]
 pub struct NoValueInOnUnimplemented {
     #[primary_span]
@@ -59,17 +59,13 @@ pub struct NegativePositiveConflict<'tcx> {
 
 impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NegativePositiveConflict<'_> {
     #[track_caller]
-    fn into_diagnostic(
-        self,
-        dcx: &DiagCtxt,
-        level: Level,
-    ) -> rustc_errors::DiagnosticBuilder<'_, G> {
+    fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> {
         let mut diag =
             DiagnosticBuilder::new(dcx, level, fluent::trait_selection_negative_positive_conflict);
         diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string());
         diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()));
         diag.span(self.impl_span);
-        diag.code(rustc_errors::error_code!(E0751));
+        diag.code(E0751);
         match self.negative_impl_span {
             Ok(span) => {
                 diag.span_label(span, fluent::trait_selection_negative_implementation_here);
@@ -132,7 +128,7 @@ impl AddToDiagnostic for AdjustSignatureBorrow {
 }
 
 #[derive(Diagnostic)]
-#[diag(trait_selection_closure_kind_mismatch, code = "E0525")]
+#[diag(trait_selection_closure_kind_mismatch, code = E0525)]
 pub struct ClosureKindMismatch {
     #[primary_span]
     #[label]
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
index 864580afe62..ca43436848b 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs
@@ -1,7 +1,7 @@
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::InferCtxt;
 use crate::traits::{Obligation, ObligationCause, ObligationCtxt};
-use rustc_errors::{pluralize, struct_span_code_err, Applicability, DiagnosticBuilder};
+use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_hir::Node;
 use rustc_middle::ty::{self, Ty};
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index bb1b6ec1390..972da180a33 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -6,7 +6,7 @@ use rustc_ast::AttrKind;
 use rustc_ast::{Attribute, MetaItem, NestedMetaItem};
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{struct_span_code_err, ErrorGuaranteed};
+use rustc_errors::{codes::*, struct_span_code_err, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::GenericArgsRef;
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 6a40ffebdad..cdf99870006 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -13,7 +13,7 @@ use hir::def::CtorOf;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
-    error_code, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
     MultiSpan, Style, SuggestionStyle,
 };
 use rustc_hir as hir;
@@ -2014,7 +2014,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             return false;
         };
 
-        err.code(error_code!(E0746));
+        err.code(E0746);
         err.primary_message("return type cannot have an unboxed trait object");
         err.children.clear();
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 149dcffe333..2a09e95b2c5 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -19,8 +19,8 @@ use crate::traits::{
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_errors::{
-    pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
-    MultiSpan, StashKey, Style,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder,
+    ErrorGuaranteed, MultiSpan, StashKey, Style,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace, Res};
@@ -2529,7 +2529,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                  corresponding `impl` type",
                             ),
                         );
-                        err.code(rustc_errors::error_code!(E0790));
+                        err.code(E0790);
 
                         if let Some(local_def_id) = data.trait_ref.def_id.as_local()
                             && let Some(hir::Node::Item(hir::Item {
@@ -3162,7 +3162,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             | ObligationCauseCode::ItemObligation(def_id)
                 if self.tcx.is_fn_trait(*def_id) =>
             {
-                err.code(rustc_errors::error_code!(E0059));
+                err.code(E0059);
                 err.primary_message(format!(
                     "type parameter to bare `{}` trait must be a tuple",
                     self.tcx.def_path_str(*def_id)
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index bfc6937a3eb..de08e7d2f03 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -20,7 +20,7 @@ use crate::traits::{
     self, coherence, FutureCompatOverlapErrorKind, ObligationCause, ObligationCtxt,
 };
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{error_code, DelayDm, Diagnostic};
+use rustc_errors::{codes::*, DelayDm, Diagnostic};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{GenericArgs, GenericArgsRef};
@@ -449,7 +449,7 @@ fn report_conflicting_impls<'tcx>(
                 || tcx.orphan_check_impl(impl_def_id).is_ok()
             {
                 let mut err = tcx.dcx().struct_span_err(impl_span, msg);
-                err.code(error_code!(E0119));
+                err.code(E0119);
                 decorate(tcx, &overlap, impl_span, &mut err);
                 err.emit()
             } else {
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 947d4bbe86e..bfbb45f0cb5 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -1,5 +1,6 @@
 //! Errors emitted by ty_utils
 
+use rustc_errors::codes::*;
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_middle::ty::{GenericArg, Ty};
 use rustc_span::Span;
@@ -113,7 +114,7 @@ pub struct DuplicateArg<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(ty_utils_impl_trait_not_param, code = "E0792")]
+#[diag(ty_utils_impl_trait_not_param, code = E0792)]
 pub struct NotParam<'tcx> {
     pub arg: GenericArg<'tcx>,
     #[primary_span]
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 6977681e5a3..2e321018407 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -191,8 +191,7 @@ mod thin;
 #[fundamental]
 #[stable(feature = "rust1", since = "1.0.0")]
 // The declaration of the `Box` struct must be kept in sync with the
-// `alloc::alloc::box_free` function or ICEs will happen. See the comment
-// on `box_free` for more details.
+// compiler or ICEs will happen.
 pub struct Box<
     T: ?Sized,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 02ecbe22b3e..ab08b483367 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -103,7 +103,6 @@
 #![feature(allocator_api)]
 #![feature(array_chunks)]
 #![feature(array_into_iter_constructors)]
-#![feature(array_methods)]
 #![feature(array_windows)]
 #![feature(ascii_char)]
 #![feature(assert_matches)]
@@ -149,7 +148,6 @@
 #![feature(set_ptr_value)]
 #![feature(sized_type_properties)]
 #![feature(slice_from_ptr_range)]
-#![feature(slice_group_by)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
 #![feature(slice_range)]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 7705c86001e..0338565980c 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -939,8 +939,11 @@ impl<T, A: Allocator> Rc<T, A> {
     /// it is guaranteed that exactly one of the calls returns the inner value.
     /// This means in particular that the inner value is not dropped.
     ///
-    /// This is equivalent to `Rc::try_unwrap(this).ok()`. (Note that these are not equivalent for
-    /// [`Arc`](crate::sync::Arc), due to race conditions that do not apply to `Rc`.)
+    /// [`Rc::try_unwrap`] is conceptually similar to `Rc::into_inner`.
+    /// And while they are meant for different use-cases, `Rc::into_inner(this)`
+    /// is in fact equivalent to <code>[Rc::try_unwrap]\(this).[ok][Result::ok]()</code>.
+    /// (Note that the same kind of equivalence does **not** hold true for
+    /// [`Arc`](crate::sync::Arc), due to race conditions that do not apply to `Rc`!)
     #[inline]
     #[stable(feature = "rc_into_inner", since = "1.70.0")]
     pub fn into_inner(this: Self) -> Option<T> {
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index aa3b7b7e191..4033f4eb068 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -51,14 +51,14 @@ pub use core::slice::{from_mut, from_ref};
 pub use core::slice::{from_mut_ptr_range, from_ptr_range};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{from_raw_parts, from_raw_parts_mut};
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+pub use core::slice::{ChunkBy, ChunkByMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{Chunks, Windows};
 #[stable(feature = "chunks_exact", since = "1.31.0")]
 pub use core::slice::{ChunksExact, ChunksExactMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{ChunksMut, Split, SplitMut};
-#[unstable(feature = "slice_group_by", issue = "80552")]
-pub use core::slice::{GroupBy, GroupByMut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{Iter, IterMut};
 #[stable(feature = "rchunks", since = "1.31.0")]
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 38f9f39fbf8..ade114678b7 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -30,6 +30,8 @@ pub use core::str::SplitAsciiWhitespace;
 pub use core::str::SplitInclusive;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::SplitWhitespace;
+#[unstable(feature = "str_from_raw_parts", issue = "119206")]
+pub use core::str::{from_raw_parts, from_raw_parts_mut};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::{from_utf8, from_utf8_mut, Bytes, CharIndices, Chars};
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 48c8d9d113b..d0f98f9c7db 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -983,9 +983,13 @@ impl<T, A: Allocator> Arc<T, A> {
     /// it is guaranteed that exactly one of the calls returns the inner value.
     /// This means in particular that the inner value is not dropped.
     ///
-    /// The similar expression `Arc::try_unwrap(this).ok()` does not
-    /// offer such a guarantee. See the last example below
-    /// and the documentation of [`Arc::try_unwrap`].
+    /// [`Arc::try_unwrap`] is conceptually similar to `Arc::into_inner`, but it
+    /// is meant for different use-cases. If used as a direct replacement
+    /// for `Arc::into_inner` anyway, such as with the expression
+    /// <code>[Arc::try_unwrap]\(this).[ok][Result::ok]()</code>, then it does
+    /// **not** give the same guarantee as described in the previous paragraph.
+    /// For more information, see the examples below and read the documentation
+    /// of [`Arc::try_unwrap`].
     ///
     /// # Examples
     ///
diff --git a/library/alloc/src/vec/cow.rs b/library/alloc/src/vec/cow.rs
index 2c799605b7b..b12910f3690 100644
--- a/library/alloc/src/vec/cow.rs
+++ b/library/alloc/src/vec/cow.rs
@@ -15,6 +15,19 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
     }
 }
 
+#[stable(feature = "cow_from_array_ref", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> {
+    /// Creates a [`Borrowed`] variant of [`Cow`]
+    /// from a reference to an array.
+    ///
+    /// This conversion does not allocate or clone the data.
+    ///
+    /// [`Borrowed`]: crate::borrow::Cow::Borrowed
+    fn from(s: &'a [T; N]) -> Cow<'a, [T]> {
+        Cow::Borrowed(s as &[_])
+    }
+}
+
 #[stable(feature = "cow_from_vec", since = "1.8.0")]
 impl<'a, T: Clone> From<Vec<T>> for Cow<'a, [T]> {
     /// Creates an [`Owned`] variant of [`Cow`]
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 6ca0dca1e9d..a360c430946 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2204,14 +2204,6 @@ impl<T, A: Allocator> Vec<T, A> {
             assert_failed(at, self.len());
         }
 
-        if at == 0 {
-            // the new vector can take over the original buffer and avoid the copy
-            return mem::replace(
-                self,
-                Vec::with_capacity_in(self.capacity(), self.allocator().clone()),
-            );
-        }
-
         let other_len = self.len - at;
         let mut other = Vec::with_capacity_in(other_len, self.allocator().clone());
 
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 2dcfc6b4abf..ca17dab55b0 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -29,7 +29,6 @@
 #![feature(iter_advance_by)]
 #![feature(iter_next_chunk)]
 #![feature(round_char_boundary)]
-#![feature(slice_group_by)]
 #![feature(slice_partition_dedup)]
 #![feature(string_remove_matches)]
 #![feature(const_btree_len)]
diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs
index 784839a3ffa..c0f7a11a93e 100644
--- a/library/alloc/tests/slice.rs
+++ b/library/alloc/tests/slice.rs
@@ -1614,10 +1614,10 @@ fn subslice_patterns() {
 }
 
 #[test]
-fn test_group_by() {
+fn test_chunk_by() {
     let slice = &[1, 1, 1, 3, 3, 2, 2, 2, 1, 0];
 
-    let mut iter = slice.group_by(|a, b| a == b);
+    let mut iter = slice.chunk_by(|a, b| a == b);
     assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
     assert_eq!(iter.next(), Some(&[3, 3][..]));
     assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
@@ -1625,7 +1625,7 @@ fn test_group_by() {
     assert_eq!(iter.next(), Some(&[0][..]));
     assert_eq!(iter.next(), None);
 
-    let mut iter = slice.group_by(|a, b| a == b);
+    let mut iter = slice.chunk_by(|a, b| a == b);
     assert_eq!(iter.next_back(), Some(&[0][..]));
     assert_eq!(iter.next_back(), Some(&[1][..]));
     assert_eq!(iter.next_back(), Some(&[2, 2, 2][..]));
@@ -1633,7 +1633,7 @@ fn test_group_by() {
     assert_eq!(iter.next_back(), Some(&[1, 1, 1][..]));
     assert_eq!(iter.next_back(), None);
 
-    let mut iter = slice.group_by(|a, b| a == b);
+    let mut iter = slice.chunk_by(|a, b| a == b);
     assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
     assert_eq!(iter.next_back(), Some(&[0][..]));
     assert_eq!(iter.next(), Some(&[3, 3][..]));
@@ -1643,10 +1643,10 @@ fn test_group_by() {
 }
 
 #[test]
-fn test_group_by_mut() {
+fn test_chunk_by_mut() {
     let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2, 1, 0];
 
-    let mut iter = slice.group_by_mut(|a, b| a == b);
+    let mut iter = slice.chunk_by_mut(|a, b| a == b);
     assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
     assert_eq!(iter.next(), Some(&mut [3, 3][..]));
     assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
@@ -1654,7 +1654,7 @@ fn test_group_by_mut() {
     assert_eq!(iter.next(), Some(&mut [0][..]));
     assert_eq!(iter.next(), None);
 
-    let mut iter = slice.group_by_mut(|a, b| a == b);
+    let mut iter = slice.chunk_by_mut(|a, b| a == b);
     assert_eq!(iter.next_back(), Some(&mut [0][..]));
     assert_eq!(iter.next_back(), Some(&mut [1][..]));
     assert_eq!(iter.next_back(), Some(&mut [2, 2, 2][..]));
@@ -1662,7 +1662,7 @@ fn test_group_by_mut() {
     assert_eq!(iter.next_back(), Some(&mut [1, 1, 1][..]));
     assert_eq!(iter.next_back(), None);
 
-    let mut iter = slice.group_by_mut(|a, b| a == b);
+    let mut iter = slice.chunk_by_mut(|a, b| a == b);
     assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
     assert_eq!(iter.next_back(), Some(&mut [0][..]));
     assert_eq!(iter.next(), Some(&mut [3, 3][..]));
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index d5ae8cdac1f..38a68df79cc 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -958,23 +958,35 @@ fn test_append() {
 #[test]
 fn test_split_off() {
     let mut vec = vec![1, 2, 3, 4, 5, 6];
+    let orig_ptr = vec.as_ptr();
     let orig_capacity = vec.capacity();
-    let vec2 = vec.split_off(4);
+
+    let split_off = vec.split_off(4);
     assert_eq!(vec, [1, 2, 3, 4]);
-    assert_eq!(vec2, [5, 6]);
+    assert_eq!(split_off, [5, 6]);
     assert_eq!(vec.capacity(), orig_capacity);
+    assert_eq!(vec.as_ptr(), orig_ptr);
 }
 
 #[test]
 fn test_split_off_take_all() {
-    let mut vec = vec![1, 2, 3, 4, 5, 6];
+    // Allocate enough capacity that we can tell whether the split-off vector's
+    // capacity is based on its size, or (incorrectly) on the original capacity.
+    let mut vec = Vec::with_capacity(1000);
+    vec.extend([1, 2, 3, 4, 5, 6]);
     let orig_ptr = vec.as_ptr();
     let orig_capacity = vec.capacity();
-    let vec2 = vec.split_off(0);
+
+    let split_off = vec.split_off(0);
     assert_eq!(vec, []);
-    assert_eq!(vec2, [1, 2, 3, 4, 5, 6]);
+    assert_eq!(split_off, [1, 2, 3, 4, 5, 6]);
     assert_eq!(vec.capacity(), orig_capacity);
-    assert_eq!(vec2.as_ptr(), orig_ptr);
+    assert_eq!(vec.as_ptr(), orig_ptr);
+
+    // The split-off vector should be newly-allocated, and should not have
+    // stolen the original vector's allocation.
+    assert!(split_off.capacity() < orig_capacity);
+    assert_ne!(split_off.as_ptr(), orig_ptr);
 }
 
 #[test]
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 9d95b32409c..85cce81f2c1 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -559,8 +559,6 @@ impl<T, const N: usize> [T; N] {
     /// # Example
     ///
     /// ```
-    /// #![feature(array_methods)]
-    ///
     /// let floats = [3.1, 2.7, -1.0];
     /// let float_refs: [&f64; 3] = floats.each_ref();
     /// assert_eq!(float_refs, [&3.1, &2.7, &-1.0]);
@@ -571,8 +569,6 @@ impl<T, const N: usize> [T; N] {
     /// array if its elements are not [`Copy`].
     ///
     /// ```
-    /// #![feature(array_methods)]
-    ///
     /// let strings = ["Ferris".to_string(), "♥".to_string(), "Rust".to_string()];
     /// let is_ascii = strings.each_ref().map(|s| s.is_ascii());
     /// assert_eq!(is_ascii, [true, false, true]);
@@ -580,7 +576,7 @@ impl<T, const N: usize> [T; N] {
     /// // We can still access the original array: it has not been moved.
     /// assert_eq!(strings.len(), 3);
     /// ```
-    #[unstable(feature = "array_methods", issue = "76118")]
+    #[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn each_ref(&self) -> [&T; N] {
         from_trusted_iterator(self.iter())
     }
@@ -592,7 +588,6 @@ impl<T, const N: usize> [T; N] {
     /// # Example
     ///
     /// ```
-    /// #![feature(array_methods)]
     ///
     /// let mut floats = [3.1, 2.7, -1.0];
     /// let float_refs: [&mut f64; 3] = floats.each_mut();
@@ -600,7 +595,7 @@ impl<T, const N: usize> [T; N] {
     /// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
     /// assert_eq!(floats, [0.0, 2.7, -1.0]);
     /// ```
-    #[unstable(feature = "array_methods", issue = "76118")]
+    #[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")]
     pub fn each_mut(&mut self) -> [&mut T; N] {
         from_trusted_iterator(self.iter_mut())
     }
diff --git a/library/core/src/ascii/ascii_char.rs b/library/core/src/ascii/ascii_char.rs
index cc872a5343d..5f758af1624 100644
--- a/library/core/src/ascii/ascii_char.rs
+++ b/library/core/src/ascii/ascii_char.rs
@@ -537,6 +537,22 @@ impl AsciiChar {
     }
 }
 
+macro_rules! into_int_impl {
+    ($($ty:ty)*) => {
+        $(
+            #[unstable(feature = "ascii_char", issue = "110998")]
+            impl From<AsciiChar> for $ty {
+                #[inline]
+                fn from(chr: AsciiChar) -> $ty {
+                    chr as u8 as $ty
+                }
+            }
+        )*
+    }
+}
+
+into_int_impl!(u8 u16 u32 u64 u128 char);
+
 impl [AsciiChar] {
     /// Views this slice of ASCII characters as a UTF-8 `str`.
     #[unstable(feature = "ascii_char", issue = "110998")]
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 76a53a9366a..43124535ab5 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2531,7 +2531,7 @@ extern "rust-intrinsic" {
     /// or `false`, and the caller has to ensure sound behavior for both cases.
     /// In other words, the following code has *Undefined Behavior*:
     ///
-    /// ```
+    /// ```no_run
     /// #![feature(is_val_statically_known)]
     /// #![feature(core_intrinsics)]
     /// # #![allow(internal_features)]
diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs
index d8bbd424cf2..c97a59b614f 100644
--- a/library/core/src/iter/adapters/intersperse.rs
+++ b/library/core/src/iter/adapters/intersperse.rs
@@ -1,4 +1,5 @@
-use super::Peekable;
+use crate::fmt;
+use crate::iter::{Fuse, FusedIterator};
 
 /// An iterator adapter that places a separator between all elements.
 ///
@@ -10,9 +11,18 @@ pub struct Intersperse<I: Iterator>
 where
     I::Item: Clone,
 {
+    started: bool,
     separator: I::Item,
-    iter: Peekable<I>,
-    needs_sep: bool,
+    next_item: Option<I::Item>,
+    iter: Fuse<I>,
+}
+
+#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+impl<I> FusedIterator for Intersperse<I>
+where
+    I: FusedIterator,
+    I::Item: Clone,
+{
 }
 
 impl<I: Iterator> Intersperse<I>
@@ -20,7 +30,7 @@ where
     I::Item: Clone,
 {
     pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self {
-        Self { iter: iter.peekable(), separator, needs_sep: false }
+        Self { started: false, separator, next_item: None, iter: iter.fuse() }
     }
 }
 
@@ -33,27 +43,43 @@ where
     type Item = I::Item;
 
     #[inline]
-    fn next(&mut self) -> Option<I::Item> {
-        if self.needs_sep && self.iter.peek().is_some() {
-            self.needs_sep = false;
-            Some(self.separator.clone())
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.started {
+            if let Some(v) = self.next_item.take() {
+                Some(v)
+            } else {
+                let next_item = self.iter.next();
+                if next_item.is_some() {
+                    self.next_item = next_item;
+                    Some(self.separator.clone())
+                } else {
+                    None
+                }
+            }
         } else {
-            self.needs_sep = true;
+            self.started = true;
             self.iter.next()
         }
     }
 
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        intersperse_size_hint(&self.iter, self.started, self.next_item.is_some())
+    }
+
     fn fold<B, F>(self, init: B, f: F) -> B
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> B,
     {
         let separator = self.separator;
-        intersperse_fold(self.iter, init, f, move || separator.clone(), self.needs_sep)
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        intersperse_size_hint(&self.iter, self.needs_sep)
+        intersperse_fold(
+            self.iter,
+            init,
+            f,
+            move || separator.clone(),
+            self.started,
+            self.next_item,
+        )
     }
 }
 
@@ -66,39 +92,50 @@ pub struct IntersperseWith<I, G>
 where
     I: Iterator,
 {
+    started: bool,
     separator: G,
-    iter: Peekable<I>,
-    needs_sep: bool,
+    next_item: Option<I::Item>,
+    iter: Fuse<I>,
+}
+
+#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
+impl<I, G> FusedIterator for IntersperseWith<I, G>
+where
+    I: FusedIterator,
+    G: FnMut() -> I::Item,
+{
 }
 
 #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
-impl<I, G> crate::fmt::Debug for IntersperseWith<I, G>
+impl<I, G> fmt::Debug for IntersperseWith<I, G>
 where
-    I: Iterator + crate::fmt::Debug,
-    I::Item: crate::fmt::Debug,
-    G: crate::fmt::Debug,
+    I: Iterator + fmt::Debug,
+    I::Item: fmt::Debug,
+    G: fmt::Debug,
 {
-    fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.debug_struct("IntersperseWith")
+            .field("started", &self.started)
             .field("separator", &self.separator)
             .field("iter", &self.iter)
-            .field("needs_sep", &self.needs_sep)
+            .field("next_item", &self.next_item)
             .finish()
     }
 }
 
 #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
-impl<I, G> crate::clone::Clone for IntersperseWith<I, G>
+impl<I, G> Clone for IntersperseWith<I, G>
 where
-    I: Iterator + crate::clone::Clone,
-    I::Item: crate::clone::Clone,
+    I: Iterator + Clone,
+    I::Item: Clone,
     G: Clone,
 {
     fn clone(&self) -> Self {
-        IntersperseWith {
+        Self {
+            started: self.started,
             separator: self.separator.clone(),
             iter: self.iter.clone(),
-            needs_sep: self.needs_sep.clone(),
+            next_item: self.next_item.clone(),
         }
     }
 }
@@ -109,7 +146,7 @@ where
     G: FnMut() -> I::Item,
 {
     pub(in crate::iter) fn new(iter: I, separator: G) -> Self {
-        Self { iter: iter.peekable(), separator, needs_sep: false }
+        Self { started: false, separator, next_item: None, iter: iter.fuse() }
     }
 }
 
@@ -122,38 +159,52 @@ where
     type Item = I::Item;
 
     #[inline]
-    fn next(&mut self) -> Option<I::Item> {
-        if self.needs_sep && self.iter.peek().is_some() {
-            self.needs_sep = false;
-            Some((self.separator)())
+    fn next(&mut self) -> Option<Self::Item> {
+        if self.started {
+            if let Some(v) = self.next_item.take() {
+                Some(v)
+            } else {
+                let next_item = self.iter.next();
+                if next_item.is_some() {
+                    self.next_item = next_item;
+                    Some((self.separator)())
+                } else {
+                    None
+                }
+            }
         } else {
-            self.needs_sep = true;
+            self.started = true;
             self.iter.next()
         }
     }
 
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        intersperse_size_hint(&self.iter, self.started, self.next_item.is_some())
+    }
+
     fn fold<B, F>(self, init: B, f: F) -> B
     where
         Self: Sized,
         F: FnMut(B, Self::Item) -> B,
     {
-        intersperse_fold(self.iter, init, f, self.separator, self.needs_sep)
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        intersperse_size_hint(&self.iter, self.needs_sep)
+        intersperse_fold(self.iter, init, f, self.separator, self.started, self.next_item)
     }
 }
 
-fn intersperse_size_hint<I>(iter: &I, needs_sep: bool) -> (usize, Option<usize>)
+fn intersperse_size_hint<I>(iter: &I, started: bool, next_is_some: bool) -> (usize, Option<usize>)
 where
     I: Iterator,
 {
     let (lo, hi) = iter.size_hint();
-    let next_is_elem = !needs_sep;
     (
-        lo.saturating_sub(next_is_elem as usize).saturating_add(lo),
-        hi.and_then(|hi| hi.saturating_sub(next_is_elem as usize).checked_add(hi)),
+        lo.saturating_sub(!started as usize)
+            .saturating_add(next_is_some as usize)
+            .saturating_add(lo),
+        hi.and_then(|hi| {
+            hi.saturating_sub(!started as usize)
+                .saturating_add(next_is_some as usize)
+                .checked_add(hi)
+        }),
     )
 }
 
@@ -162,7 +213,8 @@ fn intersperse_fold<I, B, F, G>(
     init: B,
     mut f: F,
     mut separator: G,
-    needs_sep: bool,
+    started: bool,
+    mut next_item: Option<I::Item>,
 ) -> B
 where
     I: Iterator,
@@ -171,12 +223,9 @@ where
 {
     let mut accum = init;
 
-    if !needs_sep {
-        if let Some(x) = iter.next() {
-            accum = f(accum, x);
-        } else {
-            return accum;
-        }
+    let first = if started { next_item.take() } else { iter.next() };
+    if let Some(x) = first {
+        accum = f(accum, x);
     }
 
     iter.fold(accum, |mut accum, x| {
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index 408002d18ca..959c3289aff 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -1893,7 +1893,6 @@ impl Ipv6Addr {
     /// # Examples
     ///
     /// ```
-    /// #![feature(ip)]
     /// use std::net::Ipv6Addr;
     ///
     /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index c2b646b9b3e..03c977abbbb 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -61,7 +61,15 @@ pub use dec2flt::ParseFloatError;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use error::ParseIntError;
 
-pub(crate) use nonzero::NonZero;
+#[unstable(
+    feature = "nonzero_internals",
+    reason = "implementation detail which may disappear or be replaced at any time",
+    issue = "none"
+)]
+pub use nonzero::ZeroablePrimitive;
+
+#[unstable(feature = "generic_nonzero", issue = "120257")]
+pub use nonzero::NonZero;
 
 #[stable(feature = "nonzero", since = "1.28.0")]
 pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 45ac544ceaa..1124719fc8d 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -3,6 +3,8 @@
 use crate::cmp::Ordering;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
+#[cfg(bootstrap)]
+use crate::marker::StructuralEq;
 use crate::marker::StructuralPartialEq;
 use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem};
 use crate::str::FromStr;
@@ -30,9 +32,7 @@ mod private {
     issue = "none"
 )]
 #[const_trait]
-pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {
-    type NonZero;
-}
+pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {}
 
 macro_rules! impl_zeroable_primitive {
     ($NonZero:ident ( $primitive:ty )) => {
@@ -48,9 +48,7 @@ macro_rules! impl_zeroable_primitive {
             reason = "implementation detail which may disappear or be replaced at any time",
             issue = "none"
         )]
-        impl const ZeroablePrimitive for $primitive {
-            type NonZero = $NonZero;
-        }
+        impl const ZeroablePrimitive for $primitive {}
     };
 }
 
@@ -67,12 +65,23 @@ impl_zeroable_primitive!(NonZeroI64(i64));
 impl_zeroable_primitive!(NonZeroI128(i128));
 impl_zeroable_primitive!(NonZeroIsize(isize));
 
-#[unstable(
-    feature = "nonzero_internals",
-    reason = "implementation detail which may disappear or be replaced at any time",
-    issue = "none"
-)]
-pub(crate) type NonZero<T> = <T as ZeroablePrimitive>::NonZero;
+/// A value that is known not to equal zero.
+///
+/// This enables some memory layout optimization.
+/// For example, `Option<NonZero<u32>>` is the same size as `u32`:
+///
+/// ```
+/// #![feature(generic_nonzero)]
+/// use core::mem::size_of;
+///
+/// assert_eq!(size_of::<Option<core::num::NonZero<u32>>>(), size_of::<u32>());
+/// ```
+#[unstable(feature = "generic_nonzero", issue = "120257")]
+#[repr(transparent)]
+#[rustc_layout_scalar_valid_range_start(1)]
+#[rustc_nonnull_optimization_guaranteed]
+#[rustc_diagnostic_item = "NonZero"]
+pub struct NonZero<T: ZeroablePrimitive>(T);
 
 macro_rules! impl_nonzero_fmt {
     ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
@@ -131,12 +140,7 @@ macro_rules! nonzero_integer {
         ///
         /// [null pointer optimization]: crate::option#representation
         #[$stability]
-        #[derive(Copy, Eq)]
-        #[repr(transparent)]
-        #[rustc_layout_scalar_valid_range_start(1)]
-        #[rustc_nonnull_optimization_guaranteed]
-        #[rustc_diagnostic_item = stringify!($Ty)]
-        pub struct $Ty($Int);
+        pub type $Ty = NonZero<$Int>;
 
         impl $Ty {
             /// Creates a non-zero without checking whether the value is non-zero.
@@ -544,6 +548,9 @@ macro_rules! nonzero_integer {
         }
 
         #[$stability]
+        impl Copy for $Ty {}
+
+        #[$stability]
         impl PartialEq for $Ty {
             #[inline]
             fn eq(&self, other: &Self) -> bool {
@@ -560,6 +567,13 @@ macro_rules! nonzero_integer {
         impl StructuralPartialEq for $Ty {}
 
         #[$stability]
+        impl Eq for $Ty {}
+
+        #[unstable(feature = "structural_match", issue = "31434")]
+        #[cfg(bootstrap)]
+        impl StructuralEq for $Ty {}
+
+        #[$stability]
         impl PartialOrd for $Ty {
             #[inline]
             fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index bb6c81a486a..a0227d9130b 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -1092,14 +1092,20 @@ pub struct Pin<Ptr> {
     //   - deter downstream users from accessing it (which would be unsound!),
     //   - let the `pin!` macro access it (such a macro requires using struct
     //     literal syntax in order to benefit from lifetime extension).
-    // Long-term, `unsafe` fields or macro hygiene are expected to offer more robust alternatives.
+    //
+    // However, if the `Deref` impl exposes a field with the same name as this
+    // field, then the two will collide, resulting in a confusing error when the
+    // user attempts to access the field through a `Pin<Ptr>`. Therefore, the
+    // name `__pointer` is designed to be unlikely to collide with any other
+    // field. Long-term, macro hygiene is expected to offer a more robust
+    // alternative, alongside `unsafe` fields.
     #[unstable(feature = "unsafe_pin_internals", issue = "none")]
     #[doc(hidden)]
-    pub pointer: Ptr,
+    pub __pointer: Ptr,
 }
 
 // The following implementations aren't derived in order to avoid soundness
-// issues. `&self.pointer` should not be accessible to untrusted trait
+// issues. `&self.__pointer` should not be accessible to untrusted trait
 // implementations.
 //
 // See <https://internals.rust-lang.org/t/unsoundness-in-pin/11311/73> for more details.
@@ -1212,7 +1218,7 @@ impl<Ptr: Deref<Target: Unpin>> Pin<Ptr> {
     #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
     #[stable(feature = "pin_into_inner", since = "1.39.0")]
     pub const fn into_inner(pin: Pin<Ptr>) -> Ptr {
-        pin.pointer
+        pin.__pointer
     }
 }
 
@@ -1349,7 +1355,7 @@ impl<Ptr: Deref> Pin<Ptr> {
     #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
     #[stable(feature = "pin", since = "1.33.0")]
     pub const unsafe fn new_unchecked(pointer: Ptr) -> Pin<Ptr> {
-        Pin { pointer }
+        Pin { __pointer: pointer }
     }
 
     /// Gets a shared reference to the pinned value this [`Pin`] points to.
@@ -1363,7 +1369,7 @@ impl<Ptr: Deref> Pin<Ptr> {
     #[inline(always)]
     pub fn as_ref(&self) -> Pin<&Ptr::Target> {
         // SAFETY: see documentation on this function
-        unsafe { Pin::new_unchecked(&*self.pointer) }
+        unsafe { Pin::new_unchecked(&*self.__pointer) }
     }
 
     /// Unwraps this `Pin<Ptr>`, returning the underlying `Ptr`.
@@ -1388,7 +1394,7 @@ impl<Ptr: Deref> Pin<Ptr> {
     #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
     #[stable(feature = "pin_into_inner", since = "1.39.0")]
     pub const unsafe fn into_inner_unchecked(pin: Pin<Ptr>) -> Ptr {
-        pin.pointer
+        pin.__pointer
     }
 }
 
@@ -1426,7 +1432,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
     #[inline(always)]
     pub fn as_mut(&mut self) -> Pin<&mut Ptr::Target> {
         // SAFETY: see documentation on this function
-        unsafe { Pin::new_unchecked(&mut *self.pointer) }
+        unsafe { Pin::new_unchecked(&mut *self.__pointer) }
     }
 
     /// Assigns a new value to the memory location pointed to by the `Pin<Ptr>`.
@@ -1455,7 +1461,7 @@ impl<Ptr: DerefMut> Pin<Ptr> {
     where
         Ptr::Target: Sized,
     {
-        *(self.pointer) = value;
+        *(self.__pointer) = value;
     }
 }
 
@@ -1481,7 +1487,7 @@ impl<'a, T: ?Sized> Pin<&'a T> {
         U: ?Sized,
         F: FnOnce(&T) -> &U,
     {
-        let pointer = &*self.pointer;
+        let pointer = &*self.__pointer;
         let new_pointer = func(pointer);
 
         // SAFETY: the safety contract for `new_unchecked` must be
@@ -1511,7 +1517,7 @@ impl<'a, T: ?Sized> Pin<&'a T> {
     #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
     #[stable(feature = "pin", since = "1.33.0")]
     pub const fn get_ref(self) -> &'a T {
-        self.pointer
+        self.__pointer
     }
 }
 
@@ -1522,7 +1528,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
     #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
     #[stable(feature = "pin", since = "1.33.0")]
     pub const fn into_ref(self) -> Pin<&'a T> {
-        Pin { pointer: self.pointer }
+        Pin { __pointer: self.__pointer }
     }
 
     /// Gets a mutable reference to the data inside of this `Pin`.
@@ -1542,7 +1548,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
     where
         T: Unpin,
     {
-        self.pointer
+        self.__pointer
     }
 
     /// Gets a mutable reference to the data inside of this `Pin`.
@@ -1560,7 +1566,7 @@ impl<'a, T: ?Sized> Pin<&'a mut T> {
     #[stable(feature = "pin", since = "1.33.0")]
     #[rustc_const_unstable(feature = "const_pin", issue = "76654")]
     pub const unsafe fn get_unchecked_mut(self) -> &'a mut T {
-        self.pointer
+        self.__pointer
     }
 
     /// Construct a new pin by mapping the interior value.
@@ -1684,21 +1690,21 @@ impl<Ptr: Receiver> Receiver for Pin<Ptr> {}
 #[stable(feature = "pin", since = "1.33.0")]
 impl<Ptr: fmt::Debug> fmt::Debug for Pin<Ptr> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&self.pointer, f)
+        fmt::Debug::fmt(&self.__pointer, f)
     }
 }
 
 #[stable(feature = "pin", since = "1.33.0")]
 impl<Ptr: fmt::Display> fmt::Display for Pin<Ptr> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.pointer, f)
+        fmt::Display::fmt(&self.__pointer, f)
     }
 }
 
 #[stable(feature = "pin", since = "1.33.0")]
 impl<Ptr: fmt::Pointer> fmt::Pointer for Pin<Ptr> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Pointer::fmt(&self.pointer, f)
+        fmt::Pointer::fmt(&self.__pointer, f)
     }
 }
 
@@ -1941,16 +1947,16 @@ pub macro pin($value:expr $(,)?) {
     // instead, dropped _at the end of the enscoping block_.
     // For instance,
     // ```rust
-    // let p = Pin { pointer: &mut <temporary> };
+    // let p = Pin { __pointer: &mut <temporary> };
     // ```
     // becomes:
     // ```rust
     // let mut anon = <temporary>;
-    // let p = Pin { pointer: &mut anon };
+    // let p = Pin { __pointer: &mut anon };
     // ```
     // which is *exactly* what we want.
     //
     // See https://doc.rust-lang.org/1.58.1/reference/destructors.html#temporary-lifetime-extension
     // for more info.
-    $crate::pin::Pin::<&mut _> { pointer: &mut { $value } }
+    $crate::pin::Pin::<&mut _> { __pointer: &mut { $value } }
 }
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 7dee30585e9..bf47d767a92 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1384,6 +1384,30 @@ mod prim_usize {}
 /// work on references as well as they do on owned values! The implementations described here are
 /// meant for generic contexts, where the final type `T` is a type parameter or otherwise not
 /// locally known.
+///
+/// # Safety
+///
+/// For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`, when such values cross an API
+/// boundary, the following invariants must generally be upheld:
+///
+/// * `t` is aligned to `align_of_val(t)`
+/// * `t` is dereferenceable for `size_of_val(t)` many bytes
+///
+/// If `t` points at address `a`, being "dereferenceable" for N bytes means that the memory range
+/// `[a, a + N)` is all contained within a single [allocated object].
+///
+/// For instance, this means that unsafe code in a safe function may assume these invariants are
+/// ensured of arguments passed by the caller, and it may assume that these invariants are ensured
+/// of return values from any safe functions it calls. In most cases, the inverse is also true:
+/// unsafe code must not violate these invariants when passing arguments to safe functions or
+/// returning values from safe functions; such violations may result in undefined behavior. Where
+/// exceptions to this latter requirement exist, they will be called out explicitly in documentation.
+///
+/// It is not decided yet whether unsafe code may violate these invariants temporarily on internal
+/// data. As a consequence, unsafe code which violates these invariants temporarily on internal data
+/// may become unsound in future versions of Rust depending on how this question is decided.
+///
+/// [allocated object]: ptr#allocated-object
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_ref {}
 
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 1c65475b81d..2d4c7e78aea 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -3248,26 +3248,26 @@ unsafe impl<'a, T> TrustedRandomAccessNoCoerce for IterMut<'a, T> {
 
 /// An iterator over slice in (non-overlapping) chunks separated by a predicate.
 ///
-/// This struct is created by the [`group_by`] method on [slices].
+/// This struct is created by the [`chunk_by`] method on [slices].
 ///
-/// [`group_by`]: slice::group_by
+/// [`chunk_by`]: slice::chunk_by
 /// [slices]: slice
-#[unstable(feature = "slice_group_by", issue = "80552")]
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
-pub struct GroupBy<'a, T: 'a, P> {
+pub struct ChunkBy<'a, T: 'a, P> {
     slice: &'a [T],
     predicate: P,
 }
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a, P> GroupBy<'a, T, P> {
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a, P> ChunkBy<'a, T, P> {
     pub(super) fn new(slice: &'a [T], predicate: P) -> Self {
-        GroupBy { slice, predicate }
+        ChunkBy { slice, predicate }
     }
 }
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a, P> Iterator for GroupBy<'a, T, P>
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a, P> Iterator for ChunkBy<'a, T, P>
 where
     P: FnMut(&T, &T) -> bool,
 {
@@ -3300,8 +3300,8 @@ where
     }
 }
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a, P> DoubleEndedIterator for GroupBy<'a, T, P>
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a, P> DoubleEndedIterator for ChunkBy<'a, T, P>
 where
     P: FnMut(&T, &T) -> bool,
 {
@@ -3322,39 +3322,39 @@ where
     }
 }
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a, P> FusedIterator for GroupBy<'a, T, P> where P: FnMut(&T, &T) -> bool {}
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a, P> FusedIterator for ChunkBy<'a, T, P> where P: FnMut(&T, &T) -> bool {}
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupBy<'a, T, P> {
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkBy<'a, T, P> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("GroupBy").field("slice", &self.slice).finish()
+        f.debug_struct("ChunkBy").field("slice", &self.slice).finish()
     }
 }
 
 /// An iterator over slice in (non-overlapping) mutable chunks separated
 /// by a predicate.
 ///
-/// This struct is created by the [`group_by_mut`] method on [slices].
+/// This struct is created by the [`chunk_by_mut`] method on [slices].
 ///
-/// [`group_by_mut`]: slice::group_by_mut
+/// [`chunk_by_mut`]: slice::chunk_by_mut
 /// [slices]: slice
-#[unstable(feature = "slice_group_by", issue = "80552")]
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
 #[must_use = "iterators are lazy and do nothing unless consumed"]
-pub struct GroupByMut<'a, T: 'a, P> {
+pub struct ChunkByMut<'a, T: 'a, P> {
     slice: &'a mut [T],
     predicate: P,
 }
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a, P> GroupByMut<'a, T, P> {
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a, P> ChunkByMut<'a, T, P> {
     pub(super) fn new(slice: &'a mut [T], predicate: P) -> Self {
-        GroupByMut { slice, predicate }
+        ChunkByMut { slice, predicate }
     }
 }
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a, P> Iterator for GroupByMut<'a, T, P>
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a, P> Iterator for ChunkByMut<'a, T, P>
 where
     P: FnMut(&T, &T) -> bool,
 {
@@ -3388,8 +3388,8 @@ where
     }
 }
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a, P> DoubleEndedIterator for GroupByMut<'a, T, P>
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a, P> DoubleEndedIterator for ChunkByMut<'a, T, P>
 where
     P: FnMut(&T, &T) -> bool,
 {
@@ -3411,12 +3411,12 @@ where
     }
 }
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a, P> FusedIterator for GroupByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {}
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a, P> FusedIterator for ChunkByMut<'a, T, P> where P: FnMut(&T, &T) -> bool {}
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for GroupByMut<'a, T, P> {
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkByMut<'a, T, P> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("GroupByMut").field("slice", &self.slice).finish()
+        f.debug_struct("ChunkByMut").field("slice", &self.slice).finish()
     }
 }
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 27dda478848..2d93ef6fbeb 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -68,8 +68,8 @@ pub use iter::{ArrayChunks, ArrayChunksMut};
 #[unstable(feature = "array_windows", issue = "75027")]
 pub use iter::ArrayWindows;
 
-#[unstable(feature = "slice_group_by", issue = "80552")]
-pub use iter::{GroupBy, GroupByMut};
+#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
+pub use iter::{ChunkBy, ChunkByMut};
 
 #[stable(feature = "split_inclusive", since = "1.51.0")]
 pub use iter::{SplitInclusive, SplitInclusiveMut};
@@ -1748,18 +1748,16 @@ impl<T> [T] {
     /// Returns an iterator over the slice producing non-overlapping runs
     /// of elements using the predicate to separate them.
     ///
-    /// The predicate is called on two elements following themselves,
-    /// it means the predicate is called on `slice[0]` and `slice[1]`
-    /// then on `slice[1]` and `slice[2]` and so on.
+    /// The predicate is called for every pair of consecutive elements,
+    /// meaning that it is called on `slice[0]` and `slice[1]`,
+    /// followed by `slice[1]` and `slice[2]`, and so on.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_group_by)]
-    ///
     /// let slice = &[1, 1, 1, 3, 3, 2, 2, 2];
     ///
-    /// let mut iter = slice.group_by(|a, b| a == b);
+    /// let mut iter = slice.chunk_by(|a, b| a == b);
     ///
     /// assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
     /// assert_eq!(iter.next(), Some(&[3, 3][..]));
@@ -1770,41 +1768,37 @@ impl<T> [T] {
     /// This method can be used to extract the sorted subslices:
     ///
     /// ```
-    /// #![feature(slice_group_by)]
-    ///
     /// let slice = &[1, 1, 2, 3, 2, 3, 2, 3, 4];
     ///
-    /// let mut iter = slice.group_by(|a, b| a <= b);
+    /// let mut iter = slice.chunk_by(|a, b| a <= b);
     ///
     /// assert_eq!(iter.next(), Some(&[1, 1, 2, 3][..]));
     /// assert_eq!(iter.next(), Some(&[2, 3][..]));
     /// assert_eq!(iter.next(), Some(&[2, 3, 4][..]));
     /// assert_eq!(iter.next(), None);
     /// ```
-    #[unstable(feature = "slice_group_by", issue = "80552")]
+    #[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
-    pub fn group_by<F>(&self, pred: F) -> GroupBy<'_, T, F>
+    pub fn chunk_by<F>(&self, pred: F) -> ChunkBy<'_, T, F>
     where
         F: FnMut(&T, &T) -> bool,
     {
-        GroupBy::new(self, pred)
+        ChunkBy::new(self, pred)
     }
 
     /// Returns an iterator over the slice producing non-overlapping mutable
     /// runs of elements using the predicate to separate them.
     ///
-    /// The predicate is called on two elements following themselves,
-    /// it means the predicate is called on `slice[0]` and `slice[1]`
-    /// then on `slice[1]` and `slice[2]` and so on.
+    /// The predicate is called for every pair of consecutive elements,
+    /// meaning that it is called on `slice[0]` and `slice[1]`,
+    /// followed by `slice[1]` and `slice[2]`, and so on.
     ///
     /// # Examples
     ///
     /// ```
-    /// #![feature(slice_group_by)]
-    ///
     /// let slice = &mut [1, 1, 1, 3, 3, 2, 2, 2];
     ///
-    /// let mut iter = slice.group_by_mut(|a, b| a == b);
+    /// let mut iter = slice.chunk_by_mut(|a, b| a == b);
     ///
     /// assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
     /// assert_eq!(iter.next(), Some(&mut [3, 3][..]));
@@ -1815,24 +1809,22 @@ impl<T> [T] {
     /// This method can be used to extract the sorted subslices:
     ///
     /// ```
-    /// #![feature(slice_group_by)]
-    ///
     /// let slice = &mut [1, 1, 2, 3, 2, 3, 2, 3, 4];
     ///
-    /// let mut iter = slice.group_by_mut(|a, b| a <= b);
+    /// let mut iter = slice.chunk_by_mut(|a, b| a <= b);
     ///
     /// assert_eq!(iter.next(), Some(&mut [1, 1, 2, 3][..]));
     /// assert_eq!(iter.next(), Some(&mut [2, 3][..]));
     /// assert_eq!(iter.next(), Some(&mut [2, 3, 4][..]));
     /// assert_eq!(iter.next(), None);
     /// ```
-    #[unstable(feature = "slice_group_by", issue = "80552")]
+    #[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
-    pub fn group_by_mut<F>(&mut self, pred: F) -> GroupByMut<'_, T, F>
+    pub fn chunk_by_mut<F>(&mut self, pred: F) -> ChunkByMut<'_, T, F>
     where
         F: FnMut(&T, &T) -> bool,
     {
-        GroupByMut::new(self, pred)
+        ChunkByMut::new(self, pred)
     }
 
     /// Divides one slice into two at an index.
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index 0f23cf7ae23..ba282f09d20 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -1,6 +1,6 @@
 //! Ways to create a `str` from bytes slice.
 
-use crate::mem;
+use crate::{mem, ptr};
 
 use super::validations::run_utf8_validation;
 use super::Utf8Error;
@@ -205,3 +205,41 @@ pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
     // comes from a reference which is guaranteed to be valid for writes.
     unsafe { &mut *(v as *mut [u8] as *mut str) }
 }
+
+/// Creates an `&str` from a pointer and a length.
+///
+/// The pointed-to bytes must be valid UTF-8.
+/// If this might not be the case, use `str::from_utf8(slice::from_raw_parts(ptr, len))`,
+/// which will return an `Err` if the data isn't valid UTF-8.
+///
+/// This function is the `str` equivalent of [`slice::from_raw_parts`](crate::slice::from_raw_parts).
+/// See that function's documentation for safety concerns and examples.
+///
+/// The mutable version of this function is [`from_raw_parts_mut`].
+#[inline]
+#[must_use]
+#[unstable(feature = "str_from_raw_parts", issue = "119206")]
+#[rustc_const_unstable(feature = "str_from_raw_parts", issue = "119206")]
+pub const unsafe fn from_raw_parts<'a>(ptr: *const u8, len: usize) -> &'a str {
+    // SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
+    unsafe { &*ptr::from_raw_parts(ptr.cast(), len) }
+}
+
+/// Creates an `&mut str` from a pointer and a length.
+///
+/// The pointed-to bytes must be valid UTF-8.
+/// If this might not be the case, use `str::from_utf8_mut(slice::from_raw_parts_mut(ptr, len))`,
+/// which will return an `Err` if the data isn't valid UTF-8.
+///
+/// This function is the `str` equivalent of [`slice::from_raw_parts_mut`](crate::slice::from_raw_parts_mut).
+/// See that function's documentation for safety concerns and examples.
+///
+/// The immutable version of this function is [`from_raw_parts`].
+#[inline]
+#[must_use]
+#[unstable(feature = "str_from_raw_parts", issue = "119206")]
+#[rustc_const_unstable(feature = "const_str_from_raw_parts_mut", issue = "119206")]
+pub const unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a str {
+    // SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
+    unsafe { &mut *ptr::from_raw_parts_mut(ptr.cast(), len) }
+}
diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs
index dd2efb00516..4d6239e11a3 100644
--- a/library/core/src/str/iter.rs
+++ b/library/core/src/str/iter.rs
@@ -1187,6 +1187,31 @@ impl<'a> DoubleEndedIterator for Lines<'a> {
 #[stable(feature = "fused", since = "1.26.0")]
 impl FusedIterator for Lines<'_> {}
 
+impl<'a> Lines<'a> {
+    /// Returns the remaining lines of the split string.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(str_lines_remainder)]
+    ///
+    /// let mut lines = "a\nb\nc\nd".lines();
+    /// assert_eq!(lines.remainder(), Some("a\nb\nc\nd"));
+    ///
+    /// lines.next();
+    /// assert_eq!(lines.remainder(), Some("b\nc\nd"));
+    ///
+    /// lines.by_ref().for_each(drop);
+    /// assert_eq!(lines.remainder(), None);
+    /// ```
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "str_lines_remainder", issue = "77998")]
+    pub fn remainder(&self) -> Option<&'a str> {
+        self.0.iter.remainder()
+    }
+}
+
 /// Created with the method [`lines_any`].
 ///
 /// [`lines_any`]: str::lines_any
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 80c5fe0de8d..ecc0613d7b9 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -33,6 +33,9 @@ pub use converts::{from_utf8, from_utf8_unchecked};
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
 pub use converts::{from_utf8_mut, from_utf8_unchecked_mut};
 
+#[unstable(feature = "str_from_raw_parts", issue = "119206")]
+pub use converts::{from_raw_parts, from_raw_parts_mut};
+
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use error::{ParseBoolError, Utf8Error};
 
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 89d2b5ef093..9a3b477c2d1 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -1,6 +1,5 @@
 #![feature(alloc_layout_extra)]
 #![feature(array_chunks)]
-#![feature(array_methods)]
 #![feature(array_windows)]
 #![feature(ascii_char)]
 #![feature(ascii_char_variants)]
@@ -101,7 +100,6 @@
 #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))]
 #![cfg_attr(test, feature(cfg_match))]
 #![feature(int_roundings)]
-#![feature(slice_group_by)]
 #![feature(split_array)]
 #![feature(strict_provenance)]
 #![feature(strict_provenance_atomic_ptr)]
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index b63091deac2..13cc0511e10 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -816,12 +816,12 @@ impl Error {
         }
     }
 
-    /// Attempt to downgrade the inner error to `E` if any.
+    /// Attempt to downcast the inner error to `E` if any.
     ///
     /// If this [`Error`] was constructed via [`new`] then this function will
     /// attempt to perform downgrade on it, otherwise it will return [`Err`].
     ///
-    /// If downgrade succeeds, it will return [`Ok`], otherwise it will also
+    /// If the downcast succeeds, it will return [`Ok`], otherwise it will also
     /// return [`Err`].
     ///
     /// [`new`]: Error::new
@@ -852,13 +852,39 @@ impl Error {
     /// impl From<io::Error> for E {
     ///     fn from(err: io::Error) -> E {
     ///         err.downcast::<E>()
-    ///             .map(|b| *b)
     ///             .unwrap_or_else(E::Io)
     ///     }
     /// }
+    ///
+    /// impl From<E> for io::Error {
+    ///     fn from(err: E) -> io::Error {
+    ///         match err {
+    ///             E::Io(io_error) => io_error,
+    ///             e => io::Error::new(io::ErrorKind::Other, e),
+    ///         }
+    ///     }
+    /// }
+    ///
+    /// # fn main() {
+    /// let e = E::SomeOtherVariant;
+    /// // Convert it to an io::Error
+    /// let io_error = io::Error::from(e);
+    /// // Cast it back to the original variant
+    /// let e = E::from(io_error);
+    /// assert!(matches!(e, E::SomeOtherVariant));
+    ///
+    /// let io_error = io::Error::from(io::ErrorKind::AlreadyExists);
+    /// // Convert it to E
+    /// let e = E::from(io_error);
+    /// // Cast it back to the original variant
+    /// let io_error = io::Error::from(e);
+    /// assert_eq!(io_error.kind(), io::ErrorKind::AlreadyExists);
+    /// assert!(io_error.get_ref().is_none());
+    /// assert!(io_error.raw_os_error().is_none());
+    /// # }
     /// ```
     #[unstable(feature = "io_error_downcast", issue = "99262")]
-    pub fn downcast<E>(self) -> result::Result<Box<E>, Self>
+    pub fn downcast<E>(self) -> result::Result<E, Self>
     where
         E: error::Error + Send + Sync + 'static,
     {
@@ -872,7 +898,7 @@ impl Error {
                 // And the compiler should be able to eliminate the branch
                 // that produces `Err` here since b.error.is::<E>()
                 // returns true.
-                Ok(res.unwrap())
+                Ok(*res.unwrap())
             }
             repr_data => Err(Self { repr: Repr::new(repr_data) }),
         }
diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs
index 36d52aef03c..fc6db2825e8 100644
--- a/library/std/src/io/error/tests.rs
+++ b/library/std/src/io/error/tests.rs
@@ -157,7 +157,7 @@ impl error::Error for E {}
 fn test_std_io_error_downcast() {
     // Case 1: custom error, downcast succeeds
     let io_error = Error::new(ErrorKind::Other, Bojji(true));
-    let e: Box<Bojji> = io_error.downcast().unwrap();
+    let e: Bojji = io_error.downcast().unwrap();
     assert!(e.0);
 
     // Case 2: custom error, downcast fails
@@ -166,7 +166,7 @@ fn test_std_io_error_downcast() {
 
     //   ensures that the custom error is intact
     assert_eq!(ErrorKind::Other, io_error.kind());
-    let e: Box<Bojji> = io_error.downcast().unwrap();
+    let e: Bojji = io_error.downcast().unwrap();
     assert!(e.0);
 
     // Case 3: os error
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 05b21eeb40f..261b570dee7 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -8,7 +8,9 @@ use crate::io::prelude::*;
 use crate::cell::{Cell, RefCell};
 use crate::fmt;
 use crate::fs::File;
-use crate::io::{self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
+use crate::io::{
+    self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, SpecReadByte,
+};
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard};
 use crate::sys::stdio;
@@ -483,6 +485,13 @@ impl Read for StdinLock<'_> {
     }
 }
 
+impl SpecReadByte for StdinLock<'_> {
+    #[inline]
+    fn spec_read_byte(&mut self) -> Option<io::Result<u8>> {
+        BufReader::spec_read_byte(&mut *self.inner)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl BufRead for StdinLock<'_> {
     fn fill_buf(&mut self) -> io::Result<&[u8]> {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 751e988a99b..2e458562744 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -323,6 +323,7 @@
 #![feature(float_gamma)]
 #![feature(float_minimum_maximum)]
 #![feature(float_next_up_down)]
+#![feature(generic_nonzero)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
 #![feature(hint_assert_unchecked)]
diff --git a/library/std/src/num.rs b/library/std/src/num.rs
index 55f6ddcf77f..1343fdfd1df 100644
--- a/library/std/src/num.rs
+++ b/library/std/src/num.rs
@@ -16,6 +16,16 @@ pub use core::num::Wrapping;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError};
 
+#[unstable(
+    feature = "nonzero_internals",
+    reason = "implementation detail which may disappear or be replaced at any time",
+    issue = "none"
+)]
+pub use core::num::ZeroablePrimitive;
+
+#[unstable(feature = "generic_nonzero", issue = "120257")]
+pub use core::num::NonZero;
+
 #[stable(feature = "signed_nonzero", since = "1.34.0")]
 pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
 #[stable(feature = "nonzero", since = "1.28.0")]
diff --git a/library/std/src/sys/pal/windows/alloc.rs b/library/std/src/sys/pal/windows/alloc.rs
index d53ea16005f..270eca37b14 100644
--- a/library/std/src/sys/pal/windows/alloc.rs
+++ b/library/std/src/sys/pal/windows/alloc.rs
@@ -95,7 +95,7 @@ static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
 #[inline]
 fn init_or_get_process_heap() -> c::HANDLE {
     let heap = HEAP.load(Ordering::Relaxed);
-    if heap.is_null() {
+    if core::intrinsics::unlikely(heap.is_null()) {
         // `HEAP` has not yet been successfully initialized
         let heap = unsafe { GetProcessHeap() };
         if !heap.is_null() {
@@ -115,6 +115,16 @@ fn init_or_get_process_heap() -> c::HANDLE {
     }
 }
 
+#[inline(never)]
+fn process_heap_alloc(flags: c::DWORD, dwBytes: c::SIZE_T) -> c::LPVOID {
+    let heap = init_or_get_process_heap();
+    if core::intrinsics::unlikely(heap.is_null()) {
+        return ptr::null_mut();
+    }
+    // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
+    unsafe { HeapAlloc(heap, flags, dwBytes) }
+}
+
 // Get a non-null handle to the default heap of the current process.
 // SAFETY: `HEAP` must have been successfully initialized.
 #[inline]
@@ -133,25 +143,17 @@ struct Header(*mut u8);
 // initialized.
 #[inline]
 unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
-    let heap = init_or_get_process_heap();
-    if heap.is_null() {
-        // Allocation has failed, could not get the current process heap.
-        return ptr::null_mut();
-    }
-
     // Allocated memory will be either zeroed or uninitialized.
     let flags = if zeroed { HEAP_ZERO_MEMORY } else { 0 };
 
     if layout.align() <= MIN_ALIGN {
-        // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
         // The returned pointer points to the start of an allocated block.
-        unsafe { HeapAlloc(heap, flags, layout.size()) as *mut u8 }
+        process_heap_alloc(flags, layout.size()) as *mut u8
     } else {
         // Allocate extra padding in order to be able to satisfy the alignment.
         let total = layout.align() + layout.size();
 
-        // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
-        let ptr = unsafe { HeapAlloc(heap, flags, total) as *mut u8 };
+        let ptr = process_heap_alloc(flags, total) as *mut u8;
         if ptr.is_null() {
             // Allocation has failed.
             return ptr::null_mut();
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index e06bc3fb09a..043473287fc 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1116,16 +1116,11 @@ pub fn rustc_cargo_env(
 /// Pass down configuration from the LLVM build into the build of
 /// rustc_llvm and rustc_codegen_llvm.
 fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
-    let target_config = builder.config.target_config.get(&target);
-
     if builder.is_rust_llvm(target) {
         cargo.env("LLVM_RUSTLLVM", "1");
     }
     let llvm::LlvmResult { llvm_config, .. } = builder.ensure(llvm::Llvm { target });
     cargo.env("LLVM_CONFIG", &llvm_config);
-    if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) {
-        cargo.env("CFG_LLVM_ROOT", s);
-    }
 
     // Some LLVM linker flags (-L and -l) may be needed to link `rustc_llvm`. Its build script
     // expects these to be passed via the `LLVM_LINKER_FLAGS` env variable, separated by
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index 55eed95492d..0db61204f77 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -74,25 +74,6 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
 
       cksum=$(sha512sum $hash_key | \
         awk '{print $1}')
-
-      url="https://$CACHE_DOMAIN/docker/$cksum"
-
-      echo "Attempting to download $url"
-      rm -f /tmp/rustci_docker_cache
-      set +e
-      retry curl --max-time 600 -y 30 -Y 10 --connect-timeout 30 -f -L -C - \
-        -o /tmp/rustci_docker_cache "$url"
-
-      docker_archive_hash=$(sha512sum /tmp/rustci_docker_cache | awk '{print $1}')
-      echo "Downloaded archive hash: ${docker_archive_hash}"
-
-      echo "Loading images into docker"
-      # docker load sometimes hangs in the CI, so time out after 10 minutes with TERM,
-      # KILL after 12 minutes
-      loaded_images=$(/usr/bin/timeout -k 720 600 docker load -i /tmp/rustci_docker_cache \
-        | sed 's/.* sha/sha/')
-      set -e
-      printf "Downloaded containers:\n$loaded_images\n"
     fi
 
     dockerfile="$docker_dir/$image/Dockerfile"
@@ -103,46 +84,65 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
         context="$script_dir"
     fi
     echo "::group::Building docker image for $image"
-
-    # As of August 2023, Github Actions have updated Docker to 23.X,
-    # which uses the BuildKit by default. It currently throws aways all
-    # intermediate layers, which breaks our usage of S3 layer caching.
-    # Therefore we opt-in to the old build backend for now.
-    export DOCKER_BUILDKIT=0
-    retry docker \
-      build \
-      --rm \
-      -t rust-ci \
-      -f "$dockerfile" \
-      "$context"
-    echo "::endgroup::"
-
-    if [ "$CI" != "" ]; then
-      s3url="s3://$SCCACHE_BUCKET/docker/$cksum"
-      upload="aws s3 cp - $s3url"
-      digest=$(docker inspect rust-ci --format '{{.Id}}')
-      echo "Built container $digest"
-      if ! grep -q "$digest" <(echo "$loaded_images"); then
-        echo "Uploading finished image $digest to $url"
-        set +e
-        # Print image history for easier debugging of layer SHAs
-        docker history rust-ci
-        docker history -q rust-ci | \
-          grep -v missing | \
-          xargs docker save | \
-          gzip | \
-          $upload
-        set -e
-      else
-        echo "Looks like docker image is the same as before, not uploading"
-      fi
-      # Record the container image for reuse, e.g. by rustup.rs builds
-      info="$dist/image-$image.txt"
-      mkdir -p "$dist"
-      echo "$url" >"$info"
-      echo "$digest" >>"$info"
-      cat "$info"
+    echo "Image input"
+    cat $hash_key
+    echo "Image input checksum ${cksum}"
+
+    # Print docker version
+    docker --version
+
+    # On non-CI or PR jobs, we don't have permissions to write to the registry cache, so we should
+    # not use `docker login` nor caching.
+    if [[ "$CI" == "" ]] || [[ "$PR_CI_JOB" == "1" ]];
+    then
+        retry docker build --rm -t rust-ci -f "$dockerfile" "$context"
+    else
+        REGISTRY=ghcr.io
+        # Most probably rust-lang-ci, but in general the owner of the repository where CI runs
+        REGISTRY_USERNAME=${GITHUB_REPOSITORY_OWNER}
+        # Tag used to push the final Docker image, so that it can be pulled by e.g. rustup
+        IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci:${cksum}
+        # Tag used to cache the Docker build
+        # It seems that it cannot be the same as $IMAGE_TAG, otherwise it overwrites the cache
+        CACHE_IMAGE_TAG=${REGISTRY}/${REGISTRY_USERNAME}/rust-ci-cache:${cksum}
+
+        # Log into the Docker registry, so that we can read/write cache and the final image
+        echo ${DOCKER_TOKEN} | docker login ${REGISTRY} \
+            --username ${REGISTRY_USERNAME} \
+            --password-stdin
+
+        # Enable a new Docker driver so that --cache-from/to works with a registry backend
+        docker buildx create --use --driver docker-container
+
+        # Build the image using registry caching backend
+        retry docker \
+          buildx \
+          build \
+          --rm \
+          -t rust-ci \
+          -f "$dockerfile" \
+          --cache-from type=registry,ref=${CACHE_IMAGE_TAG} \
+          --cache-to type=registry,ref=${CACHE_IMAGE_TAG},compression=zstd \
+          --output=type=docker \
+          "$context"
+
+        # Print images for debugging purposes
+        docker images
+
+        # Tag the built image and push it to the registry
+        docker tag rust-ci "${IMAGE_TAG}"
+        docker push "${IMAGE_TAG}"
+
+        # Record the container registry tag/url for reuse, e.g. by rustup.rs builds
+        # It should be possible to run `docker pull <$IMAGE_TAG>` to download the image
+        info="$dist/image-$image.txt"
+        mkdir -p "$dist"
+        echo "${IMAGE_TAG}" > "$info"
+        cat "$info"
+
+        echo "To download the image, run docker pull ${IMAGE_TAG}"
     fi
+    echo "::endgroup::"
 elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
     if isCI; then
         echo Cannot run disabled images on CI!
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 68a3afc910f..ceee4690004 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -34,6 +34,7 @@ x--expand-yaml-anchors--remove:
     CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
     # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs.
     HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
+    DOCKER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 
   - &public-variables
     SCCACHE_BUCKET: rust-lang-ci-sccache2
@@ -301,6 +302,7 @@ on:
 
 permissions:
   contents: read
+  packages: write
 
 defaults:
   run:
diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md
index a54abcb606e..e72bfb8bae7 100644
--- a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md
+++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md
@@ -50,6 +50,7 @@ cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc"
 [target.csky-unknown-linux-gnuabiv2hf]
 # ADJUST THIS PATH TO POINT AT YOUR TOOLCHAIN
 cc = "${TOOLCHAIN_PATH}/bin/csky-linux-gnuabiv2-gcc"
+```
 
 ### Build
 
diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis
index 624d8cc5cc5..5e0c21a13a9 100644
--- a/src/etc/natvis/libcore.natvis
+++ b/src/etc/natvis/libcore.natvis
@@ -41,40 +41,7 @@
     </Expand>
   </Type>
 
-  <Type Name="core::num::nonzero::NonZeroI8">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroI16">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroI32">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroI64">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroI128">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroIsize">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroU8">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroU16">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroU32">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroU64">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroU128">
-    <DisplayString>{__0}</DisplayString>
-  </Type>
-  <Type Name="core::num::nonzero::NonZeroUsize">
+  <Type Name="core::num::nonzero::NonZero&lt;*&gt;">
     <DisplayString>{__0}</DisplayString>
   </Type>
 
@@ -99,9 +66,9 @@
   </Type>
 
   <Type Name="core::pin::Pin&lt;*&gt;">
-    <DisplayString>Pin({(void*)pointer}: {pointer})</DisplayString>
+    <DisplayString>Pin({(void*)__pointer}: {__pointer})</DisplayString>
     <Expand>
-      <ExpandedItem>pointer</ExpandedItem>
+      <ExpandedItem>__pointer</ExpandedItem>
     </Expand>
   </Type>
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 8706abda979..e1829da6e2c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -15,6 +15,7 @@ use rustc_ast::token::{Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_attr as attr;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
+use rustc_errors::{codes::*, struct_span_code_err, FatalError};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
@@ -2271,7 +2272,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
         ty::Placeholder(..) => panic!("Placeholder"),
         ty::CoroutineWitness(..) => panic!("CoroutineWitness"),
         ty::Infer(..) => panic!("Infer"),
-        ty::Error(_) => rustc_errors::FatalError.raise(),
+        ty::Error(_) => FatalError.raise(),
     }
 }
 
@@ -2995,7 +2996,7 @@ fn clean_use_statement_inner<'tcx>(
         visibility.is_accessible_from(parent_mod, cx.tcx) && !current_mod.is_top_level_module();
 
     if pub_underscore && let Some(ref inline) = inline_attr {
-        rustc_errors::struct_span_code_err!(
+        struct_span_code_err!(
             cx.tcx.dcx(),
             inline.span(),
             E0780,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 7cf385de6b7..9eb62c25892 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::emitter::{DynEmitter, HumanEmitter};
 use rustc_errors::json::JsonEmitter;
-use rustc_errors::TerminalUrl;
+use rustc_errors::{codes::*, TerminalUrl};
 use rustc_feature::UnstableFeatures;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 658ed862ae7..8c10f14116a 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -3,7 +3,6 @@
     html_playground_url = "https://play.rust-lang.org/"
 )]
 #![feature(rustc_private)]
-#![feature(array_methods)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 4d32bbec914..5fa45ceeb39 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -5606,6 +5606,7 @@ Released 2018-09-13
 [`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting
 [`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map
 [`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl
+[`suspicious_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_open_options
 [`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_operation_groupings
 [`suspicious_splitn`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_splitn
 [`suspicious_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_to_owned
@@ -5814,6 +5815,7 @@ Released 2018-09-13
 [`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments
 [`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates
 [`allowed-dotfiles`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-dotfiles
+[`allowed-duplicate-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allowed-duplicate-crates
 [`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
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 3b62ae0524a..7f7aff92bf1 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -212,7 +212,7 @@ default configuration of Clippy. By default, any configuration will replace the
 * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`.
 * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list.
 
-**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
+**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "ClojureScript", "CoffeeScript", "JavaScript", "PureScript", "TypeScript", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "OCaml", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "WebGL", "WebGL2", "WebGPU", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]`
 
 ---
 **Affected lints:**
@@ -768,7 +768,19 @@ Additional dotfiles (files or directories starting with a dot) to allow
 * [`path_ends_with_ext`](https://rust-lang.github.io/rust-clippy/master/index.html#path_ends_with_ext)
 
 
+## `allowed-duplicate-crates`
+A list of crate names to allow duplicates of
+
+**Default Value:** `[]`
+
+---
+**Affected lints:**
+* [`multiple_crate_versions`](https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions)
+
+
 ## `enforce-iter-loop-reborrow`
+Whether to recommend using implicit into iter for reborrowed values.
+
 #### Example
 ```no_run
 let mut vec = vec![1, 2, 3];
@@ -793,7 +805,7 @@ for _ in &mut *rmvec {}
 
 
 ## `check-private-items`
-
+Whether to also run the listed lints on private items.
 
 **Default Value:** `false`
 
@@ -806,9 +818,10 @@ for _ in &mut *rmvec {}
 
 
 ## `pub-underscore-fields-behavior`
+Lint "public" fields in a struct that are prefixed with an underscore based on their
+exported visibility, or whether they are marked as "pub".
 
-
-**Default Value:** `"PublicallyExported"`
+**Default Value:** `"PubliclyExported"`
 
 ---
 **Affected lints:**
diff --git a/src/tools/clippy/clippy_config/src/conf.rs b/src/tools/clippy/clippy_config/src/conf.rs
index 5477d9b83a7..4e9ddbf8259 100644
--- a/src/tools/clippy/clippy_config/src/conf.rs
+++ b/src/tools/clippy/clippy_config/src/conf.rs
@@ -2,7 +2,9 @@ use crate::msrvs::Msrv;
 use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
 use crate::ClippyConfiguration;
 use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
 use rustc_session::Session;
+use rustc_span::edit_distance::edit_distance;
 use rustc_span::{BytePos, Pos, SourceFile, Span, SyntaxContext};
 use serde::de::{IgnoredAny, IntoDeserializer, MapAccess, Visitor};
 use serde::{Deserialize, Deserializer, Serialize};
@@ -26,7 +28,7 @@ const DEFAULT_DOC_VALID_IDENTS: &[&str] = &[
     "NaN", "NaNs",
     "OAuth", "GraphQL",
     "OCaml",
-    "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenDNS",
+    "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry",
     "WebGL", "WebGL2", "WebGPU",
     "TensorFlow",
     "TrueType",
@@ -59,18 +61,25 @@ impl TryConf {
 #[derive(Debug)]
 struct ConfError {
     message: String,
+    suggestion: Option<Suggestion>,
     span: Span,
 }
 
 impl ConfError {
     fn from_toml(file: &SourceFile, error: &toml::de::Error) -> Self {
         let span = error.span().unwrap_or(0..file.source_len.0 as usize);
-        Self::spanned(file, error.message(), span)
+        Self::spanned(file, error.message(), None, span)
     }
 
-    fn spanned(file: &SourceFile, message: impl Into<String>, span: Range<usize>) -> Self {
+    fn spanned(
+        file: &SourceFile,
+        message: impl Into<String>,
+        suggestion: Option<Suggestion>,
+        span: Range<usize>,
+    ) -> Self {
         Self {
             message: message.into(),
+            suggestion,
             span: Span::new(
                 file.start_pos + BytePos::from_usize(span.start),
                 file.start_pos + BytePos::from_usize(span.end),
@@ -147,16 +156,18 @@ macro_rules! define_Conf {
                     match Field::deserialize(name.get_ref().as_str().into_deserializer()) {
                         Err(e) => {
                             let e: FieldError = e;
-                            errors.push(ConfError::spanned(self.0, e.0, name.span()));
+                            errors.push(ConfError::spanned(self.0, e.error, e.suggestion, name.span()));
                         }
                         $(Ok(Field::$name) => {
-                            $(warnings.push(ConfError::spanned(self.0, format!("deprecated field `{}`. {}", name.get_ref(), $dep), name.span()));)?
+                            $(warnings.push(ConfError::spanned(self.0, format!("deprecated field `{}`. {}", name.get_ref(), $dep), None, name.span()));)?
                             let raw_value = map.next_value::<toml::Spanned<toml::Value>>()?;
                             let value_span = raw_value.span();
                             match <$ty>::deserialize(raw_value.into_inner()) {
-                                Err(e) => errors.push(ConfError::spanned(self.0, e.to_string().replace('\n', " ").trim(), value_span)),
+                                Err(e) => errors.push(ConfError::spanned(self.0, e.to_string().replace('\n', " ").trim(), None, value_span)),
                                 Ok(value) => match $name {
-                                    Some(_) => errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), name.span())),
+                                    Some(_) => {
+                                        errors.push(ConfError::spanned(self.0, format!("duplicate field `{}`", name.get_ref()), None, name.span()));
+                                    }
                                     None => {
                                         $name = Some(value);
                                         // $new_conf is the same as one of the defined `$name`s, so
@@ -165,7 +176,7 @@ macro_rules! define_Conf {
                                             Some(_) => errors.push(ConfError::spanned(self.0, concat!(
                                                 "duplicate field `", stringify!($new_conf),
                                                 "` (provided as `", stringify!($name), "`)"
-                                            ), name.span())),
+                                            ), None, name.span())),
                                             None => $new_conf = $name.clone(),
                                         })?
                                     },
@@ -523,7 +534,11 @@ define_Conf! {
     ///
     /// Additional dotfiles (files or directories starting with a dot) to allow
     (allowed_dotfiles: FxHashSet<String> = FxHashSet::default()),
-    /// Lint: EXPLICIT_ITER_LOOP
+    /// Lint: MULTIPLE_CRATE_VERSIONS.
+    ///
+    /// A list of crate names to allow duplicates of
+    (allowed_duplicate_crates: FxHashSet<String> = FxHashSet::default()),
+    /// Lint: EXPLICIT_ITER_LOOP.
     ///
     /// Whether to recommend using implicit into iter for reborrowed values.
     ///
@@ -543,15 +558,15 @@ define_Conf! {
     /// for _ in &mut *rmvec {}
     /// ```
     (enforce_iter_loop_reborrow: bool = false),
-    /// Lint: MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC, MISSING_PANICS_DOC, MISSING_ERRORS_DOC
+    /// Lint: MISSING_SAFETY_DOC, UNNECESSARY_SAFETY_DOC, MISSING_PANICS_DOC, MISSING_ERRORS_DOC.
     ///
     /// Whether to also run the listed lints on private items.
     (check_private_items: bool = false),
-    /// Lint: PUB_UNDERSCORE_FIELDS
+    /// 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),
+    (pub_underscore_fields_behavior: PubUnderscoreFieldsBehaviour = PubUnderscoreFieldsBehaviour::PubliclyExported),
 }
 
 /// Search for the configuration file.
@@ -669,10 +684,16 @@ impl Conf {
 
         // all conf errors are non-fatal, we just use the default conf in case of error
         for error in errors {
-            sess.dcx().span_err(
+            let mut diag = sess.dcx().struct_span_err(
                 error.span,
                 format!("error reading Clippy's configuration file: {}", error.message),
             );
+
+            if let Some(sugg) = error.suggestion {
+                diag.span_suggestion(error.span, sugg.message, sugg.suggestion, Applicability::MaybeIncorrect);
+            }
+
+            diag.emit();
         }
 
         for warning in warnings {
@@ -689,19 +710,31 @@ impl Conf {
 const SEPARATOR_WIDTH: usize = 4;
 
 #[derive(Debug)]
-struct FieldError(String);
+struct FieldError {
+    error: String,
+    suggestion: Option<Suggestion>,
+}
+
+#[derive(Debug)]
+struct Suggestion {
+    message: &'static str,
+    suggestion: &'static str,
+}
 
 impl std::error::Error for FieldError {}
 
 impl Display for FieldError {
     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
-        f.pad(&self.0)
+        f.pad(&self.error)
     }
 }
 
 impl serde::de::Error for FieldError {
     fn custom<T: Display>(msg: T) -> Self {
-        Self(msg.to_string())
+        Self {
+            error: msg.to_string(),
+            suggestion: None,
+        }
     }
 
     fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
@@ -723,7 +756,20 @@ impl serde::de::Error for FieldError {
                 write!(msg, "{:SEPARATOR_WIDTH$}{field:column_width$}", " ").unwrap();
             }
         }
-        Self(msg)
+
+        let suggestion = expected
+            .iter()
+            .filter_map(|expected| {
+                let dist = edit_distance(field, expected, 4)?;
+                Some((dist, expected))
+            })
+            .min_by_key(|&(dist, _)| dist)
+            .map(|(_, suggestion)| Suggestion {
+                message: "perhaps you meant",
+                suggestion,
+            });
+
+        Self { error: msg, suggestion }
     }
 }
 
diff --git a/src/tools/clippy/clippy_config/src/lib.rs b/src/tools/clippy/clippy_config/src/lib.rs
index f5dcb16d670..533e375a310 100644
--- a/src/tools/clippy/clippy_config/src/lib.rs
+++ b/src/tools/clippy/clippy_config/src/lib.rs
@@ -11,6 +11,7 @@ extern crate rustc_ast;
 extern crate rustc_data_structures;
 #[allow(unused_extern_crates)]
 extern crate rustc_driver;
+extern crate rustc_errors;
 extern crate rustc_session;
 extern crate rustc_span;
 
diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs
index baee09629ac..435aa9244c5 100644
--- a/src/tools/clippy/clippy_config/src/types.rs
+++ b/src/tools/clippy/clippy_config/src/types.rs
@@ -129,6 +129,6 @@ unimplemented_serialize! {
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
 pub enum PubUnderscoreFieldsBehaviour {
-    PublicallyExported,
+    PubliclyExported,
     AllPubFields,
 }
diff --git a/src/tools/clippy/clippy_dev/Cargo.toml b/src/tools/clippy/clippy_dev/Cargo.toml
index ce738e3f4ec..5ec67554e7d 100644
--- a/src/tools/clippy/clippy_dev/Cargo.toml
+++ b/src/tools/clippy/clippy_dev/Cargo.toml
@@ -4,11 +4,11 @@ version = "0.0.1"
 edition = "2021"
 
 [dependencies]
-aho-corasick = "0.7"
+aho-corasick = "1.0"
 clap = "4.1.4"
 indoc = "1.0"
 itertools = "0.11"
-opener = "0.5"
+opener = "0.6"
 shell-escape = "0.1"
 walkdir = "2.3"
 
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 6b76a44debf..2222abff7ad 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -504,9 +504,8 @@ fn replace_ident_like(contents: &str, replacements: &[(&str, &str)]) -> Option<S
     }
 
     let searcher = AhoCorasickBuilder::new()
-        .dfa(true)
         .match_kind(aho_corasick::MatchKind::LeftmostLongest)
-        .build_with_size::<u16, _, _>(replacements.iter().map(|&(x, _)| x.as_bytes()))
+        .build(replacements.iter().map(|&(x, _)| x.as_bytes()))
         .unwrap();
 
     let mut result = String::with_capacity(contents.len() + 1024);
@@ -928,7 +927,7 @@ fn remove_line_splices(s: &str) -> String {
         .and_then(|s| s.strip_suffix('"'))
         .unwrap_or_else(|| panic!("expected quoted string, found `{s}`"));
     let mut res = String::with_capacity(s.len());
-    unescape::unescape_literal(s, unescape::Mode::Str, &mut |range, ch| {
+    unescape::unescape_unicode(s, unescape::Mode::Str, &mut |range, ch| {
         if ch.is_ok() {
             res.push_str(&s[range]);
         }
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 8cba35f3d87..416e9a680dd 100644
--- a/src/tools/clippy/clippy_lints/Cargo.toml
+++ b/src/tools/clippy/clippy_lints/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2021"
 
 [dependencies]
 arrayvec = { version = "0.7", default-features = false }
-cargo_metadata = "0.15.3"
+cargo_metadata = "0.18"
 clippy_config = { path = "../clippy_config" }
 clippy_utils = { path = "../clippy_utils" }
 declare_clippy_lint = { path = "../declare_clippy_lint" }
diff --git a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
index 657d52d0e9e..1102c7fb236 100644
--- a/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
+++ b/src/tools/clippy/clippy_lints/src/arc_with_non_send_sync.rs
@@ -14,10 +14,10 @@ declare_clippy_lint! {
     /// This lint warns when you use `Arc` with a type that does not implement `Send` or `Sync`.
     ///
     /// ### Why is this bad?
-    /// `Arc<T>` is an Atomic `RC<T>` and guarantees that updates to the reference counter are
-    /// Atomic. This is useful in multiprocessing scenarios. To send an `Arc<T>` across processes
-    /// and make use of the atomic ref counter, `T` must be [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-Send-for-Arc%3CT%3E),
-    /// either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc`
+    /// `Arc<T>` is a thread-safe `Rc<T>` and guarantees that updates to the reference counter
+    /// use atomic operations. To send an `Arc<T>` across thread boundaries and
+    /// share ownership between multiple threads, `T` must be [both `Send` and `Sync`](https://doc.rust-lang.org/std/sync/struct.Arc.html#thread-safety),
+    /// so either `T` should be made `Send + Sync` or an `Rc` should be used instead of an `Arc`
     ///
     /// ### Example
     /// ```no_run
diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs
index 1417e230aee..ff4dffd0607 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs
+++ b/src/tools/clippy/clippy_lints/src/blocks_in_conditions.rs
@@ -67,6 +67,11 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInConditions {
         );
 
         if let ExprKind::Block(block, _) = &cond.kind {
+            if !block.span.eq_ctxt(expr.span) {
+                // If the block comes from a macro, or as an argument to a macro,
+                // do not lint.
+                return;
+            }
             if block.rules == BlockCheckMode::DefaultBlock {
                 if block.stmts.is_empty() {
                     if let Some(ex) = &block.expr {
diff --git a/src/tools/clippy/clippy_lints/src/cargo/mod.rs b/src/tools/clippy/clippy_lints/src/cargo/mod.rs
index fea6924d89e..d8107f61f37 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/mod.rs
@@ -6,6 +6,7 @@ mod wildcard_dependencies;
 use cargo_metadata::MetadataCommand;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_lint_allowed;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::hir_id::CRATE_HIR_ID;
 use rustc_lint::{LateContext, LateLintPass, Lint};
 use rustc_session::impl_lint_pass;
@@ -128,6 +129,8 @@ declare_clippy_lint! {
     /// ### Known problems
     /// Because this can be caused purely by the dependencies
     /// themselves, it's not always possible to fix this issue.
+    /// In those cases, you can allow that specific crate using
+    /// the `allowed_duplicate_crates` configuration option.
     ///
     /// ### Example
     /// ```toml
@@ -163,6 +166,7 @@ declare_clippy_lint! {
 }
 
 pub struct Cargo {
+    pub allowed_duplicate_crates: FxHashSet<String>,
     pub ignore_publish: bool,
 }
 
@@ -208,7 +212,7 @@ impl LateLintPass<'_> for Cargo {
         {
             match MetadataCommand::new().exec() {
                 Ok(metadata) => {
-                    multiple_crate_versions::check(cx, &metadata);
+                    multiple_crate_versions::check(cx, &metadata, &self.allowed_duplicate_crates);
                 },
                 Err(e) => {
                     for lint in WITH_DEPS_LINTS {
diff --git a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs
index ec681adb7ae..3f30a77fcfe 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs
@@ -3,27 +3,40 @@
 use cargo_metadata::{DependencyKind, Metadata, Node, Package, PackageId};
 use clippy_utils::diagnostics::span_lint;
 use itertools::Itertools;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_lint::LateContext;
 use rustc_span::DUMMY_SP;
 
 use super::MULTIPLE_CRATE_VERSIONS;
 
-pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) {
+pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, allowed_duplicate_crates: &FxHashSet<String>) {
     let local_name = cx.tcx.crate_name(LOCAL_CRATE);
     let mut packages = metadata.packages.clone();
     packages.sort_by(|a, b| a.name.cmp(&b.name));
 
     if let Some(resolve) = &metadata.resolve
         && let Some(local_id) = packages.iter().find_map(|p| {
-            if p.name == local_name.as_str() {
+            // p.name contains the original crate names with dashes intact
+            // local_name contains the crate name as a namespace, with the dashes converted to underscores
+            // the code below temporarily rectifies this discrepancy
+            if p.name
+                .as_bytes()
+                .iter()
+                .map(|b| if b == &b'-' { &b'_' } else { b })
+                .eq(local_name.as_str().as_bytes())
+            {
                 Some(&p.id)
             } else {
                 None
             }
         })
     {
-        for (name, group) in &packages.iter().group_by(|p| p.name.clone()) {
+        for (name, group) in &packages
+            .iter()
+            .filter(|p| !allowed_duplicate_crates.contains(&p.name))
+            .group_by(|p| &p.name)
+        {
             let group: Vec<&Package> = group.collect();
 
             if group.len() <= 1 {
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 20230106d53..639edd8da30 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -439,6 +439,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::STR_SPLIT_AT_NEWLINE_INFO,
     crate::methods::SUSPICIOUS_COMMAND_ARG_SPACE_INFO,
     crate::methods::SUSPICIOUS_MAP_INFO,
+    crate::methods::SUSPICIOUS_OPEN_OPTIONS_INFO,
     crate::methods::SUSPICIOUS_SPLITN_INFO,
     crate::methods::SUSPICIOUS_TO_OWNED_INFO,
     crate::methods::TYPE_ID_ON_BOX_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
index 2472e2ee76f..e617c19eff0 100644
--- a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::last_path_segment;
 use clippy_utils::source::snippet_with_context;
+use clippy_utils::{last_path_segment, std_or_core};
 use rustc_errors::Applicability;
 use rustc_hir::{def, Expr, ExprKind, GenericArg, QPath, TyKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -42,12 +42,14 @@ impl<'tcx> LateLintPass<'tcx> for DefaultIterEmpty {
             && ty.span.ctxt() == ctxt
         {
             let mut applicability = Applicability::MachineApplicable;
-            let sugg = make_sugg(cx, ty_path, ctxt, &mut applicability);
+            let Some(path) = std_or_core(cx) else { return };
+            let path = format!("{path}::iter::empty");
+            let sugg = make_sugg(cx, ty_path, ctxt, &mut applicability, &path);
             span_lint_and_sugg(
                 cx,
                 DEFAULT_INSTEAD_OF_ITER_EMPTY,
                 expr.span,
-                "`std::iter::empty()` is the more idiomatic way",
+                &format!("`{path}()` is the more idiomatic way"),
                 "try",
                 sugg,
                 applicability,
@@ -61,6 +63,7 @@ fn make_sugg(
     ty_path: &rustc_hir::QPath<'_>,
     ctxt: SyntaxContext,
     applicability: &mut Applicability,
+    path: &str,
 ) -> String {
     if let Some(last) = last_path_segment(ty_path).args
         && let Some(iter_ty) = last.args.iter().find_map(|arg| match arg {
@@ -69,10 +72,10 @@ fn make_sugg(
         })
     {
         format!(
-            "std::iter::empty::<{}>()",
+            "{path}::<{}>()",
             snippet_with_context(cx, iter_ty.span, ctxt, "..", applicability).0
         )
     } else {
-        "std::iter::empty()".to_owned()
+        format!("{path}()")
     }
 }
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 712bc075650..c4437a3c4b3 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_hir_and_then;
+use clippy_utils::numeric_literal;
 use clippy_utils::source::snippet_opt;
-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::{Block, Body, Expr, ExprKind, FnRetTy, HirId, ItemKind, Lit, Node, Stmt, StmtKind};
+use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
@@ -50,11 +50,11 @@ declare_lint_pass!(DefaultNumericFallback => [DEFAULT_NUMERIC_FALLBACK]);
 
 impl<'tcx> LateLintPass<'tcx> for DefaultNumericFallback {
     fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
-        let is_parent_const = if let Some(Node::Item(item)) = get_parent_node(cx.tcx, body.id().hir_id) {
-            matches!(item.kind, ItemKind::Const(..))
-        } else {
-            false
-        };
+        let hir = cx.tcx.hir();
+        let is_parent_const = matches!(
+            hir.body_const_context(hir.body_owner_def_id(body.id())),
+            Some(ConstContext::Const { inline: false } | ConstContext::Static(_))
+        );
         let mut visitor = NumericFallbackVisitor::new(cx, is_parent_const);
         visitor.visit_body(body);
     }
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index df596338b95..6144ec7b3ca 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy};
-use clippy_utils::{is_lint_allowed, match_def_path, paths};
+use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, match_def_path, paths};
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_expr, walk_fn, walk_item, FnKind, Visitor};
@@ -450,6 +450,7 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
         && let Some(eq_trait_def_id) = cx.tcx.get_diagnostic_item(sym::Eq)
         && let Some(def_id) = trait_ref.trait_def_id()
         && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
+        && !has_non_exhaustive_attr(cx.tcx, *adt)
         && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
         && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])
         // If all of our fields implement `Eq`, we can implement `Eq` too
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 8b018220c17..8dde4f227ed 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
@@ -6,7 +6,7 @@ use clippy_utils::diagnostics::span_lint;
 use rustc_ast::{CoroutineKind, Fn, FnRetTy, Item, ItemKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::emitter::HumanEmitter;
-use rustc_errors::DiagCtxt;
+use rustc_errors::{DiagCtxt, DiagnosticBuilder};
 use rustc_lint::LateContext;
 use rustc_parse::maybe_new_parser_from_source_str;
 use rustc_parse::parser::ForceCollect;
@@ -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) => {
-                        errs.into_iter().for_each(|err| err.cancel());
+                        errs.into_iter().for_each(DiagnosticBuilder::cancel);
                         return (false, test_attr_spans);
                     },
                 };
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
index fa1f98ba013..1933a00891b 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -6,8 +6,8 @@ use clippy_utils::source::snippet_opt;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_path, Visitor};
 use rustc_hir::{
-    GenericArg, GenericArgs, HirId, Impl, ImplItemKind, ImplItemRef, Item, ItemKind, PatKind, Path, PathSegment, Ty,
-    TyKind,
+    FnRetTy, GenericArg, GenericArgs, HirId, Impl, ImplItemKind, ImplItemRef, Item, ItemKind, PatKind, Path,
+    PathSegment, Ty, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter::OnlyBodies;
@@ -197,10 +197,13 @@ fn convert_to_from(
         // fn into([mut] self) -> T  ->  fn into([mut] v: T) -> T
         //               ~~~~                          ~~~~
         (self_ident.span, format!("val: {from}")),
+    ];
+
+    if let FnRetTy::Return(_) = sig.decl.output {
         // fn into(self) -> T  ->  fn into(self) -> Self
         //                  ~                       ~~~~
-        (sig.decl.output.span(), String::from("Self")),
-    ];
+        suggestions.push((sig.decl.output.span(), String::from("Self")));
+    }
 
     let mut finder = SelfFinder {
         cx,
diff --git a/src/tools/clippy/clippy_lints/src/inherent_impl.rs b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
index fb7b82ec304..1127f00abde 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_impl.rs
@@ -53,7 +53,9 @@ impl<'tcx> LateLintPass<'tcx> for MultipleInherentImpl {
         // List of spans to lint. (lint_span, first_span)
         let mut lint_spans = Vec::new();
 
-        let Ok(impls) = cx.tcx.crate_inherent_impls(()) else { return };
+        let Ok(impls) = cx.tcx.crate_inherent_impls(()) else {
+            return;
+        };
         let inherent_impls = cx
             .tcx
             .with_stable_hashing_context(|hcx| impls.inherent_impls.to_sorted(&hcx, true));
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index efdd3925949..feb4d188f39 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -574,6 +574,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         warn_on_all_wildcard_imports,
         check_private_items,
         pub_underscore_fields_behavior,
+        ref allowed_duplicate_crates,
 
         blacklisted_names: _,
         cyclomatic_complexity_threshold: _,
@@ -719,7 +720,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(needless_update::NeedlessUpdate));
     store.register_late_pass(|_| Box::new(needless_borrowed_ref::NeedlessBorrowedRef));
     store.register_late_pass(|_| Box::new(borrow_deref_ref::BorrowDerefRef));
-    store.register_late_pass(|_| Box::new(no_effect::NoEffect));
+    store.register_late_pass(|_| Box::<no_effect::NoEffect>::default());
     store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment));
     store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv())));
     store.register_late_pass(move |_| {
@@ -947,6 +948,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(move |_| {
         Box::new(cargo::Cargo {
             ignore_publish: cargo_ignore_publish,
+            allowed_duplicate_crates: allowed_duplicate_crates.clone(),
         })
     });
     store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index c245eaf1ab4..920a887a6fd 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -31,7 +31,7 @@ pub(super) fn check<'tcx>(
             vec.span,
             "it looks like the same item is being pushed into this Vec",
             None,
-            &format!("try using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"),
+            &format!("consider using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"),
         );
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index c22f76484d0..fa4f4a47e38 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lin
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_non_aggregate_primitive_type;
-use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators};
+use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators, std_or_core};
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
 use rustc_hir::{Expr, ExprKind};
@@ -128,6 +128,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
         // check if replacement is mem::MaybeUninit::uninit().assume_init()
         && cx.tcx.is_diagnostic_item(sym::assume_init, method_def_id)
     {
+        let Some(top_crate) = std_or_core(cx) else { return };
         let mut applicability = Applicability::MachineApplicable;
         span_lint_and_sugg(
             cx,
@@ -136,7 +137,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
             "replacing with `mem::MaybeUninit::uninit().assume_init()`",
             "consider using",
             format!(
-                "std::ptr::read({})",
+                "{top_crate}::ptr::read({})",
                 snippet_with_applicability(cx, dest.span, "", &mut applicability)
             ),
             applicability,
@@ -149,6 +150,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
         && let Some(repl_def_id) = cx.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id()
     {
         if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) {
+            let Some(top_crate) = std_or_core(cx) else { return };
             let mut applicability = Applicability::MachineApplicable;
             span_lint_and_sugg(
                 cx,
@@ -157,7 +159,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
                 "replacing with `mem::uninitialized()`",
                 "consider using",
                 format!(
-                    "std::ptr::read({})",
+                    "{top_crate}::ptr::read({})",
                     snippet_with_applicability(cx, dest.span, "", &mut applicability)
                 ),
                 applicability,
@@ -184,14 +186,17 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
         return;
     }
     if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) {
+        let Some(top_crate) = std_or_core(cx) else { return };
         span_lint_and_then(
             cx,
             MEM_REPLACE_WITH_DEFAULT,
             expr_span,
-            "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`",
+            &format!(
+                "replacing a value of type `T` with `T::default()` is better expressed using `{top_crate}::mem::take`"
+            ),
             |diag| {
                 if !expr_span.from_expansion() {
-                    let suggestion = format!("std::mem::take({})", snippet(cx, dest.span, ""));
+                    let suggestion = format!("{top_crate}::mem::take({})", snippet(cx, dest.span, ""));
 
                     diag.span_suggestion(
                         expr_span,
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
index 70abe4891d9..4c7c56e7174 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
-use clippy_utils::{get_expr_use_or_unification_node, is_no_std_crate, is_res_lang_ctor, path_res};
+use clippy_utils::{get_expr_use_or_unification_node, is_res_lang_ctor, path_res, std_or_core};
 
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
@@ -58,10 +58,10 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re
         return;
     }
 
+    let Some(top_crate) = std_or_core(cx) else { return };
     if let Some(i) = item {
         let sugg = format!(
-            "{}::iter::once({}{})",
-            if is_no_std_crate(cx) { "core" } else { "std" },
+            "{top_crate}::iter::once({}{})",
             iter_type.ref_prefix(),
             snippet(cx, i.span, "...")
         );
@@ -81,11 +81,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, method_name: &str, re
             expr.span,
             &format!("`{method_name}` call on an empty collection"),
             "try",
-            if is_no_std_crate(cx) {
-                "core::iter::empty()".to_string()
-            } else {
-                "std::iter::empty()".to_string()
-            },
+            format!("{top_crate}::iter::empty()"),
             Applicability::MaybeIncorrect,
         );
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs
index 02f28779cf6..aa1ec60d434 100644
--- a/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/join_absolute_paths.rs
@@ -42,7 +42,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx Expr<'tcx>, join_a
                     )
                     .span_suggestion(
                         expr_span,
-                        "if this is intentional, try using `Path::new` instead",
+                        "if this is intentional, consider using `Path::new`",
                         format!("PathBuf::from({arg_str})"),
                         Applicability::Unspecified,
                     );
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index 04bdbc1ea25..bf437db7e72 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -50,7 +50,7 @@ pub fn check(
         super::MANUAL_SATURATING_ARITHMETIC,
         expr.span,
         "manual saturating arithmetic",
-        &format!("try using `saturating_{arith}`"),
+        &format!("consider using `saturating_{arith}`"),
         format!(
             "{}.saturating_{arith}({})",
             snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability),
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 f9f636bbbf7..27e17b43b01 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -113,9 +113,15 @@ fn handle_path(
     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);
+        // The `copied` and `cloned` methods are only available on `&T` and `&mut T` in `Option`
+        // and `Result`.
+        if let ty::Adt(_, args) = cx.typeck_results().expr_ty(recv).kind()
+            && let args = args.as_slice()
+            && let Some(ty) = args.iter().find_map(|generic_arg| generic_arg.as_type())
+            && ty.is_ref()
+        {
+            lint_path(cx, e.span, recv.span, is_copy(cx, ty.peel_refs()));
+        }
     }
 }
 
@@ -139,17 +145,19 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) {
     );
 }
 
-fn lint_path(cx: &LateContext<'_>, replace: Span, root: Span) {
+fn lint_path(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool) {
     let mut applicability = Applicability::MachineApplicable;
 
+    let replacement = if is_copy { "copied" } else { "cloned" };
+
     span_lint_and_sugg(
         cx,
         MAP_CLONE,
         replace,
         "you are explicitly cloning with `.map()`",
-        "consider calling the dedicated `cloned` method",
+        &format!("consider calling the dedicated `{replacement}` method"),
         format!(
-            "{}.cloned()",
+            "{}.{replacement}()",
             snippet_with_applicability(cx, root, "..", &mut applicability),
         ),
         applicability,
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 89ea3597dc0..03bcf108914 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -2829,6 +2829,44 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for the suspicious use of `OpenOptions::create()`
+    /// without an explicit `OpenOptions::truncate()`.
+    ///
+    /// ### Why is this bad?
+    /// `create()` alone will either create a new file or open an
+    /// existing file. If the file already exists, it will be
+    /// overwritten when written to, but the file will not be
+    /// truncated by default.
+    /// If less data is written to the file
+    /// than it already contains, the remainder of the file will
+    /// remain unchanged, and the end of the file will contain old
+    /// data.
+    /// In most cases, one should either use `create_new` to ensure
+    /// the file is created from scratch, or ensure `truncate` is
+    /// called so that the truncation behaviour is explicit. `truncate(true)`
+    /// will ensure the file is entirely overwritten with new data, whereas
+    /// `truncate(false)` will explicitely keep the default behavior.
+    ///
+    /// ### Example
+    /// ```rust,no_run
+    /// use std::fs::OpenOptions;
+    ///
+    /// OpenOptions::new().create(true);
+    /// ```
+    /// Use instead:
+    /// ```rust,no_run
+    /// use std::fs::OpenOptions;
+    ///
+    /// OpenOptions::new().create(true).truncate(true);
+    /// ```
+    #[clippy::version = "1.75.0"]
+    pub SUSPICIOUS_OPEN_OPTIONS,
+    suspicious,
+    "suspicious combination of options for opening a file"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     ///* Checks for [push](https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.push)
     /// calls on `PathBuf` that can cause overwrites.
     ///
@@ -4033,6 +4071,7 @@ impl_lint_pass!(Methods => [
     MAP_ERR_IGNORE,
     MUT_MUTEX_LOCK,
     NONSENSICAL_OPEN_OPTIONS,
+    SUSPICIOUS_OPEN_OPTIONS,
     PATH_BUF_PUSH_OVERWRITE,
     RANGE_ZIP_WITH_LEN,
     REPEAT_ONCE,
diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
index 65c986dcacc..77484ab91a9 100644
--- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
@@ -1,46 +1,74 @@
-use clippy_utils::diagnostics::span_lint;
-use clippy_utils::ty::is_type_diagnostic_item;
+use rustc_data_structures::fx::FxHashMap;
+
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
+use clippy_utils::{match_any_def_paths, paths};
 use rustc_ast::ast::LitKind;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
+use rustc_middle::ty::Ty;
 use rustc_span::source_map::Spanned;
 use rustc_span::{sym, Span};
 
-use super::NONSENSICAL_OPEN_OPTIONS;
+use super::{NONSENSICAL_OPEN_OPTIONS, SUSPICIOUS_OPEN_OPTIONS};
+
+fn is_open_options(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
+    is_type_diagnostic_item(cx, ty, sym::FsOpenOptions) || match_type(cx, ty, &paths::TOKIO_IO_OPEN_OPTIONS)
+}
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx Expr<'_>) {
     if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
         && let Some(impl_id) = cx.tcx.impl_of_method(method_id)
-        && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::FsOpenOptions)
+        && is_open_options(cx, cx.tcx.type_of(impl_id).instantiate_identity())
     {
         let mut options = Vec::new();
-        get_open_options(cx, recv, &mut options);
-        check_open_options(cx, &options, e.span);
+        if get_open_options(cx, recv, &mut options) {
+            check_open_options(cx, &options, e.span);
+        }
     }
 }
 
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[derive(Eq, PartialEq, Clone, Debug)]
 enum Argument {
-    True,
-    False,
+    Set(bool),
     Unknown,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Eq, PartialEq, Hash, Clone)]
 enum OpenOption {
-    Write,
+    Append,
+    Create,
+    CreateNew,
     Read,
     Truncate,
-    Create,
-    Append,
+    Write,
+}
+impl std::fmt::Display for OpenOption {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            OpenOption::Append => write!(f, "append"),
+            OpenOption::Create => write!(f, "create"),
+            OpenOption::CreateNew => write!(f, "create_new"),
+            OpenOption::Read => write!(f, "read"),
+            OpenOption::Truncate => write!(f, "truncate"),
+            OpenOption::Write => write!(f, "write"),
+        }
+    }
 }
 
-fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec<(OpenOption, Argument)>) {
-    if let ExprKind::MethodCall(path, receiver, arguments, _) = argument.kind {
+/// Collects information about a method call chain on `OpenOptions`.
+/// Returns false if an unexpected expression kind was found "on the way",
+/// and linting should then be avoided.
+fn get_open_options(
+    cx: &LateContext<'_>,
+    argument: &Expr<'_>,
+    options: &mut Vec<(OpenOption, Argument, Span)>,
+) -> bool {
+    if let ExprKind::MethodCall(path, receiver, arguments, span) = argument.kind {
         let obj_ty = cx.typeck_results().expr_ty(receiver).peel_refs();
 
         // Only proceed if this is a call on some object of type std::fs::OpenOptions
-        if is_type_diagnostic_item(cx, obj_ty, sym::FsOpenOptions) && !arguments.is_empty() {
+        if !arguments.is_empty() && is_open_options(cx, obj_ty) {
             let argument_option = match arguments[0].kind {
                 ExprKind::Lit(span) => {
                     if let Spanned {
@@ -48,11 +76,12 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec
                         ..
                     } = span
                     {
-                        if *lit { Argument::True } else { Argument::False }
+                        Argument::Set(*lit)
                     } else {
                         // The function is called with a literal which is not a boolean literal.
                         // This is theoretically possible, but not very likely.
-                        return;
+                        // We'll ignore it for now
+                        return get_open_options(cx, receiver, options);
                     }
                 },
                 _ => Argument::Unknown,
@@ -60,106 +89,77 @@ fn get_open_options(cx: &LateContext<'_>, argument: &Expr<'_>, options: &mut Vec
 
             match path.ident.as_str() {
                 "create" => {
-                    options.push((OpenOption::Create, argument_option));
+                    options.push((OpenOption::Create, argument_option, span));
+                },
+                "create_new" => {
+                    options.push((OpenOption::CreateNew, argument_option, span));
                 },
                 "append" => {
-                    options.push((OpenOption::Append, argument_option));
+                    options.push((OpenOption::Append, argument_option, span));
                 },
                 "truncate" => {
-                    options.push((OpenOption::Truncate, argument_option));
+                    options.push((OpenOption::Truncate, argument_option, span));
                 },
                 "read" => {
-                    options.push((OpenOption::Read, argument_option));
+                    options.push((OpenOption::Read, argument_option, span));
                 },
                 "write" => {
-                    options.push((OpenOption::Write, argument_option));
+                    options.push((OpenOption::Write, argument_option, span));
+                },
+                _ => {
+                    // Avoid linting altogether if this method is from a trait.
+                    // This might be a user defined extension trait with a method like `truncate_write`
+                    // which would be a false positive
+                    if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(argument.hir_id)
+                        && cx.tcx.trait_of_item(method_def_id).is_some()
+                    {
+                        return false;
+                    }
                 },
-                _ => (),
             }
 
-            get_open_options(cx, receiver, options);
+            get_open_options(cx, receiver, options)
+        } else {
+            false
         }
+    } else if let ExprKind::Call(callee, _) = argument.kind
+        && let ExprKind::Path(path) = callee.kind
+        && let Some(did) = cx.qpath_res(&path, callee.hir_id).opt_def_id()
+    {
+        match_any_def_paths(
+            cx,
+            did,
+            &[
+                &paths::TOKIO_IO_OPEN_OPTIONS_NEW,
+                &paths::OPEN_OPTIONS_NEW,
+                &paths::FILE_OPTIONS,
+                &paths::TOKIO_FILE_OPTIONS,
+            ],
+        )
+        .is_some()
+    } else {
+        false
     }
 }
 
-fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)], span: Span) {
-    let (mut create, mut append, mut truncate, mut read, mut write) = (false, false, false, false, false);
-    let (mut create_arg, mut append_arg, mut truncate_arg, mut read_arg, mut write_arg) =
-        (false, false, false, false, false);
-    // This code is almost duplicated (oh, the irony), but I haven't found a way to
-    // unify it.
-
-    for option in options {
-        match *option {
-            (OpenOption::Create, arg) => {
-                if create {
-                    span_lint(
-                        cx,
-                        NONSENSICAL_OPEN_OPTIONS,
-                        span,
-                        "the method `create` is called more than once",
-                    );
-                } else {
-                    create = true;
-                }
-                create_arg = create_arg || (arg == Argument::True);
-            },
-            (OpenOption::Append, arg) => {
-                if append {
-                    span_lint(
-                        cx,
-                        NONSENSICAL_OPEN_OPTIONS,
-                        span,
-                        "the method `append` is called more than once",
-                    );
-                } else {
-                    append = true;
-                }
-                append_arg = append_arg || (arg == Argument::True);
-            },
-            (OpenOption::Truncate, arg) => {
-                if truncate {
-                    span_lint(
-                        cx,
-                        NONSENSICAL_OPEN_OPTIONS,
-                        span,
-                        "the method `truncate` is called more than once",
-                    );
-                } else {
-                    truncate = true;
-                }
-                truncate_arg = truncate_arg || (arg == Argument::True);
-            },
-            (OpenOption::Read, arg) => {
-                if read {
-                    span_lint(
-                        cx,
-                        NONSENSICAL_OPEN_OPTIONS,
-                        span,
-                        "the method `read` is called more than once",
-                    );
-                } else {
-                    read = true;
-                }
-                read_arg = read_arg || (arg == Argument::True);
-            },
-            (OpenOption::Write, arg) => {
-                if write {
-                    span_lint(
-                        cx,
-                        NONSENSICAL_OPEN_OPTIONS,
-                        span,
-                        "the method `write` is called more than once",
-                    );
-                } else {
-                    write = true;
-                }
-                write_arg = write_arg || (arg == Argument::True);
-            },
+fn check_open_options(cx: &LateContext<'_>, settings: &[(OpenOption, Argument, Span)], span: Span) {
+    // The args passed to these methods, if they have been called
+    let mut options = FxHashMap::default();
+    for (option, arg, sp) in settings {
+        if let Some((_, prev_span)) = options.insert(option.clone(), (arg.clone(), *sp)) {
+            span_lint(
+                cx,
+                NONSENSICAL_OPEN_OPTIONS,
+                prev_span,
+                &format!("the method `{}` is called more than once", &option),
+            );
         }
     }
 
-    if read && truncate && read_arg && truncate_arg && !(write && write_arg) {
+    if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Read)
+        && let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate)
+        && let None | Some((Argument::Set(false), _)) = options.get(&OpenOption::Write)
+    {
         span_lint(
             cx,
             NONSENSICAL_OPEN_OPTIONS,
@@ -167,7 +167,10 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
             "file opened with `truncate` and `read`",
         );
     }
-    if append && truncate && append_arg && truncate_arg {
+
+    if let Some((Argument::Set(true), _)) = options.get(&OpenOption::Append)
+        && let Some((Argument::Set(true), _)) = options.get(&OpenOption::Truncate)
+    {
         span_lint(
             cx,
             NONSENSICAL_OPEN_OPTIONS,
@@ -175,4 +178,29 @@ fn check_open_options(cx: &LateContext<'_>, options: &[(OpenOption, Argument)],
             "file opened with `append` and `truncate`",
         );
     }
+
+    if let Some((Argument::Set(true), create_span)) = options.get(&OpenOption::Create)
+        && let None = options.get(&OpenOption::Truncate)
+        && let None | Some((Argument::Set(false), _)) = options.get(&OpenOption::Append)
+    {
+        span_lint_and_then(
+            cx,
+            SUSPICIOUS_OPEN_OPTIONS,
+            *create_span,
+            "file opened with `create`, but `truncate` behavior not defined",
+            |diag| {
+                diag.span_suggestion(
+                    create_span.shrink_to_hi(),
+                    "add",
+                    ".truncate(true)".to_string(),
+                    rustc_errors::Applicability::MaybeIncorrect,
+                )
+                .help("if you intend to overwrite an existing file entirely, call `.truncate(true)`")
+                .help(
+                    "if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`",
+                )
+                .help("alternatively, use `.append(true)` to append to the file instead of overwriting it");
+            },
+        );
+    }
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index 756dbe62d84..88e2af15658 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -97,7 +97,7 @@ pub(super) fn check(
         };
         let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" };
         let hint = format!("{}.{method_hint}()", snippet(cx, as_ref_recv.span, ".."));
-        let suggestion = format!("try using {method_hint} instead");
+        let suggestion = format!("consider using {method_hint}");
 
         let msg = format!("called `{current_method}` on an `Option` value");
         span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_err_ok.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_err_ok.rs
index 91e39d5a1cd..4e424d4c066 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_err_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_err_ok.rs
@@ -33,7 +33,7 @@ pub(super) fn check<'tcx>(
             OPTION_MAP_OR_ERR_OK,
             expr.span,
             msg,
-            "try using `ok_or` instead",
+            "consider using `ok_or`",
             format!("{self_snippet}.ok_or({err_snippet})"),
             Applicability::MachineApplicable,
         );
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
index ff4d8cc9e3e..193deafccf6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
@@ -72,7 +72,7 @@ pub(super) fn check<'tcx>(
                 OPTION_MAP_OR_NONE,
                 expr.span,
                 msg,
-                "try using `map` instead",
+                "consider using `map`",
                 format!("{self_snippet}.map({arg_snippet} {func_snippet})"),
                 Applicability::MachineApplicable,
             );
@@ -85,7 +85,7 @@ pub(super) fn check<'tcx>(
             OPTION_MAP_OR_NONE,
             expr.span,
             msg,
-            "try using `and_then` instead",
+            "consider using `and_then`",
             format!("{self_snippet}.and_then({func_snippet})"),
             Applicability::MachineApplicable,
         );
@@ -97,7 +97,7 @@ pub(super) fn check<'tcx>(
             RESULT_MAP_OR_INTO_OPTION,
             expr.span,
             msg,
-            "try using `ok` instead",
+            "consider using `ok`",
             format!("{self_snippet}.ok()"),
             Applicability::MachineApplicable,
         );
diff --git a/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs b/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs
index bc16a112816..3b0dc506305 100644
--- a/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/result_map_or_else_none.rs
@@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
             RESULT_MAP_OR_INTO_OPTION,
             expr.span,
             msg,
-            "try using `ok` instead",
+            "consider using `ok`",
             format!("{self_snippet}.ok()"),
             Applicability::MachineApplicable,
         );
diff --git a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
index 6339011c92f..ef1baa6c988 100644
--- a/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/search_is_some.rs
@@ -63,7 +63,7 @@ pub(super) fn check<'tcx>(
                     SEARCH_IS_SOME,
                     method_span.with_hi(expr.span.hi()),
                     &msg,
-                    "use `any()` instead",
+                    "consider using",
                     format!(
                         "any({})",
                         any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
@@ -77,7 +77,7 @@ pub(super) fn check<'tcx>(
                     SEARCH_IS_SOME,
                     expr.span,
                     &msg,
-                    "use `!_.any()` instead",
+                    "consider using",
                     format!(
                         "!{iter}.any({})",
                         any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
@@ -118,7 +118,7 @@ pub(super) fn check<'tcx>(
                         SEARCH_IS_SOME,
                         method_span.with_hi(expr.span.hi()),
                         &msg,
-                        "use `contains()` instead",
+                        "consider using",
                         format!("contains({find_arg})"),
                         applicability,
                     );
@@ -132,7 +132,7 @@ pub(super) fn check<'tcx>(
                         SEARCH_IS_SOME,
                         expr.span,
                         &msg,
-                        "use `!_.contains()` instead",
+                        "consider using",
                         format!("!{string}.contains({find_arg})"),
                         applicability,
                     );
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
index 3983f0c0cab..363b1f2b812 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_pattern.rs
@@ -57,7 +57,7 @@ pub(super) fn check(
                 SINGLE_CHAR_PATTERN,
                 arg.span,
                 "single-character string constant used as pattern",
-                "try using a `char` instead",
+                "consider using a `char`",
                 hint,
                 applicability,
             );
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
index e2b389e96da..c3ad4db3875 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_join.rs
@@ -32,7 +32,7 @@ pub(super) fn check<'tcx>(
             UNNECESSARY_JOIN,
             span.with_hi(expr.span.hi()),
             r#"called `.collect::<Vec<String>>().join("")` on an iterator"#,
-            "try using",
+            "consider using",
             "collect::<String>()".to_owned(),
             applicability,
         );
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
index 696e5e74d60..6911da69b94 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_sort_by.rs
@@ -203,7 +203,7 @@ pub(super) fn check<'tcx>(
             cx,
             UNNECESSARY_SORT_BY,
             expr.span,
-            "use Vec::sort_by_key here instead",
+            "consider using `sort_by_key`",
             "try",
             format!(
                 "{}.sort{}_by_key(|{}| {})",
@@ -226,7 +226,7 @@ pub(super) fn check<'tcx>(
             cx,
             UNNECESSARY_SORT_BY,
             expr.span,
-            "use Vec::sort here instead",
+            "consider using `sort`",
             "try",
             format!(
                 "{}.sort{}()",
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 66727e5a29d..514015af045 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -1,7 +1,9 @@
 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_diag_trait_item, match_def_path, paths, peel_blocks};
+use clippy_utils::{
+    get_parent_expr, is_diag_trait_item, match_def_path, path_to_local_id, paths, peel_blocks, strip_pat_refs,
+};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
@@ -108,9 +110,12 @@ fn check_qpath(cx: &LateContext<'_>, qpath: hir::QPath<'_>, hir_id: hir::HirId)
 
 fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
     match arg.kind {
-        hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
+        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);
+            if let closure_body = cx.tcx.hir().body(body)
+                && let [param] = closure_body.params
+                && let hir::PatKind::Binding(_, local_id, ..) = strip_pat_refs(param.pat).kind =>
+        {
             let closure_expr = peel_blocks(closure_body.value);
             match closure_expr.kind {
                 hir::ExprKind::MethodCall(method, obj, [], _) => {
@@ -122,14 +127,17 @@ fn is_calling_clone(cx: &LateContext<'_>, arg: &hir::Expr<'_>) -> bool {
                         // no autoderefs
                         && !cx.typeck_results().expr_adjustments(obj).iter()
                             .any(|a| matches!(a.kind, Adjust::Deref(Some(..))))
+                        && path_to_local_id(obj, local_id)
                     {
                         true
                     } else {
                         false
                     }
                 },
-                hir::ExprKind::Call(call, [_]) => {
-                    if let hir::ExprKind::Path(qpath) = call.kind {
+                hir::ExprKind::Call(call, [recv]) => {
+                    if let hir::ExprKind::Path(qpath) = call.kind
+                        && path_to_local_id(recv, local_id)
+                    {
                         check_qpath(cx, qpath, call.hir_id)
                     } else {
                         false
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index 64ef709e2fa..d2eef6ae433 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -5,16 +5,15 @@ use clippy_utils::visitors::for_each_expr_with_closures;
 use clippy_utils::{get_parent_node, inherits_cfg, is_from_proc_macro, is_self};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_qpath, FnKind, Visitor};
+use rustc_hir::intravisit::FnKind;
 use rustc_hir::{
     BlockCheckMode, Body, Closure, Expr, ExprKind, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node,
-    PatKind, QPath,
+    PatKind,
 };
 use rustc_hir_typeck::expr_use_visitor as euv;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::associated_body;
-use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath};
 use rustc_session::impl_lint_pass;
@@ -234,12 +233,29 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
         }
     }
 
-    fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
-        cx.tcx.hir().visit_all_item_likes_in_crate(&mut FnNeedsMutVisitor {
-            cx,
-            used_fn_def_ids: &mut self.used_fn_def_ids,
-        });
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        // #11182; do not lint if mutability is required elsewhere
+        if let ExprKind::Path(..) = expr.kind
+            && let Some(parent) = get_parent_node(cx.tcx, expr.hir_id)
+            && let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(expr).kind()
+            && let Some(def_id) = def_id.as_local()
+        {
+            if let Node::Expr(e) = parent
+                && let ExprKind::Call(call, _) = e.kind
+                && call.hir_id == expr.hir_id
+            {
+                return;
+            }
 
+            // We don't need to check each argument individually as you cannot coerce a function
+            // taking `&mut` -> `&`, for some reason, so if we've gotten this far we know it's
+            // passed as a `fn`-like argument (or is unified) and should ignore every "unused"
+            // argument entirely
+            self.used_fn_def_ids.insert(def_id);
+        }
+    }
+
+    fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
         for (fn_def_id, unused) in self
             .fn_def_ids_to_maybe_unused_mut
             .iter()
@@ -501,48 +517,3 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
         }
     }
 }
-
-/// A final pass to check for paths referencing this function that require the argument to be
-/// `&mut`, basically if the function is ever used as a `fn`-like argument.
-struct FnNeedsMutVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    used_fn_def_ids: &'a mut FxHashSet<LocalDefId>,
-}
-
-impl<'tcx> Visitor<'tcx> for FnNeedsMutVisitor<'_, 'tcx> {
-    type NestedFilter = OnlyBodies;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.cx.tcx.hir()
-    }
-
-    fn visit_qpath(&mut self, qpath: &'tcx QPath<'tcx>, hir_id: HirId, _: Span) {
-        walk_qpath(self, qpath, hir_id);
-
-        let Self { cx, used_fn_def_ids } = self;
-
-        // #11182; do not lint if mutability is required elsewhere
-        if let Node::Expr(expr) = cx.tcx.hir_node(hir_id)
-            && let Some(parent) = get_parent_node(cx.tcx, expr.hir_id)
-            && let ty::FnDef(def_id, _) = cx
-                .tcx
-                .typeck(cx.tcx.hir().enclosing_body_owner(hir_id))
-                .expr_ty(expr)
-                .kind()
-            && let Some(def_id) = def_id.as_local()
-        {
-            if let Node::Expr(e) = parent
-                && let ExprKind::Call(call, _) = e.kind
-                && call.hir_id == expr.hir_id
-            {
-                return;
-            }
-
-            // We don't need to check each argument individually as you cannot coerce a function
-            // taking `&mut` -> `&`, for some reason, so if we've gotten this far we know it's
-            // passed as a `fn`-like argument (or is unified) and should ignore every "unused"
-            // argument entirely
-            used_fn_def_ids.insert(def_id);
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs
index 6bbe427ea29..0d234f7f9b5 100644
--- a/src/tools/clippy/clippy_lints/src/no_effect.rs
+++ b/src/tools/clippy/clippy_lints/src/no_effect.rs
@@ -1,16 +1,18 @@
 use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::has_drop;
-use clippy_utils::{get_parent_node, is_lint_allowed, peel_blocks};
+use clippy_utils::{any_parent_is_automatically_derived, get_parent_node, is_lint_allowed, path_to_local, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{
-    is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, ItemKind, Node, PatKind, Stmt, StmtKind, UnsafeSource,
+    is_range_literal, BinOpKind, BlockCheckMode, Expr, ExprKind, HirId, HirIdMap, ItemKind, Node, PatKind, Stmt,
+    StmtKind, UnsafeSource,
 };
 use rustc_infer::infer::TyCtxtInferExt as _;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
+use rustc_span::Span;
 use std::ops::Deref;
 
 declare_clippy_lint! {
@@ -74,94 +76,125 @@ declare_clippy_lint! {
     "outer expressions with no effect"
 }
 
-declare_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION, NO_EFFECT_UNDERSCORE_BINDING]);
+#[derive(Default)]
+pub struct NoEffect {
+    underscore_bindings: HirIdMap<Span>,
+    local_bindings: Vec<Vec<HirId>>,
+}
+
+impl_lint_pass!(NoEffect => [NO_EFFECT, UNNECESSARY_OPERATION, NO_EFFECT_UNDERSCORE_BINDING]);
 
 impl<'tcx> LateLintPass<'tcx> for NoEffect {
     fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
-        if check_no_effect(cx, stmt) {
+        if self.check_no_effect(cx, stmt) {
             return;
         }
         check_unnecessary_operation(cx, stmt);
     }
-}
 
-fn check_no_effect(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
-    if let StmtKind::Semi(expr) = stmt.kind {
-        // move `expr.span.from_expansion()` ahead
-        if expr.span.from_expansion() {
-            return false;
+    fn check_block(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Block<'tcx>) {
+        self.local_bindings.push(Vec::default());
+    }
+
+    fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &'tcx rustc_hir::Block<'tcx>) {
+        for hir_id in self.local_bindings.pop().unwrap() {
+            if let Some(span) = self.underscore_bindings.remove(&hir_id) {
+                span_lint_hir(
+                    cx,
+                    NO_EFFECT_UNDERSCORE_BINDING,
+                    hir_id,
+                    span,
+                    "binding to `_` prefixed variable with no side-effect",
+                );
+            }
         }
-        let expr = peel_blocks(expr);
+    }
 
-        if is_operator_overridden(cx, expr) {
-            // Return `true`, to prevent `check_unnecessary_operation` from
-            // linting on this statement as well.
-            return true;
+    fn check_expr(&mut self, _: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
+        if let Some(def_id) = path_to_local(expr) {
+            self.underscore_bindings.remove(&def_id);
         }
-        if has_no_effect(cx, expr) {
-            span_lint_hir_and_then(
-                cx,
-                NO_EFFECT,
-                expr.hir_id,
-                stmt.span,
-                "statement with no effect",
-                |diag| {
-                    for parent in cx.tcx.hir().parent_iter(stmt.hir_id) {
-                        if let Node::Item(item) = parent.1
-                            && let ItemKind::Fn(..) = item.kind
-                            && let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id)
-                            && let [.., final_stmt] = block.stmts
-                            && final_stmt.hir_id == stmt.hir_id
-                        {
-                            let expr_ty = cx.typeck_results().expr_ty(expr);
-                            let mut ret_ty = cx
-                                .tcx
-                                .fn_sig(item.owner_id)
-                                .instantiate_identity()
-                                .output()
-                                .skip_binder();
+    }
+}
+
+impl NoEffect {
+    fn check_no_effect(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
+        if let StmtKind::Semi(expr) = stmt.kind {
+            // move `expr.span.from_expansion()` ahead
+            if expr.span.from_expansion() {
+                return false;
+            }
+            let expr = peel_blocks(expr);
 
-                            // Remove `impl Future<Output = T>` to get `T`
-                            if cx.tcx.ty_is_opaque_future(ret_ty)
-                                && let Some(true_ret_ty) = cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty)
+            if is_operator_overridden(cx, expr) {
+                // Return `true`, to prevent `check_unnecessary_operation` from
+                // linting on this statement as well.
+                return true;
+            }
+            if has_no_effect(cx, expr) {
+                span_lint_hir_and_then(
+                    cx,
+                    NO_EFFECT,
+                    expr.hir_id,
+                    stmt.span,
+                    "statement with no effect",
+                    |diag| {
+                        for parent in cx.tcx.hir().parent_iter(stmt.hir_id) {
+                            if let Node::Item(item) = parent.1
+                                && let ItemKind::Fn(..) = item.kind
+                                && let Some(Node::Block(block)) = get_parent_node(cx.tcx, stmt.hir_id)
+                                && let [.., final_stmt] = block.stmts
+                                && final_stmt.hir_id == stmt.hir_id
                             {
-                                ret_ty = true_ret_ty;
-                            }
+                                let expr_ty = cx.typeck_results().expr_ty(expr);
+                                let mut ret_ty = cx
+                                    .tcx
+                                    .fn_sig(item.owner_id)
+                                    .instantiate_identity()
+                                    .output()
+                                    .skip_binder();
+
+                                // Remove `impl Future<Output = T>` to get `T`
+                                if cx.tcx.ty_is_opaque_future(ret_ty)
+                                    && let Some(true_ret_ty) =
+                                        cx.tcx.infer_ctxt().build().get_impl_future_output_ty(ret_ty)
+                                {
+                                    ret_ty = true_ret_ty;
+                                }
 
-                            if !ret_ty.is_unit() && ret_ty == expr_ty {
-                                diag.span_suggestion(
-                                    stmt.span.shrink_to_lo(),
-                                    "did you mean to return it?",
-                                    "return ",
-                                    Applicability::MaybeIncorrect,
-                                );
+                                if !ret_ty.is_unit() && ret_ty == expr_ty {
+                                    diag.span_suggestion(
+                                        stmt.span.shrink_to_lo(),
+                                        "did you mean to return it?",
+                                        "return ",
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
                             }
                         }
-                    }
-                },
-            );
-            return true;
-        }
-    } else if let StmtKind::Local(local) = stmt.kind {
-        if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id)
-            && let Some(init) = local.init
-            && local.els.is_none()
-            && !local.pat.span.from_expansion()
-            && has_no_effect(cx, init)
-            && let PatKind::Binding(_, _, ident, _) = local.pat.kind
-            && ident.name.to_ident_string().starts_with('_')
-        {
-            span_lint_hir(
-                cx,
-                NO_EFFECT_UNDERSCORE_BINDING,
-                init.hir_id,
-                stmt.span,
-                "binding to `_` prefixed variable with no side-effect",
-            );
-            return true;
+                    },
+                );
+                return true;
+            }
+        } else if let StmtKind::Local(local) = stmt.kind {
+            if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id)
+                && let Some(init) = local.init
+                && local.els.is_none()
+                && !local.pat.span.from_expansion()
+                && has_no_effect(cx, init)
+                && let PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
+                && ident.name.to_ident_string().starts_with('_')
+                && !any_parent_is_automatically_derived(cx.tcx, local.hir_id)
+            {
+                if let Some(l) = self.local_bindings.last_mut() {
+                    l.push(hir_id);
+                    self.underscore_bindings.insert(hir_id, ident.span);
+                }
+                return true;
+            }
         }
+        false
     }
-    false
 }
 
 fn is_operator_overridden(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
index 929efb6c574..96ea063aa74 100644
--- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -1,11 +1,11 @@
 use super::ARITHMETIC_SIDE_EFFECTS;
 use clippy_utils::consts::{constant, constant_simple, Constant};
 use clippy_utils::diagnostics::span_lint;
-use clippy_utils::ty::type_diagnostic_name;
+use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{self, Ty};
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::sym;
@@ -88,37 +88,44 @@ impl ArithmeticSideEffects {
     }
 
     /// Verifies built-in types that have specific allowed operations
-    fn has_specific_allowed_type_and_operation(
-        cx: &LateContext<'_>,
-        lhs_ty: Ty<'_>,
+    fn has_specific_allowed_type_and_operation<'tcx>(
+        cx: &LateContext<'tcx>,
+        lhs_ty: Ty<'tcx>,
         op: &Spanned<hir::BinOpKind>,
-        rhs_ty: Ty<'_>,
+        rhs_ty: Ty<'tcx>,
     ) -> bool {
         let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem);
-        let is_non_zero_u = |symbol: Option<Symbol>| {
-            matches!(
-                symbol,
-                Some(
-                    sym::NonZeroU128
-                        | sym::NonZeroU16
-                        | sym::NonZeroU32
-                        | sym::NonZeroU64
-                        | sym::NonZeroU8
-                        | sym::NonZeroUsize
-                )
-            )
+        let is_non_zero_u = |cx: &LateContext<'tcx>, ty: Ty<'tcx>| {
+            let tcx = cx.tcx;
+
+            let ty::Adt(adt, substs) = ty.kind() else { return false };
+
+            if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) {
+                return false;
+            };
+
+            let int_type = substs.type_at(0);
+            let unsigned_int_types = [
+                tcx.types.u8,
+                tcx.types.u16,
+                tcx.types.u32,
+                tcx.types.u64,
+                tcx.types.u128,
+                tcx.types.usize,
+            ];
+
+            unsigned_int_types.contains(&int_type)
         };
         let is_sat_or_wrap = |ty: Ty<'_>| {
-            let is_sat = type_diagnostic_name(cx, ty) == Some(sym::Saturating);
-            let is_wrap = type_diagnostic_name(cx, ty) == Some(sym::Wrapping);
-            is_sat || is_wrap
+            is_type_diagnostic_item(cx, ty, sym::Saturating) || is_type_diagnostic_item(cx, ty, sym::Wrapping)
         };
 
-        // If the RHS is NonZeroU*, then division or module by zero will never occur
-        if is_non_zero_u(type_diagnostic_name(cx, rhs_ty)) && is_div_or_rem {
+        // If the RHS is `NonZero<u*>`, then division or module by zero will never occur.
+        if is_non_zero_u(cx, rhs_ty) && is_div_or_rem {
             return true;
         }
-        // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module
+
+        // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module.
         if is_sat_or_wrap(lhs_ty) {
             return !is_div_or_rem;
         }
diff --git a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
index 9db2e24630a..a69989e400b 100644
--- a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
@@ -1,13 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_opt;
+use clippy_utils::std_or_core;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 
 use super::PTR_EQ;
 
-static LINT_MSG: &str = "use `std::ptr::eq` when comparing raw pointers";
-
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     expr: &'tcx Expr<'_>,
@@ -26,13 +25,14 @@ pub(super) fn check<'tcx>(
             && let Some(left_snip) = snippet_opt(cx, left_var.span)
             && let Some(right_snip) = snippet_opt(cx, right_var.span)
         {
+            let Some(top_crate) = std_or_core(cx) else { return };
             span_lint_and_sugg(
                 cx,
                 PTR_EQ,
                 expr.span,
-                LINT_MSG,
+                &format!("use `{top_crate}::ptr::eq` when comparing raw pointers"),
                 "try",
-                format!("std::ptr::eq({left_snip}, {right_snip})"),
+                format!("{top_crate}::ptr::eq({left_snip}, {right_snip})"),
                 Applicability::MachineApplicable,
             );
         }
diff --git a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
index 00465ce4381..88b5a6cfe2a 100644
--- a/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
+++ b/src/tools/clippy/clippy_lints/src/pub_underscore_fields.rs
@@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for PubUnderscoreFields {
         };
 
         let is_visible = |field: &FieldDef<'_>| match self.behavior {
-            PubUnderscoreFieldsBehaviour::PublicallyExported => cx.effective_visibilities.is_reachable(field.def_id),
+            PubUnderscoreFieldsBehaviour::PubliclyExported => 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()
diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
index 62f3c09aa7e..650324d4249 100644
--- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
@@ -1,11 +1,13 @@
 use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
+use clippy_utils::get_enclosing_block;
 use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
 use clippy_utils::source::snippet;
-use clippy_utils::visitors::for_each_expr;
-use core::ops::ControlFlow;
-use hir::{Expr, ExprKind, Local, PatKind, PathSegment, QPath, StmtKind};
+
+use hir::{Expr, ExprKind, HirId, Local, PatKind, PathSegment, QPath, StmtKind};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 
@@ -49,57 +51,40 @@ declare_lint_pass!(ReadZeroByteVec => [READ_ZERO_BYTE_VEC]);
 
 impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &hir::Block<'tcx>) {
-        for (idx, stmt) in block.stmts.iter().enumerate() {
-            if !stmt.span.from_expansion()
-                // matches `let v = Vec::new();`
-                && let StmtKind::Local(local) = stmt.kind
-                && let Local { pat, init: Some(init), .. } = local
-                && let PatKind::Binding(_, _, ident, _) = pat.kind
+        for stmt in block.stmts {
+            if stmt.span.from_expansion() {
+                return;
+            }
+
+            if let StmtKind::Local(local) = stmt.kind
+                && let Local {
+                    pat, init: Some(init), ..
+                } = local
+                && let PatKind::Binding(_, id, ident, _) = pat.kind
                 && let Some(vec_init_kind) = get_vec_init_kind(cx, init)
             {
-                let visitor = |expr: &Expr<'_>| {
-                    if let ExprKind::MethodCall(path, _, [arg], _) = expr.kind
-                        && let PathSegment {
-                            ident: read_or_read_exact,
-                            ..
-                        } = *path
-                        && matches!(read_or_read_exact.as_str(), "read" | "read_exact")
-                        && let ExprKind::AddrOf(_, hir::Mutability::Mut, inner) = arg.kind
-                        && let ExprKind::Path(QPath::Resolved(None, inner_path)) = inner.kind
-                        && let [inner_seg] = inner_path.segments
-                        && ident.name == inner_seg.ident.name
-                    {
-                        ControlFlow::Break(())
-                    } else {
-                        ControlFlow::Continue(())
-                    }
+                let mut visitor = ReadVecVisitor {
+                    local_id: id,
+                    read_zero_expr: None,
+                    has_resize: false,
                 };
 
-                let (read_found, next_stmt_span) = if let Some(next_stmt) = block.stmts.get(idx + 1) {
-                    // case { .. stmt; stmt; .. }
-                    (for_each_expr(next_stmt, visitor).is_some(), next_stmt.span)
-                } else if let Some(e) = block.expr {
-                    // case { .. stmt; expr }
-                    (for_each_expr(e, visitor).is_some(), e.span)
-                } else {
+                let Some(enclosing_block) = get_enclosing_block(cx, id) else {
                     return;
                 };
+                visitor.visit_block(enclosing_block);
 
-                if read_found && !next_stmt_span.from_expansion() {
+                if let Some(expr) = visitor.read_zero_expr {
                     let applicability = Applicability::MaybeIncorrect;
                     match vec_init_kind {
                         VecInitKind::WithConstCapacity(len) => {
                             span_lint_and_sugg(
                                 cx,
                                 READ_ZERO_BYTE_VEC,
-                                next_stmt_span,
+                                expr.span,
                                 "reading zero byte data to `Vec`",
                                 "try",
-                                format!(
-                                    "{}.resize({len}, 0); {}",
-                                    ident.as_str(),
-                                    snippet(cx, next_stmt_span, "..")
-                                ),
+                                format!("{}.resize({len}, 0); {}", ident.as_str(), snippet(cx, expr.span, "..")),
                                 applicability,
                             );
                         },
@@ -108,25 +93,20 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
                             span_lint_and_sugg(
                                 cx,
                                 READ_ZERO_BYTE_VEC,
-                                next_stmt_span,
+                                expr.span,
                                 "reading zero byte data to `Vec`",
                                 "try",
                                 format!(
                                     "{}.resize({}, 0); {}",
                                     ident.as_str(),
                                     snippet(cx, e.span, ".."),
-                                    snippet(cx, next_stmt_span, "..")
+                                    snippet(cx, expr.span, "..")
                                 ),
                                 applicability,
                             );
                         },
                         _ => {
-                            span_lint(
-                                cx,
-                                READ_ZERO_BYTE_VEC,
-                                next_stmt_span,
-                                "reading zero byte data to `Vec`",
-                            );
+                            span_lint(cx, READ_ZERO_BYTE_VEC, expr.span, "reading zero byte data to `Vec`");
                         },
                     }
                 }
@@ -134,3 +114,47 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
         }
     }
 }
+
+struct ReadVecVisitor<'tcx> {
+    local_id: HirId,
+    read_zero_expr: Option<&'tcx Expr<'tcx>>,
+    has_resize: bool,
+}
+
+impl<'tcx> Visitor<'tcx> for ReadVecVisitor<'tcx> {
+    fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
+        if let ExprKind::MethodCall(path, receiver, args, _) = e.kind {
+            let PathSegment { ident, .. } = *path;
+
+            match ident.as_str() {
+                "read" | "read_exact" => {
+                    let [arg] = args else { return };
+                    if let ExprKind::AddrOf(_, hir::Mutability::Mut, inner) = arg.kind
+                        && let ExprKind::Path(QPath::Resolved(None, inner_path)) = inner.kind
+                        && let [inner_seg] = inner_path.segments
+                        && let Res::Local(res_id) = inner_seg.res
+                        && self.local_id == res_id
+                    {
+                        self.read_zero_expr = Some(e);
+                        return;
+                    }
+                },
+                "resize" => {
+                    // If the Vec is resized, then it's a valid read
+                    if let ExprKind::Path(QPath::Resolved(_, inner_path)) = receiver.kind
+                        && let Res::Local(res_id) = inner_path.res
+                        && self.local_id == res_id
+                    {
+                        self.has_resize = true;
+                        return;
+                    }
+                },
+                _ => {},
+            }
+        }
+
+        if !self.has_resize && self.read_zero_expr.is_none() {
+            walk_expr(self, e);
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
index 2cd3e57f885..6540626f7d5 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
@@ -5,6 +5,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Block, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
+use rustc_span::{ExpnKind, MacroKind, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -39,6 +40,7 @@ impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned {
     fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
         if !block.span.from_expansion()
             && let Some(expr) = block.expr
+            && !from_attr_macro(expr.span)
             && let t_expr = cx.typeck_results().expr_ty(expr)
             && t_expr.is_unit()
             && let mut app = Applicability::MachineApplicable
@@ -63,3 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned {
         }
     }
 }
+
+fn from_attr_macro(span: Span) -> bool {
+    matches!(span.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Attr, _))
+}
diff --git a/src/tools/clippy/clippy_lints/src/single_call_fn.rs b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
index 8e181c3ccc7..03877420774 100644
--- a/src/tools/clippy/clippy_lints/src/single_call_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/single_call_fn.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_hir_and_then;
 use clippy_utils::{is_from_proc_macro, is_in_test_function};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::LocalDefId;
@@ -88,16 +88,18 @@ impl<'tcx> LateLintPass<'tcx> for SingleCallFn {
         };
         cx.tcx.hir().visit_all_item_likes_in_crate(&mut v);
 
-        for usage in self.def_id_to_usage.values() {
+        for (&def_id, usage) in &self.def_id_to_usage {
             let single_call_fn_span = usage.0;
             if let [caller_span] = *usage.1 {
-                span_lint_and_help(
+                span_lint_hir_and_then(
                     cx,
                     SINGLE_CALL_FN,
+                    cx.tcx.local_def_id_to_hir_id(def_id),
                     single_call_fn_span,
                     "this function is only used once",
-                    Some(caller_span),
-                    "used here",
+                    |diag| {
+                        diag.span_help(caller_span, "used here");
+                    },
                 );
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index e4054393d0a..768623b5d03 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -390,6 +390,14 @@ fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &'
     }
 }
 
+fn get_ty_res(ty: Ty<'_>) -> Option<Res> {
+    match ty.kind {
+        TyKind::Path(QPath::Resolved(_, path)) => Some(path.res),
+        TyKind::Path(QPath::TypeRelative(ty, _)) => get_ty_res(*ty),
+        _ => None,
+    }
+}
+
 // FIXME: ComparableTraitRef does not support nested bounds needed for associated_type_bounds
 fn into_comparable_trait_ref(trait_ref: &TraitRef<'_>) -> ComparableTraitRef {
     ComparableTraitRef(
@@ -401,10 +409,8 @@ fn into_comparable_trait_ref(trait_ref: &TraitRef<'_>) -> ComparableTraitRef {
             .filter_map(|segment| {
                 // get trait bound type arguments
                 Some(segment.args?.args.iter().filter_map(|arg| {
-                    if let GenericArg::Type(ty) = arg
-                        && let TyKind::Path(QPath::Resolved(_, path)) = ty.kind
-                    {
-                        return Some(path.res);
+                    if let GenericArg::Type(ty) = arg {
+                        return get_ty_res(**ty);
                     }
                     None
                 }))
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
index 7d31c375f8c..2a6c2481254 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
@@ -1,6 +1,6 @@
 use super::TRANSMUTE_INT_TO_CHAR;
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::sugg;
+use clippy_utils::{std_or_core, sugg};
 use rustc_ast as ast;
 use rustc_errors::Applicability;
 use rustc_hir::Expr;
@@ -25,6 +25,7 @@ pub(super) fn check<'tcx>(
                 e.span,
                 &format!("transmute from a `{from_ty}` to a `char`"),
                 |diag| {
+                    let Some(top_crate) = std_or_core(cx) else { return };
                     let arg = sugg::Sugg::hir(cx, arg, "..");
                     let arg = if let ty::Int(_) = from_ty.kind() {
                         arg.as_ty(ast::UintTy::U32.name_str())
@@ -34,7 +35,7 @@ pub(super) fn check<'tcx>(
                     diag.span_suggestion(
                         e.span,
                         "consider using",
-                        format!("std::char::from_u32({arg}).unwrap()"),
+                        format!("{top_crate}::char::from_u32({arg}).unwrap()"),
                         Applicability::Unspecified,
                     );
                 },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
index 5df645491ff..97068efd43c 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
@@ -16,40 +16,55 @@ pub(super) fn check<'tcx>(
     to_ty: Ty<'tcx>,
     arg: &'tcx Expr<'_>,
 ) -> bool {
-    let (ty::Int(_) | ty::Uint(_), Some(to_ty_adt)) = (&from_ty.kind(), to_ty.ty_adt_def()) else {
+    let tcx = cx.tcx;
+
+    let (ty::Int(_) | ty::Uint(_), ty::Adt(adt, substs)) = (&from_ty.kind(), to_ty.kind()) else {
         return false;
     };
-    let Some(to_type_sym) = cx.tcx.get_diagnostic_name(to_ty_adt.did()) else {
+
+    if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) {
         return false;
     };
 
-    if !matches!(
-        to_type_sym,
-        sym::NonZeroU8
-            | sym::NonZeroU16
-            | sym::NonZeroU32
-            | sym::NonZeroU64
-            | sym::NonZeroU128
-            | sym::NonZeroI8
-            | sym::NonZeroI16
-            | sym::NonZeroI32
-            | sym::NonZeroI64
-            | sym::NonZeroI128
-    ) {
+    // FIXME: This can be simplified once `NonZero<T>` is stable.
+    let coercable_types = [
+        ("NonZeroU8", tcx.types.u8),
+        ("NonZeroU16", tcx.types.u16),
+        ("NonZeroU32", tcx.types.u32),
+        ("NonZeroU64", tcx.types.u64),
+        ("NonZeroU128", tcx.types.u128),
+        ("NonZeroUsize", tcx.types.usize),
+        ("NonZeroI8", tcx.types.i8),
+        ("NonZeroI16", tcx.types.i16),
+        ("NonZeroI32", tcx.types.i32),
+        ("NonZeroI64", tcx.types.i64),
+        ("NonZeroI128", tcx.types.i128),
+        ("NonZeroIsize", tcx.types.isize),
+    ];
+
+    let int_type = substs.type_at(0);
+
+    let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| {
+        if *t == int_type && *t == from_ty {
+            Some(nonzero_alias)
+        } else {
+            None
+        }
+    }) else {
         return false;
-    }
+    };
 
     span_lint_and_then(
         cx,
         TRANSMUTE_INT_TO_NON_ZERO,
         e.span,
-        &format!("transmute from a `{from_ty}` to a `{to_type_sym}`"),
+        &format!("transmute from a `{from_ty}` to a `{nonzero_alias}`"),
         |diag| {
             let arg = sugg::Sugg::hir(cx, arg, "..");
             diag.span_suggestion(
                 e.span,
                 "consider using",
-                format!("{to_type_sym}::{}({arg})", sym::new_unchecked),
+                format!("{nonzero_alias}::{}({arg})", sym::new_unchecked),
                 Applicability::Unspecified,
             );
         },
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
index 98e9ea2d775..6c885ebdea1 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs
@@ -1,7 +1,7 @@
 use super::{TRANSMUTE_BYTES_TO_STR, TRANSMUTE_PTR_TO_PTR};
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet;
-use clippy_utils::sugg;
+use clippy_utils::{std_or_core, sugg};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, Mutability};
 use rustc_lint::LateContext;
@@ -25,6 +25,8 @@ pub(super) fn check<'tcx>(
             && let ty::Uint(ty::UintTy::U8) = slice_ty.kind()
             && from_mutbl == to_mutbl
         {
+            let Some(top_crate) = std_or_core(cx) else { return true };
+
             let postfix = if *from_mutbl == Mutability::Mut { "_mut" } else { "" };
 
             let snippet = snippet(cx, arg.span, "..");
@@ -36,9 +38,9 @@ pub(super) fn check<'tcx>(
                 &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
                 "consider using",
                 if const_context {
-                    format!("std::str::from_utf8_unchecked{postfix}({snippet})")
+                    format!("{top_crate}::str::from_utf8_unchecked{postfix}({snippet})")
                 } else {
-                    format!("std::str::from_utf8{postfix}({snippet}).unwrap()")
+                    format!("{top_crate}::str::from_utf8{postfix}({snippet}).unwrap()")
                 },
                 Applicability::MaybeIncorrect,
             );
diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
index b418db53ea4..209035804e4 100644
--- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
+++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs
@@ -167,7 +167,15 @@ fn check_partial_eq(cx: &LateContext<'_>, method_span: Span, method_def_id: Loca
                     false
                 }
             },
-            ExprKind::MethodCall(segment, _receiver, &[_arg], _) if segment.ident.name == name.name => {
+            ExprKind::MethodCall(segment, receiver, &[_arg], _) if segment.ident.name == name.name => {
+                if let Some(ty) = cx.typeck_results().expr_ty_opt(receiver)
+                    && let Some(ty_id) = get_ty_def_id(ty)
+                    && self_arg != ty_id
+                {
+                    // Since this called on a different type, the lint should not be
+                    // triggered here.
+                    return;
+                }
                 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
diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
index 1de9adfcb96..adc66e15ff5 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -1,9 +1,10 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use clippy_utils::{is_trait_method, is_try, match_trait_method, paths};
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::{is_res_lang_ctor, is_trait_method, match_trait_method, paths};
+use hir::{ExprKind, PatKind};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::sym;
+use rustc_span::{sym, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -45,126 +46,219 @@ declare_clippy_lint! {
 
 declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]);
 
+#[derive(Copy, Clone)]
+enum IoOp {
+    AsyncWrite(bool),
+    AsyncRead(bool),
+    SyncRead(bool),
+    SyncWrite(bool),
+}
+
 impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
-    fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
-        let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = s.kind else {
-            return;
-        };
+    /// We perform the check on the block level.
+    /// If we want to catch match and if expressions that act as returns of the block
+    ///   we need to check them at `check_expr` or `check_block` as they are not stmts
+    ///   but we can't check them at `check_expr` because we need the broader context
+    ///   because we should do this only for the final expression of the block, and not for
+    ///   `StmtKind::Local` which binds values => the io amount is used.
+    ///
+    /// To check for unused io amount in stmts, we only consider `StmtKind::Semi`.
+    /// `StmtKind::Local` is not considered because it binds values => the io amount is used.
+    /// `StmtKind::Expr` is not considered because requires unit type => the io amount is used.
+    /// `StmtKind::Item` is not considered because it's not an expression.
+    ///
+    /// We then check the individual expressions via `check_expr`. We use the same logic for
+    /// semi expressions and the final expression as we need to check match and if expressions
+    /// for binding of the io amount to `Ok(_)`.
+    ///
+    /// We explicitly check for the match source to be Normal as it needs special logic
+    /// to consider the arms, and we want to avoid breaking the logic for situations where things
+    /// get desugared to match.
+    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'tcx>) {
+        for stmt in block.stmts {
+            if let hir::StmtKind::Semi(exp) = stmt.kind {
+                check_expr(cx, exp);
+            }
+        }
 
-        match expr.kind {
-            hir::ExprKind::Match(res, _, _) if is_try(cx, expr).is_some() => {
-                if let hir::ExprKind::Call(func, [ref arg_0, ..]) = res.kind {
-                    if matches!(
-                        func.kind,
-                        hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..))
-                    ) {
-                        check_map_error(cx, arg_0, expr);
+        if let Some(exp) = block.expr
+            && matches!(exp.kind, hir::ExprKind::If(_, _, _) | hir::ExprKind::Match(_, _, _))
+        {
+            check_expr(cx, exp);
+        }
+    }
+}
+
+fn check_expr<'a>(cx: &LateContext<'a>, expr: &'a hir::Expr<'a>) {
+    match expr.kind {
+        hir::ExprKind::If(cond, _, _)
+            if let ExprKind::Let(hir::Let { pat, init, .. }) = cond.kind
+                && pattern_is_ignored_ok(cx, pat)
+                && let Some(op) = should_lint(cx, init) =>
+        {
+            emit_lint(cx, cond.span, op, &[pat.span]);
+        },
+        hir::ExprKind::Match(expr, arms, hir::MatchSource::Normal) if let Some(op) = should_lint(cx, expr) => {
+            let found_arms: Vec<_> = arms
+                .iter()
+                .filter_map(|arm| {
+                    if pattern_is_ignored_ok(cx, arm.pat) {
+                        Some(arm.span)
+                    } else {
+                        None
                     }
-                } else {
-                    check_map_error(cx, res, expr);
-                }
-            },
-            hir::ExprKind::MethodCall(path, arg_0, ..) => match path.ident.as_str() {
-                "expect" | "unwrap" | "unwrap_or" | "unwrap_or_else" | "is_ok" | "is_err" => {
-                    check_map_error(cx, arg_0, expr);
-                },
-                _ => (),
-            },
-            _ => (),
+                })
+                .collect();
+            if !found_arms.is_empty() {
+                emit_lint(cx, expr.span, op, found_arms.as_slice());
+            }
+        },
+        _ if let Some(op) = should_lint(cx, expr) => {
+            emit_lint(cx, expr.span, op, &[]);
+        },
+        _ => {},
+    };
+}
+
+fn should_lint<'a>(cx: &LateContext<'a>, mut inner: &'a hir::Expr<'a>) -> Option<IoOp> {
+    inner = unpack_match(inner);
+    inner = unpack_try(inner);
+    inner = unpack_call_chain(inner);
+    inner = unpack_await(inner);
+    // we type-check it to get whether it's a read/write or their vectorized forms
+    // and keep only the ones that are produce io amount
+    check_io_mode(cx, inner)
+}
+
+fn pattern_is_ignored_ok(cx: &LateContext<'_>, pat: &hir::Pat<'_>) -> bool {
+    // the if checks whether we are in a result Ok( ) pattern
+    // and the return checks whether it is unhandled
+
+    if let PatKind::TupleStruct(ref path, inner_pat, ddp) = pat.kind
+        // we check against Result::Ok to avoid linting on Err(_) or something else.
+        && is_res_lang_ctor(cx, cx.qpath_res(path, pat.hir_id), hir::LangItem::ResultOk)
+    {
+        return match (inner_pat, ddp.as_opt_usize()) {
+            // Ok(_) pattern
+            ([inner_pat], None) if matches!(inner_pat.kind, PatKind::Wild) => true,
+            // Ok(..) pattern
+            ([], Some(0)) => true,
+            _ => false,
+        };
+    }
+    false
+}
+
+fn unpack_call_chain<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
+    while let hir::ExprKind::MethodCall(path, receiver, ..) = expr.kind {
+        if matches!(
+            path.ident.as_str(),
+            "unwrap" | "expect" | "unwrap_or" | "unwrap_or_else" | "ok" | "is_ok" | "is_err" | "or_else" | "or"
+        ) {
+            expr = receiver;
+        } else {
+            break;
         }
     }
+    expr
+}
+
+fn unpack_try<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
+    while let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind
+        && matches!(
+            func.kind,
+            hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::TryTraitBranch, ..))
+        )
+    {
+        expr = arg_0;
+    }
+    expr
+}
+
+fn unpack_match<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> {
+    while let hir::ExprKind::Match(res, _, _) = expr.kind {
+        expr = res;
+    }
+    expr
 }
 
 /// If `expr` is an (e).await, return the inner expression "e" that's being
 /// waited on.  Otherwise return None.
-fn try_remove_await<'a>(expr: &'a hir::Expr<'a>) -> Option<&hir::Expr<'a>> {
+fn unpack_await<'a>(expr: &'a hir::Expr<'a>) -> &hir::Expr<'a> {
     if let hir::ExprKind::Match(expr, _, hir::MatchSource::AwaitDesugar) = expr.kind {
         if let hir::ExprKind::Call(func, [ref arg_0, ..]) = expr.kind {
             if matches!(
                 func.kind,
                 hir::ExprKind::Path(hir::QPath::LangItem(hir::LangItem::IntoFutureIntoFuture, ..))
             ) {
-                return Some(arg_0);
+                return arg_0;
             }
         }
     }
-
-    None
+    expr
 }
 
-fn check_map_error(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>) {
-    let mut call = call;
-    while let hir::ExprKind::MethodCall(path, receiver, ..) = call.kind {
-        if matches!(path.ident.as_str(), "or" | "or_else" | "ok") {
-            call = receiver;
-        } else {
-            break;
-        }
-    }
+/// Check whether the current expr is a function call for an IO operation
+fn check_io_mode(cx: &LateContext<'_>, call: &hir::Expr<'_>) -> Option<IoOp> {
+    let hir::ExprKind::MethodCall(path, ..) = call.kind else {
+        return None;
+    };
 
-    if let Some(call) = try_remove_await(call) {
-        check_method_call(cx, call, expr, true);
-    } else {
-        check_method_call(cx, call, expr, false);
+    let vectorized = match path.ident.as_str() {
+        "write_vectored" | "read_vectored" => true,
+        "write" | "read" => false,
+        _ => {
+            return None;
+        },
+    };
+
+    match (
+        is_trait_method(cx, call, sym::IoRead),
+        is_trait_method(cx, call, sym::IoWrite),
+        match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT)
+            || match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCREADEXT),
+        match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCWRITEEXT)
+            || match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCWRITEEXT),
+    ) {
+        (true, _, _, _) => Some(IoOp::SyncRead(vectorized)),
+        (_, true, _, _) => Some(IoOp::SyncWrite(vectorized)),
+        (_, _, true, _) => Some(IoOp::AsyncRead(vectorized)),
+        (_, _, _, true) => Some(IoOp::AsyncWrite(vectorized)),
+        _ => None,
     }
 }
 
-fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Expr<'_>, is_await: bool) {
-    if let hir::ExprKind::MethodCall(path, ..) = call.kind {
-        let symbol = path.ident.as_str();
-        let read_trait = if is_await {
-            match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT)
-                || match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCREADEXT)
-        } else {
-            is_trait_method(cx, call, sym::IoRead)
-        };
-        let write_trait = if is_await {
-            match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCWRITEEXT)
-                || match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCWRITEEXT)
-        } else {
-            is_trait_method(cx, call, sym::IoWrite)
-        };
+fn emit_lint(cx: &LateContext<'_>, span: Span, op: IoOp, wild_cards: &[Span]) {
+    let (msg, help) = match op {
+        IoOp::AsyncRead(false) => (
+            "read amount is not handled",
+            Some("use `AsyncReadExt::read_exact` instead, or handle partial reads"),
+        ),
+        IoOp::SyncRead(false) => (
+            "read amount is not handled",
+            Some("use `Read::read_exact` instead, or handle partial reads"),
+        ),
+        IoOp::SyncWrite(false) => (
+            "written amount is not handled",
+            Some("use `Write::write_all` instead, or handle partial writes"),
+        ),
+        IoOp::AsyncWrite(false) => (
+            "written amount is not handled",
+            Some("use `AsyncWriteExt::write_all` instead, or handle partial writes"),
+        ),
+        IoOp::SyncRead(true) | IoOp::AsyncRead(true) => ("read amount is not handled", None),
+        IoOp::SyncWrite(true) | IoOp::AsyncWrite(true) => ("written amount is not handled", None),
+    };
 
-        match (read_trait, write_trait, symbol, is_await) {
-            (true, _, "read", false) => span_lint_and_help(
-                cx,
-                UNUSED_IO_AMOUNT,
-                expr.span,
-                "read amount is not handled",
-                None,
-                "use `Read::read_exact` instead, or handle partial reads",
-            ),
-            (true, _, "read", true) => span_lint_and_help(
-                cx,
-                UNUSED_IO_AMOUNT,
-                expr.span,
-                "read amount is not handled",
-                None,
-                "use `AsyncReadExt::read_exact` instead, or handle partial reads",
-            ),
-            (true, _, "read_vectored", _) => {
-                span_lint(cx, UNUSED_IO_AMOUNT, expr.span, "read amount is not handled");
-            },
-            (_, true, "write", false) => span_lint_and_help(
-                cx,
-                UNUSED_IO_AMOUNT,
-                expr.span,
-                "written amount is not handled",
-                None,
-                "use `Write::write_all` instead, or handle partial writes",
-            ),
-            (_, true, "write", true) => span_lint_and_help(
-                cx,
-                UNUSED_IO_AMOUNT,
-                expr.span,
-                "written amount is not handled",
-                None,
-                "use `AsyncWriteExt::write_all` instead, or handle partial writes",
-            ),
-            (_, true, "write_vectored", _) => {
-                span_lint(cx, UNUSED_IO_AMOUNT, expr.span, "written amount is not handled");
-            },
-            _ => (),
+    span_lint_and_then(cx, UNUSED_IO_AMOUNT, span, msg, |diag| {
+        if let Some(help_str) = help {
+            diag.help(help_str);
         }
-    }
+        for span in wild_cards {
+            diag.span_note(
+                *span,
+                "the result is consumed here, but the amount of I/O bytes remains unhandled",
+            );
+        }
+    });
 }
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
index 5ddedb24b15..4822970e47e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/almost_standard_lint_formulation.rs
@@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for AlmostStandardFormulation {
                                         ident.span,
                                         "non-standard lint formulation",
                                         None,
-                                        &format!("try using `{}` instead", formulation.correction),
+                                        &format!("consider using `{}`", formulation.correction),
                                     );
                                 }
                                 return;
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
index 4fb615e1d57..c62ae8d718d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -71,7 +71,9 @@ pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
         SimplifiedType::Str,
     ]
     .iter()
-    .flat_map(|&ty| cx.tcx.incoherent_impls(ty).iter().copied());
+    .flat_map(|&ty| cx.tcx.incoherent_impls(ty).into_iter())
+    .flatten()
+    .copied();
     for item_def_id in lang_items.iter().map(|(_, def_id)| def_id).chain(incoherent_impls) {
         let lang_item_path = cx.get_def_path(item_def_id);
         if path_syms.starts_with(&lang_item_path) {
diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs
index ad8619f0d3d..2d0c2cf1253 100644
--- a/src/tools/clippy/clippy_utils/src/attrs.rs
+++ b/src/tools/clippy/clippy_utils/src/attrs.rs
@@ -1,5 +1,6 @@
 use rustc_ast::{ast, attr};
 use rustc_errors::Applicability;
+use rustc_middle::ty::{AdtDef, TyCtxt};
 use rustc_session::Session;
 use rustc_span::sym;
 use std::str::FromStr;
@@ -159,3 +160,14 @@ pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool {
         .filter_map(ast::Attribute::meta_item_list)
         .any(|l| attr::list_contains_name(&l, sym::hidden))
 }
+
+pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool {
+    adt.is_variant_list_non_exhaustive()
+        || tcx.has_attr(adt.did(), sym::non_exhaustive)
+        || adt.variants().iter().any(|variant_def| {
+            variant_def.is_field_list_non_exhaustive() || tcx.has_attr(variant_def.def_id, sym::non_exhaustive)
+        })
+        || adt
+            .all_fields()
+            .any(|field_def| tcx.has_attr(field_def.did, sym::non_exhaustive))
+}
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 979b117db25..4fa93ad23c3 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -134,7 +134,7 @@ impl HirEqInterExpr<'_, '_, '_> {
     /// Checks whether two blocks are the same.
     #[expect(clippy::similar_names)]
     fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool {
-        use TokenKind::{BlockComment, LineComment, Semi, Whitespace};
+        use TokenKind::{Semi, Whitespace};
         if left.stmts.len() != right.stmts.len() {
             return false;
         }
@@ -177,7 +177,7 @@ impl HirEqInterExpr<'_, '_, '_> {
                 return false;
             }
             if !eq_span_tokens(self.inner.cx, lstart..lstmt_span.lo, rstart..rstmt_span.lo, |t| {
-                !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+                !matches!(t, Whitespace | Semi)
             }) {
                 return false;
             }
@@ -212,7 +212,7 @@ impl HirEqInterExpr<'_, '_, '_> {
             return false;
         }
         eq_span_tokens(self.inner.cx, lstart..lend, rstart..rend, |t| {
-            !matches!(t, Whitespace | LineComment { .. } | BlockComment { .. } | Semi)
+            !matches!(t, Whitespace | Semi)
         })
     }
 
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index ebe520b27eb..4e499ff4cc6 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -536,7 +536,12 @@ fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<It
         "f32" => SimplifiedType::Float(FloatTy::F32),
         "f64" => SimplifiedType::Float(FloatTy::F64),
         #[allow(trivial_casts)]
-        _ => return Result::<_, rustc_errors::ErrorGuaranteed>::Ok(&[] as &[_]).into_iter().flatten().copied(),
+        _ => {
+            return Result::<_, rustc_errors::ErrorGuaranteed>::Ok(&[] as &[_])
+                .into_iter()
+                .flatten()
+                .copied();
+        },
     };
 
     tcx.incoherent_impls(ty).into_iter().flatten().copied()
@@ -1712,7 +1717,6 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
         PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable.
         PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)),
         PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
-        PatKind::Lit(..) | PatKind::Range(..) => true,
         PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
         PatKind::Or(pats) => {
             // TODO: should be the honest check, that pats is exhaustive set
@@ -1736,7 +1740,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
                 },
             }
         },
-        PatKind::Err(_) => true,
+        PatKind::Lit(..) | PatKind::Range(..) | PatKind::Err(_) => true,
     }
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 0a820a1754c..0051f784514 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -26,6 +26,7 @@ pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
 pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
 pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
+pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
@@ -50,6 +51,7 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
 pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
 pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
+pub const OPEN_OPTIONS_NEW: [&str; 4] = ["std", "fs", "OpenOptions", "new"];
 pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
 pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
@@ -89,9 +91,15 @@ pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol",
 pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
 pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
+pub const TOKIO_FILE_OPTIONS: [&str; 5] = ["tokio", "fs", "file", "File", "options"];
+#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_ASYNCREADEXT: [&str; 5] = ["tokio", "io", "util", "async_read_ext", "AsyncReadExt"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_write_ext", "AsyncWriteExt"];
+#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
+pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "OpenOptions"];
+#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
+pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
 pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
 pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
 pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"];
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 59ebe685c11..11bb16ff6c5 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -219,7 +219,8 @@ pub fn implements_trait<'tcx>(
 
 /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
 ///
-/// The `callee_id` argument is used to determine whether this is a function call in a `const fn` environment, used for checking const traits.
+/// The `callee_id` argument is used to determine whether this is a function call in a `const fn`
+/// environment, used for checking const traits.
 pub fn implements_trait_with_env<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ParamEnv<'tcx>,
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index 2589d46e7da..d2d56e59ee3 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-01-11"
+channel = "nightly-2024-01-25"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.stderr b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.stderr
new file mode 100644
index 00000000000..8f0ca764924
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.stderr
@@ -0,0 +1,6 @@
+error: multiple versions for dependency `winapi`: 0.2.8, 0.3.9
+  |
+  = note: `-D clippy::multiple-crate-versions` implied by `-D warnings`
+  = help: to override `-D warnings` add `#[allow(clippy::multiple_crate_versions)]`
+
+error: could not compile `multiple-crate-versions` (bin "multiple-crate-versions") due to 1 previous error
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.toml b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.toml
new file mode 100644
index 00000000000..d39ad6c909a
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.toml
@@ -0,0 +1,14 @@
+# Should not lint for dev or build dependencies. See issue 5041.
+
+[package]
+# purposefully separated by - instead of _
+name = "multiple-crate-versions"
+version = "0.1.0"
+publish = false
+
+[workspace]
+
+# One of the versions of winapi is only a dev dependency: allowed
+[dependencies]
+winapi = "0.2"
+ansi_term = "=0.11.0"
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/src/main.rs b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/src/main.rs
new file mode 100644
index 00000000000..4bc61dd6299
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/src/main.rs
@@ -0,0 +1,3 @@
+#![warn(clippy::multiple_crate_versions)]
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml
new file mode 100644
index 00000000000..79317659ac0
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "multiple_crate_versions"
+version = "0.1.0"
+publish = false
+
+[workspace]
+
+[dependencies]
+winapi = "0.2"
+ansi_term = "=0.11.0"
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/clippy.toml b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/clippy.toml
new file mode 100644
index 00000000000..121361de2fe
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/clippy.toml
@@ -0,0 +1 @@
+allowed-duplicate-crates = ["winapi"]
diff --git a/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/src/main.rs b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/src/main.rs
new file mode 100644
index 00000000000..4bc61dd6299
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/src/main.rs
@@ -0,0 +1,3 @@
+#![warn(clippy::multiple_crate_versions)]
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/check_formulation.stderr b/src/tools/clippy/tests/ui-internal/check_formulation.stderr
index 96fa617601f..42a872d9a83 100644
--- a/src/tools/clippy/tests/ui-internal/check_formulation.stderr
+++ b/src/tools/clippy/tests/ui-internal/check_formulation.stderr
@@ -4,7 +4,7 @@ error: non-standard lint formulation
 LL |     /// Check for lint formulations that are correct
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: try using `Checks for` instead
+   = help: consider using `Checks for`
    = note: `-D clippy::almost-standard-lint-formulation` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::almost_standard_lint_formulation)]`
 
@@ -14,7 +14,7 @@ error: non-standard lint formulation
 LL |     /// Detects uses of incorrect formulations
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: try using `Checks for` instead
+   = help: consider using `Checks for`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
index 03556823a8f..5ca183d41a9 100644
--- a/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
+++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr
@@ -1,5 +1,5 @@
 error: use of a disallowed method `rustc_lint::context::LintContext::span_lint`
-  --> $DIR/disallow_struct_span_lint.rs:14:5
+  --> $DIR/disallow_span_lint.rs:14:5
    |
 LL |     cx.span_lint(lint, span, msg, |_| {});
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,10 +8,10 @@ LL |     cx.span_lint(lint, span, msg, |_| {});
    = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]`
 
 error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint`
-  --> $DIR/disallow_struct_span_lint.rs:24:5
+  --> $DIR/disallow_span_lint.rs:24:5
    |
 LL |     tcx.node_span_lint(lint, hir_id, span, msg, |_| {});
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
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
index 94a0d3554bc..9e472bd14ba 100644
--- 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
@@ -1 +1 @@
-pub-underscore-fields-behavior = "PublicallyExported"
\ No newline at end of file
+pub-underscore-fields-behavior = "PubliclyExported"
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/clippy.toml b/src/tools/clippy/tests/ui-toml/toml_unknown_key/clippy.toml
index b77b4580051..2b63f6e5c26 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/clippy.toml
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/clippy.toml
@@ -3,6 +3,9 @@ foobar = 42
 # so is this one
 barfoo = 53
 
+# when using underscores instead of dashes, suggest the correct one
+allow_mixed_uninlined_format_args = true
+
 # that one is ignored
 [third-party]
 clippy-feature = "nightly"
diff --git a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs
index 38009627757..49139b60a9f 100644
--- a/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.rs
@@ -1,3 +1,4 @@
+//@no-rustfix
 //@error-in-other-file: unknown field `foobar`, expected one of
 
 fn main() {}
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 ed4fb84df1a..fc683e514ba 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
@@ -11,6 +11,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            allow-private-module-inception
            allow-unwrap-in-tests
            allowed-dotfiles
+           allowed-duplicate-crates
            allowed-idents-below-min-chars
            allowed-scripts
            arithmetic-side-effects-allowed
@@ -87,6 +88,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            allow-private-module-inception
            allow-unwrap-in-tests
            allowed-dotfiles
+           allowed-duplicate-crates
            allowed-idents-below-min-chars
            allowed-scripts
            arithmetic-side-effects-allowed
@@ -150,5 +152,82 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
 LL | barfoo = 53
    | ^^^^^^
 
-error: aborting due to 2 previous errors
+error: error reading Clippy's configuration file: unknown field `allow_mixed_uninlined_format_args`, expected one of
+           absolute-paths-allowed-crates
+           absolute-paths-max-segments
+           accept-comment-above-attributes
+           accept-comment-above-statement
+           allow-dbg-in-tests
+           allow-expect-in-tests
+           allow-mixed-uninlined-format-args
+           allow-one-hash-in-raw-strings
+           allow-print-in-tests
+           allow-private-module-inception
+           allow-unwrap-in-tests
+           allowed-dotfiles
+           allowed-duplicate-crates
+           allowed-idents-below-min-chars
+           allowed-scripts
+           arithmetic-side-effects-allowed
+           arithmetic-side-effects-allowed-binary
+           arithmetic-side-effects-allowed-unary
+           array-size-threshold
+           avoid-breaking-exported-api
+           await-holding-invalid-types
+           blacklisted-names
+           cargo-ignore-publish
+           check-private-items
+           cognitive-complexity-threshold
+           cyclomatic-complexity-threshold
+           disallowed-macros
+           disallowed-methods
+           disallowed-names
+           disallowed-types
+           doc-valid-idents
+           enable-raw-pointer-heuristic-for-send
+           enforce-iter-loop-reborrow
+           enforced-import-renames
+           enum-variant-name-threshold
+           enum-variant-size-threshold
+           excessive-nesting-threshold
+           future-size-threshold
+           ignore-interior-mutability
+           large-error-threshold
+           literal-representation-threshold
+           matches-for-let-else
+           max-fn-params-bools
+           max-include-file-size
+           max-struct-bools
+           max-suggested-slice-pattern-length
+           max-trait-bounds
+           min-ident-chars-threshold
+           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
+           stack-size-threshold
+           standard-macro-braces
+           struct-field-name-threshold
+           suppress-restriction-lint-in-const
+           third-party
+           too-large-for-stack
+           too-many-arguments-threshold
+           too-many-lines-threshold
+           trivial-copy-size-limit
+           type-complexity-threshold
+           unnecessary-box-size
+           unreadable-literal-lint-fractions
+           upper-case-acronyms-aggressive
+           vec-box-size-threshold
+           verbose-bit-mask-threshold
+           warn-on-all-wildcard-imports
+  --> $DIR/$DIR/clippy.toml:7:1
+   |
+LL | allow_mixed_uninlined_format_args = true
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: perhaps you meant: `allow-mixed-uninlined-format-args`
+
+error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
index c5879557516..ac544737099 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
@@ -11,8 +11,8 @@ use quote::{quote, quote_spanned};
 use syn::spanned::Spanned;
 use syn::token::Star;
 use syn::{
-    parse_macro_input, parse_quote, FnArg, ImplItem, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType, Signature,
-    TraitItem, Type,
+    parse_macro_input, parse_quote, FnArg, ImplItem, ItemFn, ItemImpl, ItemTrait, Lifetime, Pat, PatIdent, PatType,
+    Signature, TraitItem, Type,
 };
 
 #[proc_macro_attribute]
@@ -95,3 +95,33 @@ pub fn rename_my_lifetimes(_args: TokenStream, input: TokenStream) -> TokenStrea
 
     TokenStream::from(quote!(#item))
 }
+
+#[proc_macro_attribute]
+pub fn fake_main(_attr: TokenStream, item: TokenStream) -> TokenStream {
+    let mut item = parse_macro_input!(item as ItemFn);
+    let span = item.block.brace_token.span;
+
+    if item.sig.asyncness.is_some() {
+        item.sig.asyncness = None;
+    }
+
+    let crate_name = quote! { fake_crate };
+    let block = item.block;
+    item.block = syn::parse_quote_spanned! {
+        span =>
+        {
+            #crate_name::block_on(async {
+                #block
+            })
+        }
+    };
+
+    quote! {
+        mod #crate_name {
+            pub fn block_on<F: ::std::future::Future>(_fut: F) {}
+        }
+
+        #item
+    }
+    .into()
+}
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
index 2ab441bbd0c..efef60567a9 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.fixed
@@ -85,4 +85,18 @@ fn block_in_match_expr(num: i32) -> i32 {
     }
 }
 
+// issue #12162
+macro_rules! timed {
+    ($name:expr, $body:expr $(,)?) => {{
+        let __scope = ();
+        $body
+    }};
+}
+
+fn issue_12162() {
+    if timed!("check this!", false) {
+        println!();
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/blocks_in_conditions.rs b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
index dd5ae4fb486..8bd8a939eb1 100644
--- a/src/tools/clippy/tests/ui/blocks_in_conditions.rs
+++ b/src/tools/clippy/tests/ui/blocks_in_conditions.rs
@@ -85,4 +85,18 @@ fn block_in_match_expr(num: i32) -> i32 {
     }
 }
 
+// issue #12162
+macro_rules! timed {
+    ($name:expr, $body:expr $(,)?) => {{
+        let __scope = ();
+        $body
+    }};
+}
+
+fn issue_12162() {
+    if timed!("check this!", false) {
+        println!();
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs
index 44f8b2eabce..9af81f6f7cd 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs
@@ -9,17 +9,16 @@ fn simple_examples() {
 
     // Simple
     if true {
-        //~^ ERROR: all if blocks contain the same code at the start
         println!("Hello World!");
         println!("I'm branch nr: 1");
     } else {
         println!("Hello World!");
         println!("I'm branch nr: 2");
     }
+    //~^^^^^^^ ERROR: all if blocks contain the same code at the start
 
     // Else if
     if x == 0 {
-        //~^ ERROR: all if blocks contain the same code at the start
         let y = 9;
         println!("The value y was set to: `{}`", y);
         let _z = y;
@@ -38,6 +37,7 @@ fn simple_examples() {
 
         println!("Ha, Pascal allows you to start the array where you want")
     }
+    //~^^^^^^^^^^^^^^^^^^^ ERROR: all if blocks contain the same code at the start
 
     // Return a value
     let _ = if x == 7 {
@@ -60,7 +60,6 @@ fn simple_but_suggestion_is_invalid() {
     // Can't be automatically moved because used_value_name is getting used again
     let used_value_name = 19;
     if x == 10 {
-        //~^ ERROR: all if blocks contain the same code at the start
         let used_value_name = "Different type";
         println!("Str: {}", used_value_name);
         let _ = 1;
@@ -69,6 +68,7 @@ fn simple_but_suggestion_is_invalid() {
         println!("Str: {}", used_value_name);
         let _ = 2;
     }
+    //~^^^^^^^^^ ERROR: all if blocks contain the same code at the start
     let _ = used_value_name;
 
     // This can be automatically moved as `can_be_overridden` is not used again
@@ -101,11 +101,11 @@ fn check_if_same_than_else_mask() {
     }
 
     if x == 2019 {
-        //~^ ERROR: this `if` has identical blocks
         println!("This should trigger `IS_SAME_THAN_ELSE` as usual");
     } else {
         println!("This should trigger `IS_SAME_THAN_ELSE` as usual");
     }
+    //~^^^^^ ERROR: this `if` has identical blocks
 }
 
 #[allow(clippy::vec_init_then_push)]
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr
index 9d4d42fb689..317d1577226 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr
@@ -2,7 +2,6 @@ error: all if blocks contain the same code at the start
   --> $DIR/shared_at_top.rs:11:5
    |
 LL | /     if true {
-LL | |
 LL | |         println!("Hello World!");
    | |_________________________________^
    |
@@ -21,7 +20,6 @@ error: all if blocks contain the same code at the start
   --> $DIR/shared_at_top.rs:21:5
    |
 LL | /     if x == 0 {
-LL | |
 LL | |         let y = 9;
 LL | |         println!("The value y was set to: `{}`", y);
 LL | |         let _z = y;
@@ -54,7 +52,6 @@ error: all if blocks contain the same code at the start
   --> $DIR/shared_at_top.rs:62:5
    |
 LL | /     if x == 10 {
-LL | |
 LL | |         let used_value_name = "Different type";
 LL | |         println!("Str: {}", used_value_name);
    | |_____________________________________________^
@@ -105,13 +102,12 @@ error: this `if` has identical blocks
    |
 LL |       if x == 2019 {
    |  __________________^
-LL | |
 LL | |         println!("This should trigger `IS_SAME_THAN_ELSE` as usual");
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/shared_at_top.rs:106:12
+  --> $DIR/shared_at_top.rs:105:12
    |
 LL |       } else {
    |  ____________^
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs
index 2aeacb89c0c..b63819d7c39 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs
@@ -107,9 +107,9 @@ fn valid_examples() {
 
     // Let's test empty blocks
     if false {
-        //~^ ERROR: this `if` has identical blocks
     } else {
     }
+    //~^^^ ERROR: this `if` has identical blocks
 }
 
 /// This makes sure that the `if_same_then_else` masks the `shared_code_in_if_blocks` lint
@@ -119,7 +119,6 @@ fn trigger_other_lint() {
 
     // Same block
     if x == 0 {
-        //~^ ERROR: this `if` has identical blocks
         let u = 19;
         println!("How are u today?");
         let _ = "This is a string";
@@ -128,6 +127,7 @@ fn trigger_other_lint() {
         println!("How are u today?");
         let _ = "This is a string";
     }
+    //~^^^^^^^^^ ERROR: this `if` has identical blocks
 
     // Only same expression
     let _ = if x == 6 { 7 } else { 7 };
@@ -138,28 +138,24 @@ fn trigger_other_lint() {
         println!("Well I'm the most important block");
         "I'm a pretty string"
     } else if x == 68 {
-        //~^ ERROR: this `if` has identical blocks
         println!("I'm a doppelgänger");
-        // Don't listen to my clone below
 
         if y == 90 { "=^.^=" } else { ":D" }
     } else {
-        // Don't listen to my clone above
         println!("I'm a doppelgänger");
 
         if y == 90 { "=^.^=" } else { ":D" }
     };
+    //~^^^^^^^^^ ERROR: this `if` has identical blocks
 
     if x == 0 {
         println!("I'm single");
     } else if x == 68 {
-        //~^ ERROR: this `if` has identical blocks
         println!("I'm a doppelgänger");
-        // Don't listen to my clone below
     } else {
-        // Don't listen to my clone above
         println!("I'm a doppelgänger");
     }
+    //~^^^^^ ERROR: this `if` has identical blocks
 }
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr
index fcbf12235aa..0daf2ff6967 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr
@@ -3,12 +3,11 @@ error: this `if` has identical blocks
    |
 LL |       if false {
    |  ______________^
-LL | |
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/valid_if_blocks.rs:111:12
+  --> $DIR/valid_if_blocks.rs:110:12
    |
 LL |       } else {
    |  ____________^
@@ -25,7 +24,6 @@ error: this `if` has identical blocks
    |
 LL |       if x == 0 {
    |  _______________^
-LL | |
 LL | |         let u = 19;
 LL | |         println!("How are u today?");
 LL | |         let _ = "This is a string";
@@ -33,7 +31,7 @@ LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/valid_if_blocks.rs:126:12
+  --> $DIR/valid_if_blocks.rs:125:12
    |
 LL |       } else {
    |  ____________^
@@ -60,20 +58,17 @@ error: this `if` has identical blocks
    |
 LL |       } else if x == 68 {
    |  _______________________^
-LL | |
 LL | |         println!("I'm a doppelgänger");
-LL | |         // Don't listen to my clone below
 LL | |
 LL | |         if y == 90 { "=^.^=" } else { ":D" }
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/valid_if_blocks.rs:146:12
+  --> $DIR/valid_if_blocks.rs:144:12
    |
 LL |       } else {
    |  ____________^
-LL | |         // Don't listen to my clone above
 LL | |         println!("I'm a doppelgänger");
 LL | |
 LL | |         if y == 90 { "=^.^=" } else { ":D" }
@@ -81,22 +76,19 @@ LL | |     };
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/valid_if_blocks.rs:155:23
+  --> $DIR/valid_if_blocks.rs:153:23
    |
 LL |       } else if x == 68 {
    |  _______________________^
-LL | |
 LL | |         println!("I'm a doppelgänger");
-LL | |         // Don't listen to my clone below
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/valid_if_blocks.rs:159:12
+  --> $DIR/valid_if_blocks.rs:155:12
    |
 LL |       } else {
    |  ____________^
-LL | |         // Don't listen to my clone above
 LL | |         println!("I'm a doppelgänger");
 LL | |     }
    | |_____^
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9041.stderr b/src/tools/clippy/tests/ui/crashes/ice-9041.stderr
index 00b65f00d78..67589d1a8ab 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-9041.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-9041.stderr
@@ -2,7 +2,7 @@ error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/ice-9041.rs:5:19
    |
 LL |     things.iter().find(|p| is_thing_ready(p)).is_some()
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|p| is_thing_ready(&p))`
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|p| is_thing_ready(&p))`
    |
    = note: `-D clippy::search-is-some` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]`
diff --git a/src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.fixed b/src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.fixed
new file mode 100644
index 00000000000..7300bd9bd2a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.fixed
@@ -0,0 +1,28 @@
+#![warn(clippy::default_instead_of_iter_empty)]
+#![allow(dead_code)]
+#![feature(lang_items)]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+#[derive(Default)]
+struct Iter {
+    iter: core::iter::Empty<usize>,
+}
+
+fn main() {
+    // Do lint.
+    let _ = core::iter::empty::<usize>();
+    let _foo: core::iter::Empty<usize> = core::iter::empty();
+
+    // Do not lint.
+    let _ = Iter::default();
+}
diff --git a/src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.rs b/src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.rs
new file mode 100644
index 00000000000..0bc5c7169d1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.rs
@@ -0,0 +1,28 @@
+#![warn(clippy::default_instead_of_iter_empty)]
+#![allow(dead_code)]
+#![feature(lang_items)]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+#[derive(Default)]
+struct Iter {
+    iter: core::iter::Empty<usize>,
+}
+
+fn main() {
+    // Do lint.
+    let _ = core::iter::Empty::<usize>::default();
+    let _foo: core::iter::Empty<usize> = core::iter::Empty::default();
+
+    // Do not lint.
+    let _ = Iter::default();
+}
diff --git a/src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.stderr b/src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.stderr
new file mode 100644
index 00000000000..747a31ecbf3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/default_instead_of_iter_empty_no_std.stderr
@@ -0,0 +1,17 @@
+error: `core::iter::empty()` is the more idiomatic way
+  --> $DIR/default_instead_of_iter_empty_no_std.rs:23:13
+   |
+LL |     let _ = core::iter::Empty::<usize>::default();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::iter::empty::<usize>()`
+   |
+   = note: `-D clippy::default-instead-of-iter-empty` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::default_instead_of_iter_empty)]`
+
+error: `core::iter::empty()` is the more idiomatic way
+  --> $DIR/default_instead_of_iter_empty_no_std.rs:24:42
+   |
+LL |     let _foo: core::iter::Empty<usize> = core::iter::Empty::default();
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::iter::empty()`
+
+error: aborting due to 2 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 c364c683057..e7038082c08 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
@@ -216,4 +216,44 @@ mod type_already_inferred {
     }
 }
 
+mod issue12159 {
+    #![allow(non_upper_case_globals, clippy::exhaustive_structs)]
+    pub struct Foo;
+
+    static F: i32 = 1;
+    impl Foo {
+        const LIFE_u8: u8 = 42;
+        const LIFE_i8: i8 = 42;
+        const LIFE_u16: u16 = 42;
+        const LIFE_i16: i16 = 42;
+        const LIFE_u32: u32 = 42;
+        const LIFE_i32: i32 = 42;
+        const LIFE_u64: u64 = 42;
+        const LIFE_i64: i64 = 42;
+        const LIFE_u128: u128 = 42;
+        const LIFE_i128: i128 = 42;
+        const LIFE_usize: usize = 42;
+        const LIFE_isize: isize = 42;
+        const LIFE_f32: f32 = 42.;
+        const LIFE_f64: f64 = 42.;
+
+        const fn consts() {
+            const LIFE_u8: u8 = 42;
+            const LIFE_i8: i8 = 42;
+            const LIFE_u16: u16 = 42;
+            const LIFE_i16: i16 = 42;
+            const LIFE_u32: u32 = 42;
+            const LIFE_i32: i32 = 42;
+            const LIFE_u64: u64 = 42;
+            const LIFE_i64: i64 = 42;
+            const LIFE_u128: u128 = 42;
+            const LIFE_i128: i128 = 42;
+            const LIFE_usize: usize = 42;
+            const LIFE_isize: isize = 42;
+            const LIFE_f32: f32 = 42.;
+            const LIFE_f64: f64 = 42.;
+        }
+    }
+}
+
 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 ffa7b961d1c..d8eeda70491 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
@@ -216,4 +216,44 @@ mod type_already_inferred {
     }
 }
 
+mod issue12159 {
+    #![allow(non_upper_case_globals, clippy::exhaustive_structs)]
+    pub struct Foo;
+
+    static F: i32 = 1;
+    impl Foo {
+        const LIFE_u8: u8 = 42;
+        const LIFE_i8: i8 = 42;
+        const LIFE_u16: u16 = 42;
+        const LIFE_i16: i16 = 42;
+        const LIFE_u32: u32 = 42;
+        const LIFE_i32: i32 = 42;
+        const LIFE_u64: u64 = 42;
+        const LIFE_i64: i64 = 42;
+        const LIFE_u128: u128 = 42;
+        const LIFE_i128: i128 = 42;
+        const LIFE_usize: usize = 42;
+        const LIFE_isize: isize = 42;
+        const LIFE_f32: f32 = 42.;
+        const LIFE_f64: f64 = 42.;
+
+        const fn consts() {
+            const LIFE_u8: u8 = 42;
+            const LIFE_i8: i8 = 42;
+            const LIFE_u16: u16 = 42;
+            const LIFE_i16: i16 = 42;
+            const LIFE_u32: u32 = 42;
+            const LIFE_i32: i32 = 42;
+            const LIFE_u64: u64 = 42;
+            const LIFE_i64: i64 = 42;
+            const LIFE_u128: u128 = 42;
+            const LIFE_i128: i128 = 42;
+            const LIFE_usize: usize = 42;
+            const LIFE_isize: isize = 42;
+            const LIFE_f32: f32 = 42.;
+            const LIFE_f64: f64 = 42.;
+        }
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed
index a7f5d3ec7cd..aa7a95405e0 100644
--- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed
+++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.fixed
@@ -121,4 +121,36 @@ pub fn _from_mod() -> _hidden::InPubFn {
 #[derive(PartialEq)]
 struct InternalTy;
 
+// This is a `non_exhaustive` type so should not warn.
+#[derive(Debug, PartialEq)]
+#[non_exhaustive]
+pub struct MissingEqNonExhaustive {
+    foo: u32,
+    bar: String,
+}
+
+// This is a `non_exhaustive` type so should not warn.
+#[derive(Debug, PartialEq)]
+pub struct MissingEqNonExhaustive1 {
+    foo: u32,
+    #[non_exhaustive]
+    bar: String,
+}
+
+// This is a `non_exhaustive` type so should not warn.
+#[derive(Debug, PartialEq)]
+#[non_exhaustive]
+pub enum MissingEqNonExhaustive2 {
+    Foo,
+    Bar,
+}
+
+// This is a `non_exhaustive` type so should not warn.
+#[derive(Debug, PartialEq)]
+pub enum MissingEqNonExhaustive3 {
+    Foo,
+    #[non_exhaustive]
+    Bar,
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs
index 476d2aee23a..90ac7a7989e 100644
--- a/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs
+++ b/src/tools/clippy/tests/ui/derive_partial_eq_without_eq.rs
@@ -121,4 +121,36 @@ pub fn _from_mod() -> _hidden::InPubFn {
 #[derive(PartialEq)]
 struct InternalTy;
 
+// This is a `non_exhaustive` type so should not warn.
+#[derive(Debug, PartialEq)]
+#[non_exhaustive]
+pub struct MissingEqNonExhaustive {
+    foo: u32,
+    bar: String,
+}
+
+// This is a `non_exhaustive` type so should not warn.
+#[derive(Debug, PartialEq)]
+pub struct MissingEqNonExhaustive1 {
+    foo: u32,
+    #[non_exhaustive]
+    bar: String,
+}
+
+// This is a `non_exhaustive` type so should not warn.
+#[derive(Debug, PartialEq)]
+#[non_exhaustive]
+pub enum MissingEqNonExhaustive2 {
+    Foo,
+    Bar,
+}
+
+// This is a `non_exhaustive` type so should not warn.
+#[derive(Debug, PartialEq)]
+pub enum MissingEqNonExhaustive3 {
+    Foo,
+    #[non_exhaustive]
+    Bar,
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
index bff46e55722..16f7bafd44b 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -64,7 +64,7 @@ fn test_units() {
 /// NaN NaNs
 /// OAuth GraphQL
 /// OCaml
-/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
+/// OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
 /// WebGL WebGL2 WebGPU
 /// TensorFlow
 /// TrueType
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index 4e162a97dee..4058b2bad74 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -64,7 +64,7 @@ fn test_units() {
 /// NaN NaNs
 /// OAuth GraphQL
 /// OCaml
-/// OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenDNS
+/// OpenDNS OpenGL OpenMP OpenSSH OpenSSL OpenStreetMap OpenTelemetry
 /// WebGL WebGL2 WebGPU
 /// TensorFlow
 /// TrueType
diff --git a/src/tools/clippy/tests/ui/from_over_into.fixed b/src/tools/clippy/tests/ui/from_over_into.fixed
index 18d285693e6..4a68505ee0b 100644
--- a/src/tools/clippy/tests/ui/from_over_into.fixed
+++ b/src/tools/clippy/tests/ui/from_over_into.fixed
@@ -89,4 +89,12 @@ fn msrv_1_41() {
     }
 }
 
+fn issue_12138() {
+    struct Hello;
+
+    impl From<Hello> for () {
+        fn from(val: Hello) {}
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs
index 779ef709e92..bf3ed0c2b64 100644
--- a/src/tools/clippy/tests/ui/from_over_into.rs
+++ b/src/tools/clippy/tests/ui/from_over_into.rs
@@ -89,4 +89,12 @@ fn msrv_1_41() {
     }
 }
 
+fn issue_12138() {
+    struct Hello;
+
+    impl Into<()> for Hello {
+        fn into(self) {}
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr
index 784843ce5fd..f1370ed844f 100644
--- a/src/tools/clippy/tests/ui/from_over_into.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into.stderr
@@ -86,5 +86,19 @@ LL ~         fn from(val: Vec<T>) -> Self {
 LL ~             FromOverInto(val)
    |
 
-error: aborting due to 6 previous errors
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+  --> $DIR/from_over_into.rs:95:5
+   |
+LL |     impl Into<()> for Hello {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see
+           https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
+help: replace the `Into` implementation with `From<issue_12138::Hello>`
+   |
+LL ~     impl From<Hello> for () {
+LL ~         fn from(val: Hello) {}
+   |
+
+error: aborting due to 7 previous errors
 
diff --git a/src/tools/clippy/tests/ui/if_same_then_else.rs b/src/tools/clippy/tests/ui/if_same_then_else.rs
index e84b20e9fef..d53e1383d84 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else.rs
+++ b/src/tools/clippy/tests/ui/if_same_then_else.rs
@@ -21,7 +21,6 @@ fn foo() -> bool {
 
 fn if_same_then_else() {
     if true {
-        //~^ ERROR: this `if` has identical blocks
         Foo { bar: 42 };
         0..10;
         ..;
@@ -38,6 +37,7 @@ fn if_same_then_else() {
         0..=10;
         foo();
     }
+    //~^^^^^^^^^^^^^^^^^ ERROR: this `if` has identical blocks
 
     if true {
         Foo { bar: 42 };
@@ -64,19 +64,11 @@ fn if_same_then_else() {
         foo();
     }
 
-    let _ = if true {
-        //~^ ERROR: this `if` has identical blocks
-        0.0
-    } else {
-        0.0
-    };
+    let _ = if true { 0.0 } else { 0.0 };
+    //~^ ERROR: this `if` has identical blocks
 
-    let _ = if true {
-        //~^ ERROR: this `if` has identical blocks
-        -0.0
-    } else {
-        -0.0
-    };
+    let _ = if true { -0.0 } else { -0.0 };
+    //~^ ERROR: this `if` has identical blocks
 
     let _ = if true { 0.0 } else { -0.0 };
 
@@ -87,15 +79,10 @@ fn if_same_then_else() {
         foo();
     }
 
-    let _ = if true {
-        //~^ ERROR: this `if` has identical blocks
-        42
-    } else {
-        42
-    };
+    let _ = if true { 42 } else { 42 };
+    //~^ ERROR: this `if` has identical blocks
 
     if true {
-        //~^ ERROR: this `if` has identical blocks
         let bar = if true { 42 } else { 43 };
 
         while foo() {
@@ -110,6 +97,7 @@ fn if_same_then_else() {
         }
         bar + 1;
     }
+    //~^^^^^^^^^^^^^^^ ERROR: this `if` has identical blocks
 
     if true {
         let _ = match 42 {
diff --git a/src/tools/clippy/tests/ui/if_same_then_else.stderr b/src/tools/clippy/tests/ui/if_same_then_else.stderr
index fb33e94e6c3..281f30f88b4 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else.stderr
+++ b/src/tools/clippy/tests/ui/if_same_then_else.stderr
@@ -3,16 +3,16 @@ error: this `if` has identical blocks
    |
 LL |       if true {
    |  _____________^
-LL | |
 LL | |         Foo { bar: 42 };
 LL | |         0..10;
+LL | |         ..;
 ...  |
 LL | |         foo();
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:32:12
+  --> $DIR/if_same_then_else.rs:31:12
    |
 LL |       } else {
    |  ____________^
@@ -29,75 +29,54 @@ LL | |     }
 error: this `if` has identical blocks
   --> $DIR/if_same_then_else.rs:67:21
    |
-LL |       let _ = if true {
-   |  _____________________^
-LL | |
-LL | |         0.0
-LL | |     } else {
-   | |_____^
+LL |     let _ = if true { 0.0 } else { 0.0 };
+   |                     ^^^^^^^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:70:12
+  --> $DIR/if_same_then_else.rs:67:34
    |
-LL |       } else {
-   |  ____________^
-LL | |         0.0
-LL | |     };
-   | |_____^
+LL |     let _ = if true { 0.0 } else { 0.0 };
+   |                                  ^^^^^^^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else.rs:74:21
+  --> $DIR/if_same_then_else.rs:70:21
    |
-LL |       let _ = if true {
-   |  _____________________^
-LL | |
-LL | |         -0.0
-LL | |     } else {
-   | |_____^
+LL |     let _ = if true { -0.0 } else { -0.0 };
+   |                     ^^^^^^^^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:77:12
+  --> $DIR/if_same_then_else.rs:70:35
    |
-LL |       } else {
-   |  ____________^
-LL | |         -0.0
-LL | |     };
-   | |_____^
+LL |     let _ = if true { -0.0 } else { -0.0 };
+   |                                   ^^^^^^^^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else.rs:90:21
+  --> $DIR/if_same_then_else.rs:82:21
    |
-LL |       let _ = if true {
-   |  _____________________^
-LL | |
-LL | |         42
-LL | |     } else {
-   | |_____^
+LL |     let _ = if true { 42 } else { 42 };
+   |                     ^^^^^^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:93:12
+  --> $DIR/if_same_then_else.rs:82:33
    |
-LL |       } else {
-   |  ____________^
-LL | |         42
-LL | |     };
-   | |_____^
+LL |     let _ = if true { 42 } else { 42 };
+   |                                 ^^^^^^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else.rs:97:13
+  --> $DIR/if_same_then_else.rs:85:13
    |
 LL |       if true {
    |  _____________^
-LL | |
 LL | |         let bar = if true { 42 } else { 43 };
 LL | |
+LL | |         while foo() {
 ...  |
 LL | |         bar + 1;
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:105:12
+  --> $DIR/if_same_then_else.rs:92:12
    |
 LL |       } else {
    |  ____________^
@@ -110,7 +89,7 @@ LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else.rs:250:14
+  --> $DIR/if_same_then_else.rs:238:14
    |
 LL |           if x {
    |  ______________^
@@ -119,7 +98,7 @@ LL | |         } else {
    | |_________^
    |
 note: same as this
-  --> $DIR/if_same_then_else.rs:252:16
+  --> $DIR/if_same_then_else.rs:240:16
    |
 LL |           } else {
    |  ________________^
diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.rs b/src/tools/clippy/tests/ui/if_same_then_else2.rs
index 0b171f21d0c..e23c77b0827 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else2.rs
+++ b/src/tools/clippy/tests/ui/if_same_then_else2.rs
@@ -13,7 +13,6 @@
 
 fn if_same_then_else2() -> Result<&'static str, ()> {
     if true {
-        //~^ ERROR: this `if` has identical blocks
         for _ in &[42] {
             let foo: &Option<_> = &Some::<u8>(42);
             if foo.is_some() {
@@ -32,20 +31,21 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
             }
         }
     }
+    //~^^^^^^^^^^^^^^^^^^^ ERROR: this `if` has identical blocks
 
     if true {
-        //~^ ERROR: this `if` has identical blocks
         if let Some(a) = Some(42) {}
     } else {
         if let Some(a) = Some(42) {}
     }
+    //~^^^^^ ERROR: this `if` has identical blocks
 
     if true {
-        //~^ ERROR: this `if` has identical blocks
         if let (1, .., 3) = (1, 2, 3) {}
     } else {
         if let (1, .., 3) = (1, 2, 3) {}
     }
+    //~^^^^^ ERROR: this `if` has identical blocks
 
     if true {
         if let (1, .., 3) = (1, 2, 3) {}
@@ -90,19 +90,15 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
     }
 
     // Same NaNs
-    let _ = if true {
-        //~^ ERROR: this `if` has identical blocks
-        f32::NAN
-    } else {
-        f32::NAN
-    };
+    let _ = if true { f32::NAN } else { f32::NAN };
+    //~^ ERROR: this `if` has identical blocks
 
     if true {
-        //~^ ERROR: this `if` has identical blocks
         Ok("foo")?;
     } else {
         Ok("foo")?;
     }
+    //~^^^^^ ERROR: this `if` has identical blocks
 
     if true {
         let foo = "";
@@ -122,13 +118,13 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
         let foo = "bar";
         return Ok(&foo[0..]);
     } else if true {
-        //~^ ERROR: this `if` has identical blocks
         let foo = "";
         return Ok(&foo[0..]);
     } else {
         let foo = "";
         return Ok(&foo[0..]);
     }
+    //~^^^^^^^ ERROR: this `if` has identical blocks
 
     // False positive `if_same_then_else`: `let (x, y)` vs. `let (y, x)`; see issue #3559.
     if true {
diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.stderr b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
index fe68ef2711b..4e7a7c87dc5 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else2.stderr
+++ b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
@@ -3,16 +3,16 @@ error: this `if` has identical blocks
    |
 LL |       if true {
    |  _____________^
-LL | |
 LL | |         for _ in &[42] {
 LL | |             let foo: &Option<_> = &Some::<u8>(42);
+LL | |             if foo.is_some() {
 ...  |
 LL | |         }
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:25:12
+  --> $DIR/if_same_then_else2.rs:24:12
    |
 LL |       } else {
    |  ____________^
@@ -31,13 +31,12 @@ error: this `if` has identical blocks
    |
 LL |       if true {
    |  _____________^
-LL | |
 LL | |         if let Some(a) = Some(42) {}
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:39:12
+  --> $DIR/if_same_then_else2.rs:38:12
    |
 LL |       } else {
    |  ____________^
@@ -50,13 +49,12 @@ error: this `if` has identical blocks
    |
 LL |       if true {
    |  _____________^
-LL | |
 LL | |         if let (1, .., 3) = (1, 2, 3) {}
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:46:12
+  --> $DIR/if_same_then_else2.rs:45:12
    |
 LL |       } else {
    |  ____________^
@@ -67,34 +65,26 @@ LL | |     }
 error: this `if` has identical blocks
   --> $DIR/if_same_then_else2.rs:93:21
    |
-LL |       let _ = if true {
-   |  _____________________^
-LL | |
-LL | |         f32::NAN
-LL | |     } else {
-   | |_____^
+LL |     let _ = if true { f32::NAN } else { f32::NAN };
+   |                     ^^^^^^^^^^^^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:96:12
+  --> $DIR/if_same_then_else2.rs:93:39
    |
-LL |       } else {
-   |  ____________^
-LL | |         f32::NAN
-LL | |     };
-   | |_____^
+LL |     let _ = if true { f32::NAN } else { f32::NAN };
+   |                                       ^^^^^^^^^^^^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:100:13
+  --> $DIR/if_same_then_else2.rs:96:13
    |
 LL |       if true {
    |  _____________^
-LL | |
 LL | |         Ok("foo")?;
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:103:12
+  --> $DIR/if_same_then_else2.rs:98:12
    |
 LL |       } else {
    |  ____________^
@@ -103,18 +93,17 @@ LL | |     }
    | |_____^
 
 error: this `if` has identical blocks
-  --> $DIR/if_same_then_else2.rs:124:20
+  --> $DIR/if_same_then_else2.rs:120:20
    |
 LL |       } else if true {
    |  ____________________^
-LL | |
 LL | |         let foo = "";
 LL | |         return Ok(&foo[0..]);
 LL | |     } else {
    | |_____^
    |
 note: same as this
-  --> $DIR/if_same_then_else2.rs:128:12
+  --> $DIR/if_same_then_else2.rs:123:12
    |
 LL |       } else {
    |  ____________^
diff --git a/src/tools/clippy/tests/ui/ineffective_open_options.fixed b/src/tools/clippy/tests/ui/ineffective_open_options.fixed
index 3af8f3c5aaa..88489dc46bb 100644
--- a/src/tools/clippy/tests/ui/ineffective_open_options.fixed
+++ b/src/tools/clippy/tests/ui/ineffective_open_options.fixed
@@ -26,16 +26,23 @@ fn main() {
         .unwrap();
     let file = OpenOptions::new()
         .create(true)
+        .truncate(true)
         .write(true)
         .append(false)
         .open("dump.json")
         .unwrap();
     let file = OpenOptions::new()
         .create(true)
+        .truncate(true)
         .write(false)
         .append(false)
         .open("dump.json")
         .unwrap();
     let file = OpenOptions::new().create(true).append(true).open("dump.json").unwrap();
-    let file = OpenOptions::new().create(true).write(true).open("dump.json").unwrap();
+    let file = OpenOptions::new()
+        .create(true)
+        .truncate(true)
+        .write(true)
+        .open("dump.json")
+        .unwrap();
 }
diff --git a/src/tools/clippy/tests/ui/ineffective_open_options.rs b/src/tools/clippy/tests/ui/ineffective_open_options.rs
index 4eaf6293c40..db8bca3e2ac 100644
--- a/src/tools/clippy/tests/ui/ineffective_open_options.rs
+++ b/src/tools/clippy/tests/ui/ineffective_open_options.rs
@@ -26,16 +26,23 @@ fn main() {
         .unwrap();
     let file = OpenOptions::new()
         .create(true)
+        .truncate(true)
         .write(true)
         .append(false)
         .open("dump.json")
         .unwrap();
     let file = OpenOptions::new()
         .create(true)
+        .truncate(true)
         .write(false)
         .append(false)
         .open("dump.json")
         .unwrap();
     let file = OpenOptions::new().create(true).append(true).open("dump.json").unwrap();
-    let file = OpenOptions::new().create(true).write(true).open("dump.json").unwrap();
+    let file = OpenOptions::new()
+        .create(true)
+        .truncate(true)
+        .write(true)
+        .open("dump.json")
+        .unwrap();
 }
diff --git a/src/tools/clippy/tests/ui/join_absolute_paths.stderr b/src/tools/clippy/tests/ui/join_absolute_paths.stderr
index 0c2f89d9978..ab4d189ca3a 100644
--- a/src/tools/clippy/tests/ui/join_absolute_paths.stderr
+++ b/src/tools/clippy/tests/ui/join_absolute_paths.stderr
@@ -11,7 +11,7 @@ help: if this is unintentional, try removing the starting separator
    |
 LL |     path.join("sh");
    |               ~~~~
-help: if this is intentional, try using `Path::new` instead
+help: if this is intentional, consider using `Path::new`
    |
 LL |     PathBuf::from("/sh");
    |     ~~~~~~~~~~~~~~~~~~~~
@@ -27,7 +27,7 @@ help: if this is unintentional, try removing the starting separator
    |
 LL |     path.join("\user");
    |               ~~~~~~~
-help: if this is intentional, try using `Path::new` instead
+help: if this is intentional, consider using `Path::new`
    |
 LL |     PathBuf::from("\\user");
    |     ~~~~~~~~~~~~~~~~~~~~~~~
@@ -43,7 +43,7 @@ help: if this is unintentional, try removing the starting separator
    |
 LL |     path.join("sh");
    |               ~~~~
-help: if this is intentional, try using `Path::new` instead
+help: if this is intentional, consider using `Path::new`
    |
 LL |     PathBuf::from("/sh");
    |     ~~~~~~~~~~~~~~~~~~~~
@@ -59,7 +59,7 @@ help: if this is unintentional, try removing the starting separator
    |
 LL |     path.join(r#"sh"#);
    |               ~~~~~~~
-help: if this is intentional, try using `Path::new` instead
+help: if this is intentional, consider using `Path::new`
    |
 LL |     PathBuf::from(r#"/sh"#);
    |     ~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/src/tools/clippy/tests/ui/manual_ok_or.stderr b/src/tools/clippy/tests/ui/manual_ok_or.stderr
index b277d22e59b..89df6cdbedb 100644
--- a/src/tools/clippy/tests/ui/manual_ok_or.stderr
+++ b/src/tools/clippy/tests/ui/manual_ok_or.stderr
@@ -17,7 +17,7 @@ error: called `map_or(Err(_), Ok)` on an `Option` value
   --> $DIR/manual_ok_or.rs:14:5
    |
 LL |     foo.map_or(Err("error"), Ok);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok_or` instead: `foo.ok_or("error")`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok_or`: `foo.ok_or("error")`
    |
    = note: `-D clippy::option-map-or-err-ok` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::option_map_or_err_ok)]`
diff --git a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.stderr b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.stderr
index dc36a5ee7c6..3ce108b1ca8 100644
--- a/src/tools/clippy/tests/ui/manual_saturating_arithmetic.stderr
+++ b/src/tools/clippy/tests/ui/manual_saturating_arithmetic.stderr
@@ -2,7 +2,7 @@ error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:6:13
    |
 LL |     let _ = 1u32.checked_add(1).unwrap_or(u32::max_value());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1u32.saturating_add(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1u32.saturating_add(1)`
    |
    = note: `-D clippy::manual-saturating-arithmetic` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::manual_saturating_arithmetic)]`
@@ -11,13 +11,13 @@ error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:7:13
    |
 LL |     let _ = 1u32.checked_add(1).unwrap_or(u32::MAX);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1u32.saturating_add(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1u32.saturating_add(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:8:13
    |
 LL |     let _ = 1u8.checked_add(1).unwrap_or(255);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1u8.saturating_add(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1u8.saturating_add(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:9:13
@@ -26,49 +26,49 @@ LL |       let _ = 1u128
    |  _____________^
 LL | |         .checked_add(1)
 LL | |         .unwrap_or(340_282_366_920_938_463_463_374_607_431_768_211_455);
-   | |_______________________________________________________________________^ help: try using `saturating_add`: `1u128.saturating_add(1)`
+   | |_______________________________________________________________________^ help: consider using `saturating_add`: `1u128.saturating_add(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:14:13
    |
 LL |     let _ = 1u32.checked_mul(1).unwrap_or(u32::MAX);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_mul`: `1u32.saturating_mul(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_mul`: `1u32.saturating_mul(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:16:13
    |
 LL |     let _ = 1u32.checked_sub(1).unwrap_or(u32::min_value());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1u32.saturating_sub(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1u32.saturating_sub(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:17:13
    |
 LL |     let _ = 1u32.checked_sub(1).unwrap_or(u32::MIN);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1u32.saturating_sub(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1u32.saturating_sub(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:18:13
    |
 LL |     let _ = 1u8.checked_sub(1).unwrap_or(0);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1u8.saturating_sub(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1u8.saturating_sub(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:22:13
    |
 LL |     let _ = 1i32.checked_add(1).unwrap_or(i32::max_value());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:23:13
    |
 LL |     let _ = 1i32.checked_add(1).unwrap_or(i32::MAX);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:24:13
    |
 LL |     let _ = 1i8.checked_add(1).unwrap_or(127);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i8.saturating_add(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i8.saturating_add(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:25:13
@@ -77,25 +77,25 @@ LL |       let _ = 1i128
    |  _____________^
 LL | |         .checked_add(1)
 LL | |         .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727);
-   | |_______________________________________________________________________^ help: try using `saturating_add`: `1i128.saturating_add(1)`
+   | |_______________________________________________________________________^ help: consider using `saturating_add`: `1i128.saturating_add(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:28:13
    |
 LL |     let _ = 1i32.checked_add(-1).unwrap_or(i32::min_value());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(-1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(-1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:29:13
    |
 LL |     let _ = 1i32.checked_add(-1).unwrap_or(i32::MIN);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i32.saturating_add(-1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i32.saturating_add(-1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:30:13
    |
 LL |     let _ = 1i8.checked_add(-1).unwrap_or(-128);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_add`: `1i8.saturating_add(-1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_add`: `1i8.saturating_add(-1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:31:13
@@ -104,25 +104,25 @@ LL |       let _ = 1i128
    |  _____________^
 LL | |         .checked_add(-1)
 LL | |         .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728);
-   | |________________________________________________________________________^ help: try using `saturating_add`: `1i128.saturating_add(-1)`
+   | |________________________________________________________________________^ help: consider using `saturating_add`: `1i128.saturating_add(-1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:38:13
    |
 LL |     let _ = 1i32.checked_sub(1).unwrap_or(i32::min_value());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:39:13
    |
 LL |     let _ = 1i32.checked_sub(1).unwrap_or(i32::MIN);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:40:13
    |
 LL |     let _ = 1i8.checked_sub(1).unwrap_or(-128);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i8.saturating_sub(1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i8.saturating_sub(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:41:13
@@ -131,25 +131,25 @@ LL |       let _ = 1i128
    |  _____________^
 LL | |         .checked_sub(1)
 LL | |         .unwrap_or(-170_141_183_460_469_231_731_687_303_715_884_105_728);
-   | |________________________________________________________________________^ help: try using `saturating_sub`: `1i128.saturating_sub(1)`
+   | |________________________________________________________________________^ help: consider using `saturating_sub`: `1i128.saturating_sub(1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:44:13
    |
 LL |     let _ = 1i32.checked_sub(-1).unwrap_or(i32::max_value());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(-1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(-1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:45:13
    |
 LL |     let _ = 1i32.checked_sub(-1).unwrap_or(i32::MAX);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i32.saturating_sub(-1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i32.saturating_sub(-1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:46:13
    |
 LL |     let _ = 1i8.checked_sub(-1).unwrap_or(127);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `saturating_sub`: `1i8.saturating_sub(-1)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `saturating_sub`: `1i8.saturating_sub(-1)`
 
 error: manual saturating arithmetic
   --> $DIR/manual_saturating_arithmetic.rs:47:13
@@ -158,7 +158,7 @@ LL |       let _ = 1i128
    |  _____________^
 LL | |         .checked_sub(-1)
 LL | |         .unwrap_or(170_141_183_460_469_231_731_687_303_715_884_105_727);
-   | |_______________________________________________________________________^ help: try using `saturating_sub`: `1i128.saturating_sub(-1)`
+   | |_______________________________________________________________________^ help: consider using `saturating_sub`: `1i128.saturating_sub(-1)`
 
 error: aborting due to 24 previous errors
 
diff --git a/src/tools/clippy/tests/ui/map_clone.fixed b/src/tools/clippy/tests/ui/map_clone.fixed
index 08b155a1aea..395eea69294 100644
--- a/src/tools/clippy/tests/ui/map_clone.fixed
+++ b/src/tools/clippy/tests/ui/map_clone.fixed
@@ -69,15 +69,48 @@ fn main() {
     //~^ ERROR: you are explicitly cloning with `.map()`
     let y = x.cloned();
     //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `cloned` method
     let y = x.cloned();
     //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `cloned` method
+
+    let x: Option<u32> = Some(0);
+    let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
+    let y = x.copied();
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `copied` method
+    let y = x.copied();
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `copied` method
+
+    // Should not suggest `copied` or `cloned` here since `T` is not a reference.
+    let x: Option<u32> = Some(0);
+    let y = x.map(|x| u32::clone(&x));
+    let y = x.map(|x| Clone::clone(&x));
 
     // 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()`
+    //~| HELP: consider calling the dedicated `cloned` method
     let y = x.cloned();
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `cloned` method
+
+    let x: Result<u32, ()> = Ok(0);
+    let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
+    let y = x.copied();
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `copied` method
+    let y = x.copied();
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `copied` method
+
+    // Should not suggest `copied` or `cloned` here since `T` is not a reference.
+    let x: Result<u32, ()> = Ok(0);
+    let y = x.map(|x| u32::clone(&x));
+    let y = x.map(|x| Clone::clone(&x));
 
     // We ensure that no warning is emitted here because `useless_asref` is taking over.
     let x = Some(String::new());
diff --git a/src/tools/clippy/tests/ui/map_clone.rs b/src/tools/clippy/tests/ui/map_clone.rs
index 901d9b278b4..82a103edf5a 100644
--- a/src/tools/clippy/tests/ui/map_clone.rs
+++ b/src/tools/clippy/tests/ui/map_clone.rs
@@ -69,15 +69,48 @@ fn main() {
     //~^ ERROR: you are explicitly cloning with `.map()`
     let y = x.map(Clone::clone);
     //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `cloned` method
     let y = x.map(String::clone);
     //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `cloned` method
+
+    let x: Option<u32> = Some(0);
+    let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
+    let y = x.map(|x| u32::clone(x));
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `copied` method
+    let y = x.map(|x| Clone::clone(x));
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `copied` method
+
+    // Should not suggest `copied` or `cloned` here since `T` is not a reference.
+    let x: Option<u32> = Some(0);
+    let y = x.map(|x| u32::clone(&x));
+    let y = x.map(|x| Clone::clone(&x));
 
     // 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));
+    //~| HELP: consider calling the dedicated `cloned` method
+    let y = x.map(|x| Clone::clone(x));
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `cloned` method
+
+    let x: Result<u32, ()> = Ok(0);
+    let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint.
+    let y = x.map(|x| u32::clone(x));
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `copied` method
+    let y = x.map(|x| Clone::clone(x));
+    //~^ ERROR: you are explicitly cloning with `.map()`
+    //~| HELP: consider calling the dedicated `copied` method
+
+    // Should not suggest `copied` or `cloned` here since `T` is not a reference.
+    let x: Result<u32, ()> = Ok(0);
+    let y = x.map(|x| u32::clone(&x));
+    let y = x.map(|x| Clone::clone(&x));
 
     // We ensure that no warning is emitted here because `useless_asref` is taking over.
     let x = Some(String::new());
diff --git a/src/tools/clippy/tests/ui/map_clone.stderr b/src/tools/clippy/tests/ui/map_clone.stderr
index 9d7e9317b58..2c86a67fab8 100644
--- a/src/tools/clippy/tests/ui/map_clone.stderr
+++ b/src/tools/clippy/tests/ui/map_clone.stderr
@@ -50,22 +50,46 @@ 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
+  --> $DIR/map_clone.rs:73: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
+  --> $DIR/map_clone.rs:79:13
    |
-LL |     let y = x.map(|x| String::clone(x));
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
+LL |     let y = x.map(|x| u32::clone(x));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()`
 
 error: you are explicitly cloning with `.map()`
-  --> $DIR/map_clone.rs:80:13
+  --> $DIR/map_clone.rs:82:13
+   |
+LL |     let y = x.map(|x| Clone::clone(x));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()`
+
+error: you are explicitly cloning with `.map()`
+  --> $DIR/map_clone.rs:94: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
+error: you are explicitly cloning with `.map()`
+  --> $DIR/map_clone.rs:97:13
+   |
+LL |     let y = x.map(|x| Clone::clone(x));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()`
+
+error: you are explicitly cloning with `.map()`
+  --> $DIR/map_clone.rs:103:13
+   |
+LL |     let y = x.map(|x| u32::clone(x));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()`
+
+error: you are explicitly cloning with `.map()`
+  --> $DIR/map_clone.rs:106:13
+   |
+LL |     let y = x.map(|x| Clone::clone(x));
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()`
+
+error: aborting due to 15 previous errors
 
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index 525a355f403..3428ff45906 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -13,7 +13,6 @@ fn foo() -> bool {
 fn match_same_arms() {
     let _ = match 42 {
         42 => {
-            //~^ ERROR: this match arm has an identical body to the `_` wildcard arm
             foo();
             let mut a = 42 + [23].len() as i32;
             if true {
@@ -32,6 +31,7 @@ fn match_same_arms() {
             a
         },
     };
+    //~^^^^^^^^^^^^^^^^^^^ ERROR: this match arm has an identical body to the `_` wildcard arm
 
     let _ = match 42 {
         42 => foo(),
@@ -146,13 +146,13 @@ fn match_same_arms() {
             empty!(0);
         },
         1 => {
-            //~^ ERROR: this match arm has an identical body to another arm
             empty!(0);
         },
         x => {
             empty!(x);
         },
     }
+    //~^^^^^^^ ERROR: this match arm has an identical body to another arm
 
     match_expr_like_matches_macro_priority();
 }
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr
index 40b20c7e16d..512ca7413a7 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -2,9 +2,9 @@ error: this match arm has an identical body to the `_` wildcard arm
   --> $DIR/match_same_arms2.rs:15:9
    |
 LL | /         42 => {
-LL | |
 LL | |             foo();
 LL | |             let mut a = 42 + [23].len() as i32;
+LL | |             if true {
 ...  |
 LL | |             a
 LL | |         },
@@ -12,7 +12,7 @@ LL | |         },
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> $DIR/match_same_arms2.rs:25:9
+  --> $DIR/match_same_arms2.rs:24:9
    |
 LL | /         _ => {
 LL | |             foo();
@@ -122,7 +122,6 @@ LL |           1 => {
    |           ^ help: try merging the arm patterns: `1 | 0`
    |  _________|
    | |
-LL | |
 LL | |             empty!(0);
 LL | |         },
    | |_________^
diff --git a/src/tools/clippy/tests/ui/mem_replace_no_std.fixed b/src/tools/clippy/tests/ui/mem_replace_no_std.fixed
new file mode 100644
index 00000000000..c970f2ba281
--- /dev/null
+++ b/src/tools/clippy/tests/ui/mem_replace_no_std.fixed
@@ -0,0 +1,82 @@
+#![allow(unused)]
+#![warn(
+    clippy::all,
+    clippy::style,
+    clippy::mem_replace_option_with_none,
+    clippy::mem_replace_with_default
+)]
+#![feature(lang_items)]
+#![no_std]
+
+use core::mem;
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+fn replace_option_with_none() {
+    let mut an_option = Some(1);
+    let _ = an_option.take();
+    let an_option = &mut Some(1);
+    let _ = an_option.take();
+}
+
+fn replace_with_default() {
+    let mut refstr = "hello";
+    let _ = core::mem::take(&mut refstr);
+
+    let mut slice: &[i32] = &[1, 2, 3];
+    let _ = core::mem::take(&mut slice);
+}
+
+// lint is disabled for primitives because in this case `take`
+// has no clear benefit over `replace` and sometimes is harder to read
+fn dont_lint_primitive() {
+    let mut pbool = true;
+    let _ = mem::replace(&mut pbool, false);
+
+    let mut pint = 5;
+    let _ = mem::replace(&mut pint, 0);
+}
+
+fn main() {
+    replace_option_with_none();
+    replace_with_default();
+    dont_lint_primitive();
+}
+
+fn issue9824() {
+    struct Foo<'a>(Option<&'a str>);
+    impl<'a> core::ops::Deref for Foo<'a> {
+        type Target = Option<&'a str>;
+
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<'a> core::ops::DerefMut for Foo<'a> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            &mut self.0
+        }
+    }
+
+    struct Bar {
+        opt: Option<u8>,
+        val: u8,
+    }
+
+    let mut f = Foo(Some("foo"));
+    let mut b = Bar { opt: Some(1), val: 12 };
+
+    // replace option with none
+    let _ = f.0.take();
+    let _ = (*f).take();
+    let _ = b.opt.take();
+    // replace with default
+    let _ = mem::replace(&mut b.val, u8::default());
+}
diff --git a/src/tools/clippy/tests/ui/mem_replace_no_std.rs b/src/tools/clippy/tests/ui/mem_replace_no_std.rs
new file mode 100644
index 00000000000..673d5c7b4f4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/mem_replace_no_std.rs
@@ -0,0 +1,82 @@
+#![allow(unused)]
+#![warn(
+    clippy::all,
+    clippy::style,
+    clippy::mem_replace_option_with_none,
+    clippy::mem_replace_with_default
+)]
+#![feature(lang_items)]
+#![no_std]
+
+use core::mem;
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+fn replace_option_with_none() {
+    let mut an_option = Some(1);
+    let _ = mem::replace(&mut an_option, None);
+    let an_option = &mut Some(1);
+    let _ = mem::replace(an_option, None);
+}
+
+fn replace_with_default() {
+    let mut refstr = "hello";
+    let _ = mem::replace(&mut refstr, "");
+
+    let mut slice: &[i32] = &[1, 2, 3];
+    let _ = mem::replace(&mut slice, &[]);
+}
+
+// lint is disabled for primitives because in this case `take`
+// has no clear benefit over `replace` and sometimes is harder to read
+fn dont_lint_primitive() {
+    let mut pbool = true;
+    let _ = mem::replace(&mut pbool, false);
+
+    let mut pint = 5;
+    let _ = mem::replace(&mut pint, 0);
+}
+
+fn main() {
+    replace_option_with_none();
+    replace_with_default();
+    dont_lint_primitive();
+}
+
+fn issue9824() {
+    struct Foo<'a>(Option<&'a str>);
+    impl<'a> core::ops::Deref for Foo<'a> {
+        type Target = Option<&'a str>;
+
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+    impl<'a> core::ops::DerefMut for Foo<'a> {
+        fn deref_mut(&mut self) -> &mut Self::Target {
+            &mut self.0
+        }
+    }
+
+    struct Bar {
+        opt: Option<u8>,
+        val: u8,
+    }
+
+    let mut f = Foo(Some("foo"));
+    let mut b = Bar { opt: Some(1), val: 12 };
+
+    // replace option with none
+    let _ = mem::replace(&mut f.0, None);
+    let _ = mem::replace(&mut *f, None);
+    let _ = mem::replace(&mut b.opt, None);
+    // replace with default
+    let _ = mem::replace(&mut b.val, u8::default());
+}
diff --git a/src/tools/clippy/tests/ui/mem_replace_no_std.stderr b/src/tools/clippy/tests/ui/mem_replace_no_std.stderr
new file mode 100644
index 00000000000..744fb5a1587
--- /dev/null
+++ b/src/tools/clippy/tests/ui/mem_replace_no_std.stderr
@@ -0,0 +1,50 @@
+error: replacing an `Option` with `None`
+  --> $DIR/mem_replace_no_std.rs:24:13
+   |
+LL |     let _ = mem::replace(&mut an_option, None);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
+   |
+   = note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::mem_replace_option_with_none)]`
+
+error: replacing an `Option` with `None`
+  --> $DIR/mem_replace_no_std.rs:26:13
+   |
+LL |     let _ = mem::replace(an_option, None);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `core::mem::take`
+  --> $DIR/mem_replace_no_std.rs:31:13
+   |
+LL |     let _ = mem::replace(&mut refstr, "");
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::mem::take(&mut refstr)`
+   |
+   = note: `-D clippy::mem-replace-with-default` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::mem_replace_with_default)]`
+
+error: replacing a value of type `T` with `T::default()` is better expressed using `core::mem::take`
+  --> $DIR/mem_replace_no_std.rs:34:13
+   |
+LL |     let _ = mem::replace(&mut slice, &[]);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::mem::take(&mut slice)`
+
+error: replacing an `Option` with `None`
+  --> $DIR/mem_replace_no_std.rs:77:13
+   |
+LL |     let _ = mem::replace(&mut f.0, None);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `f.0.take()`
+
+error: replacing an `Option` with `None`
+  --> $DIR/mem_replace_no_std.rs:78:13
+   |
+LL |     let _ = mem::replace(&mut *f, None);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `(*f).take()`
+
+error: replacing an `Option` with `None`
+  --> $DIR/mem_replace_no_std.rs:79:13
+   |
+LL |     let _ = mem::replace(&mut b.opt, None);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `b.opt.take()`
+
+error: aborting due to 7 previous errors
+
diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs
index 777b1e52c2d..dabeda72f0c 100644
--- a/src/tools/clippy/tests/ui/no_effect.rs
+++ b/src/tools/clippy/tests/ui/no_effect.rs
@@ -181,6 +181,8 @@ fn main() {
     //~^ ERROR: binding to `_` prefixed variable with no side-effect
     let _cat = [2, 4, 6, 8][2];
     //~^ ERROR: binding to `_` prefixed variable with no side-effect
+    let _issue_12166 = 42;
+    let underscore_variable_above_can_be_used_dont_lint = _issue_12166;
 
     #[allow(clippy::no_effect)]
     0;
diff --git a/src/tools/clippy/tests/ui/no_effect.stderr b/src/tools/clippy/tests/ui/no_effect.stderr
index f5ba234b4cb..8140ba1feee 100644
--- a/src/tools/clippy/tests/ui/no_effect.stderr
+++ b/src/tools/clippy/tests/ui/no_effect.stderr
@@ -152,31 +152,31 @@ LL |     FooString { s: s };
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:175:5
+  --> $DIR/no_effect.rs:175:9
    |
 LL |     let _unused = 1;
-   |     ^^^^^^^^^^^^^^^^
+   |         ^^^^^^^
    |
    = note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::no_effect_underscore_binding)]`
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:178:5
+  --> $DIR/no_effect.rs:178:9
    |
 LL |     let _penguin = || println!("Some helpful closure");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:180:5
+  --> $DIR/no_effect.rs:180:9
    |
 LL |     let _duck = Struct { field: 0 };
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^^
 
 error: binding to `_` prefixed variable with no side-effect
-  --> $DIR/no_effect.rs:182:5
+  --> $DIR/no_effect.rs:182:9
    |
 LL |     let _cat = [2, 4, 6, 8][2];
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         ^^^^
 
 error: aborting due to 29 previous errors
 
diff --git a/src/tools/clippy/tests/ui/open_options.rs b/src/tools/clippy/tests/ui/open_options.rs
index 0cdc5bf2bb5..4acb3780df4 100644
--- a/src/tools/clippy/tests/ui/open_options.rs
+++ b/src/tools/clippy/tests/ui/open_options.rs
@@ -1,7 +1,18 @@
+#![allow(unused_must_use)]
+#![warn(clippy::nonsensical_open_options)]
+
 use std::fs::OpenOptions;
 
-#[allow(unused_must_use)]
-#[warn(clippy::nonsensical_open_options)]
+trait OpenOptionsExt {
+    fn truncate_write(&mut self, opt: bool) -> &mut Self;
+}
+
+impl OpenOptionsExt for OpenOptions {
+    fn truncate_write(&mut self, opt: bool) -> &mut Self {
+        self.truncate(opt).write(opt)
+    }
+}
+
 fn main() {
     OpenOptions::new().read(true).truncate(true).open("foo.txt");
     //~^ ERROR: file opened with `truncate` and `read`
@@ -11,12 +22,31 @@ fn main() {
 
     OpenOptions::new().read(true).read(false).open("foo.txt");
     //~^ ERROR: the method `read` is called more than once
-    OpenOptions::new().create(true).create(false).open("foo.txt");
-    //~^ ERROR: the method `create` is called more than once
+    OpenOptions::new()
+        .create(true)
+        .truncate(true) // Ensure we don't trigger suspicious open options by having create without truncate
+        .create(false)
+        //~^ ERROR: the method `create` is called more than once
+        .open("foo.txt");
     OpenOptions::new().write(true).write(false).open("foo.txt");
     //~^ ERROR: the method `write` is called more than once
     OpenOptions::new().append(true).append(false).open("foo.txt");
     //~^ ERROR: the method `append` is called more than once
     OpenOptions::new().truncate(true).truncate(false).open("foo.txt");
     //~^ ERROR: the method `truncate` is called more than once
+
+    std::fs::File::options().read(true).read(false).open("foo.txt");
+    //~^ ERROR: the method `read` is called more than once
+
+    let mut options = std::fs::OpenOptions::new();
+    options.read(true);
+    options.read(false);
+    // Possible future improvement: recognize open options method call chains across statements.
+    options.open("foo.txt");
+
+    let mut options = std::fs::OpenOptions::new();
+    options.truncate(true);
+    options.create(true).open("foo.txt");
+
+    OpenOptions::new().create(true).truncate_write(true).open("foo.txt");
 }
diff --git a/src/tools/clippy/tests/ui/open_options.stderr b/src/tools/clippy/tests/ui/open_options.stderr
index 7ac826f52fa..4f84d1d09f9 100644
--- a/src/tools/clippy/tests/ui/open_options.stderr
+++ b/src/tools/clippy/tests/ui/open_options.stderr
@@ -1,5 +1,5 @@
 error: file opened with `truncate` and `read`
-  --> $DIR/open_options.rs:6:5
+  --> $DIR/open_options.rs:17:5
    |
 LL |     OpenOptions::new().read(true).truncate(true).open("foo.txt");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,40 +8,46 @@ LL |     OpenOptions::new().read(true).truncate(true).open("foo.txt");
    = help: to override `-D warnings` add `#[allow(clippy::nonsensical_open_options)]`
 
 error: file opened with `append` and `truncate`
-  --> $DIR/open_options.rs:9:5
+  --> $DIR/open_options.rs:20:5
    |
 LL |     OpenOptions::new().append(true).truncate(true).open("foo.txt");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the method `read` is called more than once
-  --> $DIR/open_options.rs:12:5
+  --> $DIR/open_options.rs:23:35
    |
 LL |     OpenOptions::new().read(true).read(false).open("foo.txt");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                   ^^^^^^^^^^^
 
 error: the method `create` is called more than once
-  --> $DIR/open_options.rs:14:5
+  --> $DIR/open_options.rs:28:10
    |
-LL |     OpenOptions::new().create(true).create(false).open("foo.txt");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         .create(false)
+   |          ^^^^^^^^^^^^^
 
 error: the method `write` is called more than once
-  --> $DIR/open_options.rs:16:5
+  --> $DIR/open_options.rs:31:36
    |
 LL |     OpenOptions::new().write(true).write(false).open("foo.txt");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                    ^^^^^^^^^^^^
 
 error: the method `append` is called more than once
-  --> $DIR/open_options.rs:18:5
+  --> $DIR/open_options.rs:33:37
    |
 LL |     OpenOptions::new().append(true).append(false).open("foo.txt");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                     ^^^^^^^^^^^^^
 
 error: the method `truncate` is called more than once
-  --> $DIR/open_options.rs:20:5
+  --> $DIR/open_options.rs:35:39
    |
 LL |     OpenOptions::new().truncate(true).truncate(false).open("foo.txt");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                       ^^^^^^^^^^^^^^^
+
+error: the method `read` is called more than once
+  --> $DIR/open_options.rs:38:41
+   |
+LL |     std::fs::File::options().read(true).read(false).open("foo.txt");
+   |                                         ^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/open_options_fixable.fixed b/src/tools/clippy/tests/ui/open_options_fixable.fixed
new file mode 100644
index 00000000000..90a129a9bdf
--- /dev/null
+++ b/src/tools/clippy/tests/ui/open_options_fixable.fixed
@@ -0,0 +1,7 @@
+use std::fs::OpenOptions;
+#[allow(unused_must_use)]
+#[warn(clippy::suspicious_open_options)]
+fn main() {
+    OpenOptions::new().create(true).truncate(true).open("foo.txt");
+    //~^ ERROR: file opened with `create`, but `truncate` behavior not defined
+}
diff --git a/src/tools/clippy/tests/ui/open_options_fixable.rs b/src/tools/clippy/tests/ui/open_options_fixable.rs
new file mode 100644
index 00000000000..3a9e522ba15
--- /dev/null
+++ b/src/tools/clippy/tests/ui/open_options_fixable.rs
@@ -0,0 +1,7 @@
+use std::fs::OpenOptions;
+#[allow(unused_must_use)]
+#[warn(clippy::suspicious_open_options)]
+fn main() {
+    OpenOptions::new().create(true).open("foo.txt");
+    //~^ ERROR: file opened with `create`, but `truncate` behavior not defined
+}
diff --git a/src/tools/clippy/tests/ui/open_options_fixable.stderr b/src/tools/clippy/tests/ui/open_options_fixable.stderr
new file mode 100644
index 00000000000..e327661713b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/open_options_fixable.stderr
@@ -0,0 +1,14 @@
+error: file opened with `create`, but `truncate` behavior not defined
+  --> $DIR/open_options_fixable.rs:5:24
+   |
+LL |     OpenOptions::new().create(true).open("foo.txt");
+   |                        ^^^^^^^^^^^^- help: add: `.truncate(true)`
+   |
+   = help: if you intend to overwrite an existing file entirely, call `.truncate(true)`
+   = help: if you instead know that you may want to keep some parts of the old file, call `.truncate(false)`
+   = help: alternatively, use `.append(true)` to append to the file instead of overwriting it
+   = note: `-D clippy::suspicious-open-options` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::suspicious_open_options)]`
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/clippy/tests/ui/option_as_ref_deref.stderr b/src/tools/clippy/tests/ui/option_as_ref_deref.stderr
index 9d173e409ab..036b8c749e4 100644
--- a/src/tools/clippy/tests/ui/option_as_ref_deref.stderr
+++ b/src/tools/clippy/tests/ui/option_as_ref_deref.stderr
@@ -2,7 +2,7 @@ error: called `.as_ref().map(Deref::deref)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:11:13
    |
 LL |     let _ = opt.clone().as_ref().map(Deref::deref).map(str::len);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.clone().as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.clone().as_deref()`
    |
    = note: `-D clippy::option-as-ref-deref` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::option_as_ref_deref)]`
@@ -15,103 +15,103 @@ LL |       let _ = opt.clone()
 LL | |         .as_ref().map(
 LL | |             Deref::deref
 LL | |         )
-   | |_________^ help: try using as_deref instead: `opt.clone().as_deref()`
+   | |_________^ help: consider using as_deref: `opt.clone().as_deref()`
 
 error: called `.as_mut().map(DerefMut::deref_mut)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:20:13
    |
 LL |     let _ = opt.as_mut().map(DerefMut::deref_mut);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()`
 
 error: called `.as_ref().map(String::as_str)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:22:13
    |
 LL |     let _ = opt.as_ref().map(String::as_str);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()`
 
 error: called `.as_ref().map(|x| x.as_str())` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:23:13
    |
 LL |     let _ = opt.as_ref().map(|x| x.as_str());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()`
 
 error: called `.as_mut().map(String::as_mut_str)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:24:13
    |
 LL |     let _ = opt.as_mut().map(String::as_mut_str);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()`
 
 error: called `.as_mut().map(|x| x.as_mut_str())` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:25:13
    |
 LL |     let _ = opt.as_mut().map(|x| x.as_mut_str());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()`
 
 error: called `.as_ref().map(CString::as_c_str)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:26:13
    |
 LL |     let _ = Some(CString::new(vec![]).unwrap()).as_ref().map(CString::as_c_str);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(CString::new(vec![]).unwrap()).as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(CString::new(vec![]).unwrap()).as_deref()`
 
 error: called `.as_ref().map(OsString::as_os_str)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:27:13
    |
 LL |     let _ = Some(OsString::new()).as_ref().map(OsString::as_os_str);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(OsString::new()).as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(OsString::new()).as_deref()`
 
 error: called `.as_ref().map(PathBuf::as_path)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:28:13
    |
 LL |     let _ = Some(PathBuf::new()).as_ref().map(PathBuf::as_path);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(PathBuf::new()).as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(PathBuf::new()).as_deref()`
 
 error: called `.as_ref().map(Vec::as_slice)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:29:13
    |
 LL |     let _ = Some(Vec::<()>::new()).as_ref().map(Vec::as_slice);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(Vec::<()>::new()).as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `Some(Vec::<()>::new()).as_deref()`
 
 error: called `.as_mut().map(Vec::as_mut_slice)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:30:13
    |
 LL |     let _ = Some(Vec::<()>::new()).as_mut().map(Vec::as_mut_slice);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `Some(Vec::<()>::new()).as_deref_mut()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `Some(Vec::<()>::new()).as_deref_mut()`
 
 error: called `.as_ref().map(|x| x.deref())` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:32:13
    |
 LL |     let _ = opt.as_ref().map(|x| x.deref());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()`
 
 error: called `.as_mut().map(|x| x.deref_mut())` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:33:13
    |
 LL |     let _ = opt.clone().as_mut().map(|x| x.deref_mut()).map(|x| x.len());
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.clone().as_deref_mut()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.clone().as_deref_mut()`
 
 error: called `.as_ref().map(|x| &**x)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:40:13
    |
 LL |     let _ = opt.as_ref().map(|x| &**x);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()`
 
 error: called `.as_mut().map(|x| &mut **x)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:41:13
    |
 LL |     let _ = opt.as_mut().map(|x| &mut **x);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref_mut: `opt.as_deref_mut()`
 
 error: called `.as_ref().map(std::ops::Deref::deref)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:44:13
    |
 LL |     let _ = opt.as_ref().map(std::ops::Deref::deref);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()`
 
 error: called `.as_ref().map(String::as_str)` on an `Option` value
   --> $DIR/option_as_ref_deref.rs:56:13
    |
 LL |     let _ = opt.as_ref().map(String::as_str);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using as_deref: `opt.as_deref()`
 
 error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/tests/ui/option_map_or_err_ok.stderr b/src/tools/clippy/tests/ui/option_map_or_err_ok.stderr
index a193e3c4c49..381601cb6b3 100644
--- a/src/tools/clippy/tests/ui/option_map_or_err_ok.stderr
+++ b/src/tools/clippy/tests/ui/option_map_or_err_ok.stderr
@@ -2,7 +2,7 @@ error: called `map_or(Err(_), Ok)` on an `Option` value
   --> $DIR/option_map_or_err_ok.rs:5:13
    |
 LL |     let _ = x.map_or(Err("a"), Ok);
-   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok_or` instead: `x.ok_or("a")`
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok_or`: `x.ok_or("a")`
    |
    = note: `-D clippy::option-map-or-err-ok` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::option_map_or_err_ok)]`
diff --git a/src/tools/clippy/tests/ui/option_map_or_none.stderr b/src/tools/clippy/tests/ui/option_map_or_none.stderr
index f2cfc3f9a28..d58ff83c3da 100644
--- a/src/tools/clippy/tests/ui/option_map_or_none.stderr
+++ b/src/tools/clippy/tests/ui/option_map_or_none.stderr
@@ -2,7 +2,7 @@ error: called `map_or(None, ..)` on an `Option` value
   --> $DIR/option_map_or_none.rs:10:26
    |
 LL |     let _: Option<i32> = opt.map_or(None, |x| Some(x + 1));
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `map` instead: `opt.map(|x| x + 1)`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `map`: `opt.map(|x| x + 1)`
    |
    = note: `-D clippy::option-map-or-none` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::option_map_or_none)]`
@@ -14,13 +14,13 @@ LL |       let _: Option<i32> = opt.map_or(None, |x| {
    |  __________________________^
 LL | |                         Some(x + 1)
 LL | |                        });
-   | |_________________________^ help: try using `map` instead: `opt.map(|x| x + 1)`
+   | |_________________________^ help: consider using `map`: `opt.map(|x| x + 1)`
 
 error: called `map_or(None, ..)` on an `Option` value
   --> $DIR/option_map_or_none.rs:17:26
    |
 LL |     let _: Option<i32> = opt.map_or(None, bar);
-   |                          ^^^^^^^^^^^^^^^^^^^^^ help: try using `and_then` instead: `opt.and_then(bar)`
+   |                          ^^^^^^^^^^^^^^^^^^^^^ help: consider using `and_then`: `opt.and_then(bar)`
 
 error: called `map_or(None, ..)` on an `Option` value
   --> $DIR/option_map_or_none.rs:18:26
@@ -33,7 +33,7 @@ LL | |         Some(offset + height)
 LL | |     });
    | |______^
    |
-help: try using `and_then` instead
+help: consider using `and_then`
    |
 LL ~     let _: Option<i32> = opt.and_then(|x| {
 LL +         let offset = 0;
@@ -46,7 +46,7 @@ error: called `map_or(None, Some)` on a `Result` value
   --> $DIR/option_map_or_none.rs:25:26
    |
 LL |     let _: Option<i32> = r.map_or(None, Some);
-   |                          ^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `r.ok()`
+   |                          ^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `r.ok()`
    |
    = note: `-D clippy::result-map-or-into-option` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::result_map_or_into_option)]`
diff --git a/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed b/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed
new file mode 100644
index 00000000000..97c8c394c03
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ptr_eq_no_std.fixed
@@ -0,0 +1,49 @@
+#![warn(clippy::ptr_eq)]
+#![no_std]
+#![feature(lang_items)]
+
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+macro_rules! mac {
+    ($a:expr, $b:expr) => {
+        $a as *const _ as usize == $b as *const _ as usize
+    };
+}
+
+macro_rules! another_mac {
+    ($a:expr, $b:expr) => {
+        $a as *const _ == $b as *const _
+    };
+}
+
+fn main() {
+    let a = &[1, 2, 3];
+    let b = &[1, 2, 3];
+
+    let _ = core::ptr::eq(a, b);
+    let _ = core::ptr::eq(a, b);
+    let _ = a.as_ptr() == b as *const _;
+    let _ = a.as_ptr() == b.as_ptr();
+
+    // Do not lint
+
+    let _ = mac!(a, b);
+    let _ = another_mac!(a, b);
+
+    let a = &mut [1, 2, 3];
+    let b = &mut [1, 2, 3];
+
+    let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
+    let _ = a.as_mut_ptr() == b.as_mut_ptr();
+
+    let _ = a == b;
+    let _ = core::ptr::eq(a, b);
+}
diff --git a/src/tools/clippy/tests/ui/ptr_eq_no_std.rs b/src/tools/clippy/tests/ui/ptr_eq_no_std.rs
new file mode 100644
index 00000000000..a7ba9b4d817
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ptr_eq_no_std.rs
@@ -0,0 +1,49 @@
+#![warn(clippy::ptr_eq)]
+#![no_std]
+#![feature(lang_items)]
+
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+macro_rules! mac {
+    ($a:expr, $b:expr) => {
+        $a as *const _ as usize == $b as *const _ as usize
+    };
+}
+
+macro_rules! another_mac {
+    ($a:expr, $b:expr) => {
+        $a as *const _ == $b as *const _
+    };
+}
+
+fn main() {
+    let a = &[1, 2, 3];
+    let b = &[1, 2, 3];
+
+    let _ = a as *const _ as usize == b as *const _ as usize;
+    let _ = a as *const _ == b as *const _;
+    let _ = a.as_ptr() == b as *const _;
+    let _ = a.as_ptr() == b.as_ptr();
+
+    // Do not lint
+
+    let _ = mac!(a, b);
+    let _ = another_mac!(a, b);
+
+    let a = &mut [1, 2, 3];
+    let b = &mut [1, 2, 3];
+
+    let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
+    let _ = a.as_mut_ptr() == b.as_mut_ptr();
+
+    let _ = a == b;
+    let _ = core::ptr::eq(a, b);
+}
diff --git a/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr b/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr
new file mode 100644
index 00000000000..3e289f5be61
--- /dev/null
+++ b/src/tools/clippy/tests/ui/ptr_eq_no_std.stderr
@@ -0,0 +1,17 @@
+error: use `core::ptr::eq` when comparing raw pointers
+  --> $DIR/ptr_eq_no_std.rs:31:13
+   |
+LL |     let _ = a as *const _ as usize == b as *const _ as usize;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)`
+   |
+   = note: `-D clippy::ptr-eq` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]`
+
+error: use `core::ptr::eq` when comparing raw pointers
+  --> $DIR/ptr_eq_no_std.rs:32:13
+   |
+LL |     let _ = a as *const _ == b as *const _;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/read_zero_byte_vec.rs b/src/tools/clippy/tests/ui/read_zero_byte_vec.rs
index 76b9b981851..fd5a88a37a6 100644
--- a/src/tools/clippy/tests/ui/read_zero_byte_vec.rs
+++ b/src/tools/clippy/tests/ui/read_zero_byte_vec.rs
@@ -56,14 +56,6 @@ fn test() -> io::Result<()> {
     f.read(&mut buf)?;
 
     // should not lint
-    let mut empty = vec![];
-    let mut data7 = vec![];
-    f.read(&mut empty);
-
-    // should not lint
-    f.read(&mut data7);
-
-    // should not lint
     let mut data8 = Vec::new();
     data8.resize(100, 0);
     f.read_exact(&mut data8)?;
@@ -75,6 +67,27 @@ fn test() -> io::Result<()> {
     Ok(())
 }
 
+fn test_nested() -> io::Result<()> {
+    let cap = 1000;
+    let mut f = File::open("foo.txt").unwrap();
+
+    // Issue #9274
+    // Should not lint
+    let mut v = Vec::new();
+    {
+        v.resize(10, 0);
+        f.read(&mut v)?;
+    }
+
+    let mut v = Vec::new();
+    {
+        f.read(&mut v)?;
+        //~^ ERROR: reading zero byte data to `Vec`
+    }
+
+    Ok(())
+}
+
 async fn test_futures<R: AsyncRead + Unpin>(r: &mut R) {
     // should lint
     let mut data = Vec::new();
diff --git a/src/tools/clippy/tests/ui/read_zero_byte_vec.stderr b/src/tools/clippy/tests/ui/read_zero_byte_vec.stderr
index 523ecb2948d..e85aa051c34 100644
--- a/src/tools/clippy/tests/ui/read_zero_byte_vec.stderr
+++ b/src/tools/clippy/tests/ui/read_zero_byte_vec.stderr
@@ -2,7 +2,7 @@ error: reading zero byte data to `Vec`
   --> $DIR/read_zero_byte_vec.rs:21:5
    |
 LL |     f.read_exact(&mut data).unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data.resize(20, 0); f.read_exact(&mut data).unwrap();`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data.resize(20, 0); f.read_exact(&mut data)`
    |
    = note: `-D clippy::read-zero-byte-vec` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::read_zero_byte_vec)]`
@@ -11,19 +11,19 @@ error: reading zero byte data to `Vec`
   --> $DIR/read_zero_byte_vec.rs:27:5
    |
 LL |     f.read_exact(&mut data2)?;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data2.resize(cap, 0); f.read_exact(&mut data2)?;`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `data2.resize(cap, 0); f.read_exact(&mut data2)`
 
 error: reading zero byte data to `Vec`
   --> $DIR/read_zero_byte_vec.rs:32:5
    |
 LL |     f.read_exact(&mut data3)?;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: reading zero byte data to `Vec`
-  --> $DIR/read_zero_byte_vec.rs:37:5
+  --> $DIR/read_zero_byte_vec.rs:37:13
    |
 LL |     let _ = f.read(&mut data4)?;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |             ^^^^^^^^^^^^^^^^^^
 
 error: reading zero byte data to `Vec`
   --> $DIR/read_zero_byte_vec.rs:43:9
@@ -38,28 +38,34 @@ LL |         f.read(&mut data6)
    |         ^^^^^^^^^^^^^^^^^^
 
 error: reading zero byte data to `Vec`
-  --> $DIR/read_zero_byte_vec.rs:81:5
+  --> $DIR/read_zero_byte_vec.rs:84:9
+   |
+LL |         f.read(&mut v)?;
+   |         ^^^^^^^^^^^^^^
+
+error: reading zero byte data to `Vec`
+  --> $DIR/read_zero_byte_vec.rs:94:5
    |
 LL |     r.read(&mut data).await.unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^
 
 error: reading zero byte data to `Vec`
-  --> $DIR/read_zero_byte_vec.rs:86:5
+  --> $DIR/read_zero_byte_vec.rs:99:5
    |
 LL |     r.read_exact(&mut data2).await.unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: reading zero byte data to `Vec`
-  --> $DIR/read_zero_byte_vec.rs:93:5
+  --> $DIR/read_zero_byte_vec.rs:106:5
    |
 LL |     r.read(&mut data).await.unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^
 
 error: reading zero byte data to `Vec`
-  --> $DIR/read_zero_byte_vec.rs:98:5
+  --> $DIR/read_zero_byte_vec.rs:111:5
    |
 LL |     r.read_exact(&mut data2).await.unwrap();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 10 previous errors
+error: aborting due to 11 previous errors
 
diff --git a/src/tools/clippy/tests/ui/result_map_or_into_option.stderr b/src/tools/clippy/tests/ui/result_map_or_into_option.stderr
index 3d6bfef48ec..201868f09ef 100644
--- a/src/tools/clippy/tests/ui/result_map_or_into_option.stderr
+++ b/src/tools/clippy/tests/ui/result_map_or_into_option.stderr
@@ -2,7 +2,7 @@ error: called `map_or(None, Some)` on a `Result` value
   --> $DIR/result_map_or_into_option.rs:5:13
    |
 LL |     let _ = opt.map_or(None, Some);
-   |             ^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `opt.ok()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `opt.ok()`
    |
    = note: `-D clippy::result-map-or-into-option` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::result_map_or_into_option)]`
@@ -11,13 +11,13 @@ error: called `map_or_else(|_| None, Some)` on a `Result` value
   --> $DIR/result_map_or_into_option.rs:7:13
    |
 LL |     let _ = opt.map_or_else(|_| None, Some);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `opt.ok()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `opt.ok()`
 
 error: called `map_or_else(|_| None, Some)` on a `Result` value
   --> $DIR/result_map_or_into_option.rs:10:13
    |
 LL |     let _ = opt.map_or_else(|_| { None }, Some);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `opt.ok()`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `ok`: `opt.ok()`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/same_item_push.stderr b/src/tools/clippy/tests/ui/same_item_push.stderr
index f519be46369..f569aab6490 100644
--- a/src/tools/clippy/tests/ui/same_item_push.stderr
+++ b/src/tools/clippy/tests/ui/same_item_push.stderr
@@ -4,7 +4,7 @@ error: it looks like the same item is being pushed into this Vec
 LL |         vec.push(item);
    |         ^^^
    |
-   = help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
+   = help: consider using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
    = note: `-D clippy::same-item-push` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::same_item_push)]`
 
@@ -14,7 +14,7 @@ error: it looks like the same item is being pushed into this Vec
 LL |         vec.push(item);
    |         ^^^
    |
-   = help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
+   = help: consider using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
 
 error: it looks like the same item is being pushed into this Vec
   --> $DIR/same_item_push.rs:36:9
@@ -22,7 +22,7 @@ error: it looks like the same item is being pushed into this Vec
 LL |         vec.push(13);
    |         ^^^
    |
-   = help: try using vec![13;SIZE] or vec.resize(NEW_SIZE, 13)
+   = help: consider using vec![13;SIZE] or vec.resize(NEW_SIZE, 13)
 
 error: it looks like the same item is being pushed into this Vec
   --> $DIR/same_item_push.rs:42:9
@@ -30,7 +30,7 @@ error: it looks like the same item is being pushed into this Vec
 LL |         vec.push(VALUE);
    |         ^^^
    |
-   = help: try using vec![VALUE;SIZE] or vec.resize(NEW_SIZE, VALUE)
+   = help: consider using vec![VALUE;SIZE] or vec.resize(NEW_SIZE, VALUE)
 
 error: it looks like the same item is being pushed into this Vec
   --> $DIR/same_item_push.rs:49:9
@@ -38,7 +38,7 @@ error: it looks like the same item is being pushed into this Vec
 LL |         vec.push(item);
    |         ^^^
    |
-   = help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
+   = help: consider using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
 
 error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some.stderr b/src/tools/clippy/tests/ui/search_is_some.stderr
index a7a47447f61..9dec8c9caf2 100644
--- a/src/tools/clippy/tests/ui/search_is_some.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some.stderr
@@ -40,7 +40,7 @@ error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some.rs:42:20
    |
 LL |     let _ = (0..1).find(some_closure).is_some();
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(some_closure)`
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(some_closure)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some.rs:52:13
@@ -82,7 +82,7 @@ error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some.rs:79:13
    |
 LL |     let _ = (0..1).find(some_closure).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(some_closure)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(some_closure)`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr
index f33b0430912..107f59a97d2 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_none.stderr
@@ -2,7 +2,7 @@ error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:9:13
    |
 LL |     let _ = v.iter().find(|&x| *x < 0).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| *x < 0)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x < 0)`
    |
    = note: `-D clippy::search-is-some` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]`
@@ -11,43 +11,43 @@ error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:10:13
    |
 LL |     let _ = (0..1).find(|x| **y == *x).is_none(); // one dereference less
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(|x| **y == x)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(|x| **y == x)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:11:13
    |
 LL |     let _ = (0..1).find(|x| *x == 0).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(0..1).any(|x| x == 0)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(|x| x == 0)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:12:13
    |
 LL |     let _ = v.iter().find(|x| **x == 0).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| *x == 0)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| *x == 0)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:13:13
    |
 LL |     let _ = (4..5).find(|x| *x == 1 || *x == 3 || *x == 5).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(4..5).any(|x| x == 1 || x == 3 || x == 5)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(4..5).any(|x| x == 1 || x == 3 || x == 5)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:14:13
    |
 LL |     let _ = (1..3).find(|x| [1, 2, 3].contains(x)).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(1..3).any(|x| [1, 2, 3].contains(&x))`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(1..3).any(|x| [1, 2, 3].contains(&x))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:15:13
    |
 LL |     let _ = (1..3).find(|x| *x == 0 || [1, 2, 3].contains(x)).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(1..3).any(|x| x == 0 || [1, 2, 3].contains(&x))`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(1..3).any(|x| x == 0 || [1, 2, 3].contains(&x))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:16:13
    |
 LL |     let _ = (1..3).find(|x| [1, 2, 3].contains(x) || *x == 0).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!(1..3).any(|x| [1, 2, 3].contains(&x) || x == 0)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(1..3).any(|x| [1, 2, 3].contains(&x) || x == 0)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:17:13
@@ -56,91 +56,91 @@ LL |       let _ = (1..3)
    |  _____________^
 LL | |         .find(|x| [1, 2, 3].contains(x) || *x == 0 || [4, 5, 6].contains(x) || *x == -1)
 LL | |         .is_none();
-   | |__________________^ help: use `!_.any()` instead: `!(1..3).any(|x| [1, 2, 3].contains(&x) || x == 0 || [4, 5, 6].contains(&x) || x == -1)`
+   | |__________________^ help: consider using: `!(1..3).any(|x| [1, 2, 3].contains(&x) || x == 0 || [4, 5, 6].contains(&x) || x == -1)`
 
 error: called `is_none()` after searching an `Iterator` with `position`
   --> $DIR/search_is_some_fixable_none.rs:22:13
    |
 LL |     let _ = v.iter().position(|&x| x < 0).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|&x| x < 0)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|&x| x < 0)`
 
 error: called `is_none()` after searching an `Iterator` with `rposition`
   --> $DIR/search_is_some_fixable_none.rs:25:13
    |
 LL |     let _ = v.iter().rposition(|&x| x < 0).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|&x| x < 0)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|&x| x < 0)`
 
 error: called `is_none()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_none.rs:31:13
    |
 LL |     let _ = "hello world".find("world").is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!"hello world".contains("world")`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!"hello world".contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_none.rs:32:13
    |
 LL |     let _ = "hello world".find(&s2).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!"hello world".contains(&s2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!"hello world".contains(&s2)`
 
 error: called `is_none()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_none.rs:33:13
    |
 LL |     let _ = "hello world".find(&s2[2..]).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!"hello world".contains(&s2[2..])`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!"hello world".contains(&s2[2..])`
 
 error: called `is_none()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_none.rs:35:13
    |
 LL |     let _ = s1.find("world").is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1.contains("world")`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1.contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_none.rs:36:13
    |
 LL |     let _ = s1.find(&s2).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1.contains(&s2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1.contains(&s2)`
 
 error: called `is_none()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_none.rs:37:13
    |
 LL |     let _ = s1.find(&s2[2..]).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1.contains(&s2[2..])`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1.contains(&s2[2..])`
 
 error: called `is_none()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_none.rs:39:13
    |
 LL |     let _ = s1[2..].find("world").is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains("world")`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1[2..].contains("world")`
 
 error: called `is_none()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_none.rs:40:13
    |
 LL |     let _ = s1[2..].find(&s2).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains(&s2)`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1[2..].contains(&s2)`
 
 error: called `is_none()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_none.rs:41:13
    |
 LL |     let _ = s1[2..].find(&s2[2..]).is_none();
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.contains()` instead: `!s1[2..].contains(&s2[2..])`
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!s1[2..].contains(&s2[2..])`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:57:25
    |
 LL |             .filter(|c| filter_hand.iter().find(|cc| c == cc).is_none())
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!filter_hand.iter().any(|cc| c == &cc)`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!filter_hand.iter().any(|cc| c == &cc)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:73:30
    |
 LL |             .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_none())
-   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!filter_hand.iter().any(|cc| c == cc)`
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!filter_hand.iter().any(|cc| c == cc)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:84:17
    |
 LL |         let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|v| v.foo == 1 && v.bar == 2)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|v| v.foo == 1 && v.bar == 2)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:87:17
@@ -152,7 +152,7 @@ LL | |             .find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)
 LL | |             .is_none();
    | |______________________^
    |
-help: use `!_.any()` instead
+help: consider using
    |
 LL ~         let _ = !vfoo
 LL ~             .iter().any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2);
@@ -162,49 +162,49 @@ error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:95:17
    |
 LL |         let _ = vfoo.iter().find(|a| a[0] == 42).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|a| a[0] == 42)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|a| a[0] == 42)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:101:17
    |
 LL |         let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|sub| sub[1..4].len() == 3)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|sub| sub[1..4].len() == 3)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:119:17
    |
 LL |         let _ = [ppx].iter().find(|ppp_x: &&&u32| please(**ppp_x)).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `![ppx].iter().any(|ppp_x: &&u32| please(ppp_x))`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![ppx].iter().any(|ppp_x: &&u32| please(ppp_x))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:120:17
    |
 LL |         let _ = [String::from("Hey hey")].iter().find(|s| s.len() == 2).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `![String::from("Hey hey")].iter().any(|s| s.len() == 2)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![String::from("Hey hey")].iter().any(|s| s.len() == 2)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:123:17
    |
 LL |         let _ = v.iter().find(|x| deref_enough(**x)).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| deref_enough(*x))`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| deref_enough(*x))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:124:17
    |
 LL |         let _ = v.iter().find(|x: &&u32| deref_enough(**x)).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x: &u32| deref_enough(*x))`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x: &u32| deref_enough(*x))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:127:17
    |
 LL |         let _ = v.iter().find(|x| arg_no_deref(x)).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x| arg_no_deref(&x))`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x| arg_no_deref(&x))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:129:17
    |
 LL |         let _ = v.iter().find(|x: &&u32| arg_no_deref(x)).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|x: &u32| arg_no_deref(&x))`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|x: &u32| arg_no_deref(&x))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:149:17
@@ -216,7 +216,7 @@ LL | |             .find(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] ==
 LL | |             .is_none();
    | |______________________^
    |
-help: use `!_.any()` instead
+help: consider using
    |
 LL ~         let _ = !vfoo
 LL ~             .iter().any(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2);
@@ -226,61 +226,61 @@ error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:165:17
    |
 LL |         let _ = vfoo.iter().find(|v| v.inner[0].bar == 2).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|v| v.inner[0].bar == 2)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|v| v.inner[0].bar == 2)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:170:17
    |
 LL |         let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|x| (**x)[0] == 9)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|x| (**x)[0] == 9)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:183:17
    |
 LL |         let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!vfoo.iter().any(|v| v.by_ref(&v.bar))`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!vfoo.iter().any(|v| v.by_ref(&v.bar))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:187:17
    |
 LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:188:17
    |
 LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `![&(&1, 2), &(&3, 4), &(&5, 4)].iter().any(|(&x, y)| x == *y)`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:207:17
    |
 LL |         let _ = v.iter().find(|s| s[0].is_empty()).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|s| s[0].is_empty())`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|s| s[0].is_empty())`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:208:17
    |
 LL |         let _ = v.iter().find(|s| test_string_1(&s[0])).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|s| test_string_1(&s[0]))`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|s| test_string_1(&s[0]))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:217:17
    |
 LL |         let _ = v.iter().find(|fp| fp.field.is_power_of_two()).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|fp| fp.field.is_power_of_two())`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| fp.field.is_power_of_two())`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:218:17
    |
 LL |         let _ = v.iter().find(|fp| test_u32_1(fp.field)).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|fp| test_u32_1(fp.field))`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_1(fp.field))`
 
 error: called `is_none()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_none.rs:219:17
    |
 LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|fp| test_u32_2(*fp.field))`
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
 
 error: aborting due to 43 previous errors
 
diff --git a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr
index e878e62de07..e706ce64692 100644
--- a/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some_fixable_some.stderr
@@ -2,7 +2,7 @@ error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:9:22
    |
 LL |     let _ = v.iter().find(|&x| *x < 0).is_some();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| *x < 0)`
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| *x < 0)`
    |
    = note: `-D clippy::search-is-some` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]`
@@ -11,43 +11,43 @@ error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:10:20
    |
 LL |     let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| **y == x)`
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| **y == x)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:11:20
    |
 LL |     let _ = (0..1).find(|x| *x == 0).is_some();
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| x == 0)`
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| x == 0)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:12:22
    |
 LL |     let _ = v.iter().find(|x| **x == 0).is_some();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| *x == 0)`
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| *x == 0)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:13:20
    |
 LL |     let _ = (4..5).find(|x| *x == 1 || *x == 3 || *x == 5).is_some();
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| x == 1 || x == 3 || x == 5)`
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| x == 1 || x == 3 || x == 5)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:14:20
    |
 LL |     let _ = (1..3).find(|x| [1, 2, 3].contains(x)).is_some();
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| [1, 2, 3].contains(&x))`
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| [1, 2, 3].contains(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:15:20
    |
 LL |     let _ = (1..3).find(|x| *x == 0 || [1, 2, 3].contains(x)).is_some();
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| x == 0 || [1, 2, 3].contains(&x))`
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| x == 0 || [1, 2, 3].contains(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:16:20
    |
 LL |     let _ = (1..3).find(|x| [1, 2, 3].contains(x) || *x == 0).is_some();
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| [1, 2, 3].contains(&x) || x == 0)`
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| [1, 2, 3].contains(&x) || x == 0)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:18:10
@@ -55,91 +55,91 @@ error: called `is_some()` after searching an `Iterator` with `find`
 LL |           .find(|x| [1, 2, 3].contains(x) || *x == 0 || [4, 5, 6].contains(x) || *x == -1)
    |  __________^
 LL | |         .is_some();
-   | |__________________^ help: use `any()` instead: `any(|x| [1, 2, 3].contains(&x) || x == 0 || [4, 5, 6].contains(&x) || x == -1)`
+   | |__________________^ help: consider using: `any(|x| [1, 2, 3].contains(&x) || x == 0 || [4, 5, 6].contains(&x) || x == -1)`
 
 error: called `is_some()` after searching an `Iterator` with `position`
   --> $DIR/search_is_some_fixable_some.rs:22:22
    |
 LL |     let _ = v.iter().position(|&x| x < 0).is_some();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|&x| x < 0)`
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|&x| x < 0)`
 
 error: called `is_some()` after searching an `Iterator` with `rposition`
   --> $DIR/search_is_some_fixable_some.rs:25:22
    |
 LL |     let _ = v.iter().rposition(|&x| x < 0).is_some();
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|&x| x < 0)`
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|&x| x < 0)`
 
 error: called `is_some()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_some.rs:30:27
    |
 LL |     let _ = "hello world".find("world").is_some();
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains("world")`
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains("world")`
 
 error: called `is_some()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_some.rs:31:27
    |
 LL |     let _ = "hello world".find(&s2).is_some();
-   |                           ^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2)`
+   |                           ^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2)`
 
 error: called `is_some()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_some.rs:32:27
    |
 LL |     let _ = "hello world".find(&s2[2..]).is_some();
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2[2..])`
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2[2..])`
 
 error: called `is_some()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_some.rs:34:16
    |
 LL |     let _ = s1.find("world").is_some();
-   |                ^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains("world")`
+   |                ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains("world")`
 
 error: called `is_some()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_some.rs:35:16
    |
 LL |     let _ = s1.find(&s2).is_some();
-   |                ^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2)`
+   |                ^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2)`
 
 error: called `is_some()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_some.rs:36:16
    |
 LL |     let _ = s1.find(&s2[2..]).is_some();
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2[2..])`
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2[2..])`
 
 error: called `is_some()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_some.rs:38:21
    |
 LL |     let _ = s1[2..].find("world").is_some();
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains("world")`
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains("world")`
 
 error: called `is_some()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_some.rs:39:21
    |
 LL |     let _ = s1[2..].find(&s2).is_some();
-   |                     ^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2)`
+   |                     ^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2)`
 
 error: called `is_some()` after calling `find()` on a string
   --> $DIR/search_is_some_fixable_some.rs:40:21
    |
 LL |     let _ = s1[2..].find(&s2[2..]).is_some();
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `contains()` instead: `contains(&s2[2..])`
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `contains(&s2[2..])`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:56:44
    |
 LL |             .filter(|c| filter_hand.iter().find(|cc| c == cc).is_some())
-   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|cc| c == &cc)`
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|cc| c == &cc)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:72:49
    |
 LL |             .filter(|(c, _)| filter_hand.iter().find(|cc| c == *cc).is_some())
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|cc| c == cc)`
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|cc| c == cc)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:83:29
    |
 LL |         let _ = vfoo.iter().find(|v| v.foo == 1 && v.bar == 2).is_some();
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|v| v.foo == 1 && v.bar == 2)`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| v.foo == 1 && v.bar == 2)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:88:14
@@ -147,55 +147,55 @@ error: called `is_some()` after searching an `Iterator` with `find`
 LL |               .find(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)
    |  ______________^
 LL | |             .is_some();
-   | |______________________^ help: use `any()` instead: `any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)`
+   | |______________________^ help: consider using: `any(|(i, v)| *i == 42 && v.foo == 1 && v.bar == 2)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:94:29
    |
 LL |         let _ = vfoo.iter().find(|a| a[0] == 42).is_some();
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|a| a[0] == 42)`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|a| a[0] == 42)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:100:29
    |
 LL |         let _ = vfoo.iter().find(|sub| sub[1..4].len() == 3).is_some();
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|sub| sub[1..4].len() == 3)`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|sub| sub[1..4].len() == 3)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:118:30
    |
 LL |         let _ = [ppx].iter().find(|ppp_x: &&&u32| please(**ppp_x)).is_some();
-   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|ppp_x: &&u32| please(ppp_x))`
+   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|ppp_x: &&u32| please(ppp_x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:119:50
    |
 LL |         let _ = [String::from("Hey hey")].iter().find(|s| s.len() == 2).is_some();
-   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|s| s.len() == 2)`
+   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|s| s.len() == 2)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:122:26
    |
 LL |         let _ = v.iter().find(|x| deref_enough(**x)).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| deref_enough(*x))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| deref_enough(*x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:123:26
    |
 LL |         let _ = v.iter().find(|x: &&u32| deref_enough(**x)).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x: &u32| deref_enough(*x))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| deref_enough(*x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:126:26
    |
 LL |         let _ = v.iter().find(|x| arg_no_deref(x)).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| arg_no_deref(&x))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| arg_no_deref(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:128:26
    |
 LL |         let _ = v.iter().find(|x: &&u32| arg_no_deref(x)).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x: &u32| arg_no_deref(&x))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| arg_no_deref(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:150:14
@@ -203,91 +203,91 @@ error: called `is_some()` after searching an `Iterator` with `find`
 LL |               .find(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2)
    |  ______________^
 LL | |             .is_some();
-   | |______________________^ help: use `any()` instead: `any(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2)`
+   | |______________________^ help: consider using: `any(|v| v.inner_double.bar[0][0] == 2 && v.inner.bar[0] == 2)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:164:29
    |
 LL |         let _ = vfoo.iter().find(|v| v.inner[0].bar == 2).is_some();
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|v| v.inner[0].bar == 2)`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| v.inner[0].bar == 2)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:169:29
    |
 LL |         let _ = vfoo.iter().find(|x| (**x)[0] == 9).is_some();
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x| (**x)[0] == 9)`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x| (**x)[0] == 9)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:182:29
    |
 LL |         let _ = vfoo.iter().find(|v| v.by_ref(&v.bar)).is_some();
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|v| v.by_ref(&v.bar))`
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| v.by_ref(&v.bar))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:186:55
    |
 LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|(&x, y)| x == *y).is_some();
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|(&x, y)| x == *y)`
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|(&x, y)| x == *y)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:187:55
    |
 LL |         let _ = [&(&1, 2), &(&3, 4), &(&5, 4)].iter().find(|&(&x, y)| x == *y).is_some();
-   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|(&x, y)| x == *y)`
+   |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|(&x, y)| x == *y)`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:206:26
    |
 LL |         let _ = v.iter().find(|s| s[0].is_empty()).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|s| s[0].is_empty())`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|s| s[0].is_empty())`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:207:26
    |
 LL |         let _ = v.iter().find(|s| test_string_1(&s[0])).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|s| test_string_1(&s[0]))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|s| test_string_1(&s[0]))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:216:26
    |
 LL |         let _ = v.iter().find(|fp| fp.field.is_power_of_two()).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|fp| fp.field.is_power_of_two())`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|fp| fp.field.is_power_of_two())`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:217:26
    |
 LL |         let _ = v.iter().find(|fp| test_u32_1(fp.field)).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|fp| test_u32_1(fp.field))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|fp| test_u32_1(fp.field))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:218:26
    |
 LL |         let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|fp| test_u32_2(*fp.field))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|fp| test_u32_2(*fp.field))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:233:18
    |
 LL |         v.iter().find(|x: &&u32| func(x)).is_some()
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x: &u32| func(&x))`
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| func(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:242:26
    |
 LL |         let _ = v.iter().find(|x: &&u32| arg_no_deref_impl(x)).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x: &u32| arg_no_deref_impl(&x))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| arg_no_deref_impl(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:245:26
    |
 LL |         let _ = v.iter().find(|x: &&u32| arg_no_deref_dyn(x)).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x: &u32| arg_no_deref_dyn(&x))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| arg_no_deref_dyn(&x))`
 
 error: called `is_some()` after searching an `Iterator` with `find`
   --> $DIR/search_is_some_fixable_some.rs:248:26
    |
 LL |         let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some();
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `any()` instead: `any(|x: &u32| (*arg_no_deref_dyn)(&x))`
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| (*arg_no_deref_dyn)(&x))`
 
 error: aborting due to 47 previous errors
 
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
index 15cc8d54faa..8859a68320f 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.fixed
@@ -80,6 +80,7 @@ fn main() {
         .write(true)
         .read(true)
         .create(true)
+        .truncate(true)
         .open("foo.txt")
         .unwrap();
 
@@ -104,6 +105,7 @@ fn msrv_1_54() {
         .write(true)
         .read(true)
         .create(true)
+        .truncate(true)
         .open("foo.txt")
         .unwrap();
 
@@ -124,6 +126,7 @@ fn msrv_1_55() {
         .write(true)
         .read(true)
         .create(true)
+        .truncate(true)
         .open("foo.txt")
         .unwrap();
 
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
index 197225ffbd5..7b72efb34ff 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.rs
@@ -80,6 +80,7 @@ fn main() {
         .write(true)
         .read(true)
         .create(true)
+        .truncate(true)
         .open("foo.txt")
         .unwrap();
 
@@ -104,6 +105,7 @@ fn msrv_1_54() {
         .write(true)
         .read(true)
         .create(true)
+        .truncate(true)
         .open("foo.txt")
         .unwrap();
 
@@ -124,6 +126,7 @@ fn msrv_1_55() {
         .write(true)
         .read(true)
         .create(true)
+        .truncate(true)
         .open("foo.txt")
         .unwrap();
 
diff --git a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr
index 05c11cf7f8c..b6b0d2effa8 100644
--- a/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr
+++ b/src/tools/clippy/tests/ui/seek_to_start_instead_of_rewind.stderr
@@ -14,7 +14,7 @@ LL |     t.seek(SeekFrom::Start(0));
    |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
 
 error: used `seek` to go to the start of the stream
-  --> $DIR/seek_to_start_instead_of_rewind.rs:133:7
+  --> $DIR/seek_to_start_instead_of_rewind.rs:136:7
    |
 LL |     f.seek(SeekFrom::Start(0));
    |       ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `rewind()`
diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed
index bbcc0de27d1..cdfa5d9cc78 100644
--- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed
+++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.fixed
@@ -1,6 +1,11 @@
+//@aux-build:proc_macro_attr.rs
+
 #![warn(clippy::semicolon_if_nothing_returned)]
 #![allow(clippy::redundant_closure, clippy::uninlined_format_args, clippy::needless_late_init)]
 
+#[macro_use]
+extern crate proc_macro_attr;
+
 fn get_unit() {}
 
 // the functions below trigger the lint
@@ -120,3 +125,32 @@ fn let_else_stmts() {
         return;
     };
 }
+
+mod issue12123 {
+    #[rustfmt::skip]
+    mod this_triggers {
+        #[fake_main]
+        async fn main() {
+
+        }
+    }
+
+    mod and_this {
+        #[fake_main]
+        async fn main() {
+            println!("hello");
+        }
+    }
+
+    #[rustfmt::skip]
+    mod maybe_this {
+        /** */ #[fake_main]
+        async fn main() {
+        }
+    }
+
+    mod but_this_does_not {
+        #[fake_main]
+        async fn main() {}
+    }
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
index fdc9c0c33f5..315b7e4f383 100644
--- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
+++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
@@ -1,6 +1,11 @@
+//@aux-build:proc_macro_attr.rs
+
 #![warn(clippy::semicolon_if_nothing_returned)]
 #![allow(clippy::redundant_closure, clippy::uninlined_format_args, clippy::needless_late_init)]
 
+#[macro_use]
+extern crate proc_macro_attr;
+
 fn get_unit() {}
 
 // the functions below trigger the lint
@@ -120,3 +125,32 @@ fn let_else_stmts() {
         return;
     };
 }
+
+mod issue12123 {
+    #[rustfmt::skip]
+    mod this_triggers {
+        #[fake_main]
+        async fn main() {
+
+        }
+    }
+
+    mod and_this {
+        #[fake_main]
+        async fn main() {
+            println!("hello");
+        }
+    }
+
+    #[rustfmt::skip]
+    mod maybe_this {
+        /** */ #[fake_main]
+        async fn main() {
+        }
+    }
+
+    mod but_this_does_not {
+        #[fake_main]
+        async fn main() {}
+    }
+}
diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr
index 66373a13c56..09c4d12f216 100644
--- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr
+++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.stderr
@@ -1,5 +1,5 @@
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:8:5
+  --> $DIR/semicolon_if_nothing_returned.rs:13:5
    |
 LL |     println!("Hello")
    |     ^^^^^^^^^^^^^^^^^ help: add a `;` here: `println!("Hello");`
@@ -8,25 +8,25 @@ LL |     println!("Hello")
    = help: to override `-D warnings` add `#[allow(clippy::semicolon_if_nothing_returned)]`
 
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:12:5
+  --> $DIR/semicolon_if_nothing_returned.rs:17:5
    |
 LL |     get_unit()
    |     ^^^^^^^^^^ help: add a `;` here: `get_unit();`
 
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:17:5
+  --> $DIR/semicolon_if_nothing_returned.rs:22:5
    |
 LL |     y = x + 1
    |     ^^^^^^^^^ help: add a `;` here: `y = x + 1;`
 
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:23:9
+  --> $DIR/semicolon_if_nothing_returned.rs:28:9
    |
 LL |         hello()
    |         ^^^^^^^ help: add a `;` here: `hello();`
 
 error: consider adding a `;` to the last statement for consistent formatting
-  --> $DIR/semicolon_if_nothing_returned.rs:34:9
+  --> $DIR/semicolon_if_nothing_returned.rs:39:9
    |
 LL |         ptr::drop_in_place(s.as_mut_ptr())
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add a `;` here: `ptr::drop_in_place(s.as_mut_ptr());`
diff --git a/src/tools/clippy/tests/ui/single_call_fn.rs b/src/tools/clippy/tests/ui/single_call_fn.rs
index 3cc8061647d..c20214feccc 100644
--- a/src/tools/clippy/tests/ui/single_call_fn.rs
+++ b/src/tools/clippy/tests/ui/single_call_fn.rs
@@ -69,6 +69,17 @@ fn e() {
 #[test]
 fn k() {}
 
+mod issue12182 {
+    #[allow(clippy::single_call_fn)]
+    fn print_foo(text: &str) {
+        println!("{text}");
+    }
+
+    fn use_print_foo() {
+        print_foo("foo");
+    }
+}
+
 #[test]
 fn l() {
     k();
diff --git a/src/tools/clippy/tests/ui/single_char_pattern.stderr b/src/tools/clippy/tests/ui/single_char_pattern.stderr
index 781ab316d9d..664d6b5a1e9 100644
--- a/src/tools/clippy/tests/ui/single_char_pattern.stderr
+++ b/src/tools/clippy/tests/ui/single_char_pattern.stderr
@@ -2,7 +2,7 @@ error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:7:13
    |
 LL |     x.split("x");
-   |             ^^^ help: try using a `char` instead: `'x'`
+   |             ^^^ help: consider using a `char`: `'x'`
    |
    = note: `-D clippy::single-char-pattern` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::single_char_pattern)]`
@@ -11,235 +11,235 @@ error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:13:13
    |
 LL |     x.split("ß");
-   |             ^^^ help: try using a `char` instead: `'ß'`
+   |             ^^^ help: consider using a `char`: `'ß'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:14:13
    |
 LL |     x.split("ℝ");
-   |             ^^^ help: try using a `char` instead: `'ℝ'`
+   |             ^^^ help: consider using a `char`: `'ℝ'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:15:13
    |
 LL |     x.split("💣");
-   |             ^^^^ help: try using a `char` instead: `'💣'`
+   |             ^^^^ help: consider using a `char`: `'💣'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:18:23
    |
 LL |     x.split_inclusive("x");
-   |                       ^^^ help: try using a `char` instead: `'x'`
+   |                       ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:19:16
    |
 LL |     x.contains("x");
-   |                ^^^ help: try using a `char` instead: `'x'`
+   |                ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:20:19
    |
 LL |     x.starts_with("x");
-   |                   ^^^ help: try using a `char` instead: `'x'`
+   |                   ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:21:17
    |
 LL |     x.ends_with("x");
-   |                 ^^^ help: try using a `char` instead: `'x'`
+   |                 ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:22:12
    |
 LL |     x.find("x");
-   |            ^^^ help: try using a `char` instead: `'x'`
+   |            ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:23:13
    |
 LL |     x.rfind("x");
-   |             ^^^ help: try using a `char` instead: `'x'`
+   |             ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:24:14
    |
 LL |     x.rsplit("x");
-   |              ^^^ help: try using a `char` instead: `'x'`
+   |              ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:25:24
    |
 LL |     x.split_terminator("x");
-   |                        ^^^ help: try using a `char` instead: `'x'`
+   |                        ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:26:25
    |
 LL |     x.rsplit_terminator("x");
-   |                         ^^^ help: try using a `char` instead: `'x'`
+   |                         ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:27:17
    |
 LL |     x.splitn(2, "x");
-   |                 ^^^ help: try using a `char` instead: `'x'`
+   |                 ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:28:18
    |
 LL |     x.rsplitn(2, "x");
-   |                  ^^^ help: try using a `char` instead: `'x'`
+   |                  ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:29:18
    |
 LL |     x.split_once("x");
-   |                  ^^^ help: try using a `char` instead: `'x'`
+   |                  ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:30:19
    |
 LL |     x.rsplit_once("x");
-   |                   ^^^ help: try using a `char` instead: `'x'`
+   |                   ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:31:15
    |
 LL |     x.matches("x");
-   |               ^^^ help: try using a `char` instead: `'x'`
+   |               ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:32:16
    |
 LL |     x.rmatches("x");
-   |                ^^^ help: try using a `char` instead: `'x'`
+   |                ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:33:21
    |
 LL |     x.match_indices("x");
-   |                     ^^^ help: try using a `char` instead: `'x'`
+   |                     ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:34:22
    |
 LL |     x.rmatch_indices("x");
-   |                      ^^^ help: try using a `char` instead: `'x'`
+   |                      ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:35:26
    |
 LL |     x.trim_start_matches("x");
-   |                          ^^^ help: try using a `char` instead: `'x'`
+   |                          ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:36:24
    |
 LL |     x.trim_end_matches("x");
-   |                        ^^^ help: try using a `char` instead: `'x'`
+   |                        ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:37:20
    |
 LL |     x.strip_prefix("x");
-   |                    ^^^ help: try using a `char` instead: `'x'`
+   |                    ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:38:20
    |
 LL |     x.strip_suffix("x");
-   |                    ^^^ help: try using a `char` instead: `'x'`
+   |                    ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:39:15
    |
 LL |     x.replace("x", "y");
-   |               ^^^ help: try using a `char` instead: `'x'`
+   |               ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:40:16
    |
 LL |     x.replacen("x", "y", 3);
-   |                ^^^ help: try using a `char` instead: `'x'`
+   |                ^^^ help: consider using a `char`: `'x'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:42:13
    |
 LL |     x.split("\n");
-   |             ^^^^ help: try using a `char` instead: `'\n'`
+   |             ^^^^ help: consider using a `char`: `'\n'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:43:13
    |
 LL |     x.split("'");
-   |             ^^^ help: try using a `char` instead: `'\''`
+   |             ^^^ help: consider using a `char`: `'\''`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:44:13
    |
 LL |     x.split("\'");
-   |             ^^^^ help: try using a `char` instead: `'\''`
+   |             ^^^^ help: consider using a `char`: `'\''`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:46:13
    |
 LL |     x.split("\"");
-   |             ^^^^ help: try using a `char` instead: `'"'`
+   |             ^^^^ help: consider using a `char`: `'"'`
 
 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: `','`
+   |                               ^^^ help: consider using a `char`: `','`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:52:19
    |
 LL |     x.starts_with("\x03"); // issue #2996
-   |                   ^^^^^^ help: try using a `char` instead: `'\x03'`
+   |                   ^^^^^^ help: consider using a `char`: `'\x03'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:59:13
    |
 LL |     x.split(r"a");
-   |             ^^^^ help: try using a `char` instead: `'a'`
+   |             ^^^^ help: consider using a `char`: `'a'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:60:13
    |
 LL |     x.split(r#"a"#);
-   |             ^^^^^^ help: try using a `char` instead: `'a'`
+   |             ^^^^^^ help: consider using a `char`: `'a'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:61:13
    |
 LL |     x.split(r###"a"###);
-   |             ^^^^^^^^^^ help: try using a `char` instead: `'a'`
+   |             ^^^^^^^^^^ help: consider using a `char`: `'a'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:62:13
    |
 LL |     x.split(r###"'"###);
-   |             ^^^^^^^^^^ help: try using a `char` instead: `'\''`
+   |             ^^^^^^^^^^ help: consider using a `char`: `'\''`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:63:13
    |
 LL |     x.split(r###"#"###);
-   |             ^^^^^^^^^^ help: try using a `char` instead: `'#'`
+   |             ^^^^^^^^^^ help: consider using a `char`: `'#'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:65:13
    |
 LL |     x.split(r#"\"#);
-   |             ^^^^^^ help: try using a `char` instead: `'\\'`
+   |             ^^^^^^ help: consider using a `char`: `'\\'`
 
 error: single-character string constant used as pattern
   --> $DIR/single_char_pattern.rs:66:13
    |
 LL |     x.split(r"\");
-   |             ^^^^ help: try using a `char` instead: `'\\'`
+   |             ^^^^ help: consider using a `char`: `'\\'`
 
 error: aborting due to 40 previous errors
 
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
index 4fca29698e0..7e2663d734f 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.fixed
@@ -118,4 +118,33 @@ fn bad_trait_object(arg0: &(dyn Any + Send)) {
     unimplemented!();
 }
 
-fn main() {}
+trait Proj {
+    type S;
+}
+
+impl Proj for () {
+    type S = ();
+}
+
+impl Proj for i32 {
+    type S = i32;
+}
+
+trait Base<T> {
+    fn is_base(&self);
+}
+
+trait Derived<B: Proj>: Base<B::S> + Base<()> {
+    fn is_derived(&self);
+}
+
+fn f<P: Proj>(obj: &dyn Derived<P>) {
+    obj.is_derived();
+    Base::<P::S>::is_base(obj);
+    Base::<()>::is_base(obj);
+}
+
+fn main() {
+    let _x: fn(_) = f::<()>;
+    let _x: fn(_) = f::<i32>;
+}
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
index f67c8e35ed4..fede1671a43 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds.rs
@@ -118,4 +118,33 @@ fn bad_trait_object(arg0: &(dyn Any + Send + Send)) {
     unimplemented!();
 }
 
-fn main() {}
+trait Proj {
+    type S;
+}
+
+impl Proj for () {
+    type S = ();
+}
+
+impl Proj for i32 {
+    type S = i32;
+}
+
+trait Base<T> {
+    fn is_base(&self);
+}
+
+trait Derived<B: Proj>: Base<B::S> + Base<()> {
+    fn is_derived(&self);
+}
+
+fn f<P: Proj>(obj: &dyn Derived<P>) {
+    obj.is_derived();
+    Base::<P::S>::is_base(obj);
+    Base::<()>::is_base(obj);
+}
+
+fn main() {
+    let _x: fn(_) = f::<()>;
+    let _x: fn(_) = f::<i32>;
+}
diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs
index 32f6027e991..1796ccaf28e 100644
--- a/src/tools/clippy/tests/ui/transmute.rs
+++ b/src/tools/clippy/tests/ui/transmute.rs
@@ -102,19 +102,6 @@ fn crosspointer() {
     }
 }
 
-#[warn(clippy::transmute_int_to_char)]
-fn int_to_char() {
-    let _: char = unsafe { std::mem::transmute(0_u32) };
-    //~^ ERROR: transmute from a `u32` to a `char`
-    //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings`
-    let _: char = unsafe { std::mem::transmute(0_i32) };
-    //~^ ERROR: transmute from a `i32` to a `char`
-
-    // These shouldn't warn
-    const _: char = unsafe { std::mem::transmute(0_u32) };
-    const _: char = unsafe { std::mem::transmute(0_i32) };
-}
-
 #[warn(clippy::transmute_int_to_bool)]
 fn int_to_bool() {
     let _: bool = unsafe { std::mem::transmute(0_u8) };
diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr
index cdc733b54a9..df32d478cbf 100644
--- a/src/tools/clippy/tests/ui/transmute.stderr
+++ b/src/tools/clippy/tests/ui/transmute.stderr
@@ -88,23 +88,8 @@ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
 LL |         let _: *mut Usize = core::intrinsics::transmute(my_int());
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: transmute from a `u32` to a `char`
-  --> $DIR/transmute.rs:107:28
-   |
-LL |     let _: char = unsafe { std::mem::transmute(0_u32) };
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()`
-   |
-   = note: `-D clippy::transmute-int-to-char` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]`
-
-error: transmute from a `i32` to a `char`
-  --> $DIR/transmute.rs:110:28
-   |
-LL |     let _: char = unsafe { std::mem::transmute(0_i32) };
-   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()`
-
 error: transmute from a `u8` to a `bool`
-  --> $DIR/transmute.rs:120:28
+  --> $DIR/transmute.rs:107:28
    |
 LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
@@ -113,7 +98,7 @@ LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]`
 
 error: transmute from a `u32` to a `f32`
-  --> $DIR/transmute.rs:128:31
+  --> $DIR/transmute.rs:115:31
    |
 LL |         let _: f32 = unsafe { std::mem::transmute(0_u32) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
@@ -122,25 +107,25 @@ LL |         let _: f32 = unsafe { std::mem::transmute(0_u32) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_float)]`
 
 error: transmute from a `i32` to a `f32`
-  --> $DIR/transmute.rs:131:31
+  --> $DIR/transmute.rs:118:31
    |
 LL |         let _: f32 = unsafe { std::mem::transmute(0_i32) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)`
 
 error: transmute from a `u64` to a `f64`
-  --> $DIR/transmute.rs:133:31
+  --> $DIR/transmute.rs:120:31
    |
 LL |         let _: f64 = unsafe { std::mem::transmute(0_u64) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_u64)`
 
 error: transmute from a `i64` to a `f64`
-  --> $DIR/transmute.rs:135:31
+  --> $DIR/transmute.rs:122:31
    |
 LL |         let _: f64 = unsafe { std::mem::transmute(0_i64) };
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f64::from_bits(0_i64 as u64)`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> $DIR/transmute.rs:156:30
+  --> $DIR/transmute.rs:143:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
@@ -149,85 +134,85 @@ LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    = help: to override `-D warnings` add `#[allow(clippy::transmute_num_to_bytes)]`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> $DIR/transmute.rs:159:30
+  --> $DIR/transmute.rs:146:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> $DIR/transmute.rs:161:31
+  --> $DIR/transmute.rs:148:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> $DIR/transmute.rs:163:30
+  --> $DIR/transmute.rs:150:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> $DIR/transmute.rs:165:30
+  --> $DIR/transmute.rs:152:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> $DIR/transmute.rs:167:31
+  --> $DIR/transmute.rs:154:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `f32` to a `[u8; 4]`
-  --> $DIR/transmute.rs:169:30
+  --> $DIR/transmute.rs:156:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0.0f32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f32.to_ne_bytes()`
 
 error: transmute from a `f64` to a `[u8; 8]`
-  --> $DIR/transmute.rs:171:30
+  --> $DIR/transmute.rs:158:30
    |
 LL |             let _: [u8; 8] = std::mem::transmute(0.0f64);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0.0f64.to_ne_bytes()`
 
 error: transmute from a `u8` to a `[u8; 1]`
-  --> $DIR/transmute.rs:177:30
+  --> $DIR/transmute.rs:164:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0u8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u8.to_ne_bytes()`
 
 error: transmute from a `u32` to a `[u8; 4]`
-  --> $DIR/transmute.rs:179:30
+  --> $DIR/transmute.rs:166:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0u32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u32.to_ne_bytes()`
 
 error: transmute from a `u128` to a `[u8; 16]`
-  --> $DIR/transmute.rs:181:31
+  --> $DIR/transmute.rs:168:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0u128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0u128.to_ne_bytes()`
 
 error: transmute from a `i8` to a `[u8; 1]`
-  --> $DIR/transmute.rs:183:30
+  --> $DIR/transmute.rs:170:30
    |
 LL |             let _: [u8; 1] = std::mem::transmute(0i8);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i8.to_ne_bytes()`
 
 error: transmute from a `i32` to a `[u8; 4]`
-  --> $DIR/transmute.rs:185:30
+  --> $DIR/transmute.rs:172:30
    |
 LL |             let _: [u8; 4] = std::mem::transmute(0i32);
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i32.to_ne_bytes()`
 
 error: transmute from a `i128` to a `[u8; 16]`
-  --> $DIR/transmute.rs:187:31
+  --> $DIR/transmute.rs:174:31
    |
 LL |             let _: [u8; 16] = std::mem::transmute(0i128);
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `to_ne_bytes()`: `0i128.to_ne_bytes()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> $DIR/transmute.rs:198:28
+  --> $DIR/transmute.rs:185:28
    |
 LL |     let _: &str = unsafe { std::mem::transmute(B) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@@ -236,16 +221,16 @@ LL |     let _: &str = unsafe { std::mem::transmute(B) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]`
 
 error: transmute from a `&mut [u8]` to a `&mut str`
-  --> $DIR/transmute.rs:201:32
+  --> $DIR/transmute.rs:188:32
    |
 LL |     let _: &mut str = unsafe { std::mem::transmute(mb) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> $DIR/transmute.rs:203:30
+  --> $DIR/transmute.rs:190:30
    |
 LL |     const _: &str = unsafe { std::mem::transmute(B) };
    |                              ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
 
-error: aborting due to 38 previous errors
+error: aborting due to 36 previous errors
 
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char.fixed b/src/tools/clippy/tests/ui/transmute_int_to_char.fixed
new file mode 100644
index 00000000000..17080118175
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char.fixed
@@ -0,0 +1,15 @@
+#![warn(clippy::transmute_int_to_char)]
+
+fn int_to_char() {
+    let _: char = unsafe { std::char::from_u32(0_u32).unwrap() };
+    //~^ ERROR: transmute from a `u32` to a `char`
+    //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings`
+    let _: char = unsafe { std::char::from_u32(0_i32 as u32).unwrap() };
+    //~^ ERROR: transmute from a `i32` to a `char`
+
+    // These shouldn't warn
+    const _: char = unsafe { std::mem::transmute(0_u32) };
+    const _: char = unsafe { std::mem::transmute(0_i32) };
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char.rs b/src/tools/clippy/tests/ui/transmute_int_to_char.rs
new file mode 100644
index 00000000000..5846a97e88a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char.rs
@@ -0,0 +1,15 @@
+#![warn(clippy::transmute_int_to_char)]
+
+fn int_to_char() {
+    let _: char = unsafe { std::mem::transmute(0_u32) };
+    //~^ ERROR: transmute from a `u32` to a `char`
+    //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings`
+    let _: char = unsafe { std::mem::transmute(0_i32) };
+    //~^ ERROR: transmute from a `i32` to a `char`
+
+    // These shouldn't warn
+    const _: char = unsafe { std::mem::transmute(0_u32) };
+    const _: char = unsafe { std::mem::transmute(0_i32) };
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char.stderr b/src/tools/clippy/tests/ui/transmute_int_to_char.stderr
new file mode 100644
index 00000000000..2297f5b4f8b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char.stderr
@@ -0,0 +1,17 @@
+error: transmute from a `u32` to a `char`
+  --> $DIR/transmute_int_to_char.rs:4:28
+   |
+LL |     let _: char = unsafe { std::mem::transmute(0_u32) };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()`
+   |
+   = note: `-D clippy::transmute-int-to-char` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]`
+
+error: transmute from a `i32` to a `char`
+  --> $DIR/transmute_int_to_char.rs:7:28
+   |
+LL |     let _: char = unsafe { std::mem::transmute(0_i32) };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed
new file mode 100644
index 00000000000..9ae4e11fb56
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.fixed
@@ -0,0 +1,27 @@
+#![no_std]
+#![feature(lang_items)]
+#![warn(clippy::transmute_int_to_char)]
+
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+fn int_to_char() {
+    let _: char = unsafe { core::char::from_u32(0_u32).unwrap() };
+    //~^ ERROR: transmute from a `u32` to a `char`
+    //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings`
+    let _: char = unsafe { core::char::from_u32(0_i32 as u32).unwrap() };
+    //~^ ERROR: transmute from a `i32` to a `char`
+
+    // These shouldn't warn
+    const _: char = unsafe { core::mem::transmute(0_u32) };
+    const _: char = unsafe { core::mem::transmute(0_i32) };
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs
new file mode 100644
index 00000000000..9a2afd5bd2f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.rs
@@ -0,0 +1,27 @@
+#![no_std]
+#![feature(lang_items)]
+#![warn(clippy::transmute_int_to_char)]
+
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+fn int_to_char() {
+    let _: char = unsafe { core::mem::transmute(0_u32) };
+    //~^ ERROR: transmute from a `u32` to a `char`
+    //~| NOTE: `-D clippy::transmute-int-to-char` implied by `-D warnings`
+    let _: char = unsafe { core::mem::transmute(0_i32) };
+    //~^ ERROR: transmute from a `i32` to a `char`
+
+    // These shouldn't warn
+    const _: char = unsafe { core::mem::transmute(0_u32) };
+    const _: char = unsafe { core::mem::transmute(0_i32) };
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.stderr b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.stderr
new file mode 100644
index 00000000000..aace6968696
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_char_no_std.stderr
@@ -0,0 +1,17 @@
+error: transmute from a `u32` to a `char`
+  --> $DIR/transmute_int_to_char_no_std.rs:16:28
+   |
+LL |     let _: char = unsafe { core::mem::transmute(0_u32) };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::char::from_u32(0_u32).unwrap()`
+   |
+   = note: `-D clippy::transmute-int-to-char` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_char)]`
+
+error: transmute from a `i32` to a `char`
+  --> $DIR/transmute_int_to_char_no_std.rs:19:28
+   |
+LL |     let _: char = unsafe { core::mem::transmute(0_i32) };
+   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `core::char::from_u32(0_i32 as u32).unwrap()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/transmute_ref_to_ref.rs b/src/tools/clippy/tests/ui/transmute_ref_to_ref.rs
index e7f35c57436..bdc7b9f6478 100644
--- a/src/tools/clippy/tests/ui/transmute_ref_to_ref.rs
+++ b/src/tools/clippy/tests/ui/transmute_ref_to_ref.rs
@@ -12,7 +12,7 @@ fn main() {
         let b: &[u8] = unsafe { std::mem::transmute(a) };
         //~^ ERROR: transmute from a reference to a reference
         let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8];
-        let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) };
+        let alt_slice: &[u32] = unsafe { std::mem::transmute(bytes) };
         //~^ ERROR: transmute from a reference to a reference
     }
 }
diff --git a/src/tools/clippy/tests/ui/transmute_ref_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ref_to_ref.stderr
index cc6b156b188..4238bc637ad 100644
--- a/src/tools/clippy/tests/ui/transmute_ref_to_ref.stderr
+++ b/src/tools/clippy/tests/ui/transmute_ref_to_ref.stderr
@@ -19,8 +19,8 @@ LL |         let b: &[u8] = unsafe { std::mem::transmute(a) };
 error: transmute from a reference to a reference
   --> $DIR/transmute_ref_to_ref.rs:15:42
    |
-LL |         let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) };
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])`
+LL |         let alt_slice: &[u32] = unsafe { std::mem::transmute(bytes) };
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/transmute_ref_to_ref_no_std.rs b/src/tools/clippy/tests/ui/transmute_ref_to_ref_no_std.rs
new file mode 100644
index 00000000000..b67386f8588
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_ref_to_ref_no_std.rs
@@ -0,0 +1,30 @@
+//@no-rustfix
+
+#![deny(clippy::transmute_ptr_to_ptr)]
+#![allow(dead_code)]
+#![feature(lang_items)]
+#![no_std]
+
+use core::panic::PanicInfo;
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
+
+#[panic_handler]
+fn panic(info: &PanicInfo) -> ! {
+    loop {}
+}
+
+fn main() {
+    unsafe {
+        let single_u64: &[u64] = &[0xDEAD_BEEF_DEAD_BEEF];
+        let bools: &[bool] = unsafe { core::mem::transmute(single_u64) };
+        //~^ ERROR: transmute from a reference to a reference
+        let a: &[u32] = &[0x12345678, 0x90ABCDEF, 0xFEDCBA09, 0x87654321];
+        let b: &[u8] = unsafe { core::mem::transmute(a) };
+        //~^ ERROR: transmute from a reference to a reference
+        let bytes = &[1u8, 2u8, 3u8, 4u8] as &[u8];
+        let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) };
+        //~^ ERROR: transmute from a reference to a reference
+    }
+}
diff --git a/src/tools/clippy/tests/ui/transmute_ref_to_ref_no_std.stderr b/src/tools/clippy/tests/ui/transmute_ref_to_ref_no_std.stderr
new file mode 100644
index 00000000000..ca7966ffa9e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_ref_to_ref_no_std.stderr
@@ -0,0 +1,26 @@
+error: transmute from a reference to a reference
+  --> $DIR/transmute_ref_to_ref_no_std.rs:21:39
+   |
+LL |         let bools: &[bool] = unsafe { core::mem::transmute(single_u64) };
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(single_u64 as *const [u64] as *const [bool])`
+   |
+note: the lint level is defined here
+  --> $DIR/transmute_ref_to_ref_no_std.rs:3:9
+   |
+LL | #![deny(clippy::transmute_ptr_to_ptr)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: transmute from a reference to a reference
+  --> $DIR/transmute_ref_to_ref_no_std.rs:24:33
+   |
+LL |         let b: &[u8] = unsafe { core::mem::transmute(a) };
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(a as *const [u32] as *const [u8])`
+
+error: transmute from a reference to a reference
+  --> $DIR/transmute_ref_to_ref_no_std.rs:27:42
+   |
+LL |         let alt_slice: &[u32] = unsafe { core::mem::transmute(bytes) };
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(bytes as *const [u8] as *const [u32])`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.rs b/src/tools/clippy/tests/ui/unconditional_recursion.rs
index e1a2d6a90b8..7b898a6e0e7 100644
--- a/src/tools/clippy/tests/ui/unconditional_recursion.rs
+++ b/src/tools/clippy/tests/ui/unconditional_recursion.rs
@@ -264,6 +264,28 @@ impl S13 {
     }
 }
 
-fn main() {
-    // test code goes here
+struct S14 {
+    field: String,
+}
+
+impl PartialEq for S14 {
+    fn eq(&self, other: &Self) -> bool {
+        // Should not warn!
+        self.field.eq(&other.field)
+    }
+}
+
+struct S15<'a> {
+    field: &'a S15<'a>,
 }
+
+impl PartialEq for S15<'_> {
+    fn eq(&self, other: &Self) -> bool {
+        //~^ ERROR: function cannot return without recursing
+        let mine = &self.field;
+        let theirs = &other.field;
+        mine.eq(theirs)
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.stderr b/src/tools/clippy/tests/ui/unconditional_recursion.stderr
index 5d82e2a9f31..094b80d4586 100644
--- a/src/tools/clippy/tests/ui/unconditional_recursion.stderr
+++ b/src/tools/clippy/tests/ui/unconditional_recursion.stderr
@@ -340,5 +340,22 @@ note: recursive call site
 LL |         Self::default()
    |         ^^^^^^^^^^^^^^^
 
-error: aborting due to 26 previous errors
+error: function cannot return without recursing
+  --> $DIR/unconditional_recursion.rs:283:5
+   |
+LL | /     fn eq(&self, other: &Self) -> bool {
+LL | |
+LL | |         let mine = &self.field;
+LL | |         let theirs = &other.field;
+LL | |         mine.eq(theirs)
+LL | |     }
+   | |_____^
+   |
+note: recursive call site
+  --> $DIR/unconditional_recursion.rs:287:9
+   |
+LL |         mine.eq(theirs)
+   |         ^^^^^^^^^^^^^^^
+
+error: aborting due to 27 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_join.stderr b/src/tools/clippy/tests/ui/unnecessary_join.stderr
index 8bf2ac5fdb1..205a714b694 100644
--- a/src/tools/clippy/tests/ui/unnecessary_join.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_join.stderr
@@ -4,7 +4,7 @@ error: called `.collect::<Vec<String>>().join("")` on an iterator
 LL |           .collect::<Vec<String>>()
    |  __________^
 LL | |         .join("");
-   | |_________________^ help: try using: `collect::<String>()`
+   | |_________________^ help: consider using: `collect::<String>()`
    |
    = note: `-D clippy::unnecessary-join` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_join)]`
@@ -15,7 +15,7 @@ error: called `.collect::<Vec<String>>().join("")` on an iterator
 LL |           .collect::<Vec<_>>()
    |  __________^
 LL | |         .join("");
-   | |_________________^ help: try using: `collect::<String>()`
+   | |_________________^ help: consider using: `collect::<String>()`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr
index 9d54c8d50e3..f4409113a45 100644
--- a/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_sort_by.stderr
@@ -1,4 +1,4 @@
-error: use Vec::sort here instead
+error: consider using `sort`
   --> $DIR/unnecessary_sort_by.rs:12:5
    |
 LL |     vec.sort_by(|a, b| a.cmp(b));
@@ -7,67 +7,67 @@ LL |     vec.sort_by(|a, b| a.cmp(b));
    = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]`
 
-error: use Vec::sort here instead
+error: consider using `sort`
   --> $DIR/unnecessary_sort_by.rs:13:5
    |
 LL |     vec.sort_unstable_by(|a, b| a.cmp(b));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable()`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:14:5
    |
 LL |     vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:15:5
    |
 LL |     vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b)));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| id(-a))`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:18:5
    |
 LL |     vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs()))`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:19:5
    |
 LL |     vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a)));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|b| std::cmp::Reverse(id(-b)))`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:29:5
    |
 LL |     vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:30:5
    |
 LL |     vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs()));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_unstable_by_key(|a| (***a).abs())`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:89:9
    |
 LL |         args.sort_by(|a, b| a.name().cmp(&b.name()));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:90:9
    |
 LL |         args.sort_unstable_by(|a, b| a.name().cmp(&b.name()));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_unstable_by_key(|a| a.name())`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:92:9
    |
 LL |         args.sort_by(|a, b| b.name().cmp(&a.name()));
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| std::cmp::Reverse(b.name()))`
 
-error: use Vec::sort_by_key here instead
+error: consider using `sort_by_key`
   --> $DIR/unnecessary_sort_by.rs:93:9
    |
 LL |         args.sort_unstable_by(|a, b| b.name().cmp(&a.name()));
diff --git a/src/tools/clippy/tests/ui/unused_io_amount.rs b/src/tools/clippy/tests/ui/unused_io_amount.rs
index 62aec6e9eaf..9974600dad5 100644
--- a/src/tools/clippy/tests/ui/unused_io_amount.rs
+++ b/src/tools/clippy/tests/ui/unused_io_amount.rs
@@ -1,4 +1,5 @@
 #![allow(dead_code, clippy::needless_pass_by_ref_mut)]
+#![allow(clippy::redundant_pattern_matching)]
 #![warn(clippy::unused_io_amount)]
 
 extern crate futures;
@@ -142,4 +143,90 @@ async fn undetected_bad_async_write<W: AsyncWrite + Unpin>(w: &mut W) {
     future.await.unwrap();
 }
 
+fn match_okay_underscore<T: io::Read + io::Write>(s: &mut T) {
+    match s.write(b"test") {
+        //~^ ERROR: written amount is not handled
+        Ok(_) => todo!(),
+        //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled
+        Err(_) => todo!(),
+    };
+
+    let mut buf = [0u8; 4];
+    match s.read(&mut buf) {
+        //~^ ERROR: read amount is not handled
+        Ok(_) => todo!(),
+        //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled
+        Err(_) => todo!(),
+    }
+}
+
+fn match_okay_underscore_read_expr<T: io::Read + io::Write>(s: &mut T) {
+    match s.read(&mut [0u8; 4]) {
+        //~^ ERROR: read amount is not handled
+        Ok(_) => todo!(),
+        //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled
+        Err(_) => todo!(),
+    }
+}
+
+fn match_okay_underscore_write_expr<T: io::Read + io::Write>(s: &mut T) {
+    match s.write(b"test") {
+        //~^ ERROR: written amount is not handled
+        Ok(_) => todo!(),
+        //~^ NOTE: the result is consumed here, but the amount of I/O bytes remains unhandled
+        Err(_) => todo!(),
+    }
+}
+
+fn returned_value_should_not_lint<T: io::Read + io::Write>(s: &mut T) -> Result<usize, std::io::Error> {
+    s.write(b"test")
+}
+
+fn if_okay_underscore_read_expr<T: io::Read + io::Write>(s: &mut T) {
+    if let Ok(_) = s.read(&mut [0u8; 4]) {
+        //~^ ERROR: read amount is not handled
+        todo!()
+    }
+}
+
+fn if_okay_underscore_write_expr<T: io::Read + io::Write>(s: &mut T) {
+    if let Ok(_) = s.write(b"test") {
+        //~^ ERROR: written amount is not handled
+        todo!()
+    }
+}
+
+fn if_okay_dots_write_expr<T: io::Read + io::Write>(s: &mut T) {
+    if let Ok(..) = s.write(b"test") {
+        //~^ ERROR: written amount is not handled
+        todo!()
+    }
+}
+
+fn if_okay_underscore_write_expr_true_negative<T: io::Read + io::Write>(s: &mut T) {
+    if let Ok(bound) = s.write(b"test") {
+        todo!()
+    }
+}
+
+fn match_okay_underscore_true_neg<T: io::Read + io::Write>(s: &mut T) {
+    match s.write(b"test") {
+        Ok(bound) => todo!(),
+        Err(_) => todo!(),
+    };
+}
+
+fn true_negative<T: io::Read + io::Write>(s: &mut T) {
+    let mut buf = [0u8; 4];
+    let read_amount = s.read(&mut buf).unwrap();
+}
+
+fn on_return_should_not_raise<T: io::Read + io::Write>(s: &mut T) -> io::Result<usize> {
+    /// this is bad code because it goes around the problem of handling the read amount
+    /// by returning it, which makes it impossible to know this is a resonpose from the
+    /// correct account.
+    let mut buf = [0u8; 4];
+    s.read(&mut buf)
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/unused_io_amount.stderr b/src/tools/clippy/tests/ui/unused_io_amount.stderr
index f9aef596a1c..4af56d264bf 100644
--- a/src/tools/clippy/tests/ui/unused_io_amount.stderr
+++ b/src/tools/clippy/tests/ui/unused_io_amount.stderr
@@ -1,5 +1,5 @@
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:9:5
+  --> $DIR/unused_io_amount.rs:10:5
    |
 LL |     s.write(b"test")?;
    |     ^^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL |     s.write(b"test")?;
    = help: to override `-D warnings` add `#[allow(clippy::unused_io_amount)]`
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:12:5
+  --> $DIR/unused_io_amount.rs:13:5
    |
 LL |     s.read(&mut buf)?;
    |     ^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     s.read(&mut buf)?;
    = help: use `Read::read_exact` instead, or handle partial reads
 
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:18:5
+  --> $DIR/unused_io_amount.rs:19:5
    |
 LL |     s.write(b"test").unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL |     s.write(b"test").unwrap();
    = help: use `Write::write_all` instead, or handle partial writes
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:21:5
+  --> $DIR/unused_io_amount.rs:22:5
    |
 LL |     s.read(&mut buf).unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -33,19 +33,19 @@ LL |     s.read(&mut buf).unwrap();
    = help: use `Read::read_exact` instead, or handle partial reads
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:26:5
+  --> $DIR/unused_io_amount.rs:27:5
    |
 LL |     s.read_vectored(&mut [io::IoSliceMut::new(&mut [])])?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:28:5
+  --> $DIR/unused_io_amount.rs:29:5
    |
 LL |     s.write_vectored(&[io::IoSlice::new(&[])])?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:36:5
+  --> $DIR/unused_io_amount.rs:37:5
    |
 LL |     reader.read(&mut result).ok()?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,7 +53,7 @@ LL |     reader.read(&mut result).ok()?;
    = help: use `Read::read_exact` instead, or handle partial reads
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:46:5
+  --> $DIR/unused_io_amount.rs:47:5
    |
 LL |     reader.read(&mut result).or_else(|err| Err(err))?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -61,7 +61,7 @@ LL |     reader.read(&mut result).or_else(|err| Err(err))?;
    = help: use `Read::read_exact` instead, or handle partial reads
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:59:5
+  --> $DIR/unused_io_amount.rs:60:5
    |
 LL |     reader.read(&mut result).or(Err(Error::Kind))?;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -69,7 +69,7 @@ LL |     reader.read(&mut result).or(Err(Error::Kind))?;
    = help: use `Read::read_exact` instead, or handle partial reads
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:67:5
+  --> $DIR/unused_io_amount.rs:68:5
    |
 LL | /     reader
 LL | |
@@ -82,7 +82,7 @@ LL | |         .expect("error");
    = help: use `Read::read_exact` instead, or handle partial reads
 
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:77:5
+  --> $DIR/unused_io_amount.rs:78:5
    |
 LL |     s.write(b"ok").is_ok();
    |     ^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +90,7 @@ LL |     s.write(b"ok").is_ok();
    = help: use `Write::write_all` instead, or handle partial writes
 
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:79:5
+  --> $DIR/unused_io_amount.rs:80:5
    |
 LL |     s.write(b"err").is_err();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -98,7 +98,7 @@ LL |     s.write(b"err").is_err();
    = help: use `Write::write_all` instead, or handle partial writes
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:82:5
+  --> $DIR/unused_io_amount.rs:83:5
    |
 LL |     s.read(&mut buf).is_ok();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -106,7 +106,7 @@ LL |     s.read(&mut buf).is_ok();
    = help: use `Read::read_exact` instead, or handle partial reads
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:84:5
+  --> $DIR/unused_io_amount.rs:85:5
    |
 LL |     s.read(&mut buf).is_err();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -114,7 +114,7 @@ LL |     s.read(&mut buf).is_err();
    = help: use `Read::read_exact` instead, or handle partial reads
 
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:89:5
+  --> $DIR/unused_io_amount.rs:90:5
    |
 LL |     w.write(b"hello world").await.unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -122,7 +122,7 @@ LL |     w.write(b"hello world").await.unwrap();
    = help: use `AsyncWriteExt::write_all` instead, or handle partial writes
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:95:5
+  --> $DIR/unused_io_amount.rs:96:5
    |
 LL |     r.read(&mut buf[..]).await.unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -130,7 +130,15 @@ LL |     r.read(&mut buf[..]).await.unwrap();
    = help: use `AsyncReadExt::read_exact` instead, or handle partial reads
 
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:109:9
+  --> $DIR/unused_io_amount.rs:104:5
+   |
+LL |     w.write(b"hello world");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `AsyncWriteExt::write_all` instead, or handle partial writes
+
+error: written amount is not handled
+  --> $DIR/unused_io_amount.rs:110:9
    |
 LL |         w.write(b"hello world").await?;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -138,7 +146,7 @@ LL |         w.write(b"hello world").await?;
    = help: use `AsyncWriteExt::write_all` instead, or handle partial writes
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:118:9
+  --> $DIR/unused_io_amount.rs:119:9
    |
 LL |         r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -146,7 +154,7 @@ LL |         r.read(&mut buf[..]).await.or(Err(Error::Kind))?;
    = help: use `AsyncReadExt::read_exact` instead, or handle partial reads
 
 error: written amount is not handled
-  --> $DIR/unused_io_amount.rs:127:5
+  --> $DIR/unused_io_amount.rs:128:5
    |
 LL |     w.write(b"hello world").await.unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,12 +162,103 @@ LL |     w.write(b"hello world").await.unwrap();
    = help: use `AsyncWriteExt::write_all` instead, or handle partial writes
 
 error: read amount is not handled
-  --> $DIR/unused_io_amount.rs:133:5
+  --> $DIR/unused_io_amount.rs:134:5
    |
 LL |     r.read(&mut buf[..]).await.unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: use `AsyncReadExt::read_exact` instead, or handle partial reads
 
-error: aborting due to 20 previous errors
+error: written amount is not handled
+  --> $DIR/unused_io_amount.rs:147:11
+   |
+LL |     match s.write(b"test") {
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = help: use `Write::write_all` instead, or handle partial writes
+note: the result is consumed here, but the amount of I/O bytes remains unhandled
+  --> $DIR/unused_io_amount.rs:149:9
+   |
+LL |         Ok(_) => todo!(),
+   |         ^^^^^^^^^^^^^^^^
+
+error: read amount is not handled
+  --> $DIR/unused_io_amount.rs:155:11
+   |
+LL |     match s.read(&mut buf) {
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = help: use `Read::read_exact` instead, or handle partial reads
+note: the result is consumed here, but the amount of I/O bytes remains unhandled
+  --> $DIR/unused_io_amount.rs:157:9
+   |
+LL |         Ok(_) => todo!(),
+   |         ^^^^^^^^^^^^^^^^
+
+error: read amount is not handled
+  --> $DIR/unused_io_amount.rs:164:11
+   |
+LL |     match s.read(&mut [0u8; 4]) {
+   |           ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `Read::read_exact` instead, or handle partial reads
+note: the result is consumed here, but the amount of I/O bytes remains unhandled
+  --> $DIR/unused_io_amount.rs:166:9
+   |
+LL |         Ok(_) => todo!(),
+   |         ^^^^^^^^^^^^^^^^
+
+error: written amount is not handled
+  --> $DIR/unused_io_amount.rs:173:11
+   |
+LL |     match s.write(b"test") {
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = help: use `Write::write_all` instead, or handle partial writes
+note: the result is consumed here, but the amount of I/O bytes remains unhandled
+  --> $DIR/unused_io_amount.rs:175:9
+   |
+LL |         Ok(_) => todo!(),
+   |         ^^^^^^^^^^^^^^^^
+
+error: read amount is not handled
+  --> $DIR/unused_io_amount.rs:186:8
+   |
+LL |     if let Ok(_) = s.read(&mut [0u8; 4]) {
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `Read::read_exact` instead, or handle partial reads
+note: the result is consumed here, but the amount of I/O bytes remains unhandled
+  --> $DIR/unused_io_amount.rs:186:12
+   |
+LL |     if let Ok(_) = s.read(&mut [0u8; 4]) {
+   |            ^^^^^
+
+error: written amount is not handled
+  --> $DIR/unused_io_amount.rs:193:8
+   |
+LL |     if let Ok(_) = s.write(b"test") {
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `Write::write_all` instead, or handle partial writes
+note: the result is consumed here, but the amount of I/O bytes remains unhandled
+  --> $DIR/unused_io_amount.rs:193:12
+   |
+LL |     if let Ok(_) = s.write(b"test") {
+   |            ^^^^^
+
+error: written amount is not handled
+  --> $DIR/unused_io_amount.rs:200:8
+   |
+LL |     if let Ok(..) = s.write(b"test") {
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use `Write::write_all` instead, or handle partial writes
+note: the result is consumed here, but the amount of I/O bytes remains unhandled
+  --> $DIR/unused_io_amount.rs:200:12
+   |
+LL |     if let Ok(..) = s.write(b"test") {
+   |            ^^^^^^
+
+error: aborting due to 28 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_asref.fixed b/src/tools/clippy/tests/ui/useless_asref.fixed
index 88b95095bc0..c98f2928e03 100644
--- a/src/tools/clippy/tests/ui/useless_asref.fixed
+++ b/src/tools/clippy/tests/ui/useless_asref.fixed
@@ -144,6 +144,42 @@ fn foo() {
     //~^ ERROR: this call to `as_ref.map(...)` does nothing
 }
 
+mod issue12135 {
+    pub struct Struct {
+        field: Option<InnerStruct>,
+    }
+
+    #[derive(Clone)]
+    pub struct Foo;
+
+    #[derive(Clone)]
+    struct InnerStruct {
+        x: Foo,
+    }
+
+    impl InnerStruct {
+        fn method(&self) -> &Foo {
+            &self.x
+        }
+    }
+
+    pub fn f(x: &Struct) -> Option<Foo> {
+        x.field.clone();
+        //~^ ERROR: this call to `as_ref.map(...)` does nothing
+        x.field.clone();
+        //~^ ERROR: this call to `as_ref.map(...)` does nothing
+        x.field.clone();
+        //~^ ERROR: this call to `as_ref.map(...)` does nothing
+
+        // https://github.com/rust-lang/rust-clippy/pull/12136#discussion_r1451565223
+        #[allow(clippy::clone_on_copy)]
+        Some(1).clone();
+        //~^ ERROR: this call to `as_ref.map(...)` does nothing
+
+        x.field.as_ref().map(|v| v.method().clone())
+    }
+}
+
 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 504dc1f5cbf..f9d603f116d 100644
--- a/src/tools/clippy/tests/ui/useless_asref.rs
+++ b/src/tools/clippy/tests/ui/useless_asref.rs
@@ -144,6 +144,42 @@ fn foo() {
     //~^ ERROR: this call to `as_ref.map(...)` does nothing
 }
 
+mod issue12135 {
+    pub struct Struct {
+        field: Option<InnerStruct>,
+    }
+
+    #[derive(Clone)]
+    pub struct Foo;
+
+    #[derive(Clone)]
+    struct InnerStruct {
+        x: Foo,
+    }
+
+    impl InnerStruct {
+        fn method(&self) -> &Foo {
+            &self.x
+        }
+    }
+
+    pub fn f(x: &Struct) -> Option<Foo> {
+        x.field.as_ref().map(|v| v.clone());
+        //~^ ERROR: this call to `as_ref.map(...)` does nothing
+        x.field.as_ref().map(Clone::clone);
+        //~^ ERROR: this call to `as_ref.map(...)` does nothing
+        x.field.as_ref().map(|v| Clone::clone(v));
+        //~^ ERROR: this call to `as_ref.map(...)` does nothing
+
+        // https://github.com/rust-lang/rust-clippy/pull/12136#discussion_r1451565223
+        #[allow(clippy::clone_on_copy)]
+        Some(1).as_ref().map(|&x| x.clone());
+        //~^ ERROR: this call to `as_ref.map(...)` does nothing
+
+        x.field.as_ref().map(|v| v.method().clone())
+    }
+}
+
 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 deb5d90f2f6..e158df2664d 100644
--- a/src/tools/clippy/tests/ui/useless_asref.stderr
+++ b/src/tools/clippy/tests/ui/useless_asref.stderr
@@ -88,5 +88,29 @@ error: this call to `as_ref.map(...)` does nothing
 LL |     let z = x.as_ref().map(|z| String::clone(z));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.clone()`
 
-error: aborting due to 14 previous errors
+error: this call to `as_ref.map(...)` does nothing
+  --> $DIR/useless_asref.rs:167:9
+   |
+LL |         x.field.as_ref().map(|v| v.clone());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()`
+
+error: this call to `as_ref.map(...)` does nothing
+  --> $DIR/useless_asref.rs:169:9
+   |
+LL |         x.field.as_ref().map(Clone::clone);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()`
+
+error: this call to `as_ref.map(...)` does nothing
+  --> $DIR/useless_asref.rs:171:9
+   |
+LL |         x.field.as_ref().map(|v| Clone::clone(v));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.field.clone()`
+
+error: this call to `as_ref.map(...)` does nothing
+  --> $DIR/useless_asref.rs:176:9
+   |
+LL |         Some(1).as_ref().map(|&x| x.clone());
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(1).clone()`
+
+error: aborting due to 18 previous errors
 
diff --git a/src/tools/clippy/triagebot.toml b/src/tools/clippy/triagebot.toml
index a05765b3981..3eadc66f544 100644
--- a/src/tools/clippy/triagebot.toml
+++ b/src/tools/clippy/triagebot.toml
@@ -19,7 +19,6 @@ new_pr = true
 
 [assign]
 contributing_url = "https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md"
-users_on_vacation = ["blyxyas"]
 
 [assign.owners]
 "/.github" = ["@flip1995"]
diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml
index 76c2e330b21..f4dac6e947e 100644
--- a/src/tools/error_index_generator/Cargo.toml
+++ b/src/tools/error_index_generator/Cargo.toml
@@ -5,7 +5,6 @@ edition = "2021"
 
 [dependencies]
 mdbook = { version = "0.4", default-features = false, features = ["search"] }
-rustc_error_codes = { version = "0.0.0", path = "../../../compiler/rustc_error_codes" }
 
 [[bin]]
 name = "error_index_generator"
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index 865d7172cd3..2de2d959a95 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -4,13 +4,15 @@ extern crate rustc_driver;
 extern crate rustc_log;
 extern crate rustc_session;
 
+extern crate rustc_errors;
+use rustc_errors::codes::DIAGNOSTICS;
+
 use std::env;
 use std::error::Error;
 use std::fs::{self, File};
 use std::io::Write;
 use std::path::Path;
 use std::path::PathBuf;
-
 use std::str::FromStr;
 
 use mdbook::book::{parse_summary, BookItem, Chapter};
@@ -38,7 +40,7 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
 
     write!(output_file, "# Rust Compiler Error Index\n")?;
 
-    for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() {
+    for (err_code, description) in DIAGNOSTICS.iter() {
         write!(output_file, "## {}\n{}\n", err_code, description)?
     }
 
@@ -85,7 +87,7 @@ This page lists all the error codes emitted by the Rust compiler.
 "
     );
 
-    let err_codes = rustc_error_codes::DIAGNOSTICS;
+    let err_codes = DIAGNOSTICS;
     let mut chapters = Vec::with_capacity(err_codes.len());
 
     for (err_code, explanation) in err_codes.iter() {
diff --git a/src/tools/miri/.github/workflows/sysroots.yml b/src/tools/miri/.github/workflows/sysroots.yml
index 509521e7478..96d7d4d1118 100644
--- a/src/tools/miri/.github/workflows/sysroots.yml
+++ b/src/tools/miri/.github/workflows/sysroots.yml
@@ -1,8 +1,8 @@
 name: Tier 2 sysroots
 
-on: push
-#  schedule:
-#    - cron: '44 4 * * *' # At 4:44 UTC every day.
+on:
+  schedule:
+    - cron: '44 4 * * *' # At 4:44 UTC every day.
 
 defaults:
   run:
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 6cd22a91518..8cd996d8564 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -486,9 +486,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
 
 [[package]]
 name = "measureme"
-version = "10.1.2"
+version = "11.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45e381dcdad44c3c435f8052b08c5c4a1449c48ab56f312345eae12d7a693dbe"
+checksum = "dfa4a40f09af7aa6faef38285402a78847d0d72bf8827006cd2a332e1e6e4a8d"
 dependencies = [
  "log",
  "memmap2",
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 3dee742fa0d..6695f123c78 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -590,6 +590,7 @@ Definite bugs found:
 * [Incorrect use of `compare_exchange_weak` in `once_cell`](https://github.com/matklad/once_cell/issues/186)
 * [Dropping with unaligned pointers in `vec::IntoIter`](https://github.com/rust-lang/rust/pull/106084)
 * [Deallocating with the wrong layout in new specializations for in-place `Iterator::collect`](https://github.com/rust-lang/rust/pull/118460)
+* [Incorrect offset computation for highly-aligned types in `portable-atomic-util`](https://github.com/taiki-e/portable-atomic/pull/138)
 
 Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment):
 
diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs
index a7412f90c85..79ce1f4ca32 100644
--- a/src/tools/miri/cargo-miri/src/phases.rs
+++ b/src/tools/miri/cargo-miri/src/phases.rs
@@ -501,11 +501,10 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
     // Set missing env vars. We prefer build-time env vars over run-time ones; see
     // <https://github.com/rust-lang/miri/issues/1661> for the kind of issue that fixes.
     for (name, val) in info.env {
-        // `CARGO_MAKEFLAGS` contains information about how to reach the
-        // jobserver, but by the time the program is being run, that jobserver
-        // no longer exists. Hence we shouldn't forward this.
-        // FIXME: Miri builds the final crate without a jobserver.
-        // This may be fixed with github.com/rust-lang/cargo/issues/12597.
+        // `CARGO_MAKEFLAGS` contains information about how to reach the jobserver, but by the time
+        // the program is being run, that jobserver no longer exists (cargo only runs the jobserver
+        // for the build portion of `cargo run`/`cargo test`). Hence we shouldn't forward this.
+        // Also see <https://github.com/rust-lang/rust/pull/113730>.
         if name == "CARGO_MAKEFLAGS" {
             continue;
         }
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 548e12ffdea..6624672775f 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-5bcd86d89b2b7b6a490f7e075dd4eb346deb5f98
+dd2559e08e1530806740931037d6bb83ef956161
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 905b2fc4d60..d6b1e135808 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -217,7 +217,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
     /// Helper function to get a `windows` constant as a `Scalar`.
     fn eval_windows(&self, module: &str, name: &str) -> Scalar<Provenance> {
-        self.eval_context_ref().eval_path_scalar(&["std", "sys", "pal","windows", module, name])
+        self.eval_context_ref().eval_path_scalar(&["std", "sys", "pal", "windows", module, name])
     }
 
     /// Helper function to get a `windows` constant as a `u32`.
@@ -249,7 +249,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn windows_ty_layout(&self, name: &str) -> TyAndLayout<'tcx> {
         let this = self.eval_context_ref();
         let ty = this
-            .resolve_path(&["std", "sys", "pal","windows", "c", name], Namespace::TypeNS)
+            .resolve_path(&["std", "sys", "pal", "windows", "c", name], Namespace::TypeNS)
             .ty(*this.tcx, ty::ParamEnv::reveal_all());
         this.layout_of(ty).unwrap()
     }
@@ -270,6 +270,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         bug!("No field named {} in type {}", name, base.layout().ty);
     }
 
+    /// Search if `base` (which must be a struct or union type) contains the `name` field.
+    fn projectable_has_field<P: Projectable<'tcx, Provenance>>(
+        &self,
+        base: &P,
+        name: &str,
+    ) -> bool {
+        let adt = base.layout().ty.ty_adt_def().unwrap();
+        for field in adt.non_enum_variant().fields.iter() {
+            if field.name.as_str() == name {
+                return true;
+            }
+        }
+        false
+    }
+
     /// Write an int of the appropriate size to `dest`. The target type may be signed or unsigned,
     /// we try to do the right thing anyway. `i128` can fit all integer types except for `u128` so
     /// this method is fine for almost all integer types.
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index b0b6d994366..057b883a3bf 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -94,7 +94,6 @@ pub use crate::shims::os_str::EvalContextExt as _;
 pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
 pub use crate::shims::time::EvalContextExt as _;
 pub use crate::shims::tls::TlsData;
-pub use crate::shims::EvalContextExt as _;
 
 pub use crate::borrow_tracker::stacked_borrows::{
     EvalContextExt as _, Item, Permission, Stack, Stacks,
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 4cd48b2e5a3..946887637ff 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -10,8 +10,8 @@ use std::process;
 
 use either::Either;
 use rand::rngs::StdRng;
-use rand::SeedableRng;
 use rand::Rng;
+use rand::SeedableRng;
 
 use rustc_ast::ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -83,7 +83,8 @@ pub struct FrameExtra<'tcx> {
 impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         // Omitting `timing`, it does not support `Debug`.
-        let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _, salt: _ } = self;
+        let FrameExtra { borrow_tracker, catch_unwind, timing: _, is_user_relevant: _, salt: _ } =
+            self;
         f.debug_struct("FrameData")
             .field("borrow_tracker", borrow_tracker)
             .field("catch_unwind", catch_unwind)
@@ -93,7 +94,8 @@ impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> {
 
 impl VisitProvenance for FrameExtra<'_> {
     fn visit_provenance(&self, visit: &mut VisitWith<'_>) {
-        let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _, salt: _ } = self;
+        let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _, salt: _ } =
+            self;
 
         catch_unwind.visit_provenance(visit);
         borrow_tracker.visit_provenance(visit);
@@ -710,7 +712,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
         Ok(())
     }
 
-    fn add_extern_static(
+    pub(crate) fn add_extern_static(
         this: &mut MiriInterpCx<'mir, 'tcx>,
         name: &str,
         ptr: Pointer<Option<Provenance>>,
@@ -720,75 +722,6 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
         this.machine.extern_statics.try_insert(Symbol::intern(name), ptr).unwrap();
     }
 
-    fn alloc_extern_static(
-        this: &mut MiriInterpCx<'mir, 'tcx>,
-        name: &str,
-        val: ImmTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx> {
-        let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
-        this.write_immediate(*val, &place)?;
-        Self::add_extern_static(this, name, place.ptr());
-        Ok(())
-    }
-
-    /// Sets up the "extern statics" for this machine.
-    fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
-        // "__rust_no_alloc_shim_is_unstable"
-        let val = ImmTy::from_int(0, this.machine.layouts.u8);
-        Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?;
-
-        match this.tcx.sess.target.os.as_ref() {
-            "linux" => {
-                // "environ"
-                Self::add_extern_static(
-                    this,
-                    "environ",
-                    this.machine.env_vars.environ.as_ref().unwrap().ptr(),
-                );
-                // A couple zero-initialized pointer-sized extern statics.
-                // Most of them are for weak symbols, which we all set to null (indicating that the
-                // symbol is not supported, and triggering fallback code which ends up calling a
-                // syscall that we do support).
-                for name in &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"]
-                {
-                    let val = ImmTy::from_int(0, this.machine.layouts.usize);
-                    Self::alloc_extern_static(this, name, val)?;
-                }
-            }
-            "freebsd" => {
-                // "environ"
-                Self::add_extern_static(
-                    this,
-                    "environ",
-                    this.machine.env_vars.environ.as_ref().unwrap().ptr(),
-                );
-            }
-            "android" => {
-                // "signal" -- just needs a non-zero pointer value (function does not even get called),
-                // but we arrange for this to be callable anyway (it will then do nothing).
-                let layout = this.machine.layouts.const_raw_ptr;
-                let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal")));
-                let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
-                Self::alloc_extern_static(this, "signal", val)?;
-                // A couple zero-initialized pointer-sized extern statics.
-                // Most of them are for weak symbols, which we all set to null (indicating that the
-                // symbol is not supported, and triggering fallback code.)
-                for name in &["bsd_signal"] {
-                    let val = ImmTy::from_int(0, this.machine.layouts.usize);
-                    Self::alloc_extern_static(this, name, val)?;
-                }
-            }
-            "windows" => {
-                // "_tls_used"
-                // This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
-                let val = ImmTy::from_int(0, this.machine.layouts.u8);
-                Self::alloc_extern_static(this, "_tls_used", val)?;
-            }
-            _ => {} // No "extern statics" supported on this target
-        }
-        Ok(())
-    }
-
     pub(crate) fn communicate(&self) -> bool {
         self.isolated_op == IsolatedOp::Allow
     }
@@ -1009,7 +942,21 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
-        ecx.find_mir_or_eval_fn(instance, abi, args, dest, ret, unwind)
+        // For foreign items, try to see if we can emulate them.
+        if ecx.tcx.is_foreign_item(instance.def_id()) {
+            // An external function call that does not have a MIR body. We either find MIR elsewhere
+            // or emulate its effect.
+            // This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need
+            // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
+            // foreign function
+            // Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
+            let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
+            let link_name = ecx.item_link_name(instance.def_id());
+            return ecx.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind);
+        }
+
+        // Otherwise, load the MIR.
+        Ok(Some((ecx.load_mir(instance.def, None)?, instance)))
     }
 
     #[inline(always)]
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index 14076444696..6f19dead2e9 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -24,7 +24,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         Ok(match bin_op {
             Eq | Ne | Lt | Le | Gt | Ge => {
-                assert_eq!(left.layout.abi, right.layout.abi); // types an differ, e.g. fn ptrs with different `for`
+                assert_eq!(left.layout.abi, right.layout.abi); // types can differ, e.g. fn ptrs with different `for`
                 let size = this.pointer_size();
                 // Just compare the bits. ScalarPairs are compared lexicographically.
                 // We thus always compare pairs and simply fill scalars up with 0.
diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs
new file mode 100644
index 00000000000..0284e5b606c
--- /dev/null
+++ b/src/tools/miri/src/shims/extern_static.rs
@@ -0,0 +1,79 @@
+//! Provides the `extern static` that this platform expects.
+
+use crate::*;
+
+impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
+    fn alloc_extern_static(
+        this: &mut MiriInterpCx<'mir, 'tcx>,
+        name: &str,
+        val: ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx> {
+        let place = this.allocate(val.layout, MiriMemoryKind::ExternStatic.into())?;
+        this.write_immediate(*val, &place)?;
+        Self::add_extern_static(this, name, place.ptr());
+        Ok(())
+    }
+
+    /// Zero-initialized pointer-sized extern statics are pretty common.
+    /// Most of them are for weak symbols, which we all set to null (indicating that the
+    /// symbol is not supported, and triggering fallback code which ends up calling a
+    /// syscall that we do support).
+    fn null_ptr_extern_statics(
+        this: &mut MiriInterpCx<'mir, 'tcx>,
+        names: &[&str],
+    ) -> InterpResult<'tcx> {
+        for name in names {
+            let val = ImmTy::from_int(0, this.machine.layouts.usize);
+            Self::alloc_extern_static(this, name, val)?;
+        }
+        Ok(())
+    }
+
+    /// Sets up the "extern statics" for this machine.
+    pub fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
+        // "__rust_no_alloc_shim_is_unstable"
+        let val = ImmTy::from_int(0, this.machine.layouts.u8);
+        Self::alloc_extern_static(this, "__rust_no_alloc_shim_is_unstable", val)?;
+
+        match this.tcx.sess.target.os.as_ref() {
+            "linux" => {
+                Self::null_ptr_extern_statics(
+                    this,
+                    &["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"],
+                )?;
+                // "environ"
+                Self::add_extern_static(
+                    this,
+                    "environ",
+                    this.machine.env_vars.environ.as_ref().unwrap().ptr(),
+                );
+            }
+            "freebsd" => {
+                Self::null_ptr_extern_statics(this, &["__cxa_thread_atexit_impl"])?;
+                // "environ"
+                Self::add_extern_static(
+                    this,
+                    "environ",
+                    this.machine.env_vars.environ.as_ref().unwrap().ptr(),
+                );
+            }
+            "android" => {
+                Self::null_ptr_extern_statics(this, &["bsd_signal"])?;
+                // "signal" -- just needs a non-zero pointer value (function does not even get called),
+                // but we arrange for this to call the `signal` function anyway.
+                let layout = this.machine.layouts.const_raw_ptr;
+                let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal")));
+                let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
+                Self::alloc_extern_static(this, "signal", val)?;
+            }
+            "windows" => {
+                // "_tls_used"
+                // This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
+                let val = ImmTy::from_int(0, this.machine.layouts.u8);
+                Self::alloc_extern_static(this, "_tls_used", val)?;
+            }
+            _ => {} // No "extern statics" supported on this target
+        }
+        Ok(())
+    }
+}
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index 8edc0a4220d..e34fb118f72 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -148,7 +148,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             // ```
             // Would not be considered UB, or the other way around (`is_val_statically_known(0)`).
             "is_val_statically_known" => {
-                let [_] = check_arg_count(args)?;
+                let [arg] = check_arg_count(args)?;
+                this.validate_operand(arg)?;
                 let branch: bool = this.machine.rng.get_mut().gen();
                 this.write_scalar(Scalar::from_bool(branch), dest)?;
             }
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index 1e9d927e1a9..ea6120f7579 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -10,48 +10,8 @@ pub mod windows;
 mod x86;
 
 pub mod env;
+pub mod extern_static;
 pub mod os_str;
 pub mod panic;
 pub mod time;
 pub mod tls;
-
-// End module management, begin local code
-
-use log::trace;
-
-use rustc_middle::{mir, ty};
-use rustc_target::spec::abi::Abi;
-
-use crate::*;
-
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
-    fn find_mir_or_eval_fn(
-        &mut self,
-        instance: ty::Instance<'tcx>,
-        abi: Abi,
-        args: &[FnArg<'tcx, Provenance>],
-        dest: &PlaceTy<'tcx, Provenance>,
-        ret: Option<mir::BasicBlock>,
-        unwind: mir::UnwindAction,
-    ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
-        let this = self.eval_context_mut();
-        trace!("eval_fn_call: {:#?}, {:?}", instance, dest);
-
-        // For foreign items, try to see if we can emulate them.
-        if this.tcx.is_foreign_item(instance.def_id()) {
-            // An external function call that does not have a MIR body. We either find MIR elsewhere
-            // or emulate its effect.
-            // This will be Ok(None) if we're emulating the intrinsic entirely within Miri (no need
-            // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
-            // foreign function
-            // Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
-            let args = this.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
-            let link_name = this.item_link_name(instance.def_id());
-            return this.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind);
-        }
-
-        // Otherwise, load the MIR.
-        Ok(Some((this.load_mir(instance.def, None)?, instance)))
-    }
-}
diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs
index 23342c8045e..35036ce078d 100644
--- a/src/tools/miri/src/shims/unix/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/foreign_items.rs
@@ -155,6 +155,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
             "lseek64" => {
                 let [fd, offset, whence] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let fd = this.read_scalar(fd)?.to_i32()?;
+                let offset = this.read_scalar(offset)?.to_i64()?;
+                let whence = this.read_scalar(whence)?.to_i32()?;
+                let result = this.lseek64(fd, offset.into(), whence)?;
+                this.write_scalar(result, dest)?;
+            }
+            "lseek" => {
+                let [fd, offset, whence] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let fd = this.read_scalar(fd)?.to_i32()?;
+                let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
+                let whence = this.read_scalar(whence)?.to_i32()?;
                 let result = this.lseek64(fd, offset, whence)?;
                 this.write_scalar(result, dest)?;
             }
diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
index 7c843e106ea..64094ac307d 100644
--- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs
@@ -3,6 +3,7 @@ use rustc_target::spec::abi::Abi;
 
 use crate::*;
 use shims::foreign_items::EmulateForeignItemResult;
+use shims::unix::fs::EvalContextExt as _;
 use shims::unix::thread::EvalContextExt as _;
 
 pub fn is_dyn_sym(_name: &str) -> bool {
@@ -63,6 +64,33 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_scalar(Scalar::from_target_usize(len, this), dest)?;
             }
 
+            // File related shims
+            // For those, we both intercept `func` and `call@FBSD_1.0` symbols cases
+            // since freebsd 12 the former form can be expected.
+            "stat" | "stat@FBSD_1.0" => {
+                let [path, buf] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.macos_fbsd_stat(path, buf)?;
+                this.write_scalar(result, dest)?;
+            }
+            "lstat" | "lstat@FBSD_1.0" => {
+                let [path, buf] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.macos_fbsd_lstat(path, buf)?;
+                this.write_scalar(result, dest)?;
+            }
+            "fstat" | "fstat@FBSD_1.0" => {
+                let [fd, buf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.macos_fbsd_fstat(fd, buf)?;
+                this.write_scalar(result, dest)?;
+            }
+            "readdir_r" | "readdir_r@FBSD_1.0" => {
+                let [dirp, entry, result] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let result = this.macos_fbsd_readdir_r(dirp, entry, result)?;
+                this.write_scalar(result, dest)?;
+            }
+
             // errno
             "__error" => {
                 let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 99d8a3a2c91..53f975baa89 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -813,24 +813,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
     fn lseek64(
         &mut self,
-        fd_op: &OpTy<'tcx, Provenance>,
-        offset_op: &OpTy<'tcx, Provenance>,
-        whence_op: &OpTy<'tcx, Provenance>,
+        fd: i32,
+        offset: i128,
+        whence: i32,
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         // Isolation check is done via `FileDescriptor` trait.
 
-        let fd = this.read_scalar(fd_op)?.to_i32()?;
-        let offset = this.read_scalar(offset_op)?.to_i64()?;
-        let whence = this.read_scalar(whence_op)?.to_i32()?;
-
         let seek_from = if whence == this.eval_libc_i32("SEEK_SET") {
             SeekFrom::Start(u64::try_from(offset).unwrap())
         } else if whence == this.eval_libc_i32("SEEK_CUR") {
-            SeekFrom::Current(offset)
+            SeekFrom::Current(i64::try_from(offset).unwrap())
         } else if whence == this.eval_libc_i32("SEEK_END") {
-            SeekFrom::End(offset)
+            SeekFrom::End(i64::try_from(offset).unwrap())
         } else {
             let einval = this.eval_libc("EINVAL");
             this.set_last_error(einval)?;
@@ -897,13 +893,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         this.try_unwrap_io_result(result)
     }
 
-    fn macos_stat(
+    fn macos_fbsd_stat(
         &mut self,
         path_op: &OpTy<'tcx, Provenance>,
         buf_op: &OpTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
-        this.assert_target_os("macos", "stat");
+
+        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
+            panic!("`macos_fbsd_stat` should not be called on {}", this.tcx.sess.target.os);
+        }
 
         let path_scalar = this.read_pointer(path_op)?;
         let path = this.read_path_from_c_str(path_scalar)?.into_owned();
@@ -926,13 +925,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 
     // `lstat` is used to get symlink metadata.
-    fn macos_lstat(
+    fn macos_fbsd_lstat(
         &mut self,
         path_op: &OpTy<'tcx, Provenance>,
         buf_op: &OpTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
-        this.assert_target_os("macos", "lstat");
+
+        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
+            panic!("`macos_fbsd_lstat` should not be called on {}", this.tcx.sess.target.os);
+        }
 
         let path_scalar = this.read_pointer(path_op)?;
         let path = this.read_path_from_c_str(path_scalar)?.into_owned();
@@ -953,14 +955,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         Ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?))
     }
 
-    fn macos_fstat(
+    fn macos_fbsd_fstat(
         &mut self,
         fd_op: &OpTy<'tcx, Provenance>,
         buf_op: &OpTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
-        this.assert_target_os("macos", "fstat");
+        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
+            panic!("`macos_fbsd_fstat` should not be called on {}", this.tcx.sess.target.os);
+        }
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
 
@@ -1199,7 +1203,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
 
         #[cfg_attr(not(unix), allow(unused_variables))]
-        let mode = if this.tcx.sess.target.os == "macos" {
+        let mode = if matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
             u32::from(this.read_scalar(mode_op)?.to_u16()?)
         } else {
             this.read_scalar(mode_op)?.to_u32()?
@@ -1371,7 +1375,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         Ok(Scalar::from_maybe_pointer(entry, this))
     }
 
-    fn macos_readdir_r(
+    fn macos_fbsd_readdir_r(
         &mut self,
         dirp_op: &OpTy<'tcx, Provenance>,
         entry_op: &OpTy<'tcx, Provenance>,
@@ -1379,7 +1383,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
-        this.assert_target_os("macos", "readdir_r");
+        if !matches!(&*this.tcx.sess.target.os, "macos" | "freebsd") {
+            panic!("`macos_fbsd_readdir_r` should not be called on {}", this.tcx.sess.target.os);
+        }
 
         let dirp = this.read_target_usize(dirp_op)?;
 
@@ -1410,7 +1416,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // }
 
                 let entry_place = this.deref_pointer_as(entry_op, this.libc_ty_layout("dirent"))?;
-                let name_place = this.project_field(&entry_place, 5)?;
+                let name_place = this.project_field_named(&entry_place, "d_name")?;
 
                 let file_name = dir_entry.file_name(); // not a Path as there are no separators!
                 let (name_fits, file_name_buf_len) = this.write_os_str_to_c_str(
@@ -1434,16 +1440,41 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                 let file_type = this.file_type_to_d_type(dir_entry.file_type())?;
 
-                this.write_int_fields_named(
-                    &[
-                        ("d_ino", ino.into()),
-                        ("d_seekoff", 0),
-                        ("d_reclen", 0),
-                        ("d_namlen", file_name_len.into()),
-                        ("d_type", file_type.into()),
-                    ],
-                    &entry_place,
-                )?;
+                // macOS offset field is d_seekoff
+                if this.projectable_has_field(&entry_place, "d_seekoff") {
+                    this.write_int_fields_named(
+                        &[
+                            ("d_ino", ino.into()),
+                            ("d_seekoff", 0),
+                            ("d_reclen", 0),
+                            ("d_namlen", file_name_len.into()),
+                            ("d_type", file_type.into()),
+                        ],
+                        &entry_place,
+                    )?;
+                } else if this.projectable_has_field(&entry_place, "d_off") {
+                    // freebsd 12 and onwards had added the d_off field
+                    this.write_int_fields_named(
+                        &[
+                            ("d_fileno", ino.into()),
+                            ("d_off", 0),
+                            ("d_reclen", 0),
+                            ("d_type", file_type.into()),
+                            ("d_namlen", file_name_len.into()),
+                        ],
+                        &entry_place,
+                    )?;
+                } else {
+                    this.write_int_fields_named(
+                        &[
+                            ("d_fileno", ino.into()),
+                            ("d_reclen", 0),
+                            ("d_type", file_type.into()),
+                            ("d_namlen", file_name_len.into()),
+                        ],
+                        &entry_place,
+                    )?;
+                }
 
                 let result_place = this.deref_pointer(result_op)?;
                 this.write_scalar(this.read_scalar(entry_op)?, &result_place)?;
diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
index 07e19cadd6e..ecc07e28a29 100644
--- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs
+++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs
@@ -40,18 +40,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "stat" | "stat64" | "stat$INODE64" => {
                 let [path, buf] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_stat(path, buf)?;
+                let result = this.macos_fbsd_stat(path, buf)?;
                 this.write_scalar(result, dest)?;
             }
             "lstat" | "lstat64" | "lstat$INODE64" => {
                 let [path, buf] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_lstat(path, buf)?;
+                let result = this.macos_fbsd_lstat(path, buf)?;
                 this.write_scalar(result, dest)?;
             }
             "fstat" | "fstat64" | "fstat$INODE64" => {
                 let [fd, buf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_fstat(fd, buf)?;
+                let result = this.macos_fbsd_fstat(fd, buf)?;
                 this.write_scalar(result, dest)?;
             }
             "opendir$INODE64" => {
@@ -62,14 +62,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "readdir_r" | "readdir_r$INODE64" => {
                 let [dirp, entry, result] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let result = this.macos_readdir_r(dirp, entry, result)?;
-                this.write_scalar(result, dest)?;
-            }
-            "lseek" => {
-                let [fd, offset, whence] =
-                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                // macOS is 64bit-only, so this is lseek64
-                let result = this.lseek64(fd, offset, whence)?;
+                let result = this.macos_fbsd_readdir_r(dirp, entry, result)?;
                 this.write_scalar(result, dest)?;
             }
             "realpath$DARWIN_EXTSN" => {
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs
index adfece58661..5185db0b0e2 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs
@@ -1,5 +1,4 @@
 //@ignore-target-windows: no libc on Windows
-//@ignore-target-freebsd: FIXME needs foreign function `stat@FBSD_1.0`
 //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace
 //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT"
 
diff --git a/src/tools/miri/tests/pass/issues/issue-120337-irrefutable-let-ice.rs b/src/tools/miri/tests/pass/issues/issue-120337-irrefutable-let-ice.rs
new file mode 100644
index 00000000000..5af0d0e4bbd
--- /dev/null
+++ b/src/tools/miri/tests/pass/issues/issue-120337-irrefutable-let-ice.rs
@@ -0,0 +1,16 @@
+// Validation stops the test before the ICE we used to hit
+//@compile-flags: -Zmiri-disable-validation
+
+#![feature(never_type)]
+#[derive(Copy, Clone)]
+pub enum E {
+    A(!),
+}
+pub union U {
+    u: (),
+    e: E,
+}
+
+fn main() {
+    let E::A(ref _a) = unsafe { &(&U { u: () }).e };
+}
diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
index aa25f82ae1d..bf1feb9a7eb 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
@@ -379,14 +379,14 @@ fn unescape_string_error_message(text: &str, mode: Mode) -> &'static str {
     let mut error_message = "";
     match mode {
         Mode::CStr => {
-            rustc_lexer::unescape::unescape_c_string(text, mode, &mut |_, res| {
+            rustc_lexer::unescape::unescape_mixed(text, mode, &mut |_, res| {
                 if let Err(e) = res {
                     error_message = error_to_diagnostic_message(e, mode);
                 }
             });
         }
         Mode::ByteStr | Mode::Str => {
-            rustc_lexer::unescape::unescape_literal(text, mode, &mut |_, res| {
+            rustc_lexer::unescape::unescape_unicode(text, mode, &mut |_, res| {
                 if let Err(e) = res {
                     error_message = error_to_diagnostic_message(e, mode);
                 }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
index b39006e2ff2..7cd1f1550b9 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
@@ -6,7 +6,7 @@ use std::{
 };
 
 use rustc_lexer::unescape::{
-    unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode,
+    unescape_byte, unescape_char, unescape_mixed, unescape_unicode, MixedUnit, Mode,
 };
 
 use crate::{
@@ -193,7 +193,7 @@ pub trait IsString: AstToken {
         let text = &self.text()[text_range_no_quotes - start];
         let offset = text_range_no_quotes.start() - start;
 
-        unescape_literal(text, Self::MODE, &mut |range, unescaped_char| {
+        unescape_unicode(text, Self::MODE, &mut |range, unescaped_char| {
             let text_range =
                 TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
             cb(text_range + offset, unescaped_char);
@@ -226,7 +226,7 @@ impl ast::String {
         let mut buf = String::new();
         let mut prev_end = 0;
         let mut has_error = false;
-        unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match (
+        unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match (
             unescaped_char,
             buf.capacity() == 0,
         ) {
@@ -270,7 +270,7 @@ impl ast::ByteString {
         let mut buf: Vec<u8> = Vec::new();
         let mut prev_end = 0;
         let mut has_error = false;
-        unescape_literal(text, Self::MODE, &mut |char_range, unescaped_char| match (
+        unescape_unicode(text, Self::MODE, &mut |char_range, unescaped_char| match (
             unescaped_char,
             buf.capacity() == 0,
         ) {
@@ -311,7 +311,7 @@ impl IsString for ast::CString {
         let text = &self.text()[text_range_no_quotes - start];
         let offset = text_range_no_quotes.start() - start;
 
-        unescape_c_string(text, Self::MODE, &mut |range, unescaped_char| {
+        unescape_mixed(text, Self::MODE, &mut |range, unescaped_char| {
             let text_range =
                 TextRange::new(range.start.try_into().unwrap(), range.end.try_into().unwrap());
             // XXX: This method should only be used for highlighting ranges. The unescaped
@@ -336,12 +336,11 @@ impl ast::CString {
         let mut buf = Vec::new();
         let mut prev_end = 0;
         let mut has_error = false;
-        let mut char_buf = [0u8; 4];
-        let mut extend_unit = |buf: &mut Vec<u8>, unit: CStrUnit| match unit {
-            CStrUnit::Byte(b) => buf.push(b),
-            CStrUnit::Char(c) => buf.extend(c.encode_utf8(&mut char_buf).as_bytes()),
+        let extend_unit = |buf: &mut Vec<u8>, unit: MixedUnit| match unit {
+            MixedUnit::Char(c) => buf.extend(c.encode_utf8(&mut [0; 4]).as_bytes()),
+            MixedUnit::HighByte(b) => buf.push(b),
         };
-        unescape_c_string(text, Self::MODE, &mut |char_range, unescaped| match (
+        unescape_mixed(text, Self::MODE, &mut |char_range, unescaped| match (
             unescaped,
             buf.capacity() == 0,
         ) {
diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
index 69dffbf79f1..5c5b26f525f 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
@@ -5,7 +5,7 @@
 mod block;
 
 use rowan::Direction;
-use rustc_lexer::unescape::{self, unescape_literal, Mode};
+use rustc_lexer::unescape::{self, unescape_mixed, unescape_unicode, Mode};
 
 use crate::{
     algo,
@@ -140,7 +140,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         ast::LiteralKind::String(s) => {
             if !s.is_raw() {
                 if let Some(without_quotes) = unquote(text, 1, '"') {
-                    unescape_literal(without_quotes, Mode::Str, &mut |range, char| {
+                    unescape_unicode(without_quotes, Mode::Str, &mut |range, char| {
                         if let Err(err) = char {
                             push_err(1, range.start, err);
                         }
@@ -151,7 +151,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         ast::LiteralKind::ByteString(s) => {
             if !s.is_raw() {
                 if let Some(without_quotes) = unquote(text, 2, '"') {
-                    unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| {
+                    unescape_unicode(without_quotes, Mode::ByteStr, &mut |range, char| {
                         if let Err(err) = char {
                             push_err(1, range.start, err);
                         }
@@ -162,7 +162,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         ast::LiteralKind::CString(s) => {
             if !s.is_raw() {
                 if let Some(without_quotes) = unquote(text, 2, '"') {
-                    unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| {
+                    unescape_mixed(without_quotes, Mode::CStr, &mut |range, char| {
                         if let Err(err) = char {
                             push_err(1, range.start, err);
                         }
@@ -172,7 +172,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         }
         ast::LiteralKind::Char(_) => {
             if let Some(without_quotes) = unquote(text, 1, '\'') {
-                unescape_literal(without_quotes, Mode::Char, &mut |range, char| {
+                unescape_unicode(without_quotes, Mode::Char, &mut |range, char| {
                     if let Err(err) = char {
                         push_err(1, range.start, err);
                     }
@@ -181,7 +181,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
         }
         ast::LiteralKind::Byte(_) => {
             if let Some(without_quotes) = unquote(text, 2, '\'') {
-                unescape_literal(without_quotes, Mode::Byte, &mut |range, char| {
+                unescape_unicode(without_quotes, Mode::Byte, &mut |range, char| {
                     if let Err(err) = char {
                         push_err(2, range.start, err);
                     }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index b03811e5efd..b06c072a2b0 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -340,8 +340,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "termize",
     "thin-vec",
     "thiserror",
-    "thiserror-core",
-    "thiserror-core-impl",
     "thiserror-impl",
     "thorin-dwp",
     "thread_local",
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index 094efa981d3..6fc65e56901 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -2,7 +2,7 @@
 //!
 //! Overview of check:
 //!
-//! 1. We create a list of error codes used by the compiler. Error codes are extracted from `compiler/rustc_error_codes/src/error_codes.rs`.
+//! 1. We create a list of error codes used by the compiler. Error codes are extracted from `compiler/rustc_error_codes/src/lib.rs`.
 //!
 //! 2. We check that the error code has a long-form explanation in `compiler/rustc_error_codes/src/error_codes/`.
 //!   - The explanation is expected to contain a `doctest` that fails with the correct error code. (`EXEMPT_FROM_DOCTEST` *currently* bypasses this check)
@@ -22,7 +22,7 @@ use regex::Regex;
 
 use crate::walk::{filter_dirs, walk, walk_many};
 
-const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/error_codes.rs";
+const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/lib.rs";
 const ERROR_DOCS_PATH: &str = "compiler/rustc_error_codes/src/error_codes/";
 const ERROR_TESTS_PATH: &str = "tests/ui/error-codes/";
 
@@ -80,13 +80,14 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
         if line.starts_with('E') {
             let split_line = line.split_once(':');
 
-            // Extract the error code from the line, emitting a fatal error if it is not in a correct format.
+            // Extract the error code from the line. Emit a fatal error if it is not in the correct
+            // format.
             let err_code = if let Some(err_code) = split_line {
                 err_code.0.to_owned()
             } else {
                 errors.push(format!(
-                    "Expected a line with the format `Exxxx: include_str!(\"..\")`, but got \"{}\" \
-                    without a `:` delimiter",
+                    "Expected a line with the format `Eabcd: abcd, \
+                    but got \"{}\" without a `:` delimiter",
                     line,
                 ));
                 continue;
@@ -98,12 +99,16 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String
                 continue;
             }
 
+            let mut chars = err_code.chars();
+            chars.next();
+            let error_num_as_str = chars.as_str();
+
             // Ensure that the line references the correct markdown file.
-            let expected_filename = format!(" include_str!(\"./error_codes/{}.md\"),", err_code);
+            let expected_filename = format!(" {},", error_num_as_str);
             if expected_filename != split_line.unwrap().1 {
                 errors.push(format!(
-                    "Error code `{}` expected to reference docs with `{}` but instead found `{}` in \
-                    `compiler/rustc_error_codes/src/error_codes.rs`",
+                    "`{}:` should be followed by `{}` but instead found `{}` in \
+                    `compiler/rustc_error_codes/src/lib.rs`",
                     err_code,
                     expected_filename,
                     split_line.unwrap().1,
@@ -311,13 +316,8 @@ fn check_error_codes_used(
     no_longer_emitted: &[String],
     verbose: bool,
 ) {
-    // We want error codes which match the following cases:
-    //
-    // * foo(a, E0111, a)
-    // * foo(a, E0111)
-    // * foo(E0111, a)
-    // * #[error = "E0111"]
-    let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap();
+    // Search for error codes in the form `E0123`.
+    let regex = Regex::new(r#"\bE\d{4}\b"#).unwrap();
 
     let mut found_codes = Vec::new();
 
@@ -336,12 +336,12 @@ fn check_error_codes_used(
             }
 
             for cap in regex.captures_iter(line) {
-                if let Some(error_code) = cap.get(1) {
+                if let Some(error_code) = cap.get(0) {
                     let error_code = error_code.as_str().to_owned();
 
                     if !error_codes.contains(&error_code) {
                         // This error code isn't properly defined, we must error.
-                        errors.push(format!("Error code `{}` is used in the compiler but not defined and documented in `compiler/rustc_error_codes/src/error_codes.rs`.", error_code));
+                        errors.push(format!("Error code `{}` is used in the compiler but not defined and documented in `compiler/rustc_error_codes/src/lib.rs`.", error_code));
                         continue;
                     }
 
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 95cf9f8cb13..85553d2e338 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -24,9 +24,10 @@ const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
 
 const EXTENSION_EXCEPTION_PATHS: &[&str] = &[
     "tests/ui/asm/named-asm-labels.s", // loading an external asm file to test named labels lint
-    "tests/ui/check-cfg/my-awesome-platform.json", // testing custom targets with cfgs
-    "tests/ui/commandline-argfile-badutf8.args", // passing args via a file
-    "tests/ui/commandline-argfile.args", // passing args via a file
+    "tests/ui/codegen/mismatched-data-layout.json", // testing mismatched data layout w/ custom targets
+    "tests/ui/check-cfg/my-awesome-platform.json",  // testing custom targets with cfgs
+    "tests/ui/commandline-argfile-badutf8.args",    // passing args via a file
+    "tests/ui/commandline-argfile.args",            // passing args via a file
     "tests/ui/crate-loading/auxiliary/libfoo.rlib", // testing loading a manually created rlib
     "tests/ui/include-macros/data.bin", // testing including data with the include macros
     "tests/ui/include-macros/file.txt", // testing including data with the include macros
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index f6f2f5e88ff..dee0fa9f4a4 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -1,29 +1,5 @@
 // assembly-output: emit-asm
 // ignore-tidy-linelength
-// revisions: aarch64_apple_darwin
-// [aarch64_apple_darwin] compile-flags: --target aarch64-apple-darwin
-// [aarch64_apple_darwin] needs-llvm-components: aarch64
-// revisions: aarch64_apple_ios
-// [aarch64_apple_ios] compile-flags: --target aarch64-apple-ios
-// [aarch64_apple_ios] needs-llvm-components: aarch64
-// revisions: aarch64_apple_ios_macabi
-// [aarch64_apple_ios_macabi] compile-flags: --target aarch64-apple-ios-macabi
-// [aarch64_apple_ios_macabi] needs-llvm-components: aarch64
-// revisions: aarch64_apple_ios_sim
-// [aarch64_apple_ios_sim] compile-flags: --target aarch64-apple-ios-sim
-// [aarch64_apple_ios_sim] needs-llvm-components: aarch64
-// revisions: aarch64_apple_tvos
-// [aarch64_apple_tvos] compile-flags: --target aarch64-apple-tvos
-// [aarch64_apple_tvos] needs-llvm-components: aarch64
-// revisions: aarch64_apple_tvos_sim
-// [aarch64_apple_tvos_sim] compile-flags: --target aarch64-apple-tvos-sim
-// [aarch64_apple_tvos_sim] needs-llvm-components: aarch64
-// revisions: aarch64_apple_watchos
-// [aarch64_apple_watchos] compile-flags: --target aarch64-apple-watchos
-// [aarch64_apple_watchos] needs-llvm-components: aarch64
-// revisions: aarch64_apple_watchos_sim
-// [aarch64_apple_watchos_sim] compile-flags: --target aarch64-apple-watchos-sim
-// [aarch64_apple_watchos_sim] needs-llvm-components: aarch64
 // revisions: aarch64_be_unknown_linux_gnu
 // [aarch64_be_unknown_linux_gnu] compile-flags: --target aarch64_be-unknown-linux-gnu
 // [aarch64_be_unknown_linux_gnu] needs-llvm-components: aarch64
@@ -93,15 +69,6 @@
 // revisions: aarch64_wrs_vxworks
 // [aarch64_wrs_vxworks] compile-flags: --target aarch64-wrs-vxworks
 // [aarch64_wrs_vxworks] needs-llvm-components: aarch64
-// revisions: arm64_32_apple_watchos
-// [arm64_32_apple_watchos] compile-flags: --target arm64_32-apple-watchos
-// [arm64_32_apple_watchos] needs-llvm-components: aarch64
-// revisions: arm64e_apple_darwin
-// [arm64e_apple_darwin] compile-flags: --target arm64e-apple-darwin
-// [arm64e_apple_darwin] needs-llvm-components: aarch64
-// revisions: arm64e_apple_ios
-// [arm64e_apple_ios] compile-flags: --target arm64e-apple-ios
-// [arm64e_apple_ios] needs-llvm-components: aarch64
 // revisions: arm_linux_androideabi
 // [arm_linux_androideabi] compile-flags: --target arm-linux-androideabi
 // [arm_linux_androideabi] needs-llvm-components: arm
@@ -201,18 +168,12 @@
 // revisions: armv7a_none_eabihf
 // [armv7a_none_eabihf] compile-flags: --target armv7a-none-eabihf
 // [armv7a_none_eabihf] needs-llvm-components: arm
-// revisions: armv7k_apple_watchos
-// [armv7k_apple_watchos] compile-flags: --target armv7k-apple-watchos
-// [armv7k_apple_watchos] needs-llvm-components: arm
 // revisions: armv7r_none_eabi
 // [armv7r_none_eabi] compile-flags: --target armv7r-none-eabi
 // [armv7r_none_eabi] needs-llvm-components: arm
 // revisions: armv7r_none_eabihf
 // [armv7r_none_eabihf] compile-flags: --target armv7r-none-eabihf
 // [armv7r_none_eabihf] needs-llvm-components: arm
-// revisions: armv7s_apple_ios
-// [armv7s_apple_ios] compile-flags: --target armv7s-apple-ios
-// [armv7s_apple_ios] needs-llvm-components: arm
 // FIXME: disabled since it fails on CI saying the csky component is missing
 /*
     revisions: csky_unknown_linux_gnuabiv2
@@ -228,9 +189,6 @@
 // revisions: hexagon_unknown_none_elf
 // [hexagon_unknown_none_elf] compile-flags: --target hexagon-unknown-none-elf
 // [hexagon_unknown_none_elf] needs-llvm-components: hexagon
-// revisions: i386_apple_ios
-// [i386_apple_ios] compile-flags: --target i386-apple-ios
-// [i386_apple_ios] needs-llvm-components: x86
 // revisions: i586_pc_nto_qnx700
 // [i586_pc_nto_qnx700] compile-flags: --target i586-pc-nto-qnx700
 // [i586_pc_nto_qnx700] needs-llvm-components: x86
@@ -243,9 +201,6 @@
 // revisions: i586_unknown_netbsd
 // [i586_unknown_netbsd] compile-flags: --target i586-unknown-netbsd
 // [i586_unknown_netbsd] needs-llvm-components: x86
-// revisions: i686_apple_darwin
-// [i686_apple_darwin] compile-flags: --target i686-apple-darwin
-// [i686_apple_darwin] needs-llvm-components: x86
 // revisions: i686_linux_android
 // [i686_linux_android] compile-flags: --target i686-linux-android
 // [i686_linux_android] needs-llvm-components: x86
@@ -537,21 +492,6 @@
 // revisions: wasm32_wasi_preview2
 // [wasm32_wasi_preview2] compile-flags: --target wasm32-wasi-preview2
 // [wasm32_wasi_preview2] needs-llvm-components: webassembly
-// revisions: x86_64_apple_darwin
-// [x86_64_apple_darwin] compile-flags: --target x86_64-apple-darwin
-// [x86_64_apple_darwin] needs-llvm-components: x86
-// revisions: x86_64_apple_ios
-// [x86_64_apple_ios] compile-flags: --target x86_64-apple-ios
-// [x86_64_apple_ios] needs-llvm-components: x86
-// revisions: x86_64_apple_ios_macabi
-// [x86_64_apple_ios_macabi] compile-flags: --target x86_64-apple-ios-macabi
-// [x86_64_apple_ios_macabi] needs-llvm-components: x86
-// revisions: x86_64_apple_tvos
-// [x86_64_apple_tvos] compile-flags: --target x86_64-apple-tvos
-// [x86_64_apple_tvos] needs-llvm-components: x86
-// revisions: x86_64_apple_watchos_sim
-// [x86_64_apple_watchos_sim] compile-flags: --target x86_64-apple-watchos-sim
-// [x86_64_apple_watchos_sim] needs-llvm-components: x86
 // revisions: x86_64_fortanix_unknown_sgx
 // [x86_64_fortanix_unknown_sgx] compile-flags: --target x86_64-fortanix-unknown-sgx
 // [x86_64_fortanix_unknown_sgx] needs-llvm-components: x86
@@ -618,9 +558,6 @@
 // revisions: x86_64_wrs_vxworks
 // [x86_64_wrs_vxworks] compile-flags: --target x86_64-wrs-vxworks
 // [x86_64_wrs_vxworks] needs-llvm-components: x86
-// revisions: x86_64h_apple_darwin
-// [x86_64h_apple_darwin] compile-flags: --target x86_64h-apple-darwin
-// [x86_64h_apple_darwin] needs-llvm-components: x86
 
 // Sanity-check that each target can produce assembly code.
 
@@ -636,4 +573,4 @@ pub fn test() -> u8 {
     42
 }
 
-// CHECK: .section
+// CHECK: .text
diff --git a/tests/assembly/targets/targets-macho.rs b/tests/assembly/targets/targets-macho.rs
new file mode 100644
index 00000000000..ead9ccfc8e7
--- /dev/null
+++ b/tests/assembly/targets/targets-macho.rs
@@ -0,0 +1,81 @@
+// assembly-output: emit-asm
+// ignore-tidy-linelength
+// revisions: aarch64_apple_darwin
+// [aarch64_apple_darwin] compile-flags: --target aarch64-apple-darwin
+// [aarch64_apple_darwin] needs-llvm-components: aarch64
+// revisions: aarch64_apple_ios
+// [aarch64_apple_ios] compile-flags: --target aarch64-apple-ios
+// [aarch64_apple_ios] needs-llvm-components: aarch64
+// revisions: aarch64_apple_ios_macabi
+// [aarch64_apple_ios_macabi] compile-flags: --target aarch64-apple-ios-macabi
+// [aarch64_apple_ios_macabi] needs-llvm-components: aarch64
+// revisions: aarch64_apple_ios_sim
+// [aarch64_apple_ios_sim] compile-flags: --target aarch64-apple-ios-sim
+// [aarch64_apple_ios_sim] needs-llvm-components: aarch64
+// revisions: aarch64_apple_tvos
+// [aarch64_apple_tvos] compile-flags: --target aarch64-apple-tvos
+// [aarch64_apple_tvos] needs-llvm-components: aarch64
+// revisions: aarch64_apple_tvos_sim
+// [aarch64_apple_tvos_sim] compile-flags: --target aarch64-apple-tvos-sim
+// [aarch64_apple_tvos_sim] needs-llvm-components: aarch64
+// revisions: aarch64_apple_watchos
+// [aarch64_apple_watchos] compile-flags: --target aarch64-apple-watchos
+// [aarch64_apple_watchos] needs-llvm-components: aarch64
+// revisions: aarch64_apple_watchos_sim
+// [aarch64_apple_watchos_sim] compile-flags: --target aarch64-apple-watchos-sim
+// [aarch64_apple_watchos_sim] needs-llvm-components: aarch64
+// revisions: arm64_32_apple_watchos
+// [arm64_32_apple_watchos] compile-flags: --target arm64_32-apple-watchos
+// [arm64_32_apple_watchos] needs-llvm-components: aarch64
+// revisions: arm64e_apple_darwin
+// [arm64e_apple_darwin] compile-flags: --target arm64e-apple-darwin
+// [arm64e_apple_darwin] needs-llvm-components: aarch64
+// revisions: arm64e_apple_ios
+// [arm64e_apple_ios] compile-flags: --target arm64e-apple-ios
+// [arm64e_apple_ios] needs-llvm-components: aarch64
+// revisions: armv7k_apple_watchos
+// [armv7k_apple_watchos] compile-flags: --target armv7k-apple-watchos
+// [armv7k_apple_watchos] needs-llvm-components: arm
+// revisions: armv7s_apple_ios
+// [armv7s_apple_ios] compile-flags: --target armv7s-apple-ios
+// [armv7s_apple_ios] needs-llvm-components: arm
+// revisions: i386_apple_ios
+// [i386_apple_ios] compile-flags: --target i386-apple-ios
+// [i386_apple_ios] needs-llvm-components: x86
+// revisions: i686_apple_darwin
+// [i686_apple_darwin] compile-flags: --target i686-apple-darwin
+// [i686_apple_darwin] needs-llvm-components: x86
+// revisions: x86_64_apple_darwin
+// [x86_64_apple_darwin] compile-flags: --target x86_64-apple-darwin
+// [x86_64_apple_darwin] needs-llvm-components: x86
+// revisions: x86_64_apple_ios
+// [x86_64_apple_ios] compile-flags: --target x86_64-apple-ios
+// [x86_64_apple_ios] needs-llvm-components: x86
+// revisions: x86_64_apple_ios_macabi
+// [x86_64_apple_ios_macabi] compile-flags: --target x86_64-apple-ios-macabi
+// [x86_64_apple_ios_macabi] needs-llvm-components: x86
+// revisions: x86_64_apple_tvos
+// [x86_64_apple_tvos] compile-flags: --target x86_64-apple-tvos
+// [x86_64_apple_tvos] needs-llvm-components: x86
+// revisions: x86_64_apple_watchos_sim
+// [x86_64_apple_watchos_sim] compile-flags: --target x86_64-apple-watchos-sim
+// [x86_64_apple_watchos_sim] needs-llvm-components: x86
+// revisions: x86_64h_apple_darwin
+// [x86_64h_apple_darwin] compile-flags: --target x86_64h-apple-darwin
+// [x86_64h_apple_darwin] needs-llvm-components: x86
+
+// Sanity-check that each target can produce assembly code.
+
+#![feature(no_core, lang_items)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+#[lang = "sized"]
+trait Sized {}
+
+pub fn test() -> u8 {
+    42
+}
+
+// CHECK: .section __TEXT,__text
diff --git a/tests/debuginfo/msvc-pretty-enums.rs b/tests/debuginfo/msvc-pretty-enums.rs
index d66e4c660f7..400e8801ca2 100644
--- a/tests/debuginfo/msvc-pretty-enums.rs
+++ b/tests/debuginfo/msvc-pretty-enums.rs
@@ -46,12 +46,12 @@
 // cdb-check:    [+0x000] __0              : 0x2a [Type: unsigned int]
 
 // cdb-command: dx niche128_some
-// cdb-check: niche128_some    : Some [Type: enum2$<core::option::Option<core::num::nonzero::NonZeroI128> >]
+// cdb-check: niche128_some    : Some [Type: enum2$<core::option::Option<core::num::nonzero::NonZero<i128> > >]
 // Note: we can't actually read the value of the field because CDB cannot handle 128 bit integers.
-// cdb-check:    [+0x000] __0 [...] [Type: core::num::nonzero::NonZeroI128]
+// cdb-check:    [+0x000] __0 [...] [Type: core::num::nonzero::NonZero<i128>]
 
 // cdb-command: dx niche128_none
-// cdb-check: niche128_none    : None [Type: enum2$<core::option::Option<core::num::nonzero::NonZeroI128> >]
+// cdb-check: niche128_none    : None [Type: enum2$<core::option::Option<core::num::nonzero::NonZero<i128> > >]
 
 // cdb-command: dx wrapping_niche128_untagged
 // cdb-check: wrapping_niche128_untagged : X [Type: enum2$<msvc_pretty_enums::Wrapping128Niche>]
@@ -84,7 +84,7 @@
 
 // cdb-command: dx niche_w_fields_2_some,d
 // cdb-check: niche_w_fields_2_some,d : A [Type: enum2$<msvc_pretty_enums::NicheLayoutWithFields2>]
-// cdb-check:     [+0x[...]] __0              : 800 [Type: core::num::nonzero::NonZeroU32]
+// cdb-check:     [+0x[...]] __0              : 800 [Type: core::num::nonzero::NonZero<u32>]
 // cdb-check:     [+0x[...]] __1              : 900 [Type: unsigned __int64]
 
 // cdb-command: dx niche_w_fields_2_none,d
diff --git a/tests/debuginfo/numeric-types.rs b/tests/debuginfo/numeric-types.rs
index c122112e6c7..a1b5ae792a1 100644
--- a/tests/debuginfo/numeric-types.rs
+++ b/tests/debuginfo/numeric-types.rs
@@ -3,59 +3,59 @@
 // min-gdb-version: 8.1
 // ignore-windows-gnu // emit_debug_gdb_scripts is disabled on Windows
 
-// Tests the visualizations for `NonZero{I,U}{8,16,32,64,128,size}`, `Wrapping<T>` and
+// Tests the visualizations for `NonZero<T>`, `Wrapping<T>` and
 // `Atomic{Bool,I8,I16,I32,I64,Isize,U8,U16,U32,U64,Usize}` located in `libcore.natvis`.
 
 // === CDB TESTS ==================================================================================
 // cdb-command: g
 
 // cdb-command: dx nz_i8
-// cdb-check:nz_i8            : 11 [Type: core::num::nonzero::NonZeroI8]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI8]
+// cdb-check:nz_i8            : 11 [Type: core::num::nonzero::NonZero<i8>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<i8>]
 
 // cdb-command: dx nz_i16
-// cdb-check:nz_i16           : 22 [Type: core::num::nonzero::NonZeroI16]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI16]
+// cdb-check:nz_i16           : 22 [Type: core::num::nonzero::NonZero<i16>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<i16>]
 
 // cdb-command: dx nz_i32
-// cdb-check:nz_i32           : 33 [Type: core::num::nonzero::NonZeroI32]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI32]
+// cdb-check:nz_i32           : 33 [Type: core::num::nonzero::NonZero<i32>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<i32>]
 
 // cdb-command: dx nz_i64
-// cdb-check:nz_i64           : 44 [Type: core::num::nonzero::NonZeroI64]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI64]
+// cdb-check:nz_i64           : 44 [Type: core::num::nonzero::NonZero<i64>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<i64>]
 
 // 128-bit integers don't seem to work in CDB
 // cdb-command: dx nz_i128
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroI128]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<i128>]
 
 // cdb-command: dx nz_isize
-// cdb-check:nz_isize         : 66 [Type: core::num::nonzero::NonZeroIsize]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroIsize]
+// cdb-check:nz_isize         : 66 [Type: core::num::nonzero::NonZero<isize>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<isize>]
 
 // cdb-command: dx nz_u8
-// cdb-check:nz_u8            : 0x4d [Type: core::num::nonzero::NonZeroU8]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU8]
+// cdb-check:nz_u8            : 0x4d [Type: core::num::nonzero::NonZero<u8>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<u8>]
 
 // cdb-command: dx nz_u16
-// cdb-check:nz_u16           : 0x58 [Type: core::num::nonzero::NonZeroU16]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU16]
+// cdb-check:nz_u16           : 0x58 [Type: core::num::nonzero::NonZero<u16>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<u16>]
 
 // cdb-command: dx nz_u32
-// cdb-check:nz_u32           : 0x63 [Type: core::num::nonzero::NonZeroU32]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU32]
+// cdb-check:nz_u32           : 0x63 [Type: core::num::nonzero::NonZero<u32>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<u32>]
 
 // cdb-command: dx nz_u64
-// cdb-check:nz_u64           : 0x64 [Type: core::num::nonzero::NonZeroU64]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU64]
+// cdb-check:nz_u64           : 0x64 [Type: core::num::nonzero::NonZero<u64>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<u64>]
 
 // 128-bit integers don't seem to work in CDB
 // cdb-command: dx nz_u128
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroU128]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<u128>]
 
 // cdb-command: dx nz_usize
-// cdb-check:nz_usize         : 0x7a [Type: core::num::nonzero::NonZeroUsize]
-// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZeroUsize]
+// cdb-check:nz_usize         : 0x7a [Type: core::num::nonzero::NonZero<usize>]
+// cdb-check:    [<Raw View>]     [Type: core::num::nonzero::NonZero<usize>]
 
 // cdb-command: dx w_i8
 // cdb-check:w_i8             : 10 [Type: core::num::wrapping::Wrapping<i8>]
diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff
new file mode 100644
index 00000000000..0b6819ad483
--- /dev/null
+++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff
@@ -0,0 +1,34 @@
+- // MIR for `f` before GVN
++ // MIR for `f` after GVN
+  
+  fn f() -> u32 {
+      let mut _0: u32;
+      let _1: u32;
+      let mut _2: E;
+      let mut _3: &U;
+      let _4: U;
+      scope 1 {
+          debug i => _1;
+      }
+      scope 2 {
+          let mut _5: &U;
+      }
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _5 = const _;
+          _3 = &(*_5);
+          _2 = ((*_3).1: E);
+          StorageLive(_1);
+-         _1 = ((_2 as A).1: u32);
++         _1 = const 0_u32;
+          StorageDead(_3);
+          StorageDead(_2);
+-         _0 = _1;
++         _0 = const 0_u32;
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..0b6819ad483
--- /dev/null
+++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff
@@ -0,0 +1,34 @@
+- // MIR for `f` before GVN
++ // MIR for `f` after GVN
+  
+  fn f() -> u32 {
+      let mut _0: u32;
+      let _1: u32;
+      let mut _2: E;
+      let mut _3: &U;
+      let _4: U;
+      scope 1 {
+          debug i => _1;
+      }
+      scope 2 {
+          let mut _5: &U;
+      }
+  
+      bb0: {
+          StorageLive(_2);
+          StorageLive(_3);
+          _5 = const _;
+          _3 = &(*_5);
+          _2 = ((*_3).1: E);
+          StorageLive(_1);
+-         _1 = ((_2 as A).1: u32);
++         _1 = const 0_u32;
+          StorageDead(_3);
+          StorageDead(_2);
+-         _0 = _1;
++         _0 = const 0_u32;
+          StorageDead(_1);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn_uninhabited.rs b/tests/mir-opt/gvn_uninhabited.rs
new file mode 100644
index 00000000000..a55b2dd763a
--- /dev/null
+++ b/tests/mir-opt/gvn_uninhabited.rs
@@ -0,0 +1,24 @@
+// unit-test: GVN
+// compile-flags: -O
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+// skip-filecheck
+
+#![feature(never_type)]
+
+#[derive(Copy, Clone)]
+pub enum E {
+    A(!, u32),
+}
+
+pub union U {
+    i: u32,
+    e: E,
+}
+
+// EMIT_MIR gvn_uninhabited.f.GVN.diff
+pub const fn f() -> u32 {
+    let E::A(_, i) = unsafe { (&U { i: 0 }).e };
+    i
+}
+
+fn main() {}
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
index 8e53427e7e0..a38b8246bde 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff
@@ -36,7 +36,7 @@
 -         _4 = g() -> [return: bb1, unwind unreachable];
 +         _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)};
 +         _3 = &mut _4;
-+         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 };
++         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 };
 +         StorageDead(_3);
 +         StorageLive(_5);
 +         _5 = const false;
diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
index b06db41af9d..dc6628ab44c 100644
--- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff
@@ -36,7 +36,7 @@
 -         _4 = g() -> [return: bb1, unwind continue];
 +         _4 = {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8 (#0)};
 +         _3 = &mut _4;
-+         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { pointer: _3 };
++         _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:19:5: 19:8}> { __pointer: _3 };
 +         StorageDead(_3);
 +         StorageLive(_5);
 +         _5 = const false;
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
index cb623e83f52..be7f9cd4412 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
@@ -4,7 +4,7 @@
   fn adt_transmutes() -> () {
       let mut _0: ();
       let _1: u8;
-      let mut _2: std::option::Option<std::num::NonZeroU8>;
+      let mut _2: std::option::Option<std::num::NonZero<u8>>;
       let mut _4: std::num::Wrapping<i16>;
       let mut _6: std::num::Wrapping<i16>;
       let mut _8: Union32;
@@ -37,7 +37,7 @@
       bb0: {
           StorageLive(_1);
           StorageLive(_2);
-          _2 = Option::<NonZeroU8>::Some(const _);
+          _2 = Option::<NonZero<u8>>::Some(const _);
           _1 = move _2 as u8 (Transmute);
           StorageDead(_2);
           StorageLive(_3);
diff --git a/tests/run-make/symbol-mangling-hashed/Makefile b/tests/run-make/symbol-mangling-hashed/Makefile
new file mode 100644
index 00000000000..68894b2192a
--- /dev/null
+++ b/tests/run-make/symbol-mangling-hashed/Makefile
@@ -0,0 +1,48 @@
+include ../tools.mk
+
+# ignore-cross-compile
+# only-linux
+# only-x86_64
+
+NM=nm -D
+RLIB_NAME=liba_rlib.rlib
+DYLIB_NAME=liba_dylib.so
+SO_NAME=libb_dylib.so
+BIN_NAME=b_bin
+
+ifeq ($(UNAME),Darwin)
+NM=nm -gU
+RLIB_NAME=liba_rlib.rlib
+DYLIB_NAME=liba_dylib.dylib
+SO_NAME=libb_dylib.dylib
+BIN_NAME=b_bin
+endif
+
+ifdef IS_WINDOWS
+NM=nm -g
+RLIB_NAME=liba_rlib.dll.a
+DYLIB_NAME=liba_dylib.dll
+SO_NAME=libb_dylib.dll
+BIN_NAME=b_bin.exe
+endif
+
+all:
+	$(RUSTC) -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=hashed -C metadata=foo a_dylib.rs
+	$(RUSTC) -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=hashed -C metadata=bar a_rlib.rs
+	$(RUSTC) -C prefer-dynamic -L $(TMPDIR) b_dylib.rs
+	$(RUSTC) -C prefer-dynamic -L $(TMPDIR) b_bin.rs
+
+    # Check hashed symbol name
+
+	[ "$$($(NM) $(TMPDIR)/$(DYLIB_NAME) | grep -c hello)" -eq "0" ]
+	[ "$$($(NM) $(TMPDIR)/$(DYLIB_NAME) | grep _RNxC7a_dylib | grep -c ' T ')" -eq "1" ]
+
+	[ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep b_dylib | grep -c hello)" -eq "1" ]
+	[ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep _RNxC6a_rlib | grep -c ' T ')" -eq "1" ]
+	[ "$$($(NM) $(TMPDIR)/$(SO_NAME) | grep _RNxC7a_dylib | grep -c ' U ')" -eq "1" ]
+
+	[ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep _RNxC6a_rlib | grep -c ' U ')" -eq "1" ]
+	[ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep _RNxC7a_dylib | grep -c ' U ')" -eq "1" ]
+	[ "$$($(NM) $(TMPDIR)/$(BIN_NAME) | grep b_dylib | grep hello | grep -c ' U ')" -eq "1" ]
+
+	$(call RUN,$(BIN_NAME))
diff --git a/tests/run-make/symbol-mangling-hashed/a_dylib.rs b/tests/run-make/symbol-mangling-hashed/a_dylib.rs
new file mode 100644
index 00000000000..8aec8fd82a5
--- /dev/null
+++ b/tests/run-make/symbol-mangling-hashed/a_dylib.rs
@@ -0,0 +1,4 @@
+#![crate_type="dylib"]
+pub fn hello() {
+    println!("hello dylib");
+}
diff --git a/tests/run-make/symbol-mangling-hashed/a_rlib.rs b/tests/run-make/symbol-mangling-hashed/a_rlib.rs
new file mode 100644
index 00000000000..873c86c5d0b
--- /dev/null
+++ b/tests/run-make/symbol-mangling-hashed/a_rlib.rs
@@ -0,0 +1,5 @@
+#![crate_type="rlib"]
+
+pub fn hello() {
+    println!("hello rlib");
+}
diff --git a/tests/run-make/symbol-mangling-hashed/b_bin.rs b/tests/run-make/symbol-mangling-hashed/b_bin.rs
new file mode 100644
index 00000000000..bcc53c37e12
--- /dev/null
+++ b/tests/run-make/symbol-mangling-hashed/b_bin.rs
@@ -0,0 +1,9 @@
+extern crate a_rlib;
+extern crate a_dylib;
+extern crate b_dylib;
+
+fn main() {
+    a_rlib::hello();
+    a_dylib::hello();
+    b_dylib::hello();
+}
diff --git a/tests/run-make/symbol-mangling-hashed/b_dylib.rs b/tests/run-make/symbol-mangling-hashed/b_dylib.rs
new file mode 100644
index 00000000000..c26a04b39ec
--- /dev/null
+++ b/tests/run-make/symbol-mangling-hashed/b_dylib.rs
@@ -0,0 +1,9 @@
+#![crate_type="dylib"]
+
+extern crate a_rlib;
+extern crate a_dylib;
+
+pub fn hello() {
+    a_rlib::hello();
+    a_dylib::hello();
+}
diff --git a/tests/run-make/target-specs/Makefile b/tests/run-make/target-specs/Makefile
index 62d5365a73d..161b6602185 100644
--- a/tests/run-make/target-specs/Makefile
+++ b/tests/run-make/target-specs/Makefile
@@ -9,4 +9,4 @@ all:
 	$(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json -
 	$(RUSTC) foo.rs --target=definitely-not-builtin-target 2>&1 | $(CGREP) 'may not set is_builtin'
 	$(RUSTC) foo.rs --target=endianness-mismatch 2>&1 | $(CGREP) '"data-layout" claims architecture is little-endian'
-	$(RUSTC) foo.rs --target=mismatching-data-layout --crate-type=lib
+	$(RUSTC) foo.rs --target=mismatching-data-layout --crate-type=lib 2>&1 | $(CGREP) 'data-layout for target'
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index f553aa96505..d3cfd28082d 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -25,22 +25,26 @@ extern crate rustc_middle;
 use rustc_middle::ty::Ty;
 
 extern crate rustc_errors;
-use rustc_errors::{Applicability, DiagnosticMessage, MultiSpan, SubdiagnosticMessage};
+use rustc_errors::{Applicability, DiagnosticMessage, ErrCode, MultiSpan, SubdiagnosticMessage};
 
 extern crate rustc_session;
 
 rustc_fluent_macro::fluent_messages! { "./example.ftl" }
 
+// E0123 and E0456 are no longer used, so we define our own constants here just for this test.
+const E0123: ErrCode = ErrCode::from_u32(0123);
+const E0456: ErrCode = ErrCode::from_u32(0456);
+
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct Hello {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct HelloWarn {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 //~^ ERROR unsupported type attribute for diagnostic derive enum
 enum DiagnosticOnEnum {
     Foo,
@@ -50,53 +54,53 @@ enum DiagnosticOnEnum {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[diag = "E0123"]
 //~^ ERROR failed to resolve: maybe a missing crate `core`
 struct WrongStructAttrStyle {}
 
 #[derive(Diagnostic)]
-#[nonsense(no_crate_example, code = "E0123")]
+#[nonsense(no_crate_example, code = E0123)]
 //~^ ERROR `#[nonsense(...)]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 //~^^^ ERROR cannot find attribute `nonsense` in this scope
 struct InvalidStructAttr {}
 
 #[derive(Diagnostic)]
-#[diag("E0123")]
+#[diag(code = E0123)]
 //~^ ERROR diagnostic slug not specified
 struct InvalidLitNestedAttr {}
 
 #[derive(Diagnostic)]
-#[diag(nonsense, code = "E0123")]
+#[diag(nonsense, code = E0123)]
 //~^ ERROR cannot find value `nonsense` in module `crate::fluent_generated`
 struct InvalidNestedStructAttr {}
 
 #[derive(Diagnostic)]
-#[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+#[diag(nonsense("foo"), code = E0123, slug = "foo")]
 //~^ ERROR diagnostic slug must be the first argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr1 {}
 
 #[derive(Diagnostic)]
-#[diag(nonsense = "...", code = "E0123", slug = "foo")]
+#[diag(nonsense = "...", code = E0123, slug = "foo")]
 //~^ ERROR unknown argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr2 {}
 
 #[derive(Diagnostic)]
-#[diag(nonsense = 4, code = "E0123", slug = "foo")]
+#[diag(nonsense = 4, code = E0123, slug = "foo")]
 //~^ ERROR unknown argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr3 {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123", slug = "foo")]
+#[diag(no_crate_example, code = E0123, slug = "foo")]
 //~^ ERROR unknown argument
 struct InvalidNestedStructAttr4 {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct WrongPlaceField {
     #[suggestion = "bar"]
     //~^ ERROR `#[suggestion = ...]` is not a valid attribute
@@ -104,19 +108,19 @@ struct WrongPlaceField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
-#[diag(no_crate_example, code = "E0456")]
+#[diag(no_crate_example, code = E0123)]
+#[diag(no_crate_example, code = E0456)]
 //~^ ERROR specified multiple times
 //~^^ ERROR specified multiple times
 struct DiagSpecifiedTwice {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0456", code = "E0457")]
+#[diag(no_crate_example, code = E0123, code = E0456)]
 //~^ ERROR specified multiple times
 struct CodeSpecifiedTwice {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, no_crate::example, code = "E0456")]
+#[diag(no_crate_example, no_crate::example, code = E0123)]
 //~^ ERROR diagnostic slug must be the first argument
 struct SlugSpecifiedTwice {}
 
@@ -124,7 +128,7 @@ struct SlugSpecifiedTwice {}
 struct KindNotProvided {} //~ ERROR diagnostic slug not specified
 
 #[derive(Diagnostic)]
-#[diag(code = "E0456")]
+#[diag(code = E0123)]
 //~^ ERROR diagnostic slug not specified
 struct SlugNotProvided {}
 
@@ -133,7 +137,7 @@ struct SlugNotProvided {}
 struct CodeNotProvided {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct MessageWrongType {
     #[primary_span]
     //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -141,7 +145,7 @@ struct MessageWrongType {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct InvalidPathFieldAttr {
     #[nonsense]
     //~^ ERROR `#[nonsense]` is not a valid attribute
@@ -150,7 +154,7 @@ struct InvalidPathFieldAttr {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithField {
     name: String,
     #[label(no_crate_label)]
@@ -158,7 +162,7 @@ struct ErrorWithField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithMessageAppliedToField {
     #[label(no_crate_label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -166,7 +170,7 @@ struct ErrorWithMessageAppliedToField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithNonexistentField {
     #[suggestion(no_crate_suggestion, code = "{name}")]
     //~^ ERROR `name` doesn't refer to a field on this type
@@ -175,7 +179,7 @@ struct ErrorWithNonexistentField {
 
 #[derive(Diagnostic)]
 //~^ ERROR invalid format string: expected `'}'`
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorMissingClosingBrace {
     #[suggestion(no_crate_suggestion, code = "{name")]
     suggestion: (Span, Applicability),
@@ -185,7 +189,7 @@ struct ErrorMissingClosingBrace {
 
 #[derive(Diagnostic)]
 //~^ ERROR invalid format string: unmatched `}`
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorMissingOpeningBrace {
     #[suggestion(no_crate_suggestion, code = "name}")]
     suggestion: (Span, Applicability),
@@ -194,14 +198,14 @@ struct ErrorMissingOpeningBrace {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelOnSpan {
     #[label(no_crate_label)]
     sp: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelOnNonSpan {
     #[label(no_crate_label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -209,7 +213,7 @@ struct LabelOnNonSpan {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct Suggest {
     #[suggestion(no_crate_suggestion, code = "This is the suggested code")]
     #[suggestion(no_crate_suggestion, code = "This is the suggested code", style = "normal")]
@@ -220,7 +224,7 @@ struct Suggest {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithoutCode {
     #[suggestion(no_crate_suggestion)]
     //~^ ERROR suggestion without `code = "..."`
@@ -228,7 +232,7 @@ struct SuggestWithoutCode {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithBadKey {
     #[suggestion(nonsense = "bar")]
     //~^ ERROR invalid nested attribute
@@ -237,7 +241,7 @@ struct SuggestWithBadKey {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithShorthandMsg {
     #[suggestion(msg = "bar")]
     //~^ ERROR invalid nested attribute
@@ -246,21 +250,21 @@ struct SuggestWithShorthandMsg {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithoutMsg {
     #[suggestion(code = "bar")]
     suggestion: (Span, Applicability),
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithTypesSwapped {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     suggestion: (Applicability, Span),
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithWrongTypeApplicabilityOnly {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     //~^ ERROR wrong field type for suggestion
@@ -268,14 +272,14 @@ struct SuggestWithWrongTypeApplicabilityOnly {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithSpanOnly {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithDuplicateSpanAndApplicability {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     suggestion: (Span, Span, Applicability),
@@ -283,7 +287,7 @@ struct SuggestWithDuplicateSpanAndApplicability {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct SuggestWithDuplicateApplicabilityAndSpan {
     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
     suggestion: (Applicability, Applicability, Span),
@@ -291,7 +295,7 @@ struct SuggestWithDuplicateApplicabilityAndSpan {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct WrongKindOfAnnotation {
     #[label = "bar"]
     //~^ ERROR `#[label = ...]` is not a valid attribute
@@ -299,7 +303,7 @@ struct WrongKindOfAnnotation {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct OptionsInErrors {
     #[label(no_crate_label)]
     label: Option<Span>,
@@ -308,7 +312,7 @@ struct OptionsInErrors {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0456")]
+#[diag(no_crate_example, code = E0123)]
 struct MoveOutOfBorrowError<'tcx> {
     name: Ident,
     ty: Ty<'tcx>,
@@ -322,7 +326,7 @@ struct MoveOutOfBorrowError<'tcx> {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithLifetime<'a> {
     #[label(no_crate_label)]
     span: Span,
@@ -330,7 +334,7 @@ struct ErrorWithLifetime<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithDefaultLabelAttr<'a> {
     #[label]
     span: Span,
@@ -338,7 +342,7 @@ struct ErrorWithDefaultLabelAttr<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ArgFieldWithoutSkip {
     #[primary_span]
     span: Span,
@@ -347,7 +351,7 @@ struct ArgFieldWithoutSkip {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ArgFieldWithSkip {
     #[primary_span]
     span: Span,
@@ -358,56 +362,56 @@ struct ArgFieldWithSkip {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithSpannedNote {
     #[note]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithSpannedNoteCustom {
     #[note(no_crate_note)]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[note]
 struct ErrorWithNote {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[note(no_crate_note)]
 struct ErrorWithNoteCustom {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithSpannedHelp {
     #[help]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithSpannedHelpCustom {
     #[help(no_crate_help)]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[help]
 struct ErrorWithHelp {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[help(no_crate_help)]
 struct ErrorWithHelpCustom {
     val: String,
@@ -415,34 +419,34 @@ struct ErrorWithHelpCustom {
 
 #[derive(Diagnostic)]
 #[help]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithHelpWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
 #[help(no_crate_help)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithHelpCustomWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
 #[note]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithNoteWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
 #[note(no_crate_note)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithNoteCustomWrongOrder {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ApplicabilityInBoth {
     #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
     //~^ ERROR specified multiple times
@@ -450,7 +454,7 @@ struct ApplicabilityInBoth {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct InvalidApplicability {
     #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
     //~^ ERROR invalid applicability
@@ -458,14 +462,14 @@ struct InvalidApplicability {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ValidApplicability {
     #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
     suggestion: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct NoApplicability {
     #[suggestion(no_crate_suggestion, code = "...")]
     suggestion: Span,
@@ -483,7 +487,7 @@ struct Subdiagnostic {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct VecField {
     #[primary_span]
     #[label]
@@ -491,7 +495,7 @@ struct VecField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct UnitField {
     #[primary_span]
     spans: Span,
@@ -502,7 +506,7 @@ struct UnitField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct OptUnitField {
     #[primary_span]
     spans: Span,
@@ -526,7 +530,7 @@ struct BoolField {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelWithTrailingPath {
     #[label(no_crate_label, foo)]
     //~^ ERROR a diagnostic slug must be the first argument to the attribute
@@ -534,7 +538,7 @@ struct LabelWithTrailingPath {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelWithTrailingNameValue {
     #[label(no_crate_label, foo = "...")]
     //~^ ERROR only `no_span` is a valid nested attribute
@@ -542,7 +546,7 @@ struct LabelWithTrailingNameValue {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct LabelWithTrailingList {
     #[label(no_crate_label, foo("..."))]
     //~^ ERROR only `no_span` is a valid nested attribute
@@ -562,42 +566,42 @@ struct PrimarySpanOnLint {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct ErrorWithMultiSpan {
     #[primary_span]
     span: MultiSpan,
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[warning]
 struct ErrorWithWarn {
     val: String,
 }
 
 #[derive(Diagnostic)]
-#[error(no_crate_example, code = "E0123")]
+#[error(no_crate_example, code = E0123)]
 //~^ ERROR `#[error(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
 //~| ERROR cannot find attribute `error` in this scope
 struct ErrorAttribute {}
 
 #[derive(Diagnostic)]
-#[warn_(no_crate_example, code = "E0123")]
+#[warn_(no_crate_example, code = E0123)]
 //~^ ERROR `#[warn_(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
 //~| ERROR cannot find attribute `warn_` in this scope
 struct WarnAttribute {}
 
 #[derive(Diagnostic)]
-#[lint(no_crate_example, code = "E0123")]
+#[lint(no_crate_example, code = E0123)]
 //~^ ERROR `#[lint(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
 //~| ERROR cannot find attribute `lint` in this scope
 struct LintAttributeOnSessionDiag {}
 
 #[derive(LintDiagnostic)]
-#[lint(no_crate_example, code = "E0123")]
+#[lint(no_crate_example, code = E0123)]
 //~^ ERROR `#[lint(...)]` is not a valid attribute
 //~| ERROR `#[lint(...)]` is not a valid attribute
 //~| ERROR diagnostic slug not specified
@@ -605,7 +609,7 @@ struct LintAttributeOnSessionDiag {}
 struct LintAttributeOnLintDiag {}
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct DuplicatedSuggestionCode {
     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
     //~^ ERROR specified multiple times
@@ -613,7 +617,7 @@ struct DuplicatedSuggestionCode {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct InvalidTypeInSuggestionTuple {
     #[suggestion(no_crate_suggestion, code = "...")]
     suggestion: (Span, usize),
@@ -621,7 +625,7 @@ struct InvalidTypeInSuggestionTuple {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct MissingApplicabilityInSuggestionTuple {
     #[suggestion(no_crate_suggestion, code = "...")]
     suggestion: (Span,),
@@ -629,7 +633,7 @@ struct MissingApplicabilityInSuggestionTuple {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct MissingCodeInSuggestion {
     #[suggestion(no_crate_suggestion)]
     //~^ ERROR suggestion without `code = "..."`
@@ -637,7 +641,7 @@ struct MissingCodeInSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[multipart_suggestion(no_crate_suggestion)]
 //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
 //~| ERROR cannot find attribute `multipart_suggestion` in this scope
@@ -652,7 +656,7 @@ struct MultipartSuggestion {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[suggestion(no_crate_suggestion, code = "...")]
 //~^ ERROR `#[suggestion(...)]` is not a valid attribute
 struct SuggestionOnStruct {
@@ -661,7 +665,7 @@ struct SuggestionOnStruct {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 #[label]
 //~^ ERROR `#[label]` is not a valid attribute
 struct LabelOnStruct {
@@ -688,7 +692,7 @@ enum ExampleEnum {
 }
 
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct RawIdentDiagnosticArg {
     pub r#type: String,
 }
@@ -762,7 +766,7 @@ struct SubdiagnosticEagerSuggestion {
 
 /// with a doc comment on the type..
 #[derive(Diagnostic)]
-#[diag(no_crate_example, code = "E0123")]
+#[diag(no_crate_example, code = E0123)]
 struct WithDocComment {
     /// ..and the field
     #[primary_span]
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index f376c034587..67257c28b6e 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -1,11 +1,11 @@
 error: unsupported type attribute for diagnostic derive enum
-  --> $DIR/diagnostic-derive.rs:43:1
+  --> $DIR/diagnostic-derive.rs:47:1
    |
-LL | #[diag(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:46:5
+  --> $DIR/diagnostic-derive.rs:50:5
    |
 LL |     Foo,
    |     ^^^
@@ -13,7 +13,7 @@ LL |     Foo,
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:48:5
+  --> $DIR/diagnostic-derive.rs:52:5
    |
 LL |     Bar,
    |     ^^^
@@ -21,15 +21,15 @@ LL |     Bar,
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[nonsense(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:59:1
+  --> $DIR/diagnostic-derive.rs:63:1
    |
-LL | #[nonsense(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[nonsense(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:59:1
+  --> $DIR/diagnostic-derive.rs:63:1
    |
-LL | / #[nonsense(no_crate_example, code = "E0123")]
+LL | / #[nonsense(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -39,9 +39,9 @@ LL | | struct InvalidStructAttr {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:66:1
+  --> $DIR/diagnostic-derive.rs:70:1
    |
-LL | / #[diag("E0123")]
+LL | / #[diag(code = E0123)]
 LL | |
 LL | | struct InvalidLitNestedAttr {}
    | |______________________________^
@@ -49,15 +49,15 @@ LL | | struct InvalidLitNestedAttr {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug must be the first argument
-  --> $DIR/diagnostic-derive.rs:76:16
+  --> $DIR/diagnostic-derive.rs:80:16
    |
-LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+LL | #[diag(nonsense("foo"), code = E0123, slug = "foo")]
    |                ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:76:1
+  --> $DIR/diagnostic-derive.rs:80:1
    |
-LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense("foo"), code = E0123, slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr1 {}
@@ -66,17 +66,17 @@ LL | | struct InvalidNestedStructAttr1 {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: unknown argument
-  --> $DIR/diagnostic-derive.rs:82:8
+  --> $DIR/diagnostic-derive.rs:86:8
    |
-LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
+LL | #[diag(nonsense = "...", code = E0123, slug = "foo")]
    |        ^^^^^^^^
    |
    = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:82:1
+  --> $DIR/diagnostic-derive.rs:86:1
    |
-LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense = "...", code = E0123, slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr2 {}
@@ -85,17 +85,17 @@ LL | | struct InvalidNestedStructAttr2 {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: unknown argument
-  --> $DIR/diagnostic-derive.rs:88:8
+  --> $DIR/diagnostic-derive.rs:92:8
    |
-LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
+LL | #[diag(nonsense = 4, code = E0123, slug = "foo")]
    |        ^^^^^^^^
    |
    = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:88:1
+  --> $DIR/diagnostic-derive.rs:92:1
    |
-LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense = 4, code = E0123, slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr3 {}
@@ -104,63 +104,63 @@ LL | | struct InvalidNestedStructAttr3 {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: unknown argument
-  --> $DIR/diagnostic-derive.rs:94:42
+  --> $DIR/diagnostic-derive.rs:98:40
    |
-LL | #[diag(no_crate_example, code = "E0123", slug = "foo")]
-   |                                          ^^^^
+LL | #[diag(no_crate_example, code = E0123, slug = "foo")]
+   |                                        ^^^^
    |
    = note: only the `code` parameter is valid after the slug
 
 error: `#[suggestion = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:101:5
+  --> $DIR/diagnostic-derive.rs:105:5
    |
 LL |     #[suggestion = "bar"]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:108:8
+  --> $DIR/diagnostic-derive.rs:112:8
    |
-LL | #[diag(no_crate_example, code = "E0456")]
+LL | #[diag(no_crate_example, code = E0456)]
    |        ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:107:8
+  --> $DIR/diagnostic-derive.rs:111:8
    |
-LL | #[diag(no_crate_example, code = "E0123")]
+LL | #[diag(no_crate_example, code = E0123)]
    |        ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:108:26
+  --> $DIR/diagnostic-derive.rs:112:26
    |
-LL | #[diag(no_crate_example, code = "E0456")]
+LL | #[diag(no_crate_example, code = E0456)]
    |                          ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:107:26
+  --> $DIR/diagnostic-derive.rs:111:26
    |
-LL | #[diag(no_crate_example, code = "E0123")]
+LL | #[diag(no_crate_example, code = E0123)]
    |                          ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:114:42
+  --> $DIR/diagnostic-derive.rs:118:40
    |
-LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
-   |                                          ^^^^
+LL | #[diag(no_crate_example, code = E0123, code = E0456)]
+   |                                        ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:114:26
+  --> $DIR/diagnostic-derive.rs:118:26
    |
-LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
+LL | #[diag(no_crate_example, code = E0123, code = E0456)]
    |                          ^^^^
 
 error: diagnostic slug must be the first argument
-  --> $DIR/diagnostic-derive.rs:119:43
+  --> $DIR/diagnostic-derive.rs:123:43
    |
-LL | #[diag(no_crate_example, no_crate::example, code = "E0456")]
+LL | #[diag(no_crate_example, no_crate::example, code = E0123)]
    |                                           ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:124:1
+  --> $DIR/diagnostic-derive.rs:128:1
    |
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -168,9 +168,9 @@ LL | struct KindNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:127:1
+  --> $DIR/diagnostic-derive.rs:131:1
    |
-LL | / #[diag(code = "E0456")]
+LL | / #[diag(code = E0123)]
 LL | |
 LL | | struct SlugNotProvided {}
    | |_________________________^
@@ -178,31 +178,31 @@ LL | | struct SlugNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:138:5
+  --> $DIR/diagnostic-derive.rs:142:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: `#[nonsense]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:146:5
+  --> $DIR/diagnostic-derive.rs:150:5
    |
 LL |     #[nonsense]
    |     ^^^^^^^^^^^
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:163:5
+  --> $DIR/diagnostic-derive.rs:167:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `name` doesn't refer to a field on this type
-  --> $DIR/diagnostic-derive.rs:171:46
+  --> $DIR/diagnostic-derive.rs:175:46
    |
 LL |     #[suggestion(no_crate_suggestion, code = "{name}")]
    |                                              ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/diagnostic-derive.rs:176:10
+  --> $DIR/diagnostic-derive.rs:180:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ expected `'}'` in format string
@@ -211,7 +211,7 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/diagnostic-derive.rs:186:10
+  --> $DIR/diagnostic-derive.rs:190:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ unmatched `}` in format string
@@ -220,19 +220,19 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:206:5
+  --> $DIR/diagnostic-derive.rs:210:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:225:5
+  --> $DIR/diagnostic-derive.rs:229:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/diagnostic-derive.rs:233:18
+  --> $DIR/diagnostic-derive.rs:237:18
    |
 LL |     #[suggestion(nonsense = "bar")]
    |                  ^^^^^^^^
@@ -240,13 +240,13 @@ LL |     #[suggestion(nonsense = "bar")]
    = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:233:5
+  --> $DIR/diagnostic-derive.rs:237:5
    |
 LL |     #[suggestion(nonsense = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid nested attribute
-  --> $DIR/diagnostic-derive.rs:242:18
+  --> $DIR/diagnostic-derive.rs:246:18
    |
 LL |     #[suggestion(msg = "bar")]
    |                  ^^^
@@ -254,13 +254,13 @@ LL |     #[suggestion(msg = "bar")]
    = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:242:5
+  --> $DIR/diagnostic-derive.rs:246:5
    |
 LL |     #[suggestion(msg = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: wrong field type for suggestion
-  --> $DIR/diagnostic-derive.rs:265:5
+  --> $DIR/diagnostic-derive.rs:269:5
    |
 LL | /     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
 LL | |
@@ -270,79 +270,79 @@ LL | |     suggestion: Applicability,
    = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:281:24
+  --> $DIR/diagnostic-derive.rs:285:24
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                        ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:281:18
+  --> $DIR/diagnostic-derive.rs:285:18
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                  ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:289:33
+  --> $DIR/diagnostic-derive.rs:293:33
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                                 ^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:289:18
+  --> $DIR/diagnostic-derive.rs:293:18
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                  ^^^^^^^^^^^^^
 
 error: `#[label = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:296:5
+  --> $DIR/diagnostic-derive.rs:300:5
    |
 LL |     #[label = "bar"]
    |     ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:447:5
+  --> $DIR/diagnostic-derive.rs:451:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:449:24
+  --> $DIR/diagnostic-derive.rs:453:24
    |
 LL |     suggestion: (Span, Applicability),
    |                        ^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:455:69
+  --> $DIR/diagnostic-derive.rs:459:69
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
    |                                                                     ^^^^^^^^
 
 error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()`
-  --> $DIR/diagnostic-derive.rs:522:5
+  --> $DIR/diagnostic-derive.rs:526:5
    |
 LL |     #[help(no_crate_help)]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: a diagnostic slug must be the first argument to the attribute
-  --> $DIR/diagnostic-derive.rs:531:32
+  --> $DIR/diagnostic-derive.rs:535:32
    |
 LL |     #[label(no_crate_label, foo)]
    |                                ^
 
 error: only `no_span` is a valid nested attribute
-  --> $DIR/diagnostic-derive.rs:539:29
+  --> $DIR/diagnostic-derive.rs:543:29
    |
 LL |     #[label(no_crate_label, foo = "...")]
    |                             ^^^
 
 error: only `no_span` is a valid nested attribute
-  --> $DIR/diagnostic-derive.rs:547:29
+  --> $DIR/diagnostic-derive.rs:551:29
    |
 LL |     #[label(no_crate_label, foo("..."))]
    |                             ^^^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:559:5
+  --> $DIR/diagnostic-derive.rs:563:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -350,15 +350,15 @@ LL |     #[primary_span]
    = help: the `primary_span` field attribute is not valid for lint diagnostics
 
 error: `#[error(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:579:1
+  --> $DIR/diagnostic-derive.rs:583:1
    |
-LL | #[error(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[error(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:579:1
+  --> $DIR/diagnostic-derive.rs:583:1
    |
-LL | / #[error(no_crate_example, code = "E0123")]
+LL | / #[error(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -368,15 +368,15 @@ LL | | struct ErrorAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[warn_(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:586:1
+  --> $DIR/diagnostic-derive.rs:590:1
    |
-LL | #[warn_(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[warn_(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:586:1
+  --> $DIR/diagnostic-derive.rs:590:1
    |
-LL | / #[warn_(no_crate_example, code = "E0123")]
+LL | / #[warn_(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -386,15 +386,15 @@ LL | | struct WarnAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:593:1
+  --> $DIR/diagnostic-derive.rs:597:1
    |
-LL | #[lint(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:593:1
+  --> $DIR/diagnostic-derive.rs:597:1
    |
-LL | / #[lint(no_crate_example, code = "E0123")]
+LL | / #[lint(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -404,23 +404,23 @@ LL | | struct LintAttributeOnSessionDiag {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:600:1
+  --> $DIR/diagnostic-derive.rs:604:1
    |
-LL | #[lint(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:600:1
+  --> $DIR/diagnostic-derive.rs:604:1
    |
-LL | #[lint(no_crate_example, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(no_crate_example, code = E0123)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:600:1
+  --> $DIR/diagnostic-derive.rs:604:1
    |
-LL | / #[lint(no_crate_example, code = "E0123")]
+LL | / #[lint(no_crate_example, code = E0123)]
 LL | |
 LL | |
 LL | |
@@ -431,19 +431,19 @@ LL | | struct LintAttributeOnLintDiag {}
    = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:610:53
+  --> $DIR/diagnostic-derive.rs:614:53
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
    |                                                     ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:610:39
+  --> $DIR/diagnostic-derive.rs:614:39
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
    |                                       ^^^^
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:619:24
+  --> $DIR/diagnostic-derive.rs:623:24
    |
 LL |     suggestion: (Span, usize),
    |                        ^^^^^
@@ -451,7 +451,7 @@ LL |     suggestion: (Span, usize),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:627:17
+  --> $DIR/diagnostic-derive.rs:631:17
    |
 LL |     suggestion: (Span,),
    |                 ^^^^^^^
@@ -459,13 +459,13 @@ LL |     suggestion: (Span,),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:634:5
+  --> $DIR/diagnostic-derive.rs:638:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:641:1
+  --> $DIR/diagnostic-derive.rs:645:1
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -473,7 +473,7 @@ LL | #[multipart_suggestion(no_crate_suggestion)]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:644:1
+  --> $DIR/diagnostic-derive.rs:648:1
    |
 LL | #[multipart_suggestion()]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -481,7 +481,7 @@ LL | #[multipart_suggestion()]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:648:5
+  --> $DIR/diagnostic-derive.rs:652:5
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -489,7 +489,7 @@ LL |     #[multipart_suggestion(no_crate_suggestion)]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:656:1
+  --> $DIR/diagnostic-derive.rs:660:1
    |
 LL | #[suggestion(no_crate_suggestion, code = "...")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -497,7 +497,7 @@ LL | #[suggestion(no_crate_suggestion, code = "...")]
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
 error: `#[label]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:665:1
+  --> $DIR/diagnostic-derive.rs:669:1
    |
 LL | #[label]
    | ^^^^^^^^
@@ -505,31 +505,31 @@ LL | #[label]
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
 error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:699:7
+  --> $DIR/diagnostic-derive.rs:703:7
    |
 LL |     #[subdiagnostic(bad)]
    |       ^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:707:5
+  --> $DIR/diagnostic-derive.rs:711:5
    |
 LL |     #[subdiagnostic = "bad"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:715:7
+  --> $DIR/diagnostic-derive.rs:719:7
    |
 LL |     #[subdiagnostic(bad, bad)]
    |       ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `eager` is the only supported nested attribute for `subdiagnostic`
-  --> $DIR/diagnostic-derive.rs:723:7
+  --> $DIR/diagnostic-derive.rs:727:7
    |
 LL |     #[subdiagnostic("bad")]
    |       ^^^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:731:5
+  --> $DIR/diagnostic-derive.rs:735:5
    |
 LL |     #[subdiagnostic(eager)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -537,19 +537,19 @@ LL |     #[subdiagnostic(eager)]
    = help: eager subdiagnostics are not supported on lints
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:789:23
+  --> $DIR/diagnostic-derive.rs:793:23
    |
 LL |     #[suggestion(code())]
    |                       ^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:797:23
+  --> $DIR/diagnostic-derive.rs:801:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:821:5
+  --> $DIR/diagnostic-derive.rs:825:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -559,85 +559,85 @@ LL |     #[suggestion(no_crate_suggestion, code = "")]
    = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]`
 
 error[E0433]: failed to resolve: maybe a missing crate `core`?
-  --> $DIR/diagnostic-derive.rs:54:8
+  --> $DIR/diagnostic-derive.rs:58:8
    |
 LL | #[diag = "E0123"]
    |        ^ maybe a missing crate `core`?
 
 error[E0433]: failed to resolve: maybe a missing crate `core`?
-  --> $DIR/diagnostic-derive.rs:797:23
+  --> $DIR/diagnostic-derive.rs:801:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^ maybe a missing crate `core`?
 
 error[E0433]: failed to resolve: maybe a missing crate `core`?
-  --> $DIR/diagnostic-derive.rs:806:25
+  --> $DIR/diagnostic-derive.rs:810:25
    |
 LL |     #[suggestion(code = 3)]
    |                         ^ maybe a missing crate `core`?
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:59:3
+  --> $DIR/diagnostic-derive.rs:63:3
    |
-LL | #[nonsense(no_crate_example, code = "E0123")]
+LL | #[nonsense(no_crate_example, code = E0123)]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:146:7
+  --> $DIR/diagnostic-derive.rs:150:7
    |
 LL |     #[nonsense]
    |       ^^^^^^^^
 
 error: cannot find attribute `error` in this scope
-  --> $DIR/diagnostic-derive.rs:579:3
+  --> $DIR/diagnostic-derive.rs:583:3
    |
-LL | #[error(no_crate_example, code = "E0123")]
+LL | #[error(no_crate_example, code = E0123)]
    |   ^^^^^
 
 error: cannot find attribute `warn_` in this scope
-  --> $DIR/diagnostic-derive.rs:586:3
+  --> $DIR/diagnostic-derive.rs:590:3
    |
-LL | #[warn_(no_crate_example, code = "E0123")]
+LL | #[warn_(no_crate_example, code = E0123)]
    |   ^^^^^ help: a built-in attribute with a similar name exists: `warn`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:593:3
+  --> $DIR/diagnostic-derive.rs:597:3
    |
-LL | #[lint(no_crate_example, code = "E0123")]
+LL | #[lint(no_crate_example, code = E0123)]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:600:3
+  --> $DIR/diagnostic-derive.rs:604:3
    |
-LL | #[lint(no_crate_example, code = "E0123")]
+LL | #[lint(no_crate_example, code = E0123)]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:641:3
+  --> $DIR/diagnostic-derive.rs:645:3
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:644:3
+  --> $DIR/diagnostic-derive.rs:648:3
    |
 LL | #[multipart_suggestion()]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:648:7
+  --> $DIR/diagnostic-derive.rs:652:7
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |       ^^^^^^^^^^^^^^^^^^^^
 
 error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated`
-  --> $DIR/diagnostic-derive.rs:71:8
+  --> $DIR/diagnostic-derive.rs:75:8
    |
-LL | #[diag(nonsense, code = "E0123")]
+LL | #[diag(nonsense, code = E0123)]
    |        ^^^^^^^^ not found in `crate::fluent_generated`
 
 error[E0425]: cannot find value `__code_34` in this scope
-  --> $DIR/diagnostic-derive.rs:803:10
+  --> $DIR/diagnostic-derive.rs:807:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ not found in this scope
@@ -645,7 +645,7 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-  --> $DIR/diagnostic-derive.rs:345:12
+  --> $DIR/diagnostic-derive.rs:349:12
    |
 LL | #[derive(Diagnostic)]
    |          ---------- required by a bound introduced by this call
diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
index a0a8114e0c5..785da11b9b2 100644
--- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
+++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.rs
@@ -19,6 +19,6 @@ use rustc_errors::{Applicability, MultiSpan};
 extern crate rustc_session;
 
 #[derive(Diagnostic)]
-#[diag(compiletest_example, code = "E0123")]
+#[diag(compiletest_example, code = 0123)]
 //~^ ERROR diagnostic slug and crate name do not match
 struct Hello {}
diff --git a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr
index 4cdc24e6a6b..eda24a555f8 100644
--- a/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/enforce_slug_naming.stderr
@@ -1,7 +1,7 @@
 error: diagnostic slug and crate name do not match
   --> $DIR/enforce_slug_naming.rs:22:8
    |
-LL | #[diag(compiletest_example, code = "E0123")]
+LL | #[diag(compiletest_example, code = 0123)]
    |        ^^^^^^^^^^^^^^^^^^^
    |
    = note: slug is `compiletest_example` but the crate name is `rustc_dummy`
diff --git a/tests/ui/async-await/async-closures/higher-ranked.rs b/tests/ui/async-await/async-closures/higher-ranked.rs
new file mode 100644
index 00000000000..f0bdcf691ae
--- /dev/null
+++ b/tests/ui/async-await/async-closures/higher-ranked.rs
@@ -0,0 +1,12 @@
+// edition:2021
+
+#![feature(async_closure)]
+
+fn main() {
+    let x = async move |x: &str| {
+        //~^ ERROR lifetime may not live long enough
+        // This error is proof that the `&str` type is higher-ranked.
+        // This won't work until async closures are fully impl'd.
+        println!("{x}");
+    };
+}
diff --git a/tests/ui/async-await/async-closures/higher-ranked.stderr b/tests/ui/async-await/async-closures/higher-ranked.stderr
new file mode 100644
index 00000000000..fb02a15b079
--- /dev/null
+++ b/tests/ui/async-await/async-closures/higher-ranked.stderr
@@ -0,0 +1,17 @@
+error: lifetime may not live long enough
+  --> $DIR/higher-ranked.rs:6:34
+   |
+LL |       let x = async move |x: &str| {
+   |  ____________________________-___-_^
+   | |                            |   |
+   | |                            |   return type of closure `{async closure body@$DIR/higher-ranked.rs:6:34: 11:6}` contains a lifetime `'2`
+   | |                            let's call the lifetime of this reference `'1`
+LL | |
+LL | |         // This error is proof that the `&str` type is higher-ranked.
+LL | |         // This won't work until async closures are fully impl'd.
+LL | |         println!("{x}");
+LL | |     };
+   | |_____^ returning this value requires that `'1` must outlive `'2`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs b/tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs
new file mode 100644
index 00000000000..72f02679d77
--- /dev/null
+++ b/tests/ui/async-await/in-trait/returning-possibly-unsized-self.rs
@@ -0,0 +1,18 @@
+// check-pass
+// edition:2021
+
+#![deny(opaque_hidden_inferred_bound)]
+
+trait Repository /* : ?Sized */ {
+    async fn new() -> Self;
+}
+
+struct MyRepository {}
+
+impl Repository for MyRepository {
+    async fn new() -> Self {
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/codegen/mismatched-data-layout.json b/tests/ui/codegen/mismatched-data-layout.json
new file mode 100644
index 00000000000..4cb0602dc75
--- /dev/null
+++ b/tests/ui/codegen/mismatched-data-layout.json
@@ -0,0 +1,13 @@
+{
+    "llvm-target": "x86_64-unknown-none-gnu",
+    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
+    "arch": "x86_64",
+    "target-endian": "little",
+    "target-pointer-width": "64",
+    "target-c-int-width": "32",
+    "os": "unknown",
+    "linker-flavor": "ld.lld",
+    "linker": "rust-lld",
+    "executables": true
+}
+
diff --git a/tests/ui/codegen/mismatched-data-layouts.rs b/tests/ui/codegen/mismatched-data-layouts.rs
new file mode 100644
index 00000000000..047ec155fdc
--- /dev/null
+++ b/tests/ui/codegen/mismatched-data-layouts.rs
@@ -0,0 +1,14 @@
+// This test checks that data layout mismatches emit an error.
+//
+// build-fail
+// needs-llvm-components: x86
+// compile-flags: --crate-type=lib --target={{src-base}}/codegen/mismatched-data-layout.json -Z unstable-options
+// error-pattern: differs from LLVM target's
+// normalize-stderr-test: "`, `[A-Za-z0-9-:]*`" -> "`, `normalized data layout`"
+// normalize-stderr-test: "layout, `[A-Za-z0-9-:]*`" -> "layout, `normalized data layout`"
+
+#![feature(lang_items, no_core, auto_traits)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
diff --git a/tests/ui/codegen/mismatched-data-layouts.stderr b/tests/ui/codegen/mismatched-data-layouts.stderr
new file mode 100644
index 00000000000..1fe242266df
--- /dev/null
+++ b/tests/ui/codegen/mismatched-data-layouts.stderr
@@ -0,0 +1,4 @@
+error: data-layout for target `mismatched-data-layout-7814813422914914169`, `normalized data layout`, differs from LLVM target's `x86_64-unknown-none-gnu` default layout, `normalized data layout`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs b/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs
new file mode 100644
index 00000000000..7da6b7ca285
--- /dev/null
+++ b/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs
@@ -0,0 +1,10 @@
+// check-pass
+#![feature(never_type)]
+#[derive(Copy, Clone)]
+pub enum E { A(!), }
+pub union U { u: (), e: E, }
+pub const C: () = {
+    let E::A(ref a) = unsafe { &(&U { u: () }).e};
+};
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
index 134ea25b75a..594a2672d43 100644
--- a/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
+++ b/tests/ui/feature-gates/feature-gate-unsafe_pin_internals.rs
@@ -7,7 +7,7 @@ use core::{marker::PhantomPinned, pin::Pin};
 
 /// The `unsafe_pin_internals` is indeed unsound.
 fn non_unsafe_pin_new_unchecked<T>(pointer: &mut T) -> Pin<&mut T> {
-    Pin { pointer }
+    Pin { __pointer: pointer }
 }
 
 fn main() {
diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr
index 28dbdf4c374..3d753b9c8b8 100644
--- a/tests/ui/for/issue-20605.next.stderr
+++ b/tests/ui/for/issue-20605.next.stderr
@@ -34,15 +34,11 @@ error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIte
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^
 
-error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
-  --> $DIR/issue-20605.rs:5:9
+error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
+  --> $DIR/issue-20605.rs:5:17
    |
 LL |     for item in *things { *item = 0 }
-   |         ^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
-   = note: all local variables must have a statically known size
-   = help: unsized locals are gated as an unstable feature
+   |                 ^^^^^^^
 
 error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
   --> $DIR/issue-20605.rs:5:5
@@ -54,11 +50,15 @@ LL |     for item in *things { *item = 0 }
 note: required by a bound in `None`
   --> $SRC_DIR/core/src/option.rs:LL:COL
 
-error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
-  --> $DIR/issue-20605.rs:5:17
+error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
+  --> $DIR/issue-20605.rs:5:9
    |
 LL |     for item in *things { *item = 0 }
-   |                 ^^^^^^^
+   |         ^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
 
 error[E0614]: type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
   --> $DIR/issue-20605.rs:5:27
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
index 55353999b67..0c050c550c4 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
@@ -17,12 +17,18 @@ fn main() {
         }
         match x as i32 {
             0..5+1 => errors_only.push(x),
-            //~^ error: expected one of `=>`, `if`, or `|`, found `+`
+            //~^ error: expected a pattern range bound, found an expression
+            //~| error: exclusive range pattern syntax is experimental
             1 | -3..0 => first_or.push(x),
+            //~^ error: exclusive range pattern syntax is experimental
             y @ (0..5 | 6) => or_two.push(y),
+            //~^ error: exclusive range pattern syntax is experimental
             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+            //~^ error: exclusive range pattern syntax is experimental
+            //~| error: inline-const in pattern position is experimental
             y @ -5.. => range_from.push(y),
             y @ ..-7 => assert_eq!(y, -8),
+            //~^ error: exclusive range pattern syntax is experimental
             y => bottom.push(y),
         }
     }
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
index cf3bde9705b..cc481f7a79e 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
@@ -1,8 +1,8 @@
-error: expected one of `=>`, `if`, or `|`, found `+`
-  --> $DIR/range_pat_interactions1.rs:19:17
+error: expected a pattern range bound, found an expression
+  --> $DIR/range_pat_interactions1.rs:19:16
    |
 LL |             0..5+1 => errors_only.push(x),
-   |                 ^ expected one of `=>`, `if`, or `|`
+   |                ^^^ arbitrary expressions are not allowed in patterns
 
 error[E0408]: variable `n` is not bound in all patterns
   --> $DIR/range_pat_interactions1.rs:10:25
@@ -12,6 +12,16 @@ LL |         if let n @ 2..3|4 = x {
    |                |
    |                variable not in all patterns
 
+error[E0658]: inline-const in pattern position is experimental
+  --> $DIR/range_pat_interactions1.rs:26:20
+   |
+LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+   |                    ^^^^^
+   |
+   = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
+   = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
 error[E0658]: exclusive range pattern syntax is experimental
   --> $DIR/range_pat_interactions1.rs:10:20
    |
@@ -34,7 +44,62 @@ LL |         } else if let 2..3 | 4 = x {
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: use an inclusive range pattern, like N..=M
 
-error: aborting due to 4 previous errors
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions1.rs:19:13
+   |
+LL |             0..5+1 => errors_only.push(x),
+   |             ^^^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions1.rs:22:17
+   |
+LL |             1 | -3..0 => first_or.push(x),
+   |                 ^^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions1.rs:24:18
+   |
+LL |             y @ (0..5 | 6) => or_two.push(y),
+   |                  ^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions1.rs:26:17
+   |
+LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+   |                 ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions1.rs:30:17
+   |
+LL |             y @ ..-7 => assert_eq!(y, -8),
+   |                 ^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0408, E0658.
 For more information about an error, try `rustc --explain E0408`.
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
index 0e96cfe7858..068104c4b1b 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
@@ -8,12 +8,18 @@ fn main() {
     for x in -9 + 1..=(9 - 2) {
         match x as i32 {
             0..=(5+1) => errors_only.push(x),
-            //~^ error: expected `)`, found `+`
+            //~^ error: expected a pattern range bound, found an expression
+            //~| error: range pattern bounds cannot have parentheses
             1 | -3..0 => first_or.push(x),
+            //~^ error: exclusive range pattern syntax is experimental
             y @ (0..5 | 6) => or_two.push(y),
+            //~^ error: exclusive range pattern syntax is experimental
             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+            //~^ error: inline-const in pattern position is experimental
+            //~| error: exclusive range pattern syntax is experimental
             y @ -5.. => range_from.push(y),
             y @ ..-7 => assert_eq!(y, -8),
+            //~^ error: exclusive range pattern syntax is experimental
             y => bottom.push(y),
         }
     }
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
index a54f29a3b32..8f21a6149fb 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
@@ -1,8 +1,75 @@
-error: expected `)`, found `+`
-  --> $DIR/range_pat_interactions2.rs:10:19
+error: expected a pattern range bound, found an expression
+  --> $DIR/range_pat_interactions2.rs:10:18
    |
 LL |             0..=(5+1) => errors_only.push(x),
-   |                   ^ expected `)`
+   |                  ^^^ arbitrary expressions are not allowed in patterns
 
-error: aborting due to 1 previous error
+error: range pattern bounds cannot have parentheses
+  --> $DIR/range_pat_interactions2.rs:10:17
+   |
+LL |             0..=(5+1) => errors_only.push(x),
+   |                 ^   ^
+   |
+help: remove these parentheses
+   |
+LL -             0..=(5+1) => errors_only.push(x),
+LL +             0..=5+1 => errors_only.push(x),
+   |
+
+error[E0658]: inline-const in pattern position is experimental
+  --> $DIR/range_pat_interactions2.rs:17:20
+   |
+LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+   |                    ^^^^^
+   |
+   = note: see issue #76001 <https://github.com/rust-lang/rust/issues/76001> for more information
+   = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions2.rs:13:17
+   |
+LL |             1 | -3..0 => first_or.push(x),
+   |                 ^^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions2.rs:15:18
+   |
+LL |             y @ (0..5 | 6) => or_two.push(y),
+   |                  ^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions2.rs:17:17
+   |
+LL |             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
+   |                 ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range_pat_interactions2.rs:21:17
+   |
+LL |             y @ ..-7 => assert_eq!(y, -8),
+   |                 ^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error: aborting due to 7 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/internal/internal-unstable.rs b/tests/ui/internal/internal-unstable.rs
index 1eb27fbdc3a..a4445fefef5 100644
--- a/tests/ui/internal/internal-unstable.rs
+++ b/tests/ui/internal/internal-unstable.rs
@@ -28,6 +28,14 @@ macro_rules! bar {
     }}
 }
 
+#[allow_internal_unstable(stmt_expr_attributes)]
+macro_rules! internal_attr {
+    ($e: expr) => {
+        #[allow(overflowing_literals)]
+        $e
+    }
+}
+
 fn main() {
     // ok, the instability is contained.
     call_unstable_allow!();
@@ -51,4 +59,6 @@ fn main() {
         #[allow_internal_unstable]
         _ => {}
     }
+
+    assert_eq!(internal_attr!(1e100_f32), f32::INFINITY);
 }
diff --git a/tests/ui/internal/internal-unstable.stderr b/tests/ui/internal/internal-unstable.stderr
index af5ac21e696..78b9109d1c2 100644
--- a/tests/ui/internal/internal-unstable.stderr
+++ b/tests/ui/internal/internal-unstable.stderr
@@ -1,5 +1,5 @@
 error[E0658]: use of unstable library feature 'function'
-  --> $DIR/internal-unstable.rs:40:25
+  --> $DIR/internal-unstable.rs:48:25
    |
 LL |     pass_through_allow!(internal_unstable::unstable());
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     pass_through_allow!(internal_unstable::unstable());
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: use of unstable library feature 'function'
-  --> $DIR/internal-unstable.rs:42:27
+  --> $DIR/internal-unstable.rs:50:27
    |
 LL |     pass_through_noallow!(internal_unstable::unstable());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     pass_through_noallow!(internal_unstable::unstable());
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: use of unstable library feature 'function'
-  --> $DIR/internal-unstable.rs:46:22
+  --> $DIR/internal-unstable.rs:54:22
    |
 LL |     println!("{:?}", internal_unstable::unstable());
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |     println!("{:?}", internal_unstable::unstable());
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: use of unstable library feature 'function'
-  --> $DIR/internal-unstable.rs:48:10
+  --> $DIR/internal-unstable.rs:56:10
    |
 LL |     bar!(internal_unstable::unstable());
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr
index 8161f97dde0..0ed743818c5 100644
--- a/tests/ui/layout/zero-sized-array-enum-niche.stderr
+++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr
@@ -232,7 +232,7 @@ error: layout_of(MultipleAlignments) = Layout {
 LL | enum MultipleAlignments {
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: layout_of(Result<[u32; 0], Packed<NonZeroU16>>) = Layout {
+error: layout_of(Result<[u32; 0], Packed<NonZero<u16>>>) = Layout {
            size: Size(4 bytes),
            align: AbiAndPrefAlign {
                abi: Align(4 bytes),
diff --git a/tests/ui/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs
index 09fda33dbec..9740742fbbb 100644
--- a/tests/ui/lint/clashing-extern-fn.rs
+++ b/tests/ui/lint/clashing-extern-fn.rs
@@ -436,7 +436,7 @@ mod hidden_niche {
 
             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>;
             //~^ WARN redeclared with a different signature
-            //~| WARN block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe
+            //~| WARN block uses type `Option<UnsafeCell<NonZero<usize>>>`, which is not FFI-safe
         }
     }
 }
diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr
index 0d269e599dd..5b9244b6993 100644
--- a/tests/ui/lint/clashing-extern-fn.stderr
+++ b/tests/ui/lint/clashing-extern-fn.stderr
@@ -8,7 +8,7 @@ LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN
    = note: enum has no representation hint
    = note: `#[warn(improper_ctypes)]` on by default
 
-warning: `extern` block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe
+warning: `extern` block uses type `Option<UnsafeCell<NonZero<usize>>>`, which is not FFI-safe
   --> $DIR/clashing-extern-fn.rs:437:46
    |
 LL |             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>;
@@ -163,7 +163,7 @@ LL |             fn non_zero_usize() -> core::num::NonZeroUsize;
 LL |             fn non_zero_usize() -> usize;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
    |
-   = note: expected `unsafe extern "C" fn() -> NonZeroUsize`
+   = note: expected `unsafe extern "C" fn() -> NonZero<usize>`
               found `unsafe extern "C" fn() -> usize`
 
 warning: `non_null_ptr` redeclared with a different signature
@@ -224,7 +224,7 @@ LL |             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
    |
    = note: expected `unsafe extern "C" fn() -> usize`
-              found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZeroUsize>>`
+              found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZero<usize>>>`
 
 warning: 19 warnings emitted
 
diff --git a/tests/ui/lint/invalid_value.stderr b/tests/ui/lint/invalid_value.stderr
index 57531b0968f..bdf47343114 100644
--- a/tests/ui/lint/invalid_value.stderr
+++ b/tests/ui/lint/invalid_value.stderr
@@ -316,7 +316,7 @@ LL |         let _val: NonNull<i32> = mem::uninitialized();
    = note: `std::ptr::NonNull<i32>` must be non-null
    = note: raw pointers must be initialized
 
-error: the type `(NonZeroU32, i32)` does not permit zero-initialization
+error: the type `(NonZero<u32>, i32)` does not permit zero-initialization
   --> $DIR/invalid_value.rs:95:39
    |
 LL |         let _val: (NonZeroU32, i32) = mem::zeroed();
@@ -325,9 +325,9 @@ LL |         let _val: (NonZeroU32, i32) = mem::zeroed();
    |                                       this code causes undefined behavior when executed
    |                                       help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: `std::num::NonZeroU32` must be non-null
+   = note: `std::num::NonZero<u32>` must be non-null
 
-error: the type `(NonZeroU32, i32)` does not permit being left uninitialized
+error: the type `(NonZero<u32>, i32)` does not permit being left uninitialized
   --> $DIR/invalid_value.rs:96:39
    |
 LL |         let _val: (NonZeroU32, i32) = mem::uninitialized();
@@ -336,7 +336,7 @@ LL |         let _val: (NonZeroU32, i32) = mem::uninitialized();
    |                                       this code causes undefined behavior when executed
    |                                       help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: `std::num::NonZeroU32` must be non-null
+   = note: `std::num::NonZero<u32>` must be non-null
    = note: integers must be initialized
 
 error: the type `*const dyn Send` does not permit zero-initialization
@@ -417,7 +417,7 @@ LL |         let _val: OneFruitNonZero = mem::zeroed();
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `OneFruitNonZero` must be non-null
-note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
+note: because `std::num::NonZero<u32>` must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:39:12
    |
 LL |     Banana(NonZeroU32),
@@ -433,7 +433,7 @@ LL |         let _val: OneFruitNonZero = mem::uninitialized();
    |                                     help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
    = note: `OneFruitNonZero` must be non-null
-note: because `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
+note: because `std::num::NonZero<u32>` must be non-null (in this field of the only potentially inhabited enum variant)
   --> $DIR/invalid_value.rs:39:12
    |
 LL |     Banana(NonZeroU32),
@@ -603,7 +603,7 @@ LL |         let _val: &'static [i32] = mem::transmute((0usize, 0usize));
    |
    = note: references must be non-null
 
-error: the type `NonZeroU32` does not permit zero-initialization
+error: the type `NonZero<u32>` does not permit zero-initialization
   --> $DIR/invalid_value.rs:154:32
    |
 LL |         let _val: NonZeroU32 = mem::transmute(0);
@@ -612,7 +612,7 @@ LL |         let _val: NonZeroU32 = mem::transmute(0);
    |                                this code causes undefined behavior when executed
    |                                help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
    |
-   = note: `std::num::NonZeroU32` must be non-null
+   = note: `std::num::NonZero<u32>` must be non-null
 
 error: the type `NonNull<i32>` does not permit zero-initialization
   --> $DIR/invalid_value.rs:157:34
diff --git a/tests/ui/lint/lint-ctypes-enum.stderr b/tests/ui/lint/lint-ctypes-enum.stderr
index 8554e261778..64beefbb757 100644
--- a/tests/ui/lint/lint-ctypes-enum.stderr
+++ b/tests/ui/lint/lint-ctypes-enum.stderr
@@ -61,7 +61,7 @@ LL |    fn nonzero_i128(x: Option<num::NonZeroI128>);
    |
    = note: 128-bit integers don't currently have a known stable ABI
 
-error: `extern` block uses type `Option<TransparentUnion<NonZeroU8>>`, which is not FFI-safe
+error: `extern` block uses type `Option<TransparentUnion<NonZero<u8>>>`, which is not FFI-safe
   --> $DIR/lint-ctypes-enum.rs:86:28
    |
 LL |    fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
@@ -70,7 +70,7 @@ LL |    fn transparent_union(x: Option<TransparentUnion<num::NonZeroU8>>);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
-error: `extern` block uses type `Option<Rust<NonZeroU8>>`, which is not FFI-safe
+error: `extern` block uses type `Option<Rust<NonZero<u8>>>`, which is not FFI-safe
   --> $DIR/lint-ctypes-enum.rs:88:20
    |
 LL |    fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
@@ -79,7 +79,7 @@ LL |    fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
    = help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
    = note: enum has no representation hint
 
-error: `extern` block uses type `Result<(), NonZeroI32>`, which is not FFI-safe
+error: `extern` block uses type `Result<(), NonZero<i32>>`, which is not FFI-safe
   --> $DIR/lint-ctypes-enum.rs:89:20
    |
 LL |    fn no_result(x: Result<(), num::NonZeroI32>);
diff --git a/tests/ui/mismatched_types/non_zero_assigned_something.stderr b/tests/ui/mismatched_types/non_zero_assigned_something.stderr
index 57db71f889c..f8e86905ab9 100644
--- a/tests/ui/mismatched_types/non_zero_assigned_something.stderr
+++ b/tests/ui/mismatched_types/non_zero_assigned_something.stderr
@@ -2,10 +2,12 @@ error[E0308]: mismatched types
   --> $DIR/non_zero_assigned_something.rs:2:35
    |
 LL |     let _: std::num::NonZeroU64 = 1;
-   |            --------------------   ^ expected `NonZeroU64`, found integer
+   |            --------------------   ^ expected `NonZero<u64>`, found integer
    |            |
    |            expected due to this
    |
+   = note: expected struct `NonZero<u64>`
+                found type `{integer}`
 help: consider calling `NonZeroU64::new`
    |
 LL |     let _: std::num::NonZeroU64 = NonZeroU64::new(1).unwrap();
@@ -15,11 +17,11 @@ error[E0308]: mismatched types
   --> $DIR/non_zero_assigned_something.rs:6:43
    |
 LL |     let _: Option<std::num::NonZeroU64> = 1;
-   |            ----------------------------   ^ expected `Option<NonZeroU64>`, found integer
+   |            ----------------------------   ^ expected `Option<NonZero<u64>>`, found integer
    |            |
    |            expected due to this
    |
-   = note: expected enum `Option<NonZeroU64>`
+   = note: expected enum `Option<NonZero<u64>>`
               found type `{integer}`
 help: consider calling `NonZeroU64::new`
    |
diff --git a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr
index e1825eb5b54..be0fc0f98e2 100644
--- a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr
+++ b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr
@@ -124,7 +124,7 @@ LL |     x / 100.0
    = help: the trait `Div<{float}>` is not implemented for `u8`
    = help: the following other types implement trait `Div<Rhs>`:
              <u8 as Div>
-             <u8 as Div<NonZeroU8>>
+             <u8 as Div<NonZero<u8>>>
              <u8 as Div<&u8>>
              <&'a u8 as Div<u8>>
              <&u8 as Div<&u8>>
diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs
new file mode 100644
index 00000000000..a7412f51782
--- /dev/null
+++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs
@@ -0,0 +1,9 @@
+// Issue #118164: recovery path leaving unemitted error behind
+fn bar() -> String {
+    #[cfg(feature = )]
+    [1, 2, 3].iter().map().collect::<String>() //~ ERROR expected `;`, found `#`
+    #[attr] //~ ERROR expected statement after outer attribute
+}
+fn main() {
+    let _ = bar();
+}
diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr
new file mode 100644
index 00000000000..dd0081cc2df
--- /dev/null
+++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr
@@ -0,0 +1,27 @@
+error: expected `;`, found `#`
+  --> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:4:47
+   |
+LL |     #[cfg(feature = )]
+   |     ------------------ only `;` terminated statements or tail expressions are allowed after this attribute
+LL |     [1, 2, 3].iter().map().collect::<String>()
+   |                                               ^ expected `;` here
+LL |     #[attr]
+   |     - unexpected token
+   |
+help: add `;` here
+   |
+LL |     [1, 2, 3].iter().map().collect::<String>();
+   |                                               +
+help: alternatively, consider surrounding the expression with a block
+   |
+LL |     { [1, 2, 3].iter().map().collect::<String>() }
+   |     +                                            +
+
+error: expected statement after outer attribute
+  --> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:5:5
+   |
+LL |     #[attr]
+   |     ^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issues/issue-24197.rs b/tests/ui/parser/issues/issue-24197.rs
index aaf5137461f..9bba16e5596 100644
--- a/tests/ui/parser/issues/issue-24197.rs
+++ b/tests/ui/parser/issues/issue-24197.rs
@@ -1,3 +1,3 @@
 fn main() {
-    let buf[0] = 0; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
+    let buf[0] = 0; //~ error: expected a pattern, found an expression
 }
diff --git a/tests/ui/parser/issues/issue-24197.stderr b/tests/ui/parser/issues/issue-24197.stderr
index 3ef707f3953..7ebbf4ac370 100644
--- a/tests/ui/parser/issues/issue-24197.stderr
+++ b/tests/ui/parser/issues/issue-24197.stderr
@@ -1,8 +1,8 @@
-error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
-  --> $DIR/issue-24197.rs:2:12
+error: expected a pattern, found an expression
+  --> $DIR/issue-24197.rs:2:9
    |
 LL |     let buf[0] = 0;
-   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+   |         ^^^^^^ arbitrary expressions are not allowed in patterns
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/issues/issue-24375.rs b/tests/ui/parser/issues/issue-24375.rs
index 1d128d33e4f..a5e256b7f15 100644
--- a/tests/ui/parser/issues/issue-24375.rs
+++ b/tests/ui/parser/issues/issue-24375.rs
@@ -3,7 +3,7 @@ static tmp : [&'static str; 2]  = ["hello", "he"];
 fn main() {
     let z = "hello";
     match z {
-        tmp[0] => {} //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `[`
+        tmp[0] => {} //~ error: expected a pattern, found an expression
         _ => {}
     }
 }
diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr
index bb1e19e9e6d..e6ef07d13fd 100644
--- a/tests/ui/parser/issues/issue-24375.stderr
+++ b/tests/ui/parser/issues/issue-24375.stderr
@@ -1,8 +1,8 @@
-error: expected one of `=>`, `@`, `if`, or `|`, found `[`
-  --> $DIR/issue-24375.rs:6:12
+error: expected a pattern, found an expression
+  --> $DIR/issue-24375.rs:6:9
    |
 LL |         tmp[0] => {}
-   |            ^ expected one of `=>`, `@`, `if`, or `|`
+   |         ^^^^^^ arbitrary expressions are not allowed in patterns
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/pat-lt-bracket-5.rs b/tests/ui/parser/pat-lt-bracket-5.rs
index aaece1f6bd9..6d784494d56 100644
--- a/tests/ui/parser/pat-lt-bracket-5.rs
+++ b/tests/ui/parser/pat-lt-bracket-5.rs
@@ -1,3 +1,5 @@
 fn main() {
-    let v[0] = v[1]; //~ ERROR expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
+    let v[0] = v[1];
+    //~^ error: expected a pattern, found an expression
+    //~| error: cannot find value `v` in this scope
 }
diff --git a/tests/ui/parser/pat-lt-bracket-5.stderr b/tests/ui/parser/pat-lt-bracket-5.stderr
index e556e6c0206..18cf2df0282 100644
--- a/tests/ui/parser/pat-lt-bracket-5.stderr
+++ b/tests/ui/parser/pat-lt-bracket-5.stderr
@@ -1,8 +1,15 @@
-error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
-  --> $DIR/pat-lt-bracket-5.rs:2:10
+error: expected a pattern, found an expression
+  --> $DIR/pat-lt-bracket-5.rs:2:9
    |
 LL |     let v[0] = v[1];
-   |          ^ expected one of `:`, `;`, `=`, `@`, or `|`
+   |         ^^^^ arbitrary expressions are not allowed in patterns
 
-error: aborting due to 1 previous error
+error[E0425]: cannot find value `v` in this scope
+  --> $DIR/pat-lt-bracket-5.rs:2:16
+   |
+LL |     let v[0] = v[1];
+   |                ^ not found in this scope
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/parser/pat-lt-bracket-6.rs b/tests/ui/parser/pat-lt-bracket-6.rs
index 7becffa9fe2..496525ed537 100644
--- a/tests/ui/parser/pat-lt-bracket-6.rs
+++ b/tests/ui/parser/pat-lt-bracket-6.rs
@@ -3,7 +3,8 @@ fn main() {
     let x = Test(&0, []);
 
     let Test(&desc[..]) = x;
-    //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[`
+    //~^ error: expected a pattern, found an expression
+    //~| error: this pattern has 1 field, but the corresponding tuple struct has 2 fields
 }
 
 const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types
diff --git a/tests/ui/parser/pat-lt-bracket-6.stderr b/tests/ui/parser/pat-lt-bracket-6.stderr
index 035d0dbfe06..10c638a63e4 100644
--- a/tests/ui/parser/pat-lt-bracket-6.stderr
+++ b/tests/ui/parser/pat-lt-bracket-6.stderr
@@ -1,18 +1,30 @@
-error: expected one of `)`, `,`, `@`, or `|`, found `[`
-  --> $DIR/pat-lt-bracket-6.rs:5:19
+error: expected a pattern, found an expression
+  --> $DIR/pat-lt-bracket-6.rs:5:15
    |
 LL |     let Test(&desc[..]) = x;
-   |                   ^
-   |                   |
-   |                   expected one of `)`, `,`, `@`, or `|`
-   |                   help: missing `,`
+   |               ^^^^^^^^ arbitrary expressions are not allowed in patterns
 
 error[E0308]: mismatched types
-  --> $DIR/pat-lt-bracket-6.rs:9:30
+  --> $DIR/pat-lt-bracket-6.rs:10:30
    |
 LL | const RECOVERY_WITNESS: () = 0;
    |                              ^ expected `()`, found integer
 
-error: aborting due to 2 previous errors
+error[E0023]: this pattern has 1 field, but the corresponding tuple struct has 2 fields
+  --> $DIR/pat-lt-bracket-6.rs:5:14
+   |
+LL |     struct Test(&'static u8, [u8; 0]);
+   |                 -----------  ------- tuple struct has 2 fields
+...
+LL |     let Test(&desc[..]) = x;
+   |              ^^^^^^^^^ expected 2 fields, found 1
+   |
+help: use `_` to explicitly ignore each field
+   |
+LL |     let Test(&desc[..], _) = x;
+   |                       +++
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0023, E0308.
+For more information about an error, try `rustc --explain E0023`.
diff --git a/tests/ui/parser/pat-ranges-3.rs b/tests/ui/parser/pat-ranges-3.rs
index 8976dcf0d90..419768a2a20 100644
--- a/tests/ui/parser/pat-ranges-3.rs
+++ b/tests/ui/parser/pat-ranges-3.rs
@@ -1,5 +1,9 @@
 // Parsing of range patterns
 
 fn main() {
-    let 10 ..= 10 + 3 = 12; //~ expected one of `:`, `;`, `=`, or `|`, found `+`
+    let 10 ..= 10 + 3 = 12;
+    //~^ error: expected a pattern range bound, found an expression
+
+    let 10 - 3 ..= 10 = 8;
+    //~^ error: expected a pattern range bound, found an expression
 }
diff --git a/tests/ui/parser/pat-ranges-3.stderr b/tests/ui/parser/pat-ranges-3.stderr
index 611b35a6502..5e1f35d1b6f 100644
--- a/tests/ui/parser/pat-ranges-3.stderr
+++ b/tests/ui/parser/pat-ranges-3.stderr
@@ -1,8 +1,14 @@
-error: expected one of `:`, `;`, `=`, or `|`, found `+`
-  --> $DIR/pat-ranges-3.rs:4:19
+error: expected a pattern range bound, found an expression
+  --> $DIR/pat-ranges-3.rs:4:16
    |
 LL |     let 10 ..= 10 + 3 = 12;
-   |                   ^ expected one of `:`, `;`, `=`, or `|`
+   |                ^^^^^^ arbitrary expressions are not allowed in patterns
 
-error: aborting due to 1 previous error
+error: expected a pattern range bound, found an expression
+  --> $DIR/pat-ranges-3.rs:7:9
+   |
+LL |     let 10 - 3 ..= 10 = 8;
+   |         ^^^^^^ arbitrary expressions are not allowed in patterns
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/pat-ranges-4.rs b/tests/ui/parser/pat-ranges-4.rs
deleted file mode 100644
index 61188976b02..00000000000
--- a/tests/ui/parser/pat-ranges-4.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// Parsing of range patterns
-
-fn main() {
-    let 10 - 3 ..= 10 = 8;
-    //~^ error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-`
-}
diff --git a/tests/ui/parser/pat-ranges-4.stderr b/tests/ui/parser/pat-ranges-4.stderr
deleted file mode 100644
index c30160291d6..00000000000
--- a/tests/ui/parser/pat-ranges-4.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: expected one of `...`, `..=`, `..`, `:`, `;`, `=`, or `|`, found `-`
-  --> $DIR/pat-ranges-4.rs:4:12
-   |
-LL |     let 10 - 3 ..= 10 = 8;
-   |            ^ expected one of 7 possible tokens
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/parser/pat-recover-exprs.rs b/tests/ui/parser/pat-recover-exprs.rs
new file mode 100644
index 00000000000..ecd471467e3
--- /dev/null
+++ b/tests/ui/parser/pat-recover-exprs.rs
@@ -0,0 +1,28 @@
+fn main() {
+    match u8::MAX {
+        u8::MAX.abs() => (),
+        //~^ error: expected a pattern, found a method call
+        x.sqrt() @ .. => (),
+        //~^ error: expected a pattern, found a method call
+        //~| error: left-hand side of `@` must be a binding
+        z @ w @ v.u() => (),
+        //~^ error: expected a pattern, found a method call
+        y.ilog(3) => (),
+        //~^ error: expected a pattern, found a method call
+        n + 1 => (),
+        //~^ error: expected a pattern, found an expression
+        ("".f() + 14 * 8) => (),
+        //~^ error: expected a pattern, found an expression
+        0 | ((1) | 2) | 3 => (),
+        f?() => (),
+        //~^ error: expected a pattern, found an expression
+        (_ + 1) => (),
+        //~^ error: expected one of `)`, `,`, or `|`, found `+`
+    }
+
+    let 1 + 1 = 2;
+    //~^ error: expected a pattern, found an expression
+
+    let b = matches!(x, (x * x | x.f()) | x[0]);
+    //~^ error: expected one of `)`, `,`, `@`, or `|`, found `*`
+}
diff --git a/tests/ui/parser/pat-recover-exprs.stderr b/tests/ui/parser/pat-recover-exprs.stderr
new file mode 100644
index 00000000000..787fd03b0c3
--- /dev/null
+++ b/tests/ui/parser/pat-recover-exprs.stderr
@@ -0,0 +1,76 @@
+error: expected a pattern, found a method call
+  --> $DIR/pat-recover-exprs.rs:3:9
+   |
+LL |         u8::MAX.abs() => (),
+   |         ^^^^^^^^^^^^^ method calls are not allowed in patterns
+
+error: expected a pattern, found a method call
+  --> $DIR/pat-recover-exprs.rs:5:9
+   |
+LL |         x.sqrt() @ .. => (),
+   |         ^^^^^^^^ method calls are not allowed in patterns
+
+error: left-hand side of `@` must be a binding
+  --> $DIR/pat-recover-exprs.rs:5:9
+   |
+LL |         x.sqrt() @ .. => (),
+   |         --------^^^--
+   |         |          |
+   |         |          also a pattern
+   |         interpreted as a pattern, not a binding
+   |
+   = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+
+error: expected a pattern, found a method call
+  --> $DIR/pat-recover-exprs.rs:8:17
+   |
+LL |         z @ w @ v.u() => (),
+   |                 ^^^^^ method calls are not allowed in patterns
+
+error: expected a pattern, found a method call
+  --> $DIR/pat-recover-exprs.rs:10:9
+   |
+LL |         y.ilog(3) => (),
+   |         ^^^^^^^^^ method calls are not allowed in patterns
+
+error: expected a pattern, found an expression
+  --> $DIR/pat-recover-exprs.rs:12:9
+   |
+LL |         n + 1 => (),
+   |         ^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected a pattern, found an expression
+  --> $DIR/pat-recover-exprs.rs:14:10
+   |
+LL |         ("".f() + 14 * 8) => (),
+   |          ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected a pattern, found an expression
+  --> $DIR/pat-recover-exprs.rs:17:9
+   |
+LL |         f?() => (),
+   |         ^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected one of `)`, `,`, or `|`, found `+`
+  --> $DIR/pat-recover-exprs.rs:19:12
+   |
+LL |         (_ + 1) => (),
+   |            ^ expected one of `)`, `,`, or `|`
+
+error: expected a pattern, found an expression
+  --> $DIR/pat-recover-exprs.rs:23:9
+   |
+LL |     let 1 + 1 = 2;
+   |         ^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected one of `)`, `,`, `@`, or `|`, found `*`
+  --> $DIR/pat-recover-exprs.rs:26:28
+   |
+LL |     let b = matches!(x, (x * x | x.f()) | x[0]);
+   |                            ^ expected one of `)`, `,`, `@`, or `|`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
+   |
+   = note: while parsing argument for this `pat` macro fragment
+
+error: aborting due to 11 previous errors
+
diff --git a/tests/ui/parser/pat-recover-methodcalls.rs b/tests/ui/parser/pat-recover-methodcalls.rs
new file mode 100644
index 00000000000..54104e9a535
--- /dev/null
+++ b/tests/ui/parser/pat-recover-methodcalls.rs
@@ -0,0 +1,37 @@
+struct Foo(String);
+struct Bar { baz: String }
+
+fn foo(foo: Foo) -> bool {
+    match foo {
+        Foo("hi".to_owned()) => true,
+        //~^ error: expected a pattern, found a method call
+        _ => false
+    }
+}
+
+fn bar(bar: Bar) -> bool {
+    match bar {
+        Bar { baz: "hi".to_owned() } => true,
+        //~^ error: expected a pattern, found a method call
+        _ => false
+    }
+}
+
+fn baz() { // issue #90121
+    let foo = vec!["foo".to_string()];
+
+    match foo.as_slice() {
+        &["foo".to_string()] => {}
+        //~^ error: expected a pattern, found a method call
+        _ => {}
+    };
+}
+
+fn main() {
+    if let (-1.some(4)) = (0, Some(4)) {}
+    //~^ error: expected a pattern, found a method call
+
+    if let (-1.Some(4)) = (0, Some(4)) {}
+    //~^ error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
+    //~| help: missing `,`
+}
diff --git a/tests/ui/parser/pat-recover-methodcalls.stderr b/tests/ui/parser/pat-recover-methodcalls.stderr
new file mode 100644
index 00000000000..1f9ae81dc0c
--- /dev/null
+++ b/tests/ui/parser/pat-recover-methodcalls.stderr
@@ -0,0 +1,35 @@
+error: expected a pattern, found a method call
+  --> $DIR/pat-recover-methodcalls.rs:6:13
+   |
+LL |         Foo("hi".to_owned()) => true,
+   |             ^^^^^^^^^^^^^^^ method calls are not allowed in patterns
+
+error: expected a pattern, found a method call
+  --> $DIR/pat-recover-methodcalls.rs:14:20
+   |
+LL |         Bar { baz: "hi".to_owned() } => true,
+   |                    ^^^^^^^^^^^^^^^ method calls are not allowed in patterns
+
+error: expected a pattern, found a method call
+  --> $DIR/pat-recover-methodcalls.rs:24:11
+   |
+LL |         &["foo".to_string()] => {}
+   |           ^^^^^^^^^^^^^^^^^ method calls are not allowed in patterns
+
+error: expected a pattern, found a method call
+  --> $DIR/pat-recover-methodcalls.rs:31:13
+   |
+LL |     if let (-1.some(4)) = (0, Some(4)) {}
+   |             ^^^^^^^^^^ method calls are not allowed in patterns
+
+error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
+  --> $DIR/pat-recover-methodcalls.rs:34:15
+   |
+LL |     if let (-1.Some(4)) = (0, Some(4)) {}
+   |               ^
+   |               |
+   |               expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
+   |               help: missing `,`
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/parser/pat-recover-ranges.rs b/tests/ui/parser/pat-recover-ranges.rs
index 65a6fc6fe21..7d77e950d90 100644
--- a/tests/ui/parser/pat-recover-ranges.rs
+++ b/tests/ui/parser/pat-recover-ranges.rs
@@ -8,6 +8,22 @@ fn main() {
         (0)..=(-4) => (),
         //~^ error: range pattern bounds cannot have parentheses
         //~| error: range pattern bounds cannot have parentheses
+        ..=1 + 2 => (),
+        //~^ error: expected a pattern range bound, found an expression
+        (4).. => (),
+        //~^ error: range pattern bounds cannot have parentheses
+        (-4 + 0).. => (),
+        //~^ error: expected a pattern range bound, found an expression
+        //~| error: range pattern bounds cannot have parentheses
+        (1 + 4)...1 * 2 => (),
+        //~^ error: expected a pattern range bound, found an expression
+        //~| error: expected a pattern range bound, found an expression
+        //~| error: range pattern bounds cannot have parentheses
+        //~| warning: `...` range patterns are deprecated
+        //~| warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+        0.x()..="y".z() => (),
+        //~^ error: expected a pattern range bound, found a method call
+        //~| error: expected a pattern range bound, found a method call
     };
 }
 
diff --git a/tests/ui/parser/pat-recover-ranges.stderr b/tests/ui/parser/pat-recover-ranges.stderr
index 0d722b5aa95..a7d62bd7f8a 100644
--- a/tests/ui/parser/pat-recover-ranges.stderr
+++ b/tests/ui/parser/pat-recover-ranges.stderr
@@ -46,5 +46,87 @@ LL -         (0)..=(-4) => (),
 LL +         (0)..=-4 => (),
    |
 
-error: aborting due to 4 previous errors
+error: expected a pattern range bound, found an expression
+  --> $DIR/pat-recover-ranges.rs:11:12
+   |
+LL |         ..=1 + 2 => (),
+   |            ^^^^^ arbitrary expressions are not allowed in patterns
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/pat-recover-ranges.rs:13:9
+   |
+LL |         (4).. => (),
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (4).. => (),
+LL +         4.. => (),
+   |
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/pat-recover-ranges.rs:15:10
+   |
+LL |         (-4 + 0).. => (),
+   |          ^^^^^^ arbitrary expressions are not allowed in patterns
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/pat-recover-ranges.rs:15:9
+   |
+LL |         (-4 + 0).. => (),
+   |         ^      ^
+   |
+help: remove these parentheses
+   |
+LL -         (-4 + 0).. => (),
+LL +         -4 + 0.. => (),
+   |
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/pat-recover-ranges.rs:18:10
+   |
+LL |         (1 + 4)...1 * 2 => (),
+   |          ^^^^^ arbitrary expressions are not allowed in patterns
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/pat-recover-ranges.rs:18:9
+   |
+LL |         (1 + 4)...1 * 2 => (),
+   |         ^     ^
+   |
+help: remove these parentheses
+   |
+LL -         (1 + 4)...1 * 2 => (),
+LL +         1 + 4...1 * 2 => (),
+   |
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/pat-recover-ranges.rs:18:19
+   |
+LL |         (1 + 4)...1 * 2 => (),
+   |                   ^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected a pattern range bound, found a method call
+  --> $DIR/pat-recover-ranges.rs:24:9
+   |
+LL |         0.x()..="y".z() => (),
+   |         ^^^^^ method calls are not allowed in patterns
+
+error: expected a pattern range bound, found a method call
+  --> $DIR/pat-recover-ranges.rs:24:17
+   |
+LL |         0.x()..="y".z() => (),
+   |                 ^^^^^^^ method calls are not allowed in patterns
+
+warning: `...` range patterns are deprecated
+  --> $DIR/pat-recover-ranges.rs:18:16
+   |
+LL |         (1 + 4)...1 * 2 => (),
+   |                ^^^ help: use `..=` for an inclusive range
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(ellipsis_inclusive_range_patterns)]` on by default
+
+error: aborting due to 13 previous errors; 1 warning emitted
 
diff --git a/tests/ui/parser/pat-recover-wildcards.rs b/tests/ui/parser/pat-recover-wildcards.rs
new file mode 100644
index 00000000000..f506e2223d6
--- /dev/null
+++ b/tests/ui/parser/pat-recover-wildcards.rs
@@ -0,0 +1,61 @@
+// check that we can't do funny things with wildcards.
+
+fn a() {
+    match 1 {
+        _ + 1 => () //~ error: expected one of `=>`, `if`, or `|`, found `+`
+    }
+}
+
+fn b() {
+    match 2 {
+        (_ % 4) => () //~ error: expected one of `)`, `,`, or `|`, found `%`
+    }
+}
+
+fn c() {
+    match 3 {
+        _.x() => () //~ error: expected one of `=>`, `if`, or `|`, found `.`
+    }
+}
+
+fn d() {
+    match 4 {
+        _..=4 => () //~ error: expected one of `=>`, `if`, or `|`, found `..=`
+    }
+}
+
+fn e() {
+    match 5 {
+        .._ => () //~ error: expected one of `=>`, `if`, or `|`, found reserved identifier `_`
+    }
+}
+
+fn f() {
+    match 6 {
+        0..._ => ()
+        //~^ error: inclusive range with no end
+        //~| error: expected one of `=>`, `if`, or `|`, found reserved identifier `_`
+    }
+}
+
+fn g() {
+    match 7 {
+        (_ * 0)..5 => () //~ error: expected one of `)`, `,`, or `|`, found `*`
+    }
+}
+
+fn h() {
+    match 8 {
+        ..(_) => () //~ error: expected one of `=>`, `if`, or `|`, found `(`
+    }
+}
+
+fn i() {
+    match 9 {
+        4..=(2 + _) => ()
+        //~^ error: expected a pattern range bound, found an expression
+        //~| error: range pattern bounds cannot have parentheses
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/parser/pat-recover-wildcards.stderr b/tests/ui/parser/pat-recover-wildcards.stderr
new file mode 100644
index 00000000000..2b0c9bbc5be
--- /dev/null
+++ b/tests/ui/parser/pat-recover-wildcards.stderr
@@ -0,0 +1,77 @@
+error: expected one of `=>`, `if`, or `|`, found `+`
+  --> $DIR/pat-recover-wildcards.rs:5:11
+   |
+LL |         _ + 1 => ()
+   |           ^ expected one of `=>`, `if`, or `|`
+
+error: expected one of `)`, `,`, or `|`, found `%`
+  --> $DIR/pat-recover-wildcards.rs:11:12
+   |
+LL |         (_ % 4) => ()
+   |            ^ expected one of `)`, `,`, or `|`
+
+error: expected one of `=>`, `if`, or `|`, found `.`
+  --> $DIR/pat-recover-wildcards.rs:17:10
+   |
+LL |         _.x() => ()
+   |          ^ expected one of `=>`, `if`, or `|`
+
+error: expected one of `=>`, `if`, or `|`, found `..=`
+  --> $DIR/pat-recover-wildcards.rs:23:10
+   |
+LL |         _..=4 => ()
+   |          ^^^ expected one of `=>`, `if`, or `|`
+
+error: expected one of `=>`, `if`, or `|`, found reserved identifier `_`
+  --> $DIR/pat-recover-wildcards.rs:29:11
+   |
+LL |         .._ => ()
+   |           ^ expected one of `=>`, `if`, or `|`
+
+error[E0586]: inclusive range with no end
+  --> $DIR/pat-recover-wildcards.rs:35:10
+   |
+LL |         0..._ => ()
+   |          ^^^ help: use `..` instead
+   |
+   = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
+
+error: expected one of `=>`, `if`, or `|`, found reserved identifier `_`
+  --> $DIR/pat-recover-wildcards.rs:35:13
+   |
+LL |         0..._ => ()
+   |             ^ expected one of `=>`, `if`, or `|`
+
+error: expected one of `)`, `,`, or `|`, found `*`
+  --> $DIR/pat-recover-wildcards.rs:43:12
+   |
+LL |         (_ * 0)..5 => ()
+   |            ^ expected one of `)`, `,`, or `|`
+
+error: expected one of `=>`, `if`, or `|`, found `(`
+  --> $DIR/pat-recover-wildcards.rs:49:11
+   |
+LL |         ..(_) => ()
+   |           ^ expected one of `=>`, `if`, or `|`
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/pat-recover-wildcards.rs:55:14
+   |
+LL |         4..=(2 + _) => ()
+   |              ^^^^^ arbitrary expressions are not allowed in patterns
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/pat-recover-wildcards.rs:55:13
+   |
+LL |         4..=(2 + _) => ()
+   |             ^     ^
+   |
+help: remove these parentheses
+   |
+LL -         4..=(2 + _) => ()
+LL +         4..=2 + _ => ()
+   |
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0586`.
diff --git a/tests/ui/parser/range-exclusive-dotdotlt.rs b/tests/ui/parser/range-exclusive-dotdotlt.rs
new file mode 100644
index 00000000000..5752566026f
--- /dev/null
+++ b/tests/ui/parser/range-exclusive-dotdotlt.rs
@@ -0,0 +1,43 @@
+fn foo() {
+    let _ = 0..<10;
+    //~^ ERROR: expected type, found `10`
+    //~| HELP: remove the `<` to write an exclusive range
+}
+
+fn bar() {
+    let _ = 0..<foo;
+    //~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `;`
+    //~| HELP: remove the `<` to write an exclusive range
+}
+
+fn baz() {
+    let _ = <foo>;
+    //~^ ERROR: expected `::`, found `;`
+}
+
+fn qux() {
+    let _ = [1, 2, 3][..<1];
+    //~^ ERROR: expected type, found `1`
+    //~| HELP: remove the `<` to write an exclusive range
+}
+
+fn quux() {
+    let _ = [1, 2, 3][..<foo];
+    //~^ ERROR: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `]`
+    //~| HELP: remove the `<` to write an exclusive range
+}
+
+fn foobar() {
+    let _ = [1, 2, 3][..<foo>];
+    //~^ ERROR: expected `::`, found `]`
+}
+
+fn ok1() {
+    let _ = [1, 2, 3][..<usize>::default()];
+}
+
+fn ok2() {
+    let _ = 0..<i32>::default();
+}
+
+fn main() {}
diff --git a/tests/ui/parser/range-exclusive-dotdotlt.stderr b/tests/ui/parser/range-exclusive-dotdotlt.stderr
new file mode 100644
index 00000000000..af25e1df343
--- /dev/null
+++ b/tests/ui/parser/range-exclusive-dotdotlt.stderr
@@ -0,0 +1,46 @@
+error: expected type, found `10`
+  --> $DIR/range-exclusive-dotdotlt.rs:2:17
+   |
+LL |     let _ = 0..<10;
+   |                -^^ expected type
+   |                |
+   |                help: remove the `<` to write an exclusive range
+
+error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `;`
+  --> $DIR/range-exclusive-dotdotlt.rs:8:20
+   |
+LL |     let _ = 0..<foo;
+   |                -   ^ expected one of 7 possible tokens
+   |                |
+   |                help: remove the `<` to write an exclusive range
+
+error: expected `::`, found `;`
+  --> $DIR/range-exclusive-dotdotlt.rs:14:18
+   |
+LL |     let _ = <foo>;
+   |                  ^ expected `::`
+
+error: expected type, found `1`
+  --> $DIR/range-exclusive-dotdotlt.rs:19:26
+   |
+LL |     let _ = [1, 2, 3][..<1];
+   |                         -^ expected type
+   |                         |
+   |                         help: remove the `<` to write an exclusive range
+
+error: expected one of `!`, `(`, `+`, `::`, `<`, `>`, or `as`, found `]`
+  --> $DIR/range-exclusive-dotdotlt.rs:25:29
+   |
+LL |     let _ = [1, 2, 3][..<foo];
+   |                         -   ^ expected one of 7 possible tokens
+   |                         |
+   |                         help: remove the `<` to write an exclusive range
+
+error: expected `::`, found `]`
+  --> $DIR/range-exclusive-dotdotlt.rs:31:30
+   |
+LL |     let _ = [1, 2, 3][..<foo>];
+   |                              ^ expected `::`
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
index 367aba3bdd6..0c55164a780 100644
--- a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
@@ -1,23 +1,23 @@
 error: unreachable pattern
-  --> $DIR/empty-types.rs:47:9
+  --> $DIR/empty-types.rs:50:9
    |
 LL |         _ => {}
    |         ^
    |
 note: the lint level is defined here
-  --> $DIR/empty-types.rs:13:9
+  --> $DIR/empty-types.rs:16:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:50:9
+  --> $DIR/empty-types.rs:53:9
    |
 LL |         _x => {}
    |         ^^
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
-  --> $DIR/empty-types.rs:54:11
+  --> $DIR/empty-types.rs:57:11
    |
 LL |     match ref_never {}
    |           ^^^^^^^^^
@@ -32,31 +32,31 @@ LL +     }
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:69:9
+  --> $DIR/empty-types.rs:72:9
    |
 LL |         (_, _) => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:76:9
+  --> $DIR/empty-types.rs:79:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:79:9
+  --> $DIR/empty-types.rs:82:9
    |
 LL |         (_, _) => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:83:9
+  --> $DIR/empty-types.rs:86:9
    |
 LL |         _ => {}
    |         ^
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
-  --> $DIR/empty-types.rs:87:11
+  --> $DIR/empty-types.rs:90:11
    |
 LL |     match res_u32_never {}
    |           ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
@@ -75,19 +75,19 @@ LL +     }
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:95:9
+  --> $DIR/empty-types.rs:98:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:100:9
+  --> $DIR/empty-types.rs:103:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
-  --> $DIR/empty-types.rs:97:11
+  --> $DIR/empty-types.rs:100:11
    |
 LL |     match res_u32_never {
    |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -105,7 +105,7 @@ LL ~         Ok(1_u32..=u32::MAX) => todo!()
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:104:9
+  --> $DIR/empty-types.rs:107:9
    |
 LL |     let Ok(_x) = res_u32_never.as_ref();
    |         ^^^^^^ pattern `Err(_)` not covered
@@ -119,121 +119,121 @@ LL |     let Ok(_x) = res_u32_never.as_ref() else { todo!() };
    |                                         ++++++++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:115:9
+  --> $DIR/empty-types.rs:118:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:119:9
+  --> $DIR/empty-types.rs:122:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:122:9
+  --> $DIR/empty-types.rs:125:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:123:9
+  --> $DIR/empty-types.rs:126:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:126:9
+  --> $DIR/empty-types.rs:129:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:127:9
+  --> $DIR/empty-types.rs:130:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:136:13
+  --> $DIR/empty-types.rs:139:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:139:13
+  --> $DIR/empty-types.rs:142:13
    |
 LL |             _ if false => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:148:13
+  --> $DIR/empty-types.rs:151:13
    |
 LL |             Some(_) => {}
    |             ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:152:13
+  --> $DIR/empty-types.rs:155:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:204:13
+  --> $DIR/empty-types.rs:207:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:209:13
+  --> $DIR/empty-types.rs:212:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:214:13
+  --> $DIR/empty-types.rs:217:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:219:13
+  --> $DIR/empty-types.rs:222:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:225:13
+  --> $DIR/empty-types.rs:228:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:284:9
+  --> $DIR/empty-types.rs:287:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:287:9
+  --> $DIR/empty-types.rs:290:9
    |
 LL |         (_, _) => {}
    |         ^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:290:9
+  --> $DIR/empty-types.rs:293:9
    |
 LL |         Ok(_) => {}
    |         ^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:291:9
+  --> $DIR/empty-types.rs:294:9
    |
 LL |         Err(_) => {}
    |         ^^^^^^
 
 error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
-  --> $DIR/empty-types.rs:323:11
+  --> $DIR/empty-types.rs:326:11
    |
 LL |     match slice_never {}
    |           ^^^^^^^^^^^
@@ -247,7 +247,7 @@ LL +     }
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` not covered
-  --> $DIR/empty-types.rs:334:11
+  --> $DIR/empty-types.rs:337:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[]` not covered
@@ -260,7 +260,7 @@ LL +         &[] => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` not covered
-  --> $DIR/empty-types.rs:347:11
+  --> $DIR/empty-types.rs:350:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[]` not covered
@@ -274,7 +274,7 @@ LL +         &[] => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
-  --> $DIR/empty-types.rs:353:11
+  --> $DIR/empty-types.rs:356:11
    |
 LL |     match *slice_never {}
    |           ^^^^^^^^^^^^
@@ -288,25 +288,25 @@ LL +     }
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:363:9
+  --> $DIR/empty-types.rs:366:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:366:9
+  --> $DIR/empty-types.rs:369:9
    |
 LL |         [_, _, _] => {}
    |         ^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:369:9
+  --> $DIR/empty-types.rs:372:9
    |
 LL |         [_, ..] => {}
    |         ^^^^^^^
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
-  --> $DIR/empty-types.rs:383:11
+  --> $DIR/empty-types.rs:386:11
    |
 LL |     match array_0_never {}
    |           ^^^^^^^^^^^^^
@@ -320,13 +320,13 @@ LL +     }
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:390:9
+  --> $DIR/empty-types.rs:393:9
    |
 LL |         _ => {}
    |         ^
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/empty-types.rs:392:11
+  --> $DIR/empty-types.rs:395:11
    |
 LL |     match array_0_never {
    |           ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -340,49 +340,49 @@ LL +         [] => todo!()
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:411:9
+  --> $DIR/empty-types.rs:414:9
    |
 LL |         Some(_) => {}
    |         ^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:416:9
+  --> $DIR/empty-types.rs:419:9
    |
 LL |         Some(_a) => {}
    |         ^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:421:9
+  --> $DIR/empty-types.rs:424:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:426:9
+  --> $DIR/empty-types.rs:429:9
    |
 LL |         _a => {}
    |         ^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:598:9
+  --> $DIR/empty-types.rs:601:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:601:9
+  --> $DIR/empty-types.rs:604:9
    |
 LL |         _x => {}
    |         ^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:604:9
+  --> $DIR/empty-types.rs:607:9
    |
 LL |         _ if false => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:607:9
+  --> $DIR/empty-types.rs:610:9
    |
 LL |         _x if false => {}
    |         ^^
diff --git a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr
new file mode 100644
index 00000000000..ed5d125e684
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr
@@ -0,0 +1,630 @@
+warning: the feature `min_exhaustive_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/empty-types.rs:13:35
+   |
+LL | #![cfg_attr(min_exh_pats, feature(min_exhaustive_patterns))]
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #119612 <https://github.com/rust-lang/rust/issues/119612> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:50:9
+   |
+LL |         _ => {}
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/empty-types.rs:16:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:53:9
+   |
+LL |         _x => {}
+   |         ^^
+
+error[E0004]: non-exhaustive patterns: type `&!` is non-empty
+  --> $DIR/empty-types.rs:57:11
+   |
+LL |     match ref_never {}
+   |           ^^^^^^^^^
+   |
+   = note: the matched value is of type `&!`
+   = note: references are always considered inhabited
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match ref_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:72:9
+   |
+LL |         (_, _) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:79:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:82:9
+   |
+LL |         (_, _) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:86:9
+   |
+LL |         _ => {}
+   |         ^
+
+error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
+  --> $DIR/empty-types.rs:90:11
+   |
+LL |     match res_u32_never {}
+   |           ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
+   |
+note: `Result<u32, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<u32, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~     match res_u32_never {
+LL +         Ok(_) => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:98:9
+   |
+LL |         Err(_) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:103:9
+   |
+LL |         Err(_) => {}
+   |         ^^^^^^
+
+error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
+  --> $DIR/empty-types.rs:100:11
+   |
+LL |     match res_u32_never {
+   |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
+   |
+note: `Result<u32, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<u32, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Err(_) => {},
+LL ~         Ok(1_u32..=u32::MAX) => todo!()
+   |
+
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-types.rs:107:9
+   |
+LL |     let Ok(_x) = res_u32_never.as_ref();
+   |         ^^^^^^ pattern `Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `Result<&u32, &!>`
+help: you might want to use `let else` to handle the variant that isn't matched
+   |
+LL |     let Ok(_x) = res_u32_never.as_ref() else { todo!() };
+   |                                         ++++++++++++++++
+
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-types.rs:111:9
+   |
+LL |     let Ok(_x) = &res_u32_never;
+   |         ^^^^^^ pattern `&Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `&Result<u32, !>`
+help: you might want to use `let else` to handle the variant that isn't matched
+   |
+LL |     let Ok(_x) = &res_u32_never else { todo!() };
+   |                                 ++++++++++++++++
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:118:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:122:9
+   |
+LL |         Ok(_) => {}
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:125:9
+   |
+LL |         Ok(_) => {}
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:126:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:129:9
+   |
+LL |         Ok(_) => {}
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:130:9
+   |
+LL |         Err(_) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:139:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:142:13
+   |
+LL |             _ if false => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:151:13
+   |
+LL |             Some(_) => {}
+   |             ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:155:13
+   |
+LL |             _ => {}
+   |             ^
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/empty-types.rs:164:15
+   |
+LL |         match *ref_opt_void {
+   |               ^^^^^^^^^^^^^ pattern `Some(_)` not covered
+   |
+note: `Option<Void>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Option<Void>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             None => {},
+LL +             Some(_) => todo!()
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:207:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:212:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:217:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:222:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:228:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:287:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:290:9
+   |
+LL |         (_, _) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:293:9
+   |
+LL |         Ok(_) => {}
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:294:9
+   |
+LL |         Err(_) => {}
+   |         ^^^^^^
+
+error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
+  --> $DIR/empty-types.rs:315:11
+   |
+LL |     match *x {}
+   |           ^^
+   |
+   = note: the matched value is of type `(u32, !)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *x {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
+  --> $DIR/empty-types.rs:317:11
+   |
+LL |     match *x {}
+   |           ^^
+   |
+   = note: the matched value is of type `(!, !)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *x {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
+  --> $DIR/empty-types.rs:319:11
+   |
+LL |     match *x {}
+   |           ^^ patterns `Ok(_)` and `Err(_)` not covered
+   |
+note: `Result<!, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<!, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match *x {
+LL +         Ok(_) | Err(_) => todo!(),
+LL ~     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
+  --> $DIR/empty-types.rs:321:11
+   |
+LL |     match *x {}
+   |           ^^
+   |
+   = note: the matched value is of type `[!; 3]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *x {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
+  --> $DIR/empty-types.rs:326:11
+   |
+LL |     match slice_never {}
+   |           ^^^^^^^^^^^
+   |
+   = note: the matched value is of type `&[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match slice_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
+  --> $DIR/empty-types.rs:328:11
+   |
+LL |     match slice_never {
+   |           ^^^^^^^^^^^ pattern `&[_, ..]` not covered
+   |
+   = note: the matched value is of type `&[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [] => {},
+LL +         &[_, ..] => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered
+  --> $DIR/empty-types.rs:337:11
+   |
+LL |     match slice_never {
+   |           ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered
+   |
+   = note: the matched value is of type `&[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         [_, _, _, ..] => {},
+LL +         &[] | &[_] | &[_, _] => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
+  --> $DIR/empty-types.rs:350:11
+   |
+LL |     match slice_never {
+   |           ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered
+   |
+   = note: the matched value is of type `&[!]`
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         &[..] if false => {},
+LL +         &[] | &[_, ..] => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
+  --> $DIR/empty-types.rs:356:11
+   |
+LL |     match *slice_never {}
+   |           ^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *slice_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:366:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:369:9
+   |
+LL |         [_, _, _] => {}
+   |         ^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:372:9
+   |
+LL |         [_, ..] => {}
+   |         ^^^^^^^
+
+error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
+  --> $DIR/empty-types.rs:386:11
+   |
+LL |     match array_0_never {}
+   |           ^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `[!; 0]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match array_0_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:393:9
+   |
+LL |         _ => {}
+   |         ^
+
+error[E0004]: non-exhaustive patterns: `[]` not covered
+  --> $DIR/empty-types.rs:395:11
+   |
+LL |     match array_0_never {
+   |           ^^^^^^^^^^^^^ pattern `[]` not covered
+   |
+   = note: the matched value is of type `[!; 0]`
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [..] if false => {},
+LL +         [] => todo!()
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:414:9
+   |
+LL |         Some(_) => {}
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:419:9
+   |
+LL |         Some(_a) => {}
+   |         ^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:424:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:429:9
+   |
+LL |         _a => {}
+   |         ^^
+
+error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
+  --> $DIR/empty-types.rs:449:11
+   |
+LL |     match ref_opt_never {
+   |           ^^^^^^^^^^^^^ pattern `&Some(_)` not covered
+   |
+note: `Option<!>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `&Option<!>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         &None => {},
+LL +         &Some(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/empty-types.rs:490:11
+   |
+LL |     match *ref_opt_never {
+   |           ^^^^^^^^^^^^^^ pattern `Some(_)` not covered
+   |
+note: `Option<!>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Option<!>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         None => {},
+LL +         Some(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Err(_)` not covered
+  --> $DIR/empty-types.rs:538:11
+   |
+LL |     match *ref_res_never {
+   |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
+   |
+note: `Result<!, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<!, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Ok(_) => {},
+LL +         Err(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Err(_)` not covered
+  --> $DIR/empty-types.rs:549:11
+   |
+LL |     match *ref_res_never {
+   |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
+   |
+note: `Result<!, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<!, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Ok(_a) => {},
+LL +         Err(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
+  --> $DIR/empty-types.rs:568:11
+   |
+LL |     match *ref_tuple_half_never {}
+   |           ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `(u32, !)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *ref_tuple_half_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:601:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:604:9
+   |
+LL |         _x => {}
+   |         ^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:607:9
+   |
+LL |         _ if false => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:610:9
+   |
+LL |         _x if false => {}
+   |         ^^
+
+error[E0004]: non-exhaustive patterns: `&_` not covered
+  --> $DIR/empty-types.rs:635:11
+   |
+LL |     match ref_never {
+   |           ^^^^^^^^^ pattern `&_` not covered
+   |
+   = note: the matched value is of type `&!`
+   = note: references are always considered inhabited
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         &_a if false => {},
+LL +         &_ => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/empty-types.rs:663:11
+   |
+LL |     match *x {
+   |           ^^ pattern `Some(_)` not covered
+   |
+note: `Option<Result<!, !>>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Option<Result<!, !>>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         None => {},
+LL +         Some(_) => todo!()
+   |
+
+error: aborting due to 63 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr
index 133a95a821b..2fdb51677da 100644
--- a/tests/ui/pattern/usefulness/empty-types.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr
@@ -1,23 +1,23 @@
 error: unreachable pattern
-  --> $DIR/empty-types.rs:47:9
+  --> $DIR/empty-types.rs:50:9
    |
 LL |         _ => {}
    |         ^
    |
 note: the lint level is defined here
-  --> $DIR/empty-types.rs:13:9
+  --> $DIR/empty-types.rs:16:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:50:9
+  --> $DIR/empty-types.rs:53:9
    |
 LL |         _x => {}
    |         ^^
 
 error[E0004]: non-exhaustive patterns: type `&!` is non-empty
-  --> $DIR/empty-types.rs:54:11
+  --> $DIR/empty-types.rs:57:11
    |
 LL |     match ref_never {}
    |           ^^^^^^^^^
@@ -32,7 +32,7 @@ LL +     }
    |
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:66:11
+  --> $DIR/empty-types.rs:69:11
    |
 LL |     match tuple_half_never {}
    |           ^^^^^^^^^^^^^^^^
@@ -46,7 +46,7 @@ LL +     }
    |
 
 error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
-  --> $DIR/empty-types.rs:73:11
+  --> $DIR/empty-types.rs:76:11
    |
 LL |     match tuple_never {}
    |           ^^^^^^^^^^^
@@ -60,13 +60,13 @@ LL +     }
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:83:9
+  --> $DIR/empty-types.rs:86:9
    |
 LL |         _ => {}
    |         ^
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
-  --> $DIR/empty-types.rs:87:11
+  --> $DIR/empty-types.rs:90:11
    |
 LL |     match res_u32_never {}
    |           ^^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered
@@ -88,7 +88,7 @@ LL +     }
    |
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
-  --> $DIR/empty-types.rs:89:11
+  --> $DIR/empty-types.rs:92:11
    |
 LL |     match res_u32_never {
    |           ^^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -106,7 +106,7 @@ LL +         Err(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
-  --> $DIR/empty-types.rs:97:11
+  --> $DIR/empty-types.rs:100:11
    |
 LL |     match res_u32_never {
    |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
@@ -124,7 +124,7 @@ LL ~         Ok(1_u32..=u32::MAX) => todo!()
    |
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:102:9
+  --> $DIR/empty-types.rs:105:9
    |
 LL |     let Ok(_x) = res_u32_never;
    |         ^^^^^^ pattern `Err(_)` not covered
@@ -138,7 +138,7 @@ LL |     let Ok(_x) = res_u32_never else { todo!() };
    |                                ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:104:9
+  --> $DIR/empty-types.rs:107:9
    |
 LL |     let Ok(_x) = res_u32_never.as_ref();
    |         ^^^^^^ pattern `Err(_)` not covered
@@ -152,7 +152,7 @@ LL |     let Ok(_x) = res_u32_never.as_ref() else { todo!() };
    |                                         ++++++++++++++++
 
 error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-types.rs:108:9
+  --> $DIR/empty-types.rs:111:9
    |
 LL |     let Ok(_x) = &res_u32_never;
    |         ^^^^^^ pattern `&Err(_)` not covered
@@ -166,7 +166,7 @@ LL |     let Ok(_x) = &res_u32_never else { todo!() };
    |                                 ++++++++++++++++
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
-  --> $DIR/empty-types.rs:112:11
+  --> $DIR/empty-types.rs:115:11
    |
 LL |     match result_never {}
    |           ^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered
@@ -188,7 +188,7 @@ LL +     }
    |
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
-  --> $DIR/empty-types.rs:117:11
+  --> $DIR/empty-types.rs:120:11
    |
 LL |     match result_never {
    |           ^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -205,19 +205,19 @@ LL |         Ok(_) => {}, Err(_) => todo!()
    |                    +++++++++++++++++++
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:136:13
+  --> $DIR/empty-types.rs:139:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:139:13
+  --> $DIR/empty-types.rs:142:13
    |
 LL |             _ if false => {}
    |             ^
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:142:15
+  --> $DIR/empty-types.rs:145:15
    |
 LL |         match opt_void {
    |               ^^^^^^^^ pattern `Some(_)` not covered
@@ -235,7 +235,7 @@ LL +             Some(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:161:15
+  --> $DIR/empty-types.rs:164:15
    |
 LL |         match *ref_opt_void {
    |               ^^^^^^^^^^^^^ pattern `Some(_)` not covered
@@ -253,43 +253,43 @@ LL +             Some(_) => todo!()
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:204:13
+  --> $DIR/empty-types.rs:207:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:209:13
+  --> $DIR/empty-types.rs:212:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:214:13
+  --> $DIR/empty-types.rs:217:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:219:13
+  --> $DIR/empty-types.rs:222:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:225:13
+  --> $DIR/empty-types.rs:228:13
    |
 LL |             _ => {}
    |             ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:284:9
+  --> $DIR/empty-types.rs:287:9
    |
 LL |         _ => {}
    |         ^
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:312:11
+  --> $DIR/empty-types.rs:315:11
    |
 LL |     match *x {}
    |           ^^
@@ -303,7 +303,7 @@ LL ~     }
    |
 
 error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
-  --> $DIR/empty-types.rs:314:11
+  --> $DIR/empty-types.rs:317:11
    |
 LL |     match *x {}
    |           ^^
@@ -317,7 +317,7 @@ LL ~     }
    |
 
 error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
-  --> $DIR/empty-types.rs:316:11
+  --> $DIR/empty-types.rs:319:11
    |
 LL |     match *x {}
    |           ^^ patterns `Ok(_)` and `Err(_)` not covered
@@ -339,7 +339,7 @@ LL ~     }
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
-  --> $DIR/empty-types.rs:318:11
+  --> $DIR/empty-types.rs:321:11
    |
 LL |     match *x {}
    |           ^^
@@ -353,7 +353,7 @@ LL ~     }
    |
 
 error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
-  --> $DIR/empty-types.rs:323:11
+  --> $DIR/empty-types.rs:326:11
    |
 LL |     match slice_never {}
    |           ^^^^^^^^^^^
@@ -367,7 +367,7 @@ LL +     }
    |
 
 error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
-  --> $DIR/empty-types.rs:325:11
+  --> $DIR/empty-types.rs:328:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ pattern `&[_, ..]` not covered
@@ -380,7 +380,7 @@ LL +         &[_, ..] => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered
-  --> $DIR/empty-types.rs:334:11
+  --> $DIR/empty-types.rs:337:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered
@@ -393,7 +393,7 @@ LL +         &[] | &[_] | &[_, _] => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
-  --> $DIR/empty-types.rs:347:11
+  --> $DIR/empty-types.rs:350:11
    |
 LL |     match slice_never {
    |           ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered
@@ -407,7 +407,7 @@ LL +         &[] | &[_, ..] => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
-  --> $DIR/empty-types.rs:353:11
+  --> $DIR/empty-types.rs:356:11
    |
 LL |     match *slice_never {}
    |           ^^^^^^^^^^^^
@@ -421,7 +421,7 @@ LL +     }
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
-  --> $DIR/empty-types.rs:360:11
+  --> $DIR/empty-types.rs:363:11
    |
 LL |     match array_3_never {}
    |           ^^^^^^^^^^^^^
@@ -435,7 +435,7 @@ LL +     }
    |
 
 error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
-  --> $DIR/empty-types.rs:383:11
+  --> $DIR/empty-types.rs:386:11
    |
 LL |     match array_0_never {}
    |           ^^^^^^^^^^^^^
@@ -449,13 +449,13 @@ LL +     }
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:390:9
+  --> $DIR/empty-types.rs:393:9
    |
 LL |         _ => {}
    |         ^
 
 error[E0004]: non-exhaustive patterns: `[]` not covered
-  --> $DIR/empty-types.rs:392:11
+  --> $DIR/empty-types.rs:395:11
    |
 LL |     match array_0_never {
    |           ^^^^^^^^^^^^^ pattern `[]` not covered
@@ -469,7 +469,7 @@ LL +         [] => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
-  --> $DIR/empty-types.rs:446:11
+  --> $DIR/empty-types.rs:449:11
    |
 LL |     match ref_opt_never {
    |           ^^^^^^^^^^^^^ pattern `&Some(_)` not covered
@@ -487,7 +487,7 @@ LL +         &Some(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:487:11
+  --> $DIR/empty-types.rs:490:11
    |
 LL |     match *ref_opt_never {
    |           ^^^^^^^^^^^^^^ pattern `Some(_)` not covered
@@ -505,7 +505,7 @@ LL +         Some(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
-  --> $DIR/empty-types.rs:535:11
+  --> $DIR/empty-types.rs:538:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -523,7 +523,7 @@ LL +         Err(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `Err(_)` not covered
-  --> $DIR/empty-types.rs:546:11
+  --> $DIR/empty-types.rs:549:11
    |
 LL |     match *ref_res_never {
    |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
@@ -541,7 +541,7 @@ LL +         Err(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
-  --> $DIR/empty-types.rs:565:11
+  --> $DIR/empty-types.rs:568:11
    |
 LL |     match *ref_tuple_half_never {}
    |           ^^^^^^^^^^^^^^^^^^^^^
@@ -555,31 +555,31 @@ LL +     }
    |
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:598:9
+  --> $DIR/empty-types.rs:601:9
    |
 LL |         _ => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:601:9
+  --> $DIR/empty-types.rs:604:9
    |
 LL |         _x => {}
    |         ^^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:604:9
+  --> $DIR/empty-types.rs:607:9
    |
 LL |         _ if false => {}
    |         ^
 
 error: unreachable pattern
-  --> $DIR/empty-types.rs:607:9
+  --> $DIR/empty-types.rs:610:9
    |
 LL |         _x if false => {}
    |         ^^
 
 error[E0004]: non-exhaustive patterns: `&_` not covered
-  --> $DIR/empty-types.rs:631:11
+  --> $DIR/empty-types.rs:635:11
    |
 LL |     match ref_never {
    |           ^^^^^^^^^ pattern `&_` not covered
@@ -594,7 +594,7 @@ LL +         &_ => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `Some(_)` not covered
-  --> $DIR/empty-types.rs:659:11
+  --> $DIR/empty-types.rs:663:11
    |
 LL |     match *x {
    |           ^^ pattern `Some(_)` not covered
diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs
index 1e1d23e446d..c66fd1edc19 100644
--- a/tests/ui/pattern/usefulness/empty-types.rs
+++ b/tests/ui/pattern/usefulness/empty-types.rs
@@ -1,4 +1,5 @@
-// revisions: normal exhaustive_patterns
+// revisions: normal min_exh_pats exhaustive_patterns
+// gate-test-min_exhaustive_patterns
 //
 // This tests correct handling of empty types in exhaustiveness checking.
 //
@@ -9,6 +10,8 @@
 // This feature is useful to avoid `!` falling back to `()` all the time.
 #![feature(never_type_fallback)]
 #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
+#![cfg_attr(min_exh_pats, feature(min_exhaustive_patterns))]
+//[min_exh_pats]~^ WARN the feature `min_exhaustive_patterns` is incomplete
 #![allow(dead_code, unreachable_code)]
 #![deny(unreachable_patterns)]
 
@@ -66,17 +69,17 @@ fn basic(x: NeverBundle) {
     match tuple_half_never {}
     //[normal]~^ ERROR non-empty
     match tuple_half_never {
-        (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        (_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
 
     let tuple_never: (!, !) = x.tuple_never;
     match tuple_never {}
     //[normal]~^ ERROR non-empty
     match tuple_never {
-        _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match tuple_never {
-        (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        (_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match tuple_never.0 {}
     match tuple_never.0 {
@@ -92,12 +95,12 @@ fn basic(x: NeverBundle) {
     }
     match res_u32_never {
         Ok(_) => {}
-        Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match res_u32_never {
         //~^ ERROR non-exhaustive
         Ok(0) => {}
-        Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     let Ok(_x) = res_u32_never;
     //[normal]~^ ERROR refutable
@@ -106,25 +109,25 @@ fn basic(x: NeverBundle) {
     // Non-obvious difference: here there's an implicit dereference in the patterns, which makes the
     // inner place !known_valid. `exhaustive_patterns` ignores this.
     let Ok(_x) = &res_u32_never;
-    //[normal]~^ ERROR refutable
+    //[normal,min_exh_pats]~^ ERROR refutable
 
     let result_never: Result<!, !> = x.result_never;
     match result_never {}
     //[normal]~^ ERROR non-exhaustive
     match result_never {
-        _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match result_never {
         //[normal]~^ ERROR non-exhaustive
-        Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match result_never {
-        Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
-        _ => {}     //[exhaustive_patterns]~ ERROR unreachable pattern
+        Ok(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+        _ => {}     //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match result_never {
-        Ok(_) => {}  //[exhaustive_patterns]~ ERROR unreachable pattern
-        Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        Ok(_) => {}  //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+        Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
 }
 
@@ -145,11 +148,11 @@ fn void_same_as_never(x: NeverBundle) {
         }
         match opt_void {
             None => {}
-            Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+            Some(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
         }
         match opt_void {
             None => {}
-            _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+            _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
         }
 
         let ref_void: &Void = &x.void;
@@ -159,7 +162,7 @@ fn void_same_as_never(x: NeverBundle) {
         }
         let ref_opt_void: &Option<Void> = &None;
         match *ref_opt_void {
-            //[normal]~^ ERROR non-exhaustive
+            //[normal,min_exh_pats]~^ ERROR non-exhaustive
             None => {}
         }
         match *ref_opt_void {
@@ -284,11 +287,11 @@ fn nested_validity_tracking(bundle: NeverBundle) {
         _ => {} //~ ERROR unreachable pattern
     }
     match tuple_never {
-        (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        (_, _) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match result_never {
-        Ok(_) => {}  //[exhaustive_patterns]~ ERROR unreachable pattern
-        Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        Ok(_) => {}  //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
+        Err(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
 
     // These should be considered !known_valid and not warn unreachable.
@@ -309,13 +312,13 @@ fn invalid_empty_match(bundle: NeverBundle) {
     match *x {}
 
     let x: &(u32, !) = &bundle.tuple_half_never;
-    match *x {} //[normal]~ ERROR non-exhaustive
+    match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive
     let x: &(!, !) = &bundle.tuple_never;
-    match *x {} //[normal]~ ERROR non-exhaustive
+    match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive
     let x: &Result<!, !> = &bundle.result_never;
-    match *x {} //[normal]~ ERROR non-exhaustive
+    match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive
     let x: &[!; 3] = &bundle.array_3_never;
-    match *x {} //[normal]~ ERROR non-exhaustive
+    match *x {} //[normal,min_exh_pats]~ ERROR non-exhaustive
 }
 
 fn arrays_and_slices(x: NeverBundle) {
@@ -323,7 +326,7 @@ fn arrays_and_slices(x: NeverBundle) {
     match slice_never {}
     //~^ ERROR non-empty
     match slice_never {
-        //[normal]~^ ERROR not covered
+        //[normal,min_exh_pats]~^ ERROR not covered
         [] => {}
     }
     match slice_never {
@@ -332,7 +335,7 @@ fn arrays_and_slices(x: NeverBundle) {
         [_, _, ..] => {}
     }
     match slice_never {
-        //[normal]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered
+        //[normal,min_exh_pats]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered
         //[exhaustive_patterns]~^^ ERROR `&[]` not covered
         [_, _, _, ..] => {}
     }
@@ -345,7 +348,7 @@ fn arrays_and_slices(x: NeverBundle) {
         _x => {}
     }
     match slice_never {
-        //[normal]~^ ERROR `&[]` and `&[_, ..]` not covered
+        //[normal,min_exh_pats]~^ ERROR `&[]` and `&[_, ..]` not covered
         //[exhaustive_patterns]~^^ ERROR `&[]` not covered
         &[..] if false => {}
     }
@@ -360,13 +363,13 @@ fn arrays_and_slices(x: NeverBundle) {
     match array_3_never {}
     //[normal]~^ ERROR non-empty
     match array_3_never {
-        _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match array_3_never {
-        [_, _, _] => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        [_, _, _] => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match array_3_never {
-        [_, ..] => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        [_, ..] => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
 
     let ref_array_3_never: &[!; 3] = &array_3_never;
@@ -408,22 +411,22 @@ fn bindings(x: NeverBundle) {
     match opt_never {
         None => {}
         // !useful, !reachable
-        Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        Some(_) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match opt_never {
         None => {}
         // !useful, !reachable
-        Some(_a) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        Some(_a) => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match opt_never {
         None => {}
         // !useful, !reachable
-        _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        _ => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
     match opt_never {
         None => {}
         // !useful, !reachable
-        _a => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        _a => {} //[exhaustive_patterns,min_exh_pats]~ ERROR unreachable pattern
     }
 
     // The scrutinee is known_valid, but under the `&` isn't anymore.
@@ -444,7 +447,7 @@ fn bindings(x: NeverBundle) {
         &_a => {}
     }
     match ref_opt_never {
-        //[normal]~^ ERROR non-exhaustive
+        //[normal,min_exh_pats]~^ ERROR non-exhaustive
         &None => {}
     }
     match ref_opt_never {
@@ -485,7 +488,7 @@ fn bindings(x: NeverBundle) {
         ref _a => {}
     }
     match *ref_opt_never {
-        //[normal]~^ ERROR non-exhaustive
+        //[normal,min_exh_pats]~^ ERROR non-exhaustive
         None => {}
     }
     match *ref_opt_never {
@@ -533,7 +536,7 @@ fn bindings(x: NeverBundle) {
 
     let ref_res_never: &Result<!, !> = &x.result_never;
     match *ref_res_never {
-        //[normal]~^ ERROR non-exhaustive
+        //[normal,min_exh_pats]~^ ERROR non-exhaustive
         // useful, reachable
         Ok(_) => {}
     }
@@ -544,7 +547,7 @@ fn bindings(x: NeverBundle) {
         _ => {}
     }
     match *ref_res_never {
-        //[normal]~^ ERROR non-exhaustive
+        //[normal,min_exh_pats]~^ ERROR non-exhaustive
         // useful, !reachable
         Ok(_a) => {}
     }
@@ -563,7 +566,7 @@ fn bindings(x: NeverBundle) {
 
     let ref_tuple_half_never: &(u32, !) = &x.tuple_half_never;
     match *ref_tuple_half_never {}
-    //[normal]~^ ERROR non-empty
+    //[normal,min_exh_pats]~^ ERROR non-empty
     match *ref_tuple_half_never {
         // useful, reachable
         (_, _) => {}
@@ -614,6 +617,7 @@ fn guards_and_validity(x: NeverBundle) {
         // useful, reachable
         _ => {}
     }
+
     // Now the madness commences. The guard caused a load of the value thus asserting validity. So
     // there's no invalid value for `_` to catch. So the second pattern is unreachable despite the
     // guard not being taken.
@@ -629,7 +633,7 @@ fn guards_and_validity(x: NeverBundle) {
         _a if false => {}
     }
     match ref_never {
-        //[normal]~^ ERROR non-exhaustive
+        //[normal,min_exh_pats]~^ ERROR non-exhaustive
         // useful, !reachable
         &_a if false => {}
     }
@@ -657,7 +661,7 @@ fn diagnostics_subtlety(x: NeverBundle) {
     // Regression test for diagnostics: don't report `Some(Ok(_))` and `Some(Err(_))`.
     let x: &Option<Result<!, !>> = &None;
     match *x {
-        //[normal]~^ ERROR `Some(_)` not covered
+        //[normal,min_exh_pats]~^ ERROR `Some(_)` not covered
         None => {}
     }
 }
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
index 4203dd94d43..51ff641509d 100644
--- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
+++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.rs
@@ -1,6 +1,6 @@
 fn main() {
     let f = |3: isize| println!("hello");
-    //~^ ERROR refutable pattern in function argument
+    //~^ ERROR refutable pattern in closure argument
     //~| `..=2_isize` and `4_isize..` not covered
     f(4);
 }
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
index bd6c5002e63..be119d27ab2 100644
--- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
+++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
@@ -1,4 +1,4 @@
-error[E0005]: refutable pattern in function argument
+error[E0005]: refutable pattern in closure argument
   --> $DIR/refutable-pattern-in-fn-arg.rs:2:14
    |
 LL |     let f = |3: isize| println!("hello");
diff --git a/tests/ui/pin-macro/cant_access_internals.rs b/tests/ui/pin-macro/cant_access_internals.rs
index 5826a18b571..4aeb6a643d9 100644
--- a/tests/ui/pin-macro/cant_access_internals.rs
+++ b/tests/ui/pin-macro/cant_access_internals.rs
@@ -8,5 +8,5 @@ use core::{
 
 fn main() {
     let mut phantom_pinned = pin!(PhantomPinned);
-    mem::take(phantom_pinned.pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals'
+    mem::take(phantom_pinned.__pointer); //~ ERROR use of unstable library feature 'unsafe_pin_internals'
 }
diff --git a/tests/ui/pin-macro/cant_access_internals.stderr b/tests/ui/pin-macro/cant_access_internals.stderr
index 2737b84f599..444314a9d8b 100644
--- a/tests/ui/pin-macro/cant_access_internals.stderr
+++ b/tests/ui/pin-macro/cant_access_internals.stderr
@@ -1,8 +1,8 @@
 error[E0658]: use of unstable library feature 'unsafe_pin_internals'
   --> $DIR/cant_access_internals.rs:11:15
    |
-LL |     mem::take(phantom_pinned.pointer);
-   |               ^^^^^^^^^^^^^^^^^^^^^^
+LL |     mem::take(phantom_pinned.__pointer);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: add `#![feature(unsafe_pin_internals)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
diff --git a/tests/ui/print_type_sizes/niche-filling.stdout b/tests/ui/print_type_sizes/niche-filling.stdout
index d1753c26ca8..b53b8936603 100644
--- a/tests/ui/print_type_sizes/niche-filling.stdout
+++ b/tests/ui/print_type_sizes/niche-filling.stdout
@@ -14,17 +14,17 @@ print-type-size         field `.pre`: 1 bytes
 print-type-size         field `.post`: 2 bytes
 print-type-size         field `.val`: 4 bytes
 print-type-size     variant `None`: 0 bytes
-print-type-size type: `MyOption<Union1<std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size type: `MyOption<Union1<std::num::NonZero<u32>>>`: 8 bytes, alignment: 4 bytes
 print-type-size     discriminant: 4 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
 print-type-size     variant `None`: 0 bytes
-print-type-size type: `MyOption<Union2<std::num::NonZeroU32, std::num::NonZeroU32>>`: 8 bytes, alignment: 4 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZero<u32>, std::num::NonZero<u32>>>`: 8 bytes, alignment: 4 bytes
 print-type-size     discriminant: 4 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
 print-type-size     variant `None`: 0 bytes
-print-type-size type: `MyOption<Union2<std::num::NonZeroU32, u32>>`: 8 bytes, alignment: 4 bytes
+print-type-size type: `MyOption<Union2<std::num::NonZero<u32>, u32>>`: 8 bytes, alignment: 4 bytes
 print-type-size     discriminant: 4 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
@@ -53,22 +53,22 @@ print-type-size type: `MyOption<char>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
 print-type-size     variant `None`: 0 bytes
-print-type-size type: `MyOption<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size type: `MyOption<std::num::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `Some`: 4 bytes
 print-type-size         field `.0`: 4 bytes
 print-type-size     variant `None`: 0 bytes
-print-type-size type: `Union1<std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size type: `Union1<std::num::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `Union1`: 4 bytes
 print-type-size         field `.a`: 4 bytes
-print-type-size type: `Union2<std::num::NonZeroU32, std::num::NonZeroU32>`: 4 bytes, alignment: 4 bytes
+print-type-size type: `Union2<std::num::NonZero<u32>, std::num::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `Union2`: 4 bytes
 print-type-size         field `.a`: 4 bytes
 print-type-size         field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
-print-type-size type: `Union2<std::num::NonZeroU32, u32>`: 4 bytes, alignment: 4 bytes
+print-type-size type: `Union2<std::num::NonZero<u32>, u32>`: 4 bytes, alignment: 4 bytes
 print-type-size     variant `Union2`: 4 bytes
 print-type-size         field `.a`: 4 bytes
 print-type-size         field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
-print-type-size type: `std::num::NonZeroU32`: 4 bytes, alignment: 4 bytes
+print-type-size type: `std::num::NonZero<u32>`: 4 bytes, alignment: 4 bytes
 print-type-size     field `.0`: 4 bytes
 print-type-size type: `Enum4<(), (), (), MyOption<u8>>`: 2 bytes, alignment: 1 bytes
 print-type-size     variant `Four`: 2 bytes
diff --git a/tests/ui/str/str-escape.rs b/tests/ui/str/str-escape.rs
index 10a72421f24..89a82171063 100644
--- a/tests/ui/str/str-escape.rs
+++ b/tests/ui/str/str-escape.rs
@@ -1,5 +1,6 @@
 // check-pass
 // ignore-tidy-tab
+// edition: 2021
 
 fn main() {
     let s = "\
@@ -8,11 +9,11 @@ fn main() {
     //~^^^ WARNING multiple lines skipped by escaped newline
     assert_eq!(s, "");
 
-    let s = "foo\
+    let s = c"foo\
              bar
              ";
     //~^^^ WARNING whitespace symbol '\u{a0}' is not skipped
-    assert_eq!(s, "foo           bar\n             ");
+    assert_eq!(s, c"foo           bar\n             ");
 
     let s = "a\
  b";
@@ -22,10 +23,10 @@ fn main() {
 	b";
     assert_eq!(s, "ab");
 
-    let s = "a\
+    let s = b"a\
     b";
     //~^^ WARNING whitespace symbol '\u{c}' is not skipped
     // '\x0c' is ASCII whitespace, but it may not need skipped
     // discussion: https://github.com/rust-lang/rust/pull/108403
-    assert_eq!(s, "a\x0cb");
+    assert_eq!(s, b"a\x0cb");
 }
diff --git a/tests/ui/str/str-escape.stderr b/tests/ui/str/str-escape.stderr
index 43b4f7e36f6..00fe5444e1a 100644
--- a/tests/ui/str/str-escape.stderr
+++ b/tests/ui/str/str-escape.stderr
@@ -1,5 +1,5 @@
 warning: multiple lines skipped by escaped newline
-  --> $DIR/str-escape.rs:5:14
+  --> $DIR/str-escape.rs:6:14
    |
 LL |       let s = "\
    |  ______________^
@@ -8,20 +8,20 @@ LL | |              ";
    | |_____________^ skipping everything up to and including this point
 
 warning: whitespace symbol '\u{a0}' is not skipped
-  --> $DIR/str-escape.rs:11:17
+  --> $DIR/str-escape.rs:12:18
    |
-LL |       let s = "foo\
-   |  _________________^
+LL |       let s = c"foo\
+   |  __________________^
 LL | |              bar
    | |   ^ whitespace symbol '\u{a0}' is not skipped
    | |___|
    | 
 
 warning: whitespace symbol '\u{c}' is not skipped
-  --> $DIR/str-escape.rs:25:15
+  --> $DIR/str-escape.rs:26:16
    |
-LL |       let s = "a\
-   |  _______________^
+LL |       let s = b"a\
+   |  ________________^
 LL | |     b";
    | |    ^- whitespace symbol '\u{c}' is not skipped
    | |____|
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.fixed b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.fixed
new file mode 100644
index 00000000000..86ac07a93a3
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.fixed
@@ -0,0 +1,29 @@
+// run-rustfix
+
+struct A {
+
+}
+
+trait M {
+    fn foo(_a: Self);
+    fn bar(_a: Self);
+    fn baz(_a: i32);
+}
+
+impl M for A {
+    fn foo(_a: Self) {}
+    fn bar(_a: A) {}
+    fn baz(_a: i32) {}
+}
+
+fn main() {
+    let _a = A {};
+    A::foo(_a);
+    //~^ ERROR no method named `foo` found
+    A::baz(0);
+    //~^ ERROR no method named `baz` found
+
+    let _b = A {};
+    A::bar(_b);
+    //~^ ERROR no method named `bar` found
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.rs b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.rs
new file mode 100644
index 00000000000..9a57ffb7740
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.rs
@@ -0,0 +1,29 @@
+// run-rustfix
+
+struct A {
+
+}
+
+trait M {
+    fn foo(_a: Self);
+    fn bar(_a: Self);
+    fn baz(_a: i32);
+}
+
+impl M for A {
+    fn foo(_a: Self) {}
+    fn bar(_a: A) {}
+    fn baz(_a: i32) {}
+}
+
+fn main() {
+    let _a = A {};
+    _a.foo();
+    //~^ ERROR no method named `foo` found
+    _a.baz(0);
+    //~^ ERROR no method named `baz` found
+
+    let _b = A {};
+    _b.bar();
+    //~^ ERROR no method named `bar` found
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.stderr
new file mode 100644
index 00000000000..0df2b08d3be
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-for-impl-trait.stderr
@@ -0,0 +1,60 @@
+error[E0599]: no method named `foo` found for struct `A` in the current scope
+  --> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:21:8
+   |
+LL | struct A {
+   | -------- method `foo` not found for this struct
+...
+LL |     _a.foo();
+   |     ---^^^--
+   |     |  |
+   |     |  this is an associated function, not a method
+   |     help: use associated function syntax instead: `A::foo(_a)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in the trait `M`
+  --> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:8:5
+   |
+LL |     fn foo(_a: Self);
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `baz` found for struct `A` in the current scope
+  --> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:23:8
+   |
+LL | struct A {
+   | -------- method `baz` not found for this struct
+...
+LL |     _a.baz(0);
+   |     ---^^^---
+   |     |  |
+   |     |  this is an associated function, not a method
+   |     help: use associated function syntax instead: `A::baz(0)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in the trait `M`
+  --> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:10:5
+   |
+LL |     fn baz(_a: i32);
+   |     ^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `bar` found for struct `A` in the current scope
+  --> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:27:8
+   |
+LL | struct A {
+   | -------- method `bar` not found for this struct
+...
+LL |     _b.bar();
+   |     ---^^^--
+   |     |  |
+   |     |  this is an associated function, not a method
+   |     help: use associated function syntax instead: `A::bar(_b)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in the trait `M`
+  --> $DIR/suggest-assoc-fn-call-for-impl-trait.rs:9:5
+   |
+LL |     fn bar(_a: Self);
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/symbol-mangling-version/bad-value.bad.stderr b/tests/ui/symbol-mangling-version/bad-value.bad.stderr
index c36c73c6069..a12e5e241c0 100644
--- a/tests/ui/symbol-mangling-version/bad-value.bad.stderr
+++ b/tests/ui/symbol-mangling-version/bad-value.bad.stderr
@@ -1,2 +1,2 @@
-error: incorrect value `bad-value` for codegen option `symbol-mangling-version` - either `legacy` or `v0` (RFC 2603) was expected
+error: incorrect value `bad-value` for codegen option `symbol-mangling-version` - one of: `legacy`, `v0` (RFC 2603), or `hashed` was expected
 
diff --git a/tests/ui/symbol-mangling-version/bad-value.blank.stderr b/tests/ui/symbol-mangling-version/bad-value.blank.stderr
index 0e70af5b8ff..95456587781 100644
--- a/tests/ui/symbol-mangling-version/bad-value.blank.stderr
+++ b/tests/ui/symbol-mangling-version/bad-value.blank.stderr
@@ -1,2 +1,2 @@
-error: incorrect value `` for codegen option `symbol-mangling-version` - either `legacy` or `v0` (RFC 2603) was expected
+error: incorrect value `` for codegen option `symbol-mangling-version` - one of: `legacy`, `v0` (RFC 2603), or `hashed` was expected
 
diff --git a/tests/ui/symbol-mangling-version/bad-value.no-value.stderr b/tests/ui/symbol-mangling-version/bad-value.no-value.stderr
index 77013b72b6c..325e47a281f 100644
--- a/tests/ui/symbol-mangling-version/bad-value.no-value.stderr
+++ b/tests/ui/symbol-mangling-version/bad-value.no-value.stderr
@@ -1,2 +1,2 @@
-error: codegen option `symbol-mangling-version` requires either `legacy` or `v0` (RFC 2603) (C symbol-mangling-version=<value>)
+error: codegen option `symbol-mangling-version` requires one of: `legacy`, `v0` (RFC 2603), or `hashed` (C symbol-mangling-version=<value>)
 
diff --git a/tests/ui/symbol-mangling-version/unstable.hashed.stderr b/tests/ui/symbol-mangling-version/unstable.hashed.stderr
new file mode 100644
index 00000000000..f2ae18290f2
--- /dev/null
+++ b/tests/ui/symbol-mangling-version/unstable.hashed.stderr
@@ -0,0 +1,2 @@
+error: `-C symbol-mangling-version=hashed` requires `-Z unstable-options`
+
diff --git a/tests/ui/symbol-mangling-version/unstable.rs b/tests/ui/symbol-mangling-version/unstable.rs
index df87a39cdfb..42750a64574 100644
--- a/tests/ui/symbol-mangling-version/unstable.rs
+++ b/tests/ui/symbol-mangling-version/unstable.rs
@@ -1,6 +1,9 @@
-// revisions: legacy legacy-ok
+// revisions: legacy legacy-ok hashed hashed-ok
 // [legacy] compile-flags: -Csymbol-mangling-version=legacy
 // [legacy-ok] check-pass
 // [legacy-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=legacy
+// [hashed] compile-flags: -Csymbol-mangling-version=hashed
+// [hashed-ok] check-pass
+// [hashed-ok] compile-flags: -Zunstable-options -Csymbol-mangling-version=hashed
 
 fn main() {}
diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr
index 592cfd970c6..bffad037fba 100644
--- a/tests/ui/traits/issue-77982.stderr
+++ b/tests/ui/traits/issue-77982.stderr
@@ -44,8 +44,9 @@ LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
    |                                            type must be known at this point
    |
    = note: multiple `impl`s satisfying `u32: From<_>` found in the `core` crate:
+           - impl From<Char> for u32;
            - impl From<Ipv4Addr> for u32;
-           - impl From<NonZeroU32> for u32;
+           - impl From<NonZero<u32>> for u32;
            - impl From<bool> for u32;
            - impl From<char> for u32;
            - impl From<u16> for u32;
diff --git a/tests/ui/traits/next-solver/alias_eq_cant_be_furthur_normalized.rs b/tests/ui/traits/next-solver/alias-relate/alias_eq_cant_be_furthur_normalized.rs
index 04d1b949692..04d1b949692 100644
--- a/tests/ui/traits/next-solver/alias_eq_cant_be_furthur_normalized.rs
+++ b/tests/ui/traits/next-solver/alias-relate/alias_eq_cant_be_furthur_normalized.rs
diff --git a/tests/ui/traits/next-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs b/tests/ui/traits/next-solver/alias-relate/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
index 48157192a10..48157192a10 100644
--- a/tests/ui/traits/next-solver/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
+++ b/tests/ui/traits/next-solver/alias-relate/alias_eq_dont_use_normalizes_to_if_substs_eq.rs
diff --git a/tests/ui/traits/next-solver/alias_eq_simple.rs b/tests/ui/traits/next-solver/alias-relate/alias_eq_simple.rs
index 21ad1a4fa3c..21ad1a4fa3c 100644
--- a/tests/ui/traits/next-solver/alias_eq_simple.rs
+++ b/tests/ui/traits/next-solver/alias-relate/alias_eq_simple.rs
diff --git a/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.rs b/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.rs
index 4717aa80499..4717aa80499 100644
--- a/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.rs
+++ b/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.rs
diff --git a/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.stderr b/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.stderr
index 8c6840f72a7..8c6840f72a7 100644
--- a/tests/ui/traits/next-solver/alias_eq_substs_eq_not_intercrate.stderr
+++ b/tests/ui/traits/next-solver/alias-relate/alias_eq_substs_eq_not_intercrate.stderr
diff --git a/tests/ui/traits/next-solver/tait-eq-proj-2.rs b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs
index a3df053dd83..915643f1d2a 100644
--- a/tests/ui/traits/next-solver/tait-eq-proj-2.rs
+++ b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs
@@ -3,7 +3,7 @@
 
 #![feature(type_alias_impl_trait)]
 
-// Similar to tests/ui/traits/next-solver/tait-eq-proj.rs
+// Similar to tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs
 // but check the alias-sub relation in the other direction.
 
 type Tait = impl Iterator<Item = impl Sized>;
diff --git a/tests/ui/traits/next-solver/tait-eq-proj.rs b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs
index 871e8e1e9fc..871e8e1e9fc 100644
--- a/tests/ui/traits/next-solver/tait-eq-proj.rs
+++ b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs
diff --git a/tests/ui/traits/next-solver/tait-eq-tait.rs b/tests/ui/traits/next-solver/alias-relate/tait-eq-tait.rs
index 2629a124c3a..2629a124c3a 100644
--- a/tests/ui/traits/next-solver/tait-eq-tait.rs
+++ b/tests/ui/traits/next-solver/alias-relate/tait-eq-tait.rs
diff --git a/tests/ui/traits/next-solver/normalize-path-for-method.rs b/tests/ui/traits/next-solver/normalize-path-for-method.rs
new file mode 100644
index 00000000000..b95454306cd
--- /dev/null
+++ b/tests/ui/traits/next-solver/normalize-path-for-method.rs
@@ -0,0 +1,18 @@
+// compile-flags: -Znext-solver
+// check-pass
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+struct Foo;
+impl Foo {
+    fn new() -> Self { Foo }
+}
+
+fn main() {
+    <Foo as Mirror>::Assoc::new();
+}
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 71b1502d775..932826519b7 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
@@ -16,6 +16,7 @@ fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc
     //~^ 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 == _`
     //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
 }
 
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 bad6820f738..e4f1f9cf022 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
@@ -1,3 +1,11 @@
+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[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
   --> $DIR/recursive-self-normalization-2.rs:15:17
    |
@@ -35,7 +43,8 @@ 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: aborting due to 4 previous errors
+error: aborting due to 5 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 809a6a59ca6..32672c08c7e 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
@@ -12,6 +12,7 @@ fn test<T: Foo<Assoc = <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 == _`
+    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
     //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
 }
 
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 80005d344ba..da5c8bde568 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
@@ -1,3 +1,11 @@
+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[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
   --> $DIR/recursive-self-normalization.rs:11:17
    |
@@ -35,7 +43,8 @@ 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: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/temporary-ambiguity.rs b/tests/ui/traits/next-solver/temporary-ambiguity.rs
deleted file mode 100644
index 6102de7e446..00000000000
--- a/tests/ui/traits/next-solver/temporary-ambiguity.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// compile-flags: -Znext-solver
-// check-pass
-
-// Checks that we don't explode when we assemble >1 candidate for a goal.
-
-struct Wrapper<T>(T);
-
-trait Foo {}
-
-impl Foo for Wrapper<i32> {}
-
-impl Foo for Wrapper<()> {}
-
-fn needs_foo(_: impl Foo) {}
-
-fn main() {
-    let mut x = Default::default();
-    let w = Wrapper(x);
-    needs_foo(w);
-    x = 1;
-    let _ = x;
-}
diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr
index 97fbbdbf8f8..7e5b68353fb 100644
--- a/tests/ui/try-trait/bad-interconversion.stderr
+++ b/tests/ui/try-trait/bad-interconversion.stderr
@@ -11,7 +11,8 @@ LL |     Ok(Err(123_i32)?)
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following other types implement trait `From<T>`:
              <u8 as From<bool>>
-             <u8 as From<NonZeroU8>>
+             <u8 as From<NonZero<u8>>>
+             <u8 as From<Char>>
    = note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
 
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
diff --git a/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs b/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs
new file mode 100644
index 00000000000..39f0b9a02ee
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/struct-assignment-validity.rs
@@ -0,0 +1,31 @@
+// compile-flags: -Zvalidate-mir
+// check-pass
+
+// Check that we don't cause cycle errors when validating pre-`Reveal::All` MIR
+// that assigns opaques through normalized projections.
+
+#![feature(impl_trait_in_assoc_type)]
+
+struct Bar;
+
+trait Trait {
+    type Assoc;
+    fn foo() -> Foo;
+}
+
+impl Trait for Bar {
+    type Assoc = impl std::fmt::Debug;
+    fn foo() -> Foo
+    where
+        Self::Assoc:,
+    {
+        let x: <Bar as Trait>::Assoc = ();
+        Foo { field: () }
+    }
+}
+
+struct Foo {
+    field: <Bar as Trait>::Assoc,
+}
+
+fn main() {}
diff --git a/triagebot.toml b/triagebot.toml
index 264f6efd982..e57dd158374 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -476,7 +476,7 @@ of `ObligationCtxt`.
 """
 cc = ["@lcnr", "@compiler-errors"]
 
-[mentions."compiler/rustc_error_codes/src/error_codes.rs"]
+[mentions."compiler/rustc_error_codes/src/lib.rs"]
 message = "Some changes occurred in diagnostic error codes"
 cc = ["@GuillaumeGomez"]
 
@@ -652,6 +652,7 @@ compiler-team-contributors = [
     "@TaKO8Ki",
     "@b-naber",
     "@nnethercote",
+    "@fmease",
 ]
 compiler = [
     "compiler-team",
@@ -662,7 +663,6 @@ libs = [
     "@joshtriplett",
     "@Mark-Simulacrum",
     "@m-ou-se",
-    "@thomcc",
 ]
 bootstrap = [
     "@Mark-Simulacrum",
@@ -802,7 +802,7 @@ project-stable-mir = [
 "/library/panic_unwind" =                                ["libs"]
 "/library/proc_macro" =                                  ["@petrochenkov"]
 "/library/std" =                                         ["libs"]
-"/library/std/src/sys/pal/windows" =                     ["@ChrisDenton", "@thomcc"]
+"/library/std/src/sys/pal/windows" =                     ["@ChrisDenton"]
 "/library/stdarch" =                                     ["libs"]
 "/library/test" =                                        ["libs"]
 "/src/bootstrap" =                                       ["bootstrap"]