about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Kimock <kimockb@gmail.com>2023-03-05 12:27:42 -0500
committerBen Kimock <kimockb@gmail.com>2023-03-05 12:27:42 -0500
commitd56332ece806af134fbbb017d5e989a68bb022e0 (patch)
tree284242248144c20d716fdafea65858586dabbafe
parente397cf42ee93a6d00c6247af76be98e66a4f621f (diff)
parent740d476bbf9122b27c3aac18b5e4d2c8162cb576 (diff)
downloadrust-d56332ece806af134fbbb017d5e989a68bb022e0.tar.gz
rust-d56332ece806af134fbbb017d5e989a68bb022e0.zip
Merge from rustc
-rw-r--r--.github/workflows/ci.yml12
-rw-r--r--.mailmap2
-rw-r--r--Cargo.lock31
-rw-r--r--README.md2
-rw-r--r--compiler/rustc_abi/src/lib.rs8
-rw-r--r--compiler/rustc_ast/src/util/parser.rs2
-rw-r--r--compiler/rustc_ast_lowering/locales/en-US.ftl3
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs7
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs12
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs41
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs6
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs2
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs49
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs41
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs15
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs17
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs6
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs31
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs40
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs78
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs21
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/utils.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs39
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs5
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs76
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs15
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs46
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs6
-rw-r--r--compiler/rustc_const_eval/src/lib.rs7
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs22
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs (renamed from compiler/rustc_const_eval/src/util/might_permit_raw_init.rs)37
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs4
-rw-r--r--compiler/rustc_data_structures/Cargo.toml2
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs2
-rw-r--r--compiler/rustc_data_structures/src/sorted_map/index_map.rs5
-rw-r--r--compiler/rustc_data_structures/src/sorted_map/tests.rs4
-rw-r--r--compiler/rustc_data_structures/src/stable_hasher/tests.rs2
-rw-r--r--compiler/rustc_errors/src/emitter.rs10
-rw-r--r--compiler/rustc_errors/src/lib.rs2
-rw-r--r--compiler/rustc_expand/locales/en-US.ftl3
-rw-r--r--compiler/rustc_expand/src/errors.rs7
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs2
-rw-r--r--compiler/rustc_expand/src/proc_macro.rs2
-rw-r--r--compiler/rustc_expand/src/tests.rs1
-rw-r--r--compiler/rustc_feature/src/accepted.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs15
-rw-r--r--compiler/rustc_hir_analysis/locales/en-US.ftl16
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs44
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs43
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/check_unused.rs133
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs145
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs40
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs20
-rw-r--r--compiler/rustc_incremental/src/assert_module_sources.rs2
-rw-r--r--compiler/rustc_index/src/bit_set.rs2
-rw-r--r--compiler/rustc_infer/locales/en-US.ftl11
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs10
-rw-r--r--compiler/rustc_infer/src/infer/at.rs28
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs8
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs20
-rw-r--r--compiler/rustc_infer/src/infer/canonical/substitute.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs15
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs14
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs56
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs2
-rw-r--r--compiler/rustc_interface/locales/en-US.ftl2
-rw-r--r--compiler/rustc_lexer/src/lib.rs12
-rw-r--r--compiler/rustc_lint/src/builtin.rs2
-rw-r--r--compiler/rustc_lint/src/context.rs17
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs7
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp36
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp13
-rw-r--r--compiler/rustc_macros/src/serialize.rs47
-rw-r--r--compiler/rustc_metadata/src/locator.rs11
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs45
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs8
-rw-r--r--compiler/rustc_middle/src/arena.rs1
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs7
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs17
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs62
-rw-r--r--compiler/rustc_middle/src/infer/mod.rs3
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs12
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs82
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs22
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs2
-rw-r--r--compiler/rustc_middle/src/query/keys.rs24
-rw-r--r--compiler/rustc_middle/src/query/mod.rs42
-rw-r--r--compiler/rustc_middle/src/thir.rs33
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs16
-rw-r--r--compiler/rustc_middle/src/ty/assoc.rs2
-rw-r--r--compiler/rustc_middle/src/ty/closure.rs60
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs20
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs6
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs2
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs38
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs74
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs3
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/query.rs1
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs1
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs11
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs2
-rw-r--r--compiler/rustc_middle/src/ty/util.rs4
-rw-r--r--compiler/rustc_middle/src/values.rs2
-rw-r--r--compiler/rustc_mir_build/locales/en-US.ftl6
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs11
-rw-r--r--compiler/rustc_mir_build/src/build/expr/stmt.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs186
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs32
-rw-r--r--compiler/rustc_mir_build/src/errors.rs19
-rw-r--r--compiler/rustc_mir_build/src/lib.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs43
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs42
-rw-r--r--compiler/rustc_mir_build/src/thir/mod.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs (renamed from compiler/rustc_middle/src/thir/print.rs)27
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs4
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs19
-rw-r--r--compiler/rustc_mir_transform/src/instcombine.rs51
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs5
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs2
-rw-r--r--compiler/rustc_parse/locales/en-US.ftl6
-rw-r--r--compiler/rustc_parse/src/errors.rs11
-rw-r--r--compiler/rustc_parse/src/lexer/diagnostics.rs10
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs31
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs27
-rw-r--r--compiler/rustc_parse/src/lib.rs32
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs4
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs132
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs56
-rw-r--r--compiler/rustc_parse/src/parser/item.rs24
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs27
-rw-r--r--compiler/rustc_passes/locales/en-US.ftl3
-rw-r--r--compiler/rustc_passes/src/dead.rs2
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs63
-rw-r--r--compiler/rustc_passes/src/entry.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs16
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs2
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs2
-rw-r--r--compiler/rustc_passes/src/liveness.rs2
-rw-r--r--compiler/rustc_passes/src/liveness/rwu_table.rs2
-rw-r--r--compiler/rustc_passes/src/reachable.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs2
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs9
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs12
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs135
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs14
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs4
-rw-r--r--compiler/rustc_resolve/src/ident.rs2
-rw-r--r--compiler/rustc_resolve/src/imports.rs10
-rw-r--r--compiler/rustc_resolve/src/late.rs9
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs7
-rw-r--r--compiler/rustc_resolve/src/lib.rs20
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs16
-rw-r--r--compiler/rustc_serialize/src/serialize.rs12
-rw-r--r--compiler/rustc_session/locales/en-US.ftl2
-rw-r--r--compiler/rustc_session/src/config.rs4
-rw-r--r--compiler/rustc_session/src/filesearch.rs12
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_session/src/session.rs10
-rw-r--r--compiler/rustc_span/src/def_id.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs390
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonical/mod.rs240
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt.rs11
-rw-r--r--compiler/rustc_trait_selection/src/solve/mod.rs97
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs56
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--compiler/rustc_transmute/src/maybe_transmutable/query_context.rs4
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs166
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs1
-rw-r--r--config.toml.example1
-rw-r--r--library/alloc/src/boxed.rs9
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs2
-rw-r--r--library/alloc/src/macros.rs2
-rw-r--r--library/alloc/src/rc.rs2
-rw-r--r--library/alloc/src/string.rs4
-rw-r--r--library/alloc/src/sync.rs2
-rw-r--r--library/alloc/src/vec/mod.rs5
-rw-r--r--library/alloc/tests/vec_deque.rs14
-rw-r--r--library/core/src/any.rs2
-rw-r--r--library/core/src/array/equality.rs73
-rw-r--r--library/core/src/cell.rs2
-rw-r--r--library/core/src/cmp.rs3
-rw-r--r--library/core/src/cmp/bytewise.rs83
-rw-r--r--library/core/src/ffi/mod.rs1
-rw-r--r--library/core/src/intrinsics.rs4
-rw-r--r--library/core/src/intrinsics/mir.rs2
-rw-r--r--library/core/src/lib.rs7
-rw-r--r--library/core/src/net/display_buffer.rs (renamed from library/std/src/net/display_buffer.rs)0
-rw-r--r--library/core/src/net/ip_addr.rs2070
-rw-r--r--library/core/src/net/mod.rs24
-rw-r--r--library/core/src/net/parser.rs (renamed from library/std/src/net/parser.rs)4
-rw-r--r--library/core/src/net/socket_addr.rs664
-rw-r--r--library/core/src/option.rs119
-rw-r--r--library/core/src/primitive_docs.rs6
-rw-r--r--library/core/src/ptr/alignment.rs2
-rw-r--r--library/core/src/slice/cmp.rs27
-rw-r--r--library/core/src/slice/mod.rs2
-rw-r--r--library/core/src/slice/sort.rs4
-rw-r--r--library/core/src/str/traits.rs4
-rw-r--r--library/core/src/sync/atomic.rs135
-rw-r--r--library/core/src/task/poll.rs5
-rw-r--r--library/core/tests/iter/adapters/mod.rs2
-rw-r--r--library/core/tests/lib.rs6
-rw-r--r--library/core/tests/net/ip_addr.rs1035
-rw-r--r--library/core/tests/net/mod.rs13
-rw-r--r--library/core/tests/net/parser.rs (renamed from library/std/src/net/parser/tests.rs)4
-rw-r--r--library/core/tests/net/socket_addr.rs233
-rw-r--r--library/portable-simd/crates/core_simd/src/vector.rs2
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/build.rs1
-rw-r--r--library/std/src/lib.rs3
-rw-r--r--library/std/src/net/ip_addr.rs2075
-rw-r--r--library/std/src/net/ip_addr/tests.rs1035
-rw-r--r--library/std/src/net/mod.rs6
-rw-r--r--library/std/src/net/socket_addr.rs689
-rw-r--r--library/std/src/net/tcp/tests.rs5
-rw-r--r--library/std/src/net/udp/tests.rs5
-rw-r--r--library/std/src/os/mod.rs2
-rw-r--r--library/std/src/os/nto/fs.rs92
-rw-r--r--library/std/src/os/nto/mod.rs4
-rw-r--r--library/std/src/os/nto/raw.rs40
-rw-r--r--library/std/src/os/unix/fs.rs30
-rw-r--r--library/std/src/os/unix/fs/tests.rs57
-rw-r--r--library/std/src/os/unix/mod.rs5
-rw-r--r--library/std/src/os/unix/net/datagram.rs6
-rw-r--r--library/std/src/os/unix/net/tests.rs1
-rw-r--r--library/std/src/os/unix/process.rs26
-rw-r--r--library/std/src/os/unix/ucred.rs3
-rw-r--r--library/std/src/primitive_docs.rs6
-rw-r--r--library/std/src/process.rs2
-rw-r--r--library/std/src/sys/itron/thread.rs2
-rw-r--r--library/std/src/sys/unix/args.rs3
-rw-r--r--library/std/src/sys/unix/env.rs11
-rw-r--r--library/std/src/sys/unix/fd.rs198
-rw-r--r--library/std/src/sys/unix/fs.rs92
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs11
-rw-r--r--library/std/src/sys/unix/mod.rs2
-rw-r--r--library/std/src/sys/unix/net.rs2
-rw-r--r--library/std/src/sys/unix/os.rs12
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs74
-rw-r--r--library/std/src/sys/unix/thread.rs15
-rw-r--r--library/std/src/sys/unix/thread_parking/pthread.rs9
-rw-r--r--library/std/src/sys/unix/time.rs22
-rw-r--r--library/std/src/sys/windows/c.rs32
-rw-r--r--library/std/src/sys/windows/stdio.rs74
-rw-r--r--library/std/src/sys_common/backtrace.rs13
-rw-r--r--library/std/src/sys_common/net.rs7
-rw-r--r--library/std/src/sys_common/net/tests.rs2
-rw-r--r--library/std/src/sys_common/thread_local_key.rs10
-rw-r--r--library/std/src/sys_common/wtf8.rs2
-rw-r--r--library/test/src/lib.rs2
-rw-r--r--library/unwind/src/lib.rs4
-rw-r--r--library/unwind/src/libunwind.rs2
-rw-r--r--src/bootstrap/Cargo.lock4
-rw-r--r--src/bootstrap/Cargo.toml5
-rw-r--r--src/bootstrap/bolt.rs27
-rw-r--r--src/bootstrap/builder.rs6
-rw-r--r--src/bootstrap/check.rs88
-rw-r--r--src/bootstrap/clean.rs1
-rw-r--r--src/bootstrap/compile.rs2
-rw-r--r--src/bootstrap/config.rs1
-rw-r--r--src/bootstrap/config/tests.rs5
-rwxr-xr-xsrc/bootstrap/configure.py24
-rw-r--r--src/bootstrap/dist.rs135
-rw-r--r--src/bootstrap/doc.rs35
-rw-r--r--src/bootstrap/format.rs2
-rw-r--r--src/bootstrap/lib.rs9
-rw-r--r--src/bootstrap/metadata.rs2
-rw-r--r--src/bootstrap/metrics.rs2
-rw-r--r--src/bootstrap/native.rs44
-rw-r--r--src/bootstrap/toolstate.rs2
-rwxr-xr-xsrc/ci/docker/scripts/fuchsia-test-runner.py39
-rw-r--r--src/ci/github-actions/ci.yml2
-rwxr-xr-xsrc/ci/pgo.sh230
-rw-r--r--src/ci/stage-build.py4
m---------src/doc/book0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/rustc/src/platform-support.md6
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md8
-rw-r--r--src/doc/rustc/src/platform-support/nto-qnx.md175
-rw-r--r--src/doc/rustdoc/src/how-to-read-rustdoc.md3
-rw-r--r--src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md43
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/clean/types.rs10
-rw-r--r--src/librustdoc/clean/utils.rs2
-rw-r--r--src/librustdoc/doctest.rs14
-rw-r--r--src/librustdoc/html/format.rs20
-rw-r--r--src/librustdoc/html/markdown.rs8
-rw-r--r--src/librustdoc/html/render/print_item.rs6
-rw-r--r--src/librustdoc/html/render/search_index.rs34
-rw-r--r--src/librustdoc/html/static/.eslintrc.js1
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css5
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css1
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css1
-rw-r--r--src/librustdoc/html/static/css/themes/light.css1
-rw-r--r--src/librustdoc/html/static/js/search.js189
-rw-r--r--src/librustdoc/html/static/js/source-script.js3
-rw-r--r--src/librustdoc/json/conversions.rs2
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs1
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs1
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs16
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs2
-rw-r--r--src/librustdoc/passes/lint/html_tags.rs2
-rw-r--r--src/librustdoc/passes/propagate_doc_cfg.rs1
-rw-r--r--src/librustdoc/visit_ast.rs2
m---------src/llvm-project0
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/CHANGELOG.md7
-rw-r--r--src/tools/clippy/README.md39
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/backport.md1
-rw-r--r--src/tools/clippy/book/src/development/infrastructure/sync.md3
-rw-r--r--src/tools/clippy/book/src/lint_configuration.md20
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs9
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs78
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs93
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/mod.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs52
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/literal_representation.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs59
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_let_else.rs153
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs42
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_used.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs39
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/module_style.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_question_mark.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs65
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark_used.rs52
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs110
-rw-r--r--src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs399
-rw-r--r--src/tools/clippy/clippy_lints/src/std_instead_of_core.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs107
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/mod.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs61
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs13
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs9
-rw-r--r--src/tools/clippy/clippy_utils/src/numeric_literal.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs1
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs31
-rw-r--r--src/tools/clippy/lintcheck/src/config.rs2
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs12
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/src/driver.rs5
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.rs3
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.stderr4
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr18
-rw-r--r--src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs12
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs59
-rw-r--r--src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr52
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr1
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs6
-rw-r--r--src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr10
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs27
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr198
-rw-r--r--src/tools/clippy/tests/ui/box_default.fixed18
-rw-r--r--src/tools/clippy/tests/ui/box_default.rs18
-rw-r--r--src/tools/clippy/tests/ui/box_default.stderr14
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.fixed6
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.rs2
-rw-r--r--src/tools/clippy/tests/ui/bytes_nth.stderr10
-rw-r--r--src/tools/clippy/tests/ui/cast.stderr36
-rw-r--r--src/tools/clippy/tests/ui/cast_size.stderr18
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10044.rs3
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10044.stderr10
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs9
-rw-r--r--src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr15
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.rs4
-rw-r--r--src/tools/clippy/tests/ui/doc/doc-fixable.stderr24
-rw-r--r--src/tools/clippy/tests/ui/entry.fixed14
-rw-r--r--src/tools/clippy/tests/ui/entry.rs14
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.fixed14
-rw-r--r--src/tools/clippy/tests/ui/explicit_auto_deref.rs14
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.rs53
-rw-r--r--src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr42
-rw-r--r--src/tools/clippy/tests/ui/format.fixed6
-rw-r--r--src/tools/clippy/tests/ui/format.rs6
-rw-r--r--src/tools/clippy/tests/ui/format.stderr30
-rw-r--r--src/tools/clippy/tests/ui/impl_trait_in_params.rs17
-rw-r--r--src/tools/clippy/tests/ui/impl_trait_in_params.stderr25
-rw-r--r--src/tools/clippy/tests/ui/large_digit_groups.fixed4
-rw-r--r--src/tools/clippy/tests/ui/large_digit_groups.stderr20
-rw-r--r--src/tools/clippy/tests/ui/large_stack_arrays.rs1
-rw-r--r--src/tools/clippy/tests/ui/large_stack_arrays.stderr10
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.rs54
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_untyped.stderr51
-rw-r--r--src/tools/clippy/tests/ui/literals.stderr10
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else.rs11
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.rs29
-rw-r--r--src/tools/clippy/tests/ui/manual_let_else_match.stderr15
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/map_flatten_fixable.stderr18
-rw-r--r--src/tools/clippy/tests/ui/methods.rs1
-rw-r--r--src/tools/clippy/tests/ui/methods.stderr4
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.fixed2
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.fixed10
-rw-r--r--src/tools/clippy/tests/ui/needless_lifetimes.rs10
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed10
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs10
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr18
-rw-r--r--src/tools/clippy/tests/ui/never_loop.rs45
-rw-r--r--src/tools/clippy/tests/ui/never_loop.stderr15
-rw-r--r--src/tools/clippy/tests/ui/no_mangle_with_rust_abi.fixed48
-rw-r--r--src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs48
-rw-r--r--src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr45
-rw-r--r--src/tools/clippy/tests/ui/question_mark_used.rs15
-rw-r--r--src/tools/clippy/tests/ui/question_mark_used.stderr11
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.fixed84
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.rs80
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_tightening.stderr94
-rw-r--r--src/tools/clippy/tests/ui/suspicious_command_arg_space.rs10
-rw-r--r--src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr25
-rw-r--r--src/tools/clippy/tests/ui/swap.fixed24
-rw-r--r--src/tools/clippy/tests/ui/swap.rs29
-rw-r--r--src/tools/clippy/tests/ui/swap.stderr65
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs41
-rw-r--r--src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr64
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.fixed4
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.rs4
-rw-r--r--src/tools/clippy/tests/ui/unreadable_literal.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unreadable_literal.stderr10
-rw-r--r--src/tools/compiletest/src/runtest.rs13
-rw-r--r--src/tools/miri/src/machine.rs3
-rw-r--r--src/tools/rustdoc-js/tester.js14
-rw-r--r--src/version2
-rw-r--r--tests/codegen/array-equality.rs30
-rw-r--r--tests/codegen/consts.rs4
-rw-r--r--tests/codegen/option-as-slice.rs28
-rw-r--r--tests/codegen/remap_path_prefix/main.rs2
-rw-r--r--tests/codegen/slice-ref-equality.rs56
-rw-r--r--tests/codegen/thread-local.rs1
-rw-r--r--tests/debuginfo/captured-fields-1.rs3
-rw-r--r--tests/debuginfo/captured-fields-2.rs8
-rw-r--r--tests/mir-opt/basic_assignment.main.ElaborateDrops.diff85
-rw-r--r--tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir28
-rw-r--r--tests/mir-opt/basic_assignment.rs2
-rw-r--r--tests/mir-opt/issue_41110.test.ElaborateDrops.diff46
-rw-r--r--tests/mir-opt/issue_41888.main.ElaborateDrops.diff91
-rw-r--r--tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir18
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.closure.txt4
-rw-r--r--tests/rustdoc-gui/search-error.goml39
-rw-r--r--tests/rustdoc-js-std/option-type-signatures.js7
-rw-r--r--tests/rustdoc-js-std/parser-errors.js34
-rw-r--r--tests/rustdoc-js-std/parser-filter.js47
-rw-r--r--tests/rustdoc-js-std/parser-ident.js40
-rw-r--r--tests/rustdoc-js/macro-search.js10
-rw-r--r--tests/rustdoc-js/macro-search.rs10
-rw-r--r--tests/rustdoc-js/where-clause.js19
-rw-r--r--tests/rustdoc-js/where-clause.rs16
-rw-r--r--tests/rustdoc-ui/z-help.stdout1
-rw-r--r--tests/rustdoc/type-layout.rs8
-rw-r--r--tests/ui-toml/array_size_threshold/array_size_threshold.rs10
-rw-r--r--tests/ui-toml/array_size_threshold/array_size_threshold.stderr29
-rw-r--r--tests/ui-toml/array_size_threshold/clippy.toml1
-rw-r--r--tests/ui/abi/stack-probes-lto.rs1
-rw-r--r--tests/ui/abi/stack-probes.rs1
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs71
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr19
-rw-r--r--tests/ui/async-await/issues/issue-107280.rs15
-rw-r--r--tests/ui/async-await/issues/issue-107280.stderr82
-rw-r--r--tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr5
-rw-r--r--tests/ui/attributes/rustc-box.rs18
-rw-r--r--tests/ui/attributes/rustc-box.stderr34
-rw-r--r--tests/ui/borrowck/borrowck-vec-pattern-nesting.rs2
-rw-r--r--tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr18
-rw-r--r--tests/ui/borrowck/issue-45199.rs3
-rw-r--r--tests/ui/borrowck/issue-45199.stderr4
-rw-r--r--tests/ui/borrowck/issue-58776-borrowck-scans-children.rs1
-rw-r--r--tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr19
-rw-r--r--tests/ui/closures/2229_closure_analysis/issue_88118.rs5
-rw-r--r--tests/ui/command/command-setgroups.rs1
-rw-r--r--tests/ui/const-generics/issues/issue-105821.rs23
-rw-r--r--tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs74
-rw-r--r--tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr373
-rw-r--r--tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr4
-rw-r--r--tests/ui/extenv/extenv-not-defined-default.rs4
-rw-r--r--tests/ui/extenv/extenv-not-defined-default.stderr7
-rw-r--r--tests/ui/extenv/issue-55897.stderr3
-rw-r--r--tests/ui/for/for-else-err.rs8
-rw-r--r--tests/ui/for/for-else-err.stderr17
-rw-r--r--tests/ui/for/for-else-let-else-err.rs8
-rw-r--r--tests/ui/for/for-else-let-else-err.stderr17
-rw-r--r--tests/ui/impl-trait/hidden-lifetimes.stderr8
-rw-r--r--tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs11
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.stderr10
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr3
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr4
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr4
-rw-r--r--tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr14
-rw-r--r--tests/ui/impl-trait/nested-return-type4.stderr4
-rw-r--r--tests/ui/impl-trait/region-escape-via-bound.stderr4
-rw-r--r--tests/ui/impl-trait/static-return-lifetime-infered.stderr8
-rw-r--r--tests/ui/intrinsics/intrinsic-alignment.rs4
-rw-r--r--tests/ui/let-else/let-else-brace-before-else.fixed4
-rw-r--r--tests/ui/let-else/let-else-brace-before-else.rs4
-rw-r--r--tests/ui/let-else/let-else-brace-before-else.stderr17
-rw-r--r--tests/ui/lifetimes/issue-105227.stderr13
-rw-r--r--tests/ui/lifetimes/issue-107988.rs13
-rw-r--r--tests/ui/lifetimes/issue-107988.stderr27
-rw-r--r--tests/ui/lint/issue-104897.rs1
-rw-r--r--tests/ui/lint/issue-104897.stderr35
-rw-r--r--tests/ui/lint/unused_parens_multibyte_recovery.rs1
-rw-r--r--tests/ui/lint/unused_parens_multibyte_recovery.stderr35
-rw-r--r--tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs1
-rw-r--r--tests/ui/loops/loop-else-break-with-value.rs10
-rw-r--r--tests/ui/loops/loop-else-break-with-value.stderr18
-rw-r--r--tests/ui/loops/loop-else-err.rs8
-rw-r--r--tests/ui/loops/loop-else-err.stderr17
-rw-r--r--tests/ui/loops/loop-else-let-else-err.rs8
-rw-r--r--tests/ui/loops/loop-else-let-else-err.stderr17
-rw-r--r--tests/ui/macros/issue-102878.rs4
-rw-r--r--tests/ui/macros/issue-102878.stderr51
-rw-r--r--tests/ui/macros/macros-nonfatal-errors.stderr9
-rw-r--r--tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr22
-rw-r--r--tests/ui/methods/method-call-err-msg.stderr17
-rw-r--r--tests/ui/mir/validate/storage-live.rs30
-rw-r--r--tests/ui/mir/validate/storage-live.stderr13
-rw-r--r--tests/ui/nll/issue-73159-rpit-static.stderr1
-rw-r--r--tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr4
-rw-r--r--tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr12
-rw-r--r--tests/ui/nll/ty-outlives/impl-trait-captures.stderr4
-rw-r--r--tests/ui/numbers-arithmetic/issue-105626.rs17
-rw-r--r--tests/ui/parser/deli-ident-issue-1.rs2
-rw-r--r--tests/ui/parser/deli-ident-issue-1.stderr24
-rw-r--r--tests/ui/parser/deli-ident-issue-2.stderr16
-rw-r--r--tests/ui/parser/do-not-suggest-semicolon-before-array.rs2
-rw-r--r--tests/ui/parser/do-not-suggest-semicolon-before-array.stderr4
-rw-r--r--tests/ui/parser/issue-103451.rs1
-rw-r--r--tests/ui/parser/issue-103451.stderr24
-rw-r--r--tests/ui/parser/issue-107705.rs3
-rw-r--r--tests/ui/parser/issue-107705.stderr10
-rw-r--r--tests/ui/parser/issue-108495-dec.rs39
-rw-r--r--tests/ui/parser/issue-108495-dec.stderr69
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue-2.stderr16
-rw-r--r--tests/ui/parser/issue-68987-unmatch-issue-3.stderr16
-rw-r--r--tests/ui/parser/issue-81804.rs3
-rw-r--r--tests/ui/parser/issue-81804.stderr36
-rw-r--r--tests/ui/parser/issue-81827.rs1
-rw-r--r--tests/ui/parser/issue-81827.stderr32
-rw-r--r--tests/ui/parser/issues/issue-104367.rs6
-rw-r--r--tests/ui/parser/issues/issue-104367.stderr26
-rw-r--r--tests/ui/parser/issues/issue-105209.rs3
-rw-r--r--tests/ui/parser/issues/issue-105209.stderr22
-rw-r--r--tests/ui/parser/issues/issue-10636-2.rs4
-rw-r--r--tests/ui/parser/issues/issue-10636-2.stderr19
-rw-r--r--tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs3
-rw-r--r--tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr10
-rw-r--r--tests/ui/parser/issues/issue-58856-1.rs5
-rw-r--r--tests/ui/parser/issues/issue-58856-1.stderr29
-rw-r--r--tests/ui/parser/issues/issue-58856-2.rs5
-rw-r--r--tests/ui/parser/issues/issue-58856-2.stderr33
-rw-r--r--tests/ui/parser/issues/issue-60075.rs5
-rw-r--r--tests/ui/parser/issues/issue-60075.stderr20
-rw-r--r--tests/ui/parser/issues/issue-62524.rs2
-rw-r--r--tests/ui/parser/issues/issue-62524.stderr25
-rw-r--r--tests/ui/parser/issues/issue-62546.rs4
-rw-r--r--tests/ui/parser/issues/issue-62546.stderr15
-rw-r--r--tests/ui/parser/issues/issue-62554.rs1
-rw-r--r--tests/ui/parser/issues/issue-62554.stderr64
-rw-r--r--tests/ui/parser/issues/issue-62881.rs5
-rw-r--r--tests/ui/parser/issues/issue-62881.stderr24
-rw-r--r--tests/ui/parser/issues/issue-62894.rs1
-rw-r--r--tests/ui/parser/issues/issue-62894.stderr40
-rw-r--r--tests/ui/parser/issues/issue-62895.rs14
-rw-r--r--tests/ui/parser/issues/issue-62895.stderr51
-rw-r--r--tests/ui/parser/issues/issue-62973.rs2
-rw-r--r--tests/ui/parser/issues/issue-62973.stderr84
-rw-r--r--tests/ui/parser/issues/issue-63116.rs2
-rw-r--r--tests/ui/parser/issues/issue-63116.stderr24
-rw-r--r--tests/ui/parser/issues/issue-63135.rs4
-rw-r--r--tests/ui/parser/issues/issue-63135.stderr39
-rw-r--r--tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs4
-rw-r--r--tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr17
-rw-r--r--tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs14
-rw-r--r--tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr113
-rw-r--r--tests/ui/parser/issues/issue-68629.rsbin336 -> 129 bytes
-rw-r--r--tests/ui/parser/issues/issue-68629.stderrbin1637 -> 944 bytes
-rw-r--r--tests/ui/parser/issues/issue-84104.rs1
-rw-r--r--tests/ui/parser/issues/issue-84104.stderr10
-rw-r--r--tests/ui/parser/issues/issue-84148-2.rs1
-rw-r--r--tests/ui/parser/issues/issue-84148-2.stderr21
-rw-r--r--tests/ui/parser/issues/issue-88770.rs3
-rw-r--r--tests/ui/parser/issues/issue-88770.stderr50
-rw-r--r--tests/ui/parser/macro-mismatched-delim-paren-brace.stderr18
-rw-r--r--tests/ui/parser/match-arm-without-braces.stderr10
-rw-r--r--tests/ui/parser/mbe_missing_right_paren.rs2
-rw-r--r--tests/ui/parser/mbe_missing_right_paren.stderr23
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs6
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr25
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs2
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr11
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs3
-rw-r--r--tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr20
-rw-r--r--tests/ui/parser/missing_right_paren.rs3
-rw-r--r--tests/ui/parser/missing_right_paren.stderr25
-rw-r--r--tests/ui/parser/parser-recovery-1.rs3
-rw-r--r--tests/ui/parser/parser-recovery-1.stderr25
-rw-r--r--tests/ui/parser/parser-recovery-2.rs5
-rw-r--r--tests/ui/parser/parser-recovery-2.stderr21
-rw-r--r--tests/ui/parser/unclosed-delimiter-in-dep.rs1
-rw-r--r--tests/ui/parser/unclosed-delimiter-in-dep.stderr14
-rw-r--r--tests/ui/parser/use-unclosed-brace.rs2
-rw-r--r--tests/ui/parser/use-unclosed-brace.stderr20
-rw-r--r--tests/ui/process/process-sigpipe.rs1
-rw-r--r--tests/ui/resolve/issue-108529.rs8
-rw-r--r--tests/ui/resolve/issue-108529.stderr9
-rw-r--r--tests/ui/resolve/token-error-correct-2.rs1
-rw-r--r--tests/ui/resolve/token-error-correct-2.stderr10
-rw-r--r--tests/ui/resolve/token-error-correct-3.rs5
-rw-r--r--tests/ui/resolve/token-error-correct-3.stderr26
-rw-r--r--tests/ui/resolve/token-error-correct-4.fixed10
-rw-r--r--tests/ui/resolve/token-error-correct-4.rs5
-rw-r--r--tests/ui/resolve/token-error-correct-4.stderr18
-rw-r--r--tests/ui/resolve/token-error-correct.rs1
-rw-r--r--tests/ui/resolve/token-error-correct.stderr10
-rw-r--r--tests/ui/runtime/out-of-stack.rs1
-rw-r--r--tests/ui/runtime/signal-alternate-stack-cleanup.rs1
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.fixed10
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.rs10
-rw-r--r--tests/ui/rust-2018/remove-extern-crate.stderr22
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr5
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr5
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs12
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr93
-rw-r--r--tests/ui/structs-enums/rec-align-u64.rs4
-rw-r--r--tests/ui/suggestions/constrain-suggest-ice.rs10
-rw-r--r--tests/ui/suggestions/constrain-suggest-ice.stderr61
-rw-r--r--tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr8
-rw-r--r--tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr4
-rw-r--r--tests/ui/suggestions/multiline-multipart-suggestion.rs19
-rw-r--r--tests/ui/suggestions/multiline-multipart-suggestion.stderr46
-rw-r--r--tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs8
-rw-r--r--tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr9
-rw-r--r--tests/ui/thir-print/thir-flat.stdout21
-rw-r--r--tests/ui/thread-local/tls.rs1
-rw-r--r--tests/ui/tool-attributes/duplicate-diagnostic.rs2
-rw-r--r--tests/ui/tool-attributes/duplicate-diagnostic.stderr4
-rw-r--r--tests/ui/traits/issue-77982.stderr2
-rw-r--r--tests/ui/traits/new-solver/try-example.rs28
-rw-r--r--tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs11
-rw-r--r--tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr27
-rw-r--r--tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs7
-rw-r--r--tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr2
-rw-r--r--tests/ui/type/issue-91268.rs4
-rw-r--r--tests/ui/type/issue-91268.stderr55
-rw-r--r--tests/ui/typeck/bad-type-in-vec-contains.rs7
-rw-r--r--tests/ui/typeck/bad-type-in-vec-contains.stderr19
-rw-r--r--tests/ui/typeck/issue-31173.stderr13
-rw-r--r--tests/ui/typeck/issue-91334.rs3
-rw-r--r--tests/ui/typeck/issue-91334.stderr47
-rw-r--r--tests/ui/typeck/issue-92481.rs9
-rw-r--r--tests/ui/typeck/issue-92481.stderr61
-rw-r--r--tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs24
-rw-r--r--tests/ui/typeck/lazy-norm/equating-projection-cyclically.stderr14
-rw-r--r--tests/ui/wait-forked-but-failed-child.rs1
-rw-r--r--tests/ui/while/while-else-err.rs8
-rw-r--r--tests/ui/while/while-else-err.stderr17
-rw-r--r--tests/ui/while/while-else-let-else-err.rs8
-rw-r--r--tests/ui/while/while-else-let-else-err.stderr17
-rw-r--r--triagebot.toml2
761 files changed, 14359 insertions, 8627 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7c17dfd8c8e..44f789c592b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -322,7 +322,7 @@ jobs:
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
               DIST_REQUIRE_ALL_TOOLS: 1
-            os: macos-latest
+            os: macos-12-xl
           - name: dist-apple-various
             env:
               SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
@@ -333,7 +333,7 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
-            os: macos-latest
+            os: macos-12-xl
           - name: dist-x86_64-apple-alt
             env:
               SCRIPT: "./x.py dist bootstrap --include-default-paths"
@@ -344,7 +344,7 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
-            os: macos-latest
+            os: macos-12-xl
           - name: x86_64-apple-1
             env:
               SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps"
@@ -355,7 +355,7 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
-            os: macos-latest
+            os: macos-12-xl
           - name: x86_64-apple-2
             env:
               SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps"
@@ -366,7 +366,7 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
-            os: macos-latest
+            os: macos-12-xl
           - name: dist-aarch64-apple
             env:
               SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2"
@@ -381,7 +381,7 @@ jobs:
               NO_OVERFLOW_CHECKS: 1
               DIST_REQUIRE_ALL_TOOLS: 1
               JEMALLOC_SYS_WITH_LG_PAGE: 14
-            os: macos-latest
+            os: macos-12-xl
           - name: x86_64-msvc-1
             env:
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
diff --git a/.mailmap b/.mailmap
index 726d4c3d1d2..715bc4d3085 100644
--- a/.mailmap
+++ b/.mailmap
@@ -15,7 +15,7 @@ Adrien Tétar <adri-from-59@hotmail.fr>
 Ahmed Charles <ahmedcharles@gmail.com> <acharles@outlook.com>
 Alan Egerton <eggyal@gmail.com>
 Alan Stoate <alan.stoate@gmail.com>
-Albert Larsan <albert.larsan@gmail.com> Albert Larsan <74931857+albertlarsan68@users.noreply.github.com>
+Albert Larsan <albert.larsan@gmail.com> <74931857+albertlarsan68@users.noreply.github.com>
 Alessandro Decina <alessandro.d@gmail.com>
 Alex Burka <durka42+github@gmail.com> Alex Burka <aburka@seas.upenn.edu>
 Alex Hansen <ahansen2@trinity.edu>
diff --git a/Cargo.lock b/Cargo.lock
index f8268cbc46f..5530541cdd0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1373,9 +1373,9 @@ dependencies = [
 
 [[package]]
 name = "ena"
-version = "0.14.0"
+version = "0.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3"
+checksum = "b2e5d13ca2353ab7d0230988629def93914a8c4015f621f9b13ed2955614731d"
 dependencies = [
  "log",
 ]
@@ -1924,15 +1924,6 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "hermit-abi"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
@@ -2222,14 +2213,14 @@ dependencies = [
 
 [[package]]
 name = "is-terminal"
-version = "0.4.2"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
+checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
 dependencies = [
- "hermit-abi 0.2.6",
+ "hermit-abi 0.3.0",
  "io-lifetimes",
  "rustix",
- "windows-sys 0.42.0",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -2260,9 +2251,9 @@ dependencies = [
 
 [[package]]
 name = "jobserver"
-version = "0.1.24"
+version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
+checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
 dependencies = [
  "libc",
 ]
@@ -2328,9 +2319,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.138"
+version = "0.2.139"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
 dependencies = [
  "rustc-std-workspace-core",
 ]
@@ -3810,6 +3801,8 @@ dependencies = [
  "rustc_span",
  "rustc_symbol_mangling",
  "rustc_target",
+ "serde",
+ "serde_json",
  "smallvec",
  "tempfile",
  "tracing",
diff --git a/README.md b/README.md
index 0eb7c4b266a..c424bd12ffd 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
 # The Rust Programming Language
 
+[![Rust Community](https://img.shields.io/badge/Rust_Community%20-Join_us-brightgreen?style=plastic&logo=rust)](https://www.rust-lang.org/community)
+
 This is the main source code repository for [Rust]. It contains the compiler,
 standard library, and documentation.
 
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index aa3a666b0b2..39574ca558f 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1505,14 +1505,6 @@ pub struct PointeeInfo {
     pub safe: Option<PointerKind>,
 }
 
-/// Used in `might_permit_raw_init` to indicate the kind of initialisation
-/// that is checked to be valid
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum InitKind {
-    Zero,
-    UninitMitigated0x01Fill,
-}
-
 impl LayoutS {
     /// Returns `true` if the layout corresponds to an unsized type.
     pub fn is_unsized(&self) -> bool {
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 81efdaa44b3..3a0af04f9eb 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -225,7 +225,7 @@ impl AssocOp {
             AssignOp(_) | // `{ 42 } +=`
             As | // `{ 42 } as usize`
             // Equal | // `{ 42 } == { 42 }`    Accepting these here would regress incorrect
-            // NotEqual | // `{ 42 } != { 42 }  struct literals parser recovery.
+            // NotEqual | // `{ 42 } != { 42 }` struct literals parser recovery.
             Colon, // `{ 42 }: usize`
         )
     }
diff --git a/compiler/rustc_ast_lowering/locales/en-US.ftl b/compiler/rustc_ast_lowering/locales/en-US.ftl
index a2837deafde..3ccd84398ec 100644
--- a/compiler/rustc_ast_lowering/locales/en-US.ftl
+++ b/compiler/rustc_ast_lowering/locales/en-US.ftl
@@ -22,9 +22,6 @@ ast_lowering_misplaced_impl_trait =
 ast_lowering_misplaced_assoc_ty_binding =
     associated type bounds are only allowed in where clauses and function signatures, not in {$position}
 
-ast_lowering_rustc_box_attribute_error =
-    #[rustc_box] requires precisely one argument and no other attributes are allowed
-
 ast_lowering_underscore_expr_lhs_assign =
     in expressions, `_` can only be used on the left-hand side of an assignment
     .label = `_` not allowed here
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index def74c2adee..5e6b6050bc0 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -88,13 +88,6 @@ pub struct MisplacedAssocTyBinding<'a> {
 }
 
 #[derive(Diagnostic, Clone, Copy)]
-#[diag(ast_lowering_rustc_box_attribute_error)]
-pub struct RustcBoxAttributeError {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic, Clone, Copy)]
 #[diag(ast_lowering_underscore_expr_lhs_assign)]
 pub struct UnderscoreExprLhsAssign {
     #[primary_span]
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index d4fafe38638..ffb30b1b391 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -2,7 +2,7 @@ use super::errors::{
     AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
     BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignemnt,
     GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure,
-    RustcBoxAttributeError, UnderscoreExprLhsAssign,
+    UnderscoreExprLhsAssign,
 };
 use super::ResolverAstLoweringExt;
 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
@@ -83,15 +83,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 }
                 ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)),
                 ExprKind::Call(f, args) => {
-                    if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
-                        if let [inner] = &args[..] && e.attrs.len() == 1 {
-                            let kind = hir::ExprKind::Box(self.lower_expr(&inner));
-                            return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
-                        } else {
-                            let guar = self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
-                            hir::ExprKind::Err(guar)
-                        }
-                    } else if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
+                    if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) {
                         self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args)
                     } else {
                         let f = self.lower_expr(f);
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 7325bce6055..debe0acb04e 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -13,7 +13,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
 use rustc_hir::PredicateOrigin;
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_middle::ty::{DefIdTree, ResolverAstLowering, TyCtxt};
+use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::source_map::DesugaringKind;
 use rustc_span::symbol::{kw, sym, Ident};
@@ -1339,13 +1339,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 .map(|predicate| self.lower_where_predicate(predicate)),
         );
 
-        let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> =
-            self.lower_generic_params_mut(&generics.params).collect();
+        let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self
+            .lower_generic_params_mut(&generics.params, hir::GenericParamSource::Generics)
+            .collect();
 
         // Introduce extra lifetimes if late resolution tells us to.
         let extra_lifetimes = self.resolver.take_extra_lifetime_params(parent_node_id);
         params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
-            self.lifetime_res_to_generic_param(ident, node_id, res)
+            self.lifetime_res_to_generic_param(
+                ident,
+                node_id,
+                res,
+                hir::GenericParamSource::Generics,
+            )
         }));
 
         let has_where_clause_predicates = !generics.where_clause.predicates.is_empty();
@@ -1449,7 +1455,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 span,
             }) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
                 hir_id: self.next_id(),
-                bound_generic_params: self.lower_generic_params(bound_generic_params),
+                bound_generic_params: self
+                    .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder),
                 bounded_ty: self
                     .lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Bound)),
                 bounds: self.arena.alloc_from_iter(bounds.iter().map(|bound| {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 5d78d914b6d..b20157f2c7c 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -804,6 +804,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         ident: Ident,
         node_id: NodeId,
         res: LifetimeRes,
+        source: hir::GenericParamSource,
     ) -> Option<hir::GenericParam<'hir>> {
         let (name, kind) = match res {
             LifetimeRes::Param { .. } => {
@@ -837,6 +838,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             pure_wrt_drop: false,
             kind: hir::GenericParamKind::Lifetime { kind },
             colon_span: None,
+            source,
         })
     }
 
@@ -852,11 +854,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         binder: NodeId,
         generic_params: &[GenericParam],
     ) -> &'hir [hir::GenericParam<'hir>] {
-        let mut generic_params: Vec<_> = self.lower_generic_params_mut(generic_params).collect();
+        let mut generic_params: Vec<_> = self
+            .lower_generic_params_mut(generic_params, hir::GenericParamSource::Binder)
+            .collect();
         let extra_lifetimes = self.resolver.take_extra_lifetime_params(binder);
         debug!(?extra_lifetimes);
         generic_params.extend(extra_lifetimes.into_iter().filter_map(|(ident, node_id, res)| {
-            self.lifetime_res_to_generic_param(ident, node_id, res)
+            self.lifetime_res_to_generic_param(ident, node_id, res, hir::GenericParamSource::Binder)
         }));
         let generic_params = self.arena.alloc_from_iter(generic_params);
         debug!(?generic_params);
@@ -1375,8 +1379,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             span,
                         );
                         let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
-                        let (param, bounds, path) =
-                            self.lower_generic_and_bounds(*def_node_id, span, ident, bounds);
+                        let (param, bounds, path) = self.lower_universal_param_and_bounds(
+                            *def_node_id,
+                            span,
+                            ident,
+                            bounds,
+                        );
                         self.impl_trait_defs.push(param);
                         if let Some(bounds) = bounds {
                             self.impl_trait_bounds.push(bounds);
@@ -1530,6 +1538,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             pure_wrt_drop: false,
                             kind: hir::GenericParamKind::Lifetime { kind },
                             colon_span: None,
+                            source: hir::GenericParamSource::Generics,
                         }
                     },
                 ));
@@ -1598,7 +1607,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
     }
 
-    /// Given a `parent_def_id`, a list of `lifetimes_in_bounds and a `remapping` hash to be
+    /// Given a `parent_def_id`, a list of `lifetimes_in_bounds` and a `remapping` hash to be
     /// filled, this function creates new definitions for `Param` and `Fresh` lifetimes, inserts the
     /// new definition, adds it to the remapping with the definition of the given lifetime and
     /// returns a list of lifetimes to be lowered afterwards.
@@ -1987,6 +1996,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             pure_wrt_drop: false,
                             kind: hir::GenericParamKind::Lifetime { kind },
                             colon_span: None,
+                            source: hir::GenericParamSource::Generics,
                         }
                     },
                 ));
@@ -2152,16 +2162,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn lower_generic_params_mut<'s>(
         &'s mut self,
         params: &'s [GenericParam],
+        source: hir::GenericParamSource,
     ) -> impl Iterator<Item = hir::GenericParam<'hir>> + Captures<'a> + Captures<'s> {
-        params.iter().map(move |param| self.lower_generic_param(param))
+        params.iter().map(move |param| self.lower_generic_param(param, source))
     }
 
-    fn lower_generic_params(&mut self, params: &[GenericParam]) -> &'hir [hir::GenericParam<'hir>] {
-        self.arena.alloc_from_iter(self.lower_generic_params_mut(params))
+    fn lower_generic_params(
+        &mut self,
+        params: &[GenericParam],
+        source: hir::GenericParamSource,
+    ) -> &'hir [hir::GenericParam<'hir>] {
+        self.arena.alloc_from_iter(self.lower_generic_params_mut(params, source))
     }
 
     #[instrument(level = "trace", skip(self))]
-    fn lower_generic_param(&mut self, param: &GenericParam) -> hir::GenericParam<'hir> {
+    fn lower_generic_param(
+        &mut self,
+        param: &GenericParam,
+        source: hir::GenericParamSource,
+    ) -> hir::GenericParam<'hir> {
         let (name, kind) = self.lower_generic_param_kind(param);
 
         let hir_id = self.lower_node_id(param.id);
@@ -2174,6 +2193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             pure_wrt_drop: self.tcx.sess.contains_name(&param.attrs, sym::may_dangle),
             kind,
             colon_span: param.colon_span.map(|s| self.lower_span(s)),
+            source,
         }
     }
 
@@ -2266,7 +2286,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     #[instrument(level = "debug", skip(self), ret)]
-    fn lower_generic_and_bounds(
+    fn lower_universal_param_and_bounds(
         &mut self,
         node_id: NodeId,
         span: Span,
@@ -2286,6 +2306,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             span,
             kind: hir::GenericParamKind::Type { default: None, synthetic: true },
             colon_span: None,
+            source: hir::GenericParamSource::Generics,
         };
 
         let preds = self.lower_generic_bound_predicate(
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 1c561375626..539c822ea09 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -12,7 +12,7 @@ use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
 use rustc_ast::walk_list;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust::{self, State};
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_macros::Subdiagnostic;
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::{
@@ -192,7 +192,7 @@ impl<'a> AstValidator<'a> {
                 // We allow these:
                 //  - `Option<impl Trait>`
                 //  - `option::Option<impl Trait>`
-                //  - `option::Option<T>::Foo<impl Trait>
+                //  - `option::Option<T>::Foo<impl Trait>`
                 //
                 // But not these:
                 //  - `<impl Trait>::Foo`
@@ -643,7 +643,7 @@ fn validate_generic_param_order(
     span: Span,
 ) {
     let mut max_param: Option<ParamKindOrd> = None;
-    let mut out_of_order = FxHashMap::default();
+    let mut out_of_order = FxIndexMap::default();
     let mut param_idents = Vec::with_capacity(generics.len());
 
     for (idx, param) in generics.iter().enumerate() {
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 926b0da2ec6..96042ea3078 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -386,7 +386,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
             ).span_suggestion_verbose(
                 lhs.span.shrink_to_lo(),
                 "you might have meant to introduce a new binding",
-                "let ".to_string(),
+                "let ",
                 Applicability::MachineApplicable,
             ).emit();
         }
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index b9dcaee2373..6207a32b28d 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -4,7 +4,6 @@
 //!
 //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`.
 
-#![allow(rustc::potential_query_instability)]
 #![feature(box_patterns)]
 #![feature(if_let_guard)]
 #![feature(iter_is_partitioned)]
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 7a1066f6b58..a622a215a2e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -6,7 +6,7 @@ use rustc_errors::{
     struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
-use rustc_hir::def::Res;
+use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
 use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
 use rustc_infer::infer::TyCtxtInferExt;
@@ -236,10 +236,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             let ty = used_place.ty(self.body, self.infcx.tcx).ty;
             let needs_note = match ty.kind() {
                 ty::Closure(id, _) => {
-                    let tables = self.infcx.tcx.typeck(id.expect_local());
-                    let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(id.expect_local());
-
-                    tables.closure_kind_origins().get(hir_id).is_none()
+                    self.infcx.tcx.closure_kind_origin(id.expect_local()).is_none()
                 }
                 _ => true,
             };
@@ -1470,6 +1467,32 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
 
     /// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
     ///
+    /// Depending on the origin of the StorageDeadOrDrop, this may be
+    /// reported as either a drop or an illegal mutation of a borrowed value.
+    /// The latter is preferred when the this is a drop triggered by a
+    /// reassignment, as it's more user friendly to report a problem with the
+    /// explicit assignment than the implicit drop.
+    #[instrument(level = "debug", skip(self))]
+    pub(crate) fn report_storage_dead_or_drop_of_borrowed(
+        &mut self,
+        location: Location,
+        place_span: (Place<'tcx>, Span),
+        borrow: &BorrowData<'tcx>,
+    ) {
+        // It's sufficient to check the last desugaring as Replace is the last
+        // one to be applied.
+        if let Some(DesugaringKind::Replace) = place_span.1.desugaring_kind() {
+            self.report_illegal_mutation_of_borrowed(location, place_span, borrow)
+        } else {
+            self.report_borrowed_value_does_not_live_long_enough(
+                location,
+                borrow,
+                place_span,
+                Some(WriteKind::StorageDeadOrDrop),
+            )
+        }
+    }
+
     /// This means that some data referenced by `borrow` needs to live
     /// past the point where the StorageDeadOrDrop of `place` occurs.
     /// This is usually interpreted as meaning that `place` has too
@@ -1670,7 +1693,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 format!("`{}` would have to be valid for `{}`...", name, region_name),
             );
 
-            let fn_hir_id = self.mir_hir_id();
             err.span_label(
                 drop_span,
                 format!(
@@ -1678,19 +1700,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     name,
                     self.infcx
                         .tcx
-                        .hir()
-                        .opt_name(fn_hir_id)
+                        .opt_item_name(self.mir_def_id().to_def_id())
                         .map(|name| format!("function `{}`", name))
                         .unwrap_or_else(|| {
-                            match &self
-                                .infcx
-                                .tcx
-                                .typeck(self.mir_def_id())
-                                .node_type(fn_hir_id)
-                                .kind()
-                            {
-                                ty::Closure(..) => "enclosing closure",
-                                ty::Generator(..) => "enclosing generator",
+                            match &self.infcx.tcx.def_kind(self.mir_def_id()) {
+                                DefKind::Closure => "enclosing closure",
+                                DefKind::Generator => "enclosing generator",
                                 kind => bug!("expected closure or generator, found {:?}", kind),
                             }
                             .to_string()
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index f5bd99f15ab..af705e6a80f 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -13,7 +13,7 @@ use rustc_middle::mir::{
     Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
 };
 use rustc_middle::ty::print::Print;
-use rustc_middle::ty::{self, DefIdTree, Instance, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_mir_dataflow::move_paths::{InitLocation, LookupResult};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
@@ -115,11 +115,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
                     if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
                         let did = did.expect_local();
-                        let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
-
-                        if let Some((span, hir_place)) =
-                            self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
-                        {
+                        if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
                             diag.span_note(
                                 *span,
                                 &format!(
@@ -139,11 +135,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let Some(target) = target {
             if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
                 let did = did.expect_local();
-                let hir_id = self.infcx.tcx.hir().local_def_id_to_hir_id(did);
-
-                if let Some((span, hir_place)) =
-                    self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id)
-                {
+                if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
                     diag.span_note(
                         *span,
                         &format!(
@@ -373,14 +365,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     //
                     // We know the field exists so it's safe to call operator[] and `unwrap` here.
                     let def_id = def_id.expect_local();
-                    let var_id = self
-                        .infcx
-                        .tcx
-                        .typeck(def_id)
-                        .closure_min_captures_flattened(def_id)
-                        .nth(field.index())
-                        .unwrap()
-                        .get_root_variable();
+                    let var_id =
+                        self.infcx.tcx.closure_captures(def_id)[field.index()].get_root_variable();
 
                     Some(self.infcx.tcx.hir().name(var_id).to_string())
                 }
@@ -939,7 +925,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             return OtherUse(use_span);
         }
 
-        for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
+        // drop and replace might have moved the assignment to the next block
+        let maybe_additional_statement =
+            if let TerminatorKind::Drop { target: drop_target, .. } =
+                self.body[location.block].terminator().kind
+            {
+                self.body[drop_target].statements.first()
+            } else {
+                None
+            };
+
+        let statements =
+            self.body[location.block].statements[location.statement_index + 1..].iter();
+
+        for stmt in statements.chain(maybe_additional_statement) {
             if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
                 let (&def_id, is_generator) = match kind {
                     box AggregateKind::Closure(def_id, _) => (def_id, false),
@@ -987,7 +986,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr);
         if let hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }) = expr {
             for (captured_place, place) in
-                self.infcx.tcx.typeck(def_id).closure_min_captures_flattened(def_id).zip(places)
+                self.infcx.tcx.closure_captures(def_id).iter().zip(places)
             {
                 match place {
                     Operand::Copy(place) | Operand::Move(place)
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index ea58ad5ae3e..5e4c7292e59 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -467,7 +467,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 err.span_suggestion_verbose(
                     span.shrink_to_lo(),
                     "consider borrowing here",
-                    "&".to_string(),
+                    '&',
                     Applicability::MaybeIncorrect,
                 );
             }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 9f37b915b77..eded913ae96 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -385,7 +385,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     err.span_suggestion_verbose(
                         local_decl.source_info.span.shrink_to_lo(),
                         "consider changing this to be mutable",
-                        "mut ".to_string(),
+                        "mut ",
                         Applicability::MachineApplicable,
                     );
                     let tcx = self.infcx.tcx;
@@ -828,7 +828,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             let Some(hir::Node::Item(item)) = node else { return; };
             let hir::ItemKind::Fn(.., body_id) = item.kind else { return; };
             let body = self.infcx.tcx.hir().body(body_id);
-            let mut v = V { assign_span: span, err, ty, suggested: false };
+            let mut assign_span = span;
+            // Drop desugaring is done at MIR build so it's not in the HIR
+            if let Some(DesugaringKind::Replace) = span.desugaring_kind() {
+                assign_span.remove_mark();
+            }
+
+            let mut v = V { assign_span, err, ty, suggested: false };
             v.visit_body(body);
             if !v.suggested {
                 err.help(&format!(
@@ -901,10 +907,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         err: &mut Diagnostic,
     ) {
         let tables = tcx.typeck(closure_local_def_id);
-        let closure_hir_id = tcx.hir().local_def_id_to_hir_id(closure_local_def_id);
-        if let Some((span, closure_kind_origin)) =
-            &tables.closure_kind_origins().get(closure_hir_id)
-        {
+        if let Some((span, closure_kind_origin)) = tcx.closure_kind_origin(closure_local_def_id) {
             let reason = if let PlaceBase::Upvar(upvar_id) = closure_kind_origin.base {
                 let upvar = ty::place_to_string_for_capture(tcx, closure_kind_origin);
                 let root_hir_id = upvar_id.var_path.hir_id;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 4baf1b6aa87..ffe82b46cfd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -415,7 +415,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
     /// ```
     ///
-    /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`.
+    /// Here we would be invoked with `fr = 'a` and `outlived_fr = 'b`.
     pub(crate) fn report_region_error(
         &mut self,
         fr: RegionVid,
@@ -949,7 +949,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     .push_span_label(*span, "this has an implicit `'static` lifetime requirement");
                 multi_span.push_span_label(
                     ident.span,
-                    "calling this method introduces the `impl`'s 'static` requirement",
+                    "calling this method introduces the `impl`'s `'static` requirement",
                 );
                 err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span });
                 err.span_suggestion_verbose(
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index f6881a2e5bc..cc5a1f5ab12 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -6,7 +6,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_middle::ty::print::RegionHighlightMode;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, DefIdTree, RegionVid, Ty};
+use rustc_middle::ty::{self, RegionVid, Ty};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 18d7bde60d7..115e512a974 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -202,14 +202,14 @@ fn do_mir_borrowck<'tcx>(
     let mut errors = error::BorrowckErrors::new(infcx.tcx);
 
     // Gather the upvars of a closure, if any.
-    let tables = tcx.typeck_opt_const_arg(def);
-    if let Some(e) = tables.tainted_by_errors {
+    if let Some(e) = input_body.tainted_by_errors {
         infcx.set_tainted_by_errors(e);
         errors.set_tainted_by_errors(e);
     }
-    let upvars: Vec<_> = tables
-        .closure_min_captures_flattened(def.did)
-        .map(|captured_place| {
+    let upvars: Vec<_> = tcx
+        .closure_captures(def.did)
+        .iter()
+        .map(|&captured_place| {
             let capture = captured_place.info.capture_kind;
             let by_ref = match capture {
                 ty::UpvarCapture::ByValue => false,
@@ -1185,12 +1185,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             this.buffer_error(err);
                         }
                         WriteKind::StorageDeadOrDrop => this
-                            .report_borrowed_value_does_not_live_long_enough(
-                                location,
-                                borrow,
-                                place_span,
-                                Some(kind),
-                            ),
+                            .report_storage_dead_or_drop_of_borrowed(location, place_span, borrow),
                         WriteKind::Mutate => {
                             this.report_illegal_mutation_of_borrowed(location, place_span, borrow)
                         }
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 941da2dd3b5..21b5bd7cb94 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -889,7 +889,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// from a universe it can't name; at present, the only way for
     /// this to be true is if `scc` outlives `'static`. This is
     /// actually stricter than necessary: ideally, we'd support bounds
-    /// like `for<'a: 'b`>` that might then allow us to approximate
+    /// like `for<'a: 'b>` that might then allow us to approximate
     /// `'a` with `'b` and not `'static`. But it will have to do for
     /// now.
     fn add_incompatible_universe(&mut self, scc: ConstraintSccIndex) {
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index c361357ca21..8132800f107 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -235,7 +235,7 @@ pub(crate) struct RegionValues<N: Idx> {
     free_regions: SparseBitMatrix<N, RegionVid>,
 
     /// Placeholders represent bound regions -- so something like `'a`
-    /// in for<'a> fn(&'a u32)`.
+    /// in `for<'a> fn(&'a u32)`.
     placeholders: SparseBitMatrix<N, PlaceholderIndex>,
 }
 
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index c6b78df9a5f..717020ea5b8 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -26,11 +26,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         if !self.tcx().is_closure(mir_def_id.to_def_id()) {
             return;
         }
-        let Some(user_provided_poly_sig) =
-            self.tcx().typeck(mir_def_id).user_provided_sigs.get(&mir_def_id)
-        else {
-            return;
-        };
+        let user_provided_poly_sig = self.tcx().closure_user_provided_sig(mir_def_id);
 
         // Instantiate the canonicalized variables from user-provided signature
         // (e.g., the `_` in the code above) with fresh variables.
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index e058fe0db22..76d0b875424 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -18,13 +18,11 @@ use rustc_errors::Diagnostic;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::{BodyOwnerKind, HirId};
+use rustc_hir::BodyOwnerKind;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_infer::infer::NllRegionVariableOrigin;
 use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{
-    self, DefIdTree, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt,
-};
+use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_span::Symbol;
 use std::iter;
@@ -231,9 +229,7 @@ impl<'tcx> UniversalRegions<'tcx> {
         mir_def: ty::WithOptConstParam<LocalDefId>,
         param_env: ty::ParamEnv<'tcx>,
     ) -> Self {
-        let tcx = infcx.tcx;
-        let mir_hir_id = tcx.hir().local_def_id_to_hir_id(mir_def.did);
-        UniversalRegionsBuilder { infcx, mir_def, mir_hir_id, param_env }.build()
+        UniversalRegionsBuilder { infcx, mir_def, param_env }.build()
     }
 
     /// Given a reference to a closure type, extracts all the values
@@ -390,7 +386,6 @@ impl<'tcx> UniversalRegions<'tcx> {
 struct UniversalRegionsBuilder<'cx, 'tcx> {
     infcx: &'cx BorrowckInferCtxt<'cx, 'tcx>,
     mir_def: ty::WithOptConstParam<LocalDefId>,
-    mir_hir_id: HirId,
     param_env: ty::ParamEnv<'tcx>,
 }
 
@@ -560,12 +555,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
 
         match tcx.hir().body_owner_kind(self.mir_def.did) {
             BodyOwnerKind::Closure | BodyOwnerKind::Fn => {
-                let defining_ty = if self.mir_def.did.to_def_id() == typeck_root_def_id {
-                    tcx.type_of(typeck_root_def_id).subst_identity()
-                } else {
-                    let tables = tcx.typeck(self.mir_def.did);
-                    tables.node_type(self.mir_hir_id)
-                };
+                let defining_ty = tcx.type_of(self.mir_def.def_id_for_type_of()).subst_identity();
 
                 debug!("defining_ty (pre-replacement): {:?}", defining_ty);
 
@@ -594,7 +584,18 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                         self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs);
                     DefiningTy::Const(self.mir_def.did.to_def_id(), substs)
                 } else {
-                    let ty = tcx.typeck(self.mir_def.did).node_type(self.mir_hir_id);
+                    // FIXME this line creates a dependency between borrowck and typeck.
+                    //
+                    // This is required for `AscribeUserType` canonical query, which will call
+                    // `type_of(inline_const_def_id)`. That `type_of` would inject erased lifetimes
+                    // into borrowck, which is ICE #78174.
+                    //
+                    // As a workaround, inline consts have an additional generic param (`ty`
+                    // below), so that `type_of(inline_const_def_id).substs(substs)` uses the
+                    // proper type with NLL infer vars.
+                    let ty = tcx
+                        .typeck(self.mir_def.did)
+                        .node_type(tcx.local_def_id_to_hir_id(self.mir_def.did));
                     let substs = InlineConstSubsts::new(
                         tcx,
                         InlineConstSubstsParts { parent_substs: identity_substs, ty },
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index 6aa900f0201..f011cb754cb 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -53,7 +53,7 @@ pub fn expand_env<'cx>(
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'cx> {
     let mut exprs = match get_exprs_from_tts(cx, tts) {
-        Some(exprs) if exprs.is_empty() => {
+        Some(exprs) if exprs.is_empty() || exprs.len() > 2 => {
             cx.span_err(sp, "env! takes 1 or 2 arguments");
             return DummyResult::any(sp);
         }
@@ -64,28 +64,48 @@ pub fn expand_env<'cx>(
     let Some((var, _style)) = expr_to_string(cx, exprs.next().unwrap(), "expected string literal") else {
         return DummyResult::any(sp);
     };
-    let msg = match exprs.next() {
-        None => Symbol::intern(&format!("environment variable `{}` not defined", var)),
+
+    let custom_msg = match exprs.next() {
+        None => None,
         Some(second) => match expr_to_string(cx, second, "expected string literal") {
             None => return DummyResult::any(sp),
-            Some((s, _style)) => s,
+            Some((s, _style)) => Some(s),
         },
     };
 
-    if exprs.next().is_some() {
-        cx.span_err(sp, "env! takes 1 or 2 arguments");
-        return DummyResult::any(sp);
-    }
-
     let sp = cx.with_def_site_ctxt(sp);
     let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
     cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
     let e = match value {
         None => {
-            cx.span_err(sp, msg.as_str());
+            let (msg, help) = match custom_msg {
+                None => (
+                    format!("environment variable `{var}` not defined at compile time"),
+                    Some(help_for_missing_env_var(var.as_str())),
+                ),
+                Some(s) => (s.to_string(), None),
+            };
+            let mut diag = cx.struct_span_err(sp, &msg);
+            if let Some(help) = help {
+                diag.help(help);
+            }
+            diag.emit();
             return DummyResult::any(sp);
         }
         Some(value) => cx.expr_str(sp, value),
     };
     MacEager::expr(e)
 }
+
+fn help_for_missing_env_var(var: &str) -> String {
+    if var.starts_with("CARGO_")
+        || var.starts_with("DEP_")
+        || matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
+    {
+        format!(
+            "Cargo sets build script variables at run time. Use `std::env::var(\"{var}\")` instead"
+        )
+    } else {
+        format!("Use `std::env::var(\"{var}\")` to read the variable at run time")
+    }
+}
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 6feb3a7732e..e74aabf2fcb 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -21,7 +21,8 @@ mod simd;
 pub(crate) use cpuid::codegen_cpuid_call;
 pub(crate) use llvm::codegen_llvm_intrinsic_call;
 
-use rustc_middle::ty::layout::HasParamEnv;
+use rustc_middle::ty;
+use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_span::symbol::{kw, sym, Symbol};
@@ -627,54 +628,39 @@ fn codegen_regular_intrinsic_call<'tcx>(
             intrinsic_args!(fx, args => (); intrinsic);
 
             let ty = substs.type_at(0);
-            let layout = fx.layout_of(ty);
-            if layout.abi.is_uninhabited() {
-                with_no_trimmed_paths!({
-                    crate::base::codegen_panic_nounwind(
-                        fx,
-                        &format!("attempted to instantiate uninhabited type `{}`", layout.ty),
-                        source_info,
-                    )
-                });
-                return;
-            }
 
-            if intrinsic == sym::assert_zero_valid
-                && !fx
-                    .tcx
-                    .permits_zero_init(fx.param_env().and(ty))
-                    .expect("expected to have layout during codegen")
-            {
-                with_no_trimmed_paths!({
-                    crate::base::codegen_panic_nounwind(
-                        fx,
-                        &format!(
-                            "attempted to zero-initialize type `{}`, which is invalid",
-                            layout.ty
-                        ),
-                        source_info,
-                    );
-                });
-                return;
-            }
+            let requirement = ValidityRequirement::from_intrinsic(intrinsic);
 
-            if intrinsic == sym::assert_mem_uninitialized_valid
-                && !fx
+            if let Some(requirement) = requirement {
+                let do_panic = !fx
                     .tcx
-                    .permits_uninit_init(fx.param_env().and(ty))
-                    .expect("expected to have layout during codegen")
-            {
-                with_no_trimmed_paths!({
-                    crate::base::codegen_panic_nounwind(
-                        fx,
-                        &format!(
-                            "attempted to leave type `{}` uninitialized, which is invalid",
-                            layout.ty
-                        ),
-                        source_info,
-                    )
-                });
-                return;
+                    .check_validity_requirement((requirement, fx.param_env().and(ty)))
+                    .expect("expect to have layout during codegen");
+
+                if do_panic {
+                    let layout = fx.layout_of(ty);
+
+                    with_no_trimmed_paths!({
+                        crate::base::codegen_panic_nounwind(
+                            fx,
+                            &if layout.abi.is_uninhabited() {
+                                format!("attempted to instantiate uninhabited type `{}`", layout.ty)
+                            } else if requirement == ValidityRequirement::Zero {
+                                format!(
+                                    "attempted to zero-initialize type `{}`, which is invalid",
+                                    layout.ty
+                                )
+                            } else {
+                                format!(
+                                    "attempted to leave type `{}` uninitialized, which is invalid",
+                                    layout.ty
+                                )
+                            },
+                            source_info,
+                        )
+                    });
+                    return;
+                }
             }
         }
 
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 773c0ebbe59..a7ba2f8b695 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -36,3 +36,5 @@ smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 rustc_ast = { path = "../rustc_ast" }
 rustc_span = { path = "../rustc_span" }
 tempfile = "3.2.0"
+serde = { version = "1", features = [ "derive" ]}
+serde_json = "1"
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 40f0594b40d..a4ae1b01e86 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -761,6 +761,7 @@ pub(crate) unsafe fn codegen(
             EmitObj::None => {}
         }
 
+        record_llvm_cgu_instructions_stats(&cgcx.prof, llmod);
         drop(handlers);
     }
 
@@ -974,3 +975,23 @@ fn record_artifact_size(
         self_profiler_ref.artifact_size(artifact_kind, artifact_name.to_string_lossy(), file_size);
     }
 }
+
+fn record_llvm_cgu_instructions_stats(prof: &SelfProfilerRef, llmod: &llvm::Module) {
+    if !prof.enabled() {
+        return;
+    }
+
+    let raw_stats =
+        llvm::build_string(|s| unsafe { llvm::LLVMRustModuleInstructionStats(&llmod, s) })
+            .expect("cannot get module instruction stats");
+
+    #[derive(serde::Deserialize)]
+    struct InstructionsStats {
+        module: String,
+        total: u64,
+    }
+
+    let InstructionsStats { module, total } =
+        serde_json::from_str(&raw_stats).expect("cannot parse llvm cgu instructions stats");
+    prof.artifact_size("cgu_instructions", module, total);
+}
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index edb1c160626..b0a9a30ab46 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -10,6 +10,7 @@ use crate::value::Value;
 use rustc_ast::Mutability;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_hir::def_id::DefId;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
@@ -252,8 +253,13 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                             Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
                             _ => self.static_addr_of(init, alloc.align, None),
                         };
-                        if !self.sess().fewer_names() {
-                            llvm::set_value_name(value, format!("{:?}", alloc_id).as_bytes());
+                        if !self.sess().fewer_names() && llvm::get_value_name(value).is_empty() {
+                            let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
+                                let mut hasher = StableHasher::new();
+                                alloc.hash_stable(&mut hcx, &mut hasher);
+                                hasher.finish::<u128>()
+                            });
+                            llvm::set_value_name(value, format!("alloc_{hash:032x}").as_bytes());
                         }
                         (value, AddressSpace::DATA)
                     }
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
index 5cd0e1cb63a..6bcd3e5bf58 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
@@ -5,7 +5,7 @@ use super::CodegenUnitDebugContext;
 
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
-use rustc_middle::ty::{self, DefIdTree, Ty};
+use rustc_middle::ty::{self, Ty};
 use trace;
 
 use crate::common::CodegenCx;
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 7aab666fc5e..253c2ca7c76 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1814,8 +1814,6 @@ extern "C" {
     /// Creates a legacy pass manager -- only used for final codegen.
     pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>;
 
-    pub fn LLVMInitializePasses();
-
     pub fn LLVMTimeTraceProfilerInitialize();
 
     pub fn LLVMTimeTraceProfilerFinishThread();
@@ -2410,6 +2408,8 @@ extern "C" {
     pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize;
     pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer);
     pub fn LLVMRustModuleCost(M: &Module) -> u64;
+    #[allow(improper_ctypes)]
+    pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
 
     pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer;
     pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 20b1dd94153..ba58a2e68e9 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -120,8 +120,6 @@ unsafe fn configure_llvm(sess: &Session) {
         llvm::LLVMTimeTraceProfilerInitialize();
     }
 
-    llvm::LLVMInitializePasses();
-
     rustc_llvm::initialize_available_targets();
 
     llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 019ec0758d6..4ab56699922 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -306,7 +306,13 @@ pub fn create_compressed_metadata_file(
     symbol_name: &str,
 ) -> Vec<u8> {
     let mut compressed = rustc_metadata::METADATA_HEADER.to_vec();
+    // Our length will be backfilled once we're done writing
+    compressed.write_all(&[0; 4]).unwrap();
     FrameEncoder::new(&mut compressed).write_all(metadata.raw_data()).unwrap();
+    let meta_len = rustc_metadata::METADATA_HEADER.len();
+    let data_len = (compressed.len() - meta_len - 4) as u32;
+    compressed[meta_len..meta_len + 4].copy_from_slice(&data_len.to_be_bytes());
+
     let Some(mut file) = create_object_file(sess) else {
         return compressed.to_vec();
     };
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 067a3e167fe..fd81b1c6fe1 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -11,7 +11,7 @@ use rustc_middle::middle::exported_symbols::{
 use rustc_middle::ty::query::{ExternProviders, Providers};
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
 use rustc_middle::ty::Instance;
-use rustc_middle::ty::{self, DefIdTree, SymbolName, TyCtxt};
+use rustc_middle::ty::{self, SymbolName, TyCtxt};
 use rustc_session::config::{CrateType, OomStrategy};
 use rustc_target::spec::SanitizerSet;
 
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 7d5c0048626..c62968e5354 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -8,7 +8,7 @@ use rustc_hir::{lang_items, weak_lang_items::WEAK_LANG_ITEMS, LangItem};
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::mono::Linkage;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self as ty, DefIdTree, TyCtxt};
+use rustc_middle::ty::{self as ty, TyCtxt};
 use rustc_session::{lint, parse::feature_err};
 use rustc_span::{sym, Span};
 use rustc_target::spec::{abi, SanitizerSet};
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index f6c1b7a98aa..57a19a4ab1e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -14,7 +14,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_hir::lang_items::LangItem;
 use rustc_index::vec::Idx;
 use rustc_middle::mir::{self, AssertKind, SwitchTargets};
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
+use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
 use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
 use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt};
 use rustc_session::config::OptLevel;
@@ -655,41 +655,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // Emit a panic or a no-op for `assert_*` intrinsics.
         // These are intrinsics that compile to panics so that we can get a message
         // which mentions the offending type, even from a const context.
-        #[derive(Debug, PartialEq)]
-        enum AssertIntrinsic {
-            Inhabited,
-            ZeroValid,
-            MemUninitializedValid,
-        }
-        let panic_intrinsic = intrinsic.and_then(|i| match i {
-            sym::assert_inhabited => Some(AssertIntrinsic::Inhabited),
-            sym::assert_zero_valid => Some(AssertIntrinsic::ZeroValid),
-            sym::assert_mem_uninitialized_valid => Some(AssertIntrinsic::MemUninitializedValid),
-            _ => None,
-        });
-        if let Some(intrinsic) = panic_intrinsic {
-            use AssertIntrinsic::*;
-
+        let panic_intrinsic = intrinsic.and_then(|s| ValidityRequirement::from_intrinsic(s));
+        if let Some(requirement) = panic_intrinsic {
             let ty = instance.unwrap().substs.type_at(0);
+
+            let do_panic = !bx
+                .tcx()
+                .check_validity_requirement((requirement, bx.param_env().and(ty)))
+                .expect("expect to have layout during codegen");
+
             let layout = bx.layout_of(ty);
-            let do_panic = match intrinsic {
-                Inhabited => layout.abi.is_uninhabited(),
-                ZeroValid => !bx
-                    .tcx()
-                    .permits_zero_init(bx.param_env().and(ty))
-                    .expect("expected to have layout during codegen"),
-                MemUninitializedValid => !bx
-                    .tcx()
-                    .permits_uninit_init(bx.param_env().and(ty))
-                    .expect("expected to have layout during codegen"),
-            };
+
             Some(if do_panic {
                 let msg_str = with_no_visible_paths!({
                     with_no_trimmed_paths!({
                         if layout.abi.is_uninhabited() {
                             // Use this error even for the other intrinsics as it is more precise.
                             format!("attempted to instantiate uninhabited type `{}`", ty)
-                        } else if intrinsic == ZeroValid {
+                        } else if requirement == ValidityRequirement::Zero {
                             format!("attempted to zero-initialize type `{}`, which is invalid", ty)
                         } else {
                             format!(
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 0432a9c5a12..4301e4fe69b 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{DefIdTree, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::sym;
@@ -185,7 +185,7 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
     ("avx512vpopcntdq", Some(sym::avx512_target_feature)),
     ("bmi1", None),
     ("bmi2", None),
-    ("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
+    ("cmpxchg16b", None),
     ("ermsb", Some(sym::ermsb_target_feature)),
     ("f16c", None),
     ("fma", None),
@@ -394,7 +394,6 @@ pub fn from_target_feature(
                 Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
                 Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
                 Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
-                Some(sym::cmpxchg16b_target_feature) => rust_features.cmpxchg16b_target_feature,
                 Some(sym::movbe_target_feature) => rust_features.movbe_target_feature,
                 Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
                 Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index 9eaab1f47a7..04c90f28551 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -2,7 +2,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{DefIdTree, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::Symbol;
 
 /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index 6e47646caed..a29cdade023 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::{
     BinOp, NonDivergingIntrinsic,
 };
 use rustc_middle::ty;
-use rustc_middle::ty::layout::LayoutOf as _;
+use rustc_middle::ty::layout::{LayoutOf as _, ValidityRequirement};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
@@ -418,54 +418,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             | sym::assert_zero_valid
             | sym::assert_mem_uninitialized_valid => {
                 let ty = instance.substs.type_at(0);
-                let layout = self.layout_of(ty)?;
-
-                // For *all* intrinsics we first check `is_uninhabited` to give a more specific
-                // error message.
-                if layout.abi.is_uninhabited() {
-                    // The run-time intrinsic panics just to get a good backtrace; here we abort
-                    // since there is no problem showing a backtrace even for aborts.
-                    M::abort(
-                        self,
-                        format!(
+                let requirement = ValidityRequirement::from_intrinsic(intrinsic_name).unwrap();
+
+                let should_panic = !self
+                    .tcx
+                    .check_validity_requirement((requirement, self.param_env.and(ty)))
+                    .map_err(|_| err_inval!(TooGeneric))?;
+
+                if should_panic {
+                    let layout = self.layout_of(ty)?;
+
+                    let msg = match requirement {
+                        // For *all* intrinsics we first check `is_uninhabited` to give a more specific
+                        // error message.
+                        _ if layout.abi.is_uninhabited() => format!(
                             "aborted execution: attempted to instantiate uninhabited type `{}`",
                             ty
                         ),
-                    )?;
-                }
-
-                if intrinsic_name == sym::assert_zero_valid {
-                    let should_panic = !self
-                        .tcx
-                        .permits_zero_init(self.param_env.and(ty))
-                        .map_err(|_| err_inval!(TooGeneric))?;
-
-                    if should_panic {
-                        M::abort(
-                            self,
-                            format!(
-                                "aborted execution: attempted to zero-initialize type `{}`, which is invalid",
-                                ty
-                            ),
-                        )?;
-                    }
-                }
+                        ValidityRequirement::Inhabited => bug!("handled earlier"),
+                        ValidityRequirement::Zero => format!(
+                            "aborted execution: attempted to zero-initialize type `{}`, which is invalid",
+                            ty
+                        ),
+                        ValidityRequirement::UninitMitigated0x01Fill => format!(
+                            "aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
+                            ty
+                        ),
+                        ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"),
+                    };
 
-                if intrinsic_name == sym::assert_mem_uninitialized_valid {
-                    let should_panic = !self
-                        .tcx
-                        .permits_uninit_init(self.param_env.and(ty))
-                        .map_err(|_| err_inval!(TooGeneric))?;
-
-                    if should_panic {
-                        M::abort(
-                            self,
-                            format!(
-                                "aborted execution: attempted to leave type `{}` uninitialized, which is invalid",
-                                ty
-                            ),
-                        )?;
-                    }
+                    M::abort(self, msg)?;
                 }
             }
             sym::simd_insert => {
@@ -476,7 +458,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 assert_eq!(input_len, dest_len, "Return vector length must match input length");
                 assert!(
                     index < dest_len,
-                    "Index `{}` must be in bounds of vector with length {}`",
+                    "Index `{}` must be in bounds of vector with length {}",
                     index,
                     dest_len
                 );
@@ -496,7 +478,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let (input, input_len) = self.operand_to_simd(&args[0])?;
                 assert!(
                     index < input_len,
-                    "index `{}` must be in bounds of vector with length `{}`",
+                    "index `{}` must be in bounds of vector with length {}",
                     index,
                     input_len
                 );
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 450488315ef..92fa59aec6e 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -16,8 +16,8 @@ use rustc_target::spec::abi::Abi as CallAbi;
 use crate::const_eval::CheckAlignment;
 
 use super::{
-    AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
-    MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
+    AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx,
+    InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
 };
 
 /// Data returned by Machine::stack_pop,
@@ -105,10 +105,16 @@ pub trait Machine<'mir, 'tcx>: Sized {
     /// Extra data stored in every allocation.
     type AllocExtra: Debug + Clone + 'static;
 
+    /// Type for the bytes of the allocation.
+    type Bytes: AllocBytes + 'static;
+
     /// Memory's allocation map
     type MemoryMap: AllocMap<
             AllocId,
-            (MemoryKind<Self::MemoryKind>, Allocation<Self::Provenance, Self::AllocExtra>),
+            (
+                MemoryKind<Self::MemoryKind>,
+                Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>,
+            ),
         > + Default
         + Clone;
 
@@ -338,7 +344,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
         id: AllocId,
         alloc: Cow<'b, Allocation>,
         kind: Option<MemoryKind<Self::MemoryKind>>,
-    ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>>;
+    ) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>;
 
     fn eval_inline_asm(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
@@ -459,6 +465,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
 
     type AllocExtra = ();
     type FrameExtra = ();
+    type Bytes = Box<[u8]>;
 
     #[inline(always)]
     fn use_addr_for_alignment_check(_ecx: &InterpCx<$mir, $tcx, Self>) -> bool {
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index f4e03ad8c59..a3764a7d142 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -21,8 +21,9 @@ use rustc_target::abi::{Align, HasDataLayout, Size};
 use crate::const_eval::CheckAlignment;
 
 use super::{
-    alloc_range, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg, GlobalAlloc, InterpCx,
-    InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance, Scalar,
+    alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg,
+    GlobalAlloc, InterpCx, InterpResult, Machine, MayLeak, Pointer, PointerArithmetic, Provenance,
+    Scalar,
 };
 
 #[derive(Debug, PartialEq, Copy, Clone)]
@@ -114,16 +115,16 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
 /// A reference to some allocation that was already bounds-checked for the given region
 /// and had the on-access machine hooks run.
 #[derive(Copy, Clone)]
-pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra> {
-    alloc: &'a Allocation<Prov, Extra>,
+pub struct AllocRef<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
+    alloc: &'a Allocation<Prov, Extra, Bytes>,
     range: AllocRange,
     tcx: TyCtxt<'tcx>,
     alloc_id: AllocId,
 }
 /// A reference to some allocation that was already bounds-checked for the given region
 /// and had the on-access machine hooks run.
-pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra> {
-    alloc: &'a mut Allocation<Prov, Extra>,
+pub struct AllocRefMut<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes = Box<[u8]>> {
+    alloc: &'a mut Allocation<Prov, Extra, Bytes>,
     range: AllocRange,
     tcx: TyCtxt<'tcx>,
     alloc_id: AllocId,
@@ -483,7 +484,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         &self,
         id: AllocId,
         is_write: bool,
-    ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra>>> {
+    ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::Provenance, M::AllocExtra, M::Bytes>>> {
         let (alloc, def_id) = match self.tcx.try_get_global_alloc(id) {
             Some(GlobalAlloc::Memory(mem)) => {
                 // Memory of a constant or promoted or anonymous memory referenced by a static.
@@ -526,6 +527,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         )
     }
 
+    /// Get the base address for the bytes in an `Allocation` specified by the
+    /// `AllocID` passed in; error if no such allocation exists.
+    ///
+    /// It is up to the caller to take sufficient care when using this address:
+    /// there could be provenance or uninit memory in there, and other memory
+    /// accesses could invalidate the exposed pointer.
+    pub fn alloc_base_addr(&self, id: AllocId) -> InterpResult<'tcx, *const u8> {
+        let alloc = self.get_alloc_raw(id)?;
+        Ok(alloc.base_addr())
+    }
+
     /// Gives raw access to the `Allocation`, without bounds or alignment checks.
     /// The caller is responsible for calling the access hooks!
     ///
@@ -533,7 +545,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     fn get_alloc_raw(
         &self,
         id: AllocId,
-    ) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra>> {
+    ) -> InterpResult<'tcx, &Allocation<M::Provenance, M::AllocExtra, M::Bytes>> {
         // The error type of the inner closure here is somewhat funny. We have two
         // ways of "erroring": An actual error, or because we got a reference from
         // `get_global_alloc` that we can actually use directly without inserting anything anywhere.
@@ -569,7 +581,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         ptr: Pointer<Option<M::Provenance>>,
         size: Size,
         align: Align,
-    ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
+    ) -> InterpResult<'tcx, Option<AllocRef<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
+    {
         let ptr_and_alloc = self.check_and_deref_ptr(
             ptr,
             size,
@@ -612,7 +625,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     fn get_alloc_raw_mut(
         &mut self,
         id: AllocId,
-    ) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra>, &mut M)> {
+    ) -> InterpResult<'tcx, (&mut Allocation<M::Provenance, M::AllocExtra, M::Bytes>, &mut M)> {
         // We have "NLL problem case #3" here, which cannot be worked around without loss of
         // efficiency even for the common case where the key is in the map.
         // <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions>
@@ -641,7 +654,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         ptr: Pointer<Option<M::Provenance>>,
         size: Size,
         align: Align,
-    ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra>>> {
+    ) -> InterpResult<'tcx, Option<AllocRefMut<'a, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
+    {
         let parts = self.get_ptr_access(ptr, size, align)?;
         if let Some((alloc_id, offset, prov)) = parts {
             let tcx = *self.tcx;
@@ -840,11 +854,11 @@ pub struct DumpAllocs<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a, 'mir, 'tcx, M> {
     fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         // Cannot be a closure because it is generic in `Prov`, `Extra`.
-        fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra>(
+        fn write_allocation_track_relocs<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
             fmt: &mut std::fmt::Formatter<'_>,
             tcx: TyCtxt<'tcx>,
             allocs_to_print: &mut VecDeque<AllocId>,
-            alloc: &Allocation<Prov, Extra>,
+            alloc: &Allocation<Prov, Extra, Bytes>,
         ) -> std::fmt::Result {
             for alloc_id in alloc.provenance().provenances().filter_map(|prov| prov.get_alloc_id())
             {
@@ -912,7 +926,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
 }
 
 /// Reading and writing.
-impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> {
+impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes>
+    AllocRefMut<'a, 'tcx, Prov, Extra, Bytes>
+{
     /// `range` is relative to this allocation reference, not the base of the allocation.
     pub fn write_scalar(&mut self, range: AllocRange, val: Scalar<Prov>) -> InterpResult<'tcx> {
         let range = self.range.subrange(range);
@@ -937,7 +953,7 @@ impl<'tcx, 'a, Prov: Provenance, Extra> AllocRefMut<'a, 'tcx, Prov, Extra> {
     }
 }
 
-impl<'tcx, 'a, Prov: Provenance, Extra> AllocRef<'a, 'tcx, Prov, Extra> {
+impl<'tcx, 'a, Prov: Provenance, Extra, Bytes: AllocBytes> AllocRef<'a, 'tcx, Prov, Extra, Bytes> {
     /// `range` is relative to this allocation reference, not the base of the allocation.
     pub fn read_scalar(
         &self,
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index 244fa8030af..3c463500a60 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -353,7 +353,8 @@ where
     pub(super) fn get_place_alloc(
         &self,
         place: &MPlaceTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra>>> {
+    ) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
+    {
         assert!(place.layout.is_sized());
         assert!(!place.meta.has_meta());
         let size = place.layout.size;
@@ -364,7 +365,8 @@ where
     pub(super) fn get_place_alloc_mut(
         &mut self,
         place: &MPlaceTy<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra>>> {
+    ) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
+    {
         assert!(place.layout.is_sized());
         assert!(!place.meta.has_meta());
         let size = place.layout.size;
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index e76d4c1728e..f7881c50960 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -240,10 +240,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 // FIXME this should be more descriptive i.e. CapturePlace instead of CapturedVar
                 // https://github.com/rust-lang/project-rfc-2229/issues/46
                 if let Some(local_def_id) = def_id.as_local() {
-                    let tables = self.ecx.tcx.typeck(local_def_id);
-                    if let Some(captured_place) =
-                        tables.closure_min_captures_flattened(local_def_id).nth(field)
-                    {
+                    let captures = self.ecx.tcx.closure_captures(local_def_id);
+                    if let Some(captured_place) = captures.get(field) {
                         // Sometimes the index is beyond the number of upvars (seen
                         // for a generator).
                         let var_hir_id = captured_place.get_root_variable();
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index fc6d61c79c2..ed9efe568fb 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -38,7 +38,6 @@ use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_macros::fluent_messages;
 use rustc_middle::ty;
 use rustc_middle::ty::query::Providers;
-use rustc_target::abi::InitKind;
 
 fluent_messages! { "../locales/en-US.ftl" }
 
@@ -62,9 +61,7 @@ pub fn provide(providers: &mut Providers) {
         let (param_env, value) = param_env_and_value.into_parts();
         const_eval::deref_mir_constant(tcx, param_env, value)
     };
-    providers.permits_uninit_init = |tcx, param_env_and_ty| {
-        util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::UninitMitigated0x01Fill)
+    providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
+        util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
     };
-    providers.permits_zero_init =
-        |tcx, param_env_and_ty| util::might_permit_raw_init(tcx, param_env_and_ty, InitKind::Zero);
 }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index e4366f655e4..aa24d9053b9 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -332,7 +332,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> {
 
     fn check_static(&mut self, def_id: DefId, span: Span) {
         if self.tcx.is_thread_local_static(def_id) {
-            self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef");
+            self.tcx.sess.delay_span_bug(span, "tls access is checked in `Rvalue::ThreadLocalRef`");
         }
         self.check_op_spanned(ops::StaticAccess, span)
     }
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 3e416b89ca6..e586720a0d0 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -12,9 +12,7 @@ use rustc_infer::traits::{ImplSource, Obligation, ObligationCause};
 use rustc_middle::mir;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
-use rustc_middle::ty::{
-    suggest_constraining_type_param, Adt, Closure, DefIdTree, FnDef, FnPtr, Param, Ty,
-};
+use rustc_middle::ty::{suggest_constraining_type_param, Adt, Closure, FnDef, FnPtr, Param, Ty};
 use rustc_middle::ty::{Binder, TraitRef};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 068491646f4..fb37eb79a33 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -755,8 +755,26 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     self.fail(location, format!("explicit `{:?}` is forbidden", kind));
                 }
             }
-            StatementKind::StorageLive(..)
-            | StatementKind::StorageDead(..)
+            StatementKind::StorageLive(local) => {
+                // We check that the local is not live when entering a `StorageLive` for it.
+                // Technically, violating this restriction is only UB and not actually indicative
+                // of not well-formed MIR. This means that an optimization which turns MIR that
+                // already has UB into MIR that fails this check is not necessarily wrong. However,
+                // we have no such optimizations at the moment, and so we include this check anyway
+                // to help us catch bugs. If you happen to write an optimization that might cause
+                // this to incorrectly fire, feel free to remove this check.
+                if self.reachable_blocks.contains(location.block) {
+                    self.storage_liveness.seek_before_primary_effect(location);
+                    let locals_with_storage = self.storage_liveness.get();
+                    if locals_with_storage.contains(*local) {
+                        self.fail(
+                            location,
+                            format!("StorageLive({local:?}) which already has storage here"),
+                        );
+                    }
+                }
+            }
+            StatementKind::StorageDead(_)
             | StatementKind::Coverage(_)
             | StatementKind::ConstEvalCounter
             | StatementKind::Nop => {}
diff --git a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 2eba1e11466..23fcd22c52b 100644
--- a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -1,7 +1,7 @@
-use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout};
+use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement};
 use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_session::Limit;
-use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
+use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
 
 use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
 use crate::interpret::{InterpCx, MemoryKind, OpTy};
@@ -18,16 +18,23 @@ use crate::interpret::{InterpCx, MemoryKind, OpTy};
 /// Rust UB as long as there is no risk of miscompilations. The `strict_init_checks` can be set to
 /// do a full check against Rust UB instead (in which case we will also ignore the 0x01-filling and
 /// to the full uninit check).
-pub fn might_permit_raw_init<'tcx>(
+pub fn check_validity_requirement<'tcx>(
     tcx: TyCtxt<'tcx>,
+    kind: ValidityRequirement,
     param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
-    kind: InitKind,
 ) -> Result<bool, LayoutError<'tcx>> {
-    if tcx.sess.opts.unstable_opts.strict_init_checks {
-        might_permit_raw_init_strict(tcx.layout_of(param_env_and_ty)?, tcx, kind)
+    let layout = tcx.layout_of(param_env_and_ty)?;
+
+    // There is nothing strict or lax about inhabitedness.
+    if kind == ValidityRequirement::Inhabited {
+        return Ok(!layout.abi.is_uninhabited());
+    }
+
+    if kind == ValidityRequirement::Uninit || tcx.sess.opts.unstable_opts.strict_init_checks {
+        might_permit_raw_init_strict(layout, tcx, kind)
     } else {
         let layout_cx = LayoutCx { tcx, param_env: param_env_and_ty.param_env };
-        might_permit_raw_init_lax(tcx.layout_of(param_env_and_ty)?, &layout_cx, kind)
+        might_permit_raw_init_lax(layout, &layout_cx, kind)
     }
 }
 
@@ -36,7 +43,7 @@ pub fn might_permit_raw_init<'tcx>(
 fn might_permit_raw_init_strict<'tcx>(
     ty: TyAndLayout<'tcx>,
     tcx: TyCtxt<'tcx>,
-    kind: InitKind,
+    kind: ValidityRequirement,
 ) -> Result<bool, LayoutError<'tcx>> {
     let machine = CompileTimeInterpreter::new(
         Limit::new(0),
@@ -50,7 +57,7 @@ fn might_permit_raw_init_strict<'tcx>(
         .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
         .expect("OOM: failed to allocate for uninit check");
 
-    if kind == InitKind::Zero {
+    if kind == ValidityRequirement::Zero {
         cx.write_bytes_ptr(
             allocated.ptr,
             std::iter::repeat(0_u8).take(ty.layout.size().bytes_usize()),
@@ -72,15 +79,18 @@ fn might_permit_raw_init_strict<'tcx>(
 fn might_permit_raw_init_lax<'tcx>(
     this: TyAndLayout<'tcx>,
     cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
-    init_kind: InitKind,
+    init_kind: ValidityRequirement,
 ) -> Result<bool, LayoutError<'tcx>> {
     let scalar_allows_raw_init = move |s: Scalar| -> bool {
         match init_kind {
-            InitKind::Zero => {
+            ValidityRequirement::Inhabited => {
+                bug!("ValidityRequirement::Inhabited should have been handled above")
+            }
+            ValidityRequirement::Zero => {
                 // The range must contain 0.
                 s.valid_range(cx).contains(0)
             }
-            InitKind::UninitMitigated0x01Fill => {
+            ValidityRequirement::UninitMitigated0x01Fill => {
                 // The range must include an 0x01-filled buffer.
                 let mut val: u128 = 0x01;
                 for _ in 1..s.size(cx).bytes() {
@@ -89,6 +99,9 @@ fn might_permit_raw_init_lax<'tcx>(
                 }
                 s.valid_range(cx).contains(val)
             }
+            ValidityRequirement::Uninit => {
+                bug!("ValidityRequirement::Uninit should have been handled above")
+            }
         }
     };
 
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index 51735e33e0f..c0aabd77cee 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -1,14 +1,14 @@
 mod alignment;
 mod call_kind;
+mod check_validity_requirement;
 pub mod collect_writes;
 mod compare_types;
 mod find_self_call;
-mod might_permit_raw_init;
 mod type_name;
 
 pub use self::alignment::is_disaligned;
 pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
+pub use self::check_validity_requirement::check_validity_requirement;
 pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
 pub use self::find_self_call::find_self_call;
-pub use self::might_permit_raw_init::might_permit_raw_init;
 pub use self::type_name::type_name;
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index decbb6519ba..29cb2c0a33e 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -9,7 +9,7 @@ edition = "2021"
 arrayvec = { version = "0.7", default-features = false }
 bitflags = "1.2.1"
 cfg-if = "1.0"
-ena = "0.14"
+ena = "0.14.1"
 indexmap = { version = "1.9.1" }
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
 libc = "0.2"
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index 16f401f2057..91abdaadabd 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -426,6 +426,7 @@ impl<O: ForestObligation> ObligationForest<O> {
             // nodes. Therefore we use a `while` loop.
             let mut index = 0;
             while let Some(node) = self.nodes.get_mut(index) {
+                // This test is extremely hot.
                 if node.state.get() != NodeState::Pending
                     || !processor.needs_process_obligation(&node.obligation)
                 {
@@ -439,6 +440,7 @@ impl<O: ForestObligation> ObligationForest<O> {
                 // out of sync with `nodes`. It's not very common, but it does
                 // happen, and code in `compress` has to allow for it.
 
+                // This code is much less hot.
                 match processor.process_obligation(&mut node.obligation) {
                     ProcessResult::Unchanged => {
                         // No change in state.
diff --git a/compiler/rustc_data_structures/src/sorted_map/index_map.rs b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
index 814e7c7fb9b..7d23ff51948 100644
--- a/compiler/rustc_data_structures/src/sorted_map/index_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/index_map.rs
@@ -100,6 +100,11 @@ impl<I: Idx, K: Ord, V> SortedIndexMultiMap<I, K, V> {
             (k == &key).then_some((i, v))
         })
     }
+
+    #[inline]
+    pub fn contains_key(&self, key: K) -> bool {
+        self.get_by_key(key).next().is_some()
+    }
 }
 
 impl<I: Idx, K: Eq, V: Eq> Eq for SortedIndexMultiMap<I, K, V> {}
diff --git a/compiler/rustc_data_structures/src/sorted_map/tests.rs b/compiler/rustc_data_structures/src/sorted_map/tests.rs
index 3cc250862df..def7a7112fb 100644
--- a/compiler/rustc_data_structures/src/sorted_map/tests.rs
+++ b/compiler/rustc_data_structures/src/sorted_map/tests.rs
@@ -17,6 +17,10 @@ fn test_sorted_index_multi_map() {
     assert_eq!(set.get_by_key(3).copied().collect::<Vec<_>>(), vec![0]);
     assert!(set.get_by_key(4).next().is_none());
 
+    // `contains_key` works
+    assert!(set.contains_key(3));
+    assert!(!set.contains_key(4));
+
     // `get_by_key` returns items in insertion order.
     let twos: Vec<_> = set.get_by_key_enumerated(2).collect();
     let idxs: Vec<usize> = twos.iter().map(|(i, _)| *i).collect();
diff --git a/compiler/rustc_data_structures/src/stable_hasher/tests.rs b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
index b0d66c32a07..724be5888dd 100644
--- a/compiler/rustc_data_structures/src/stable_hasher/tests.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher/tests.rs
@@ -150,7 +150,7 @@ fn test_isize_compression() {
         let hash_b = hash(&(b as isize, a as isize));
         assert_ne!(
             hash_a, hash_b,
-            "The hash stayed the same when permuting values `{a}` and `{b}!",
+            "The hash stayed the same when permuting values `{a}` and `{b}`!",
         );
     }
 
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 211bbf4f50e..1b2e7b7e083 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1895,7 +1895,7 @@ impl EmitterWriter {
                         self.draw_code_line(
                             &mut buffer,
                             &mut row_num,
-                            &Vec::new(),
+                            &[],
                             p + line_start,
                             l,
                             show_code_change,
@@ -1919,7 +1919,7 @@ impl EmitterWriter {
                             self.draw_code_line(
                                 &mut buffer,
                                 &mut row_num,
-                                &Vec::new(),
+                                &[],
                                 p + line_start,
                                 l,
                                 show_code_change,
@@ -1936,7 +1936,7 @@ impl EmitterWriter {
                             self.draw_code_line(
                                 &mut buffer,
                                 &mut row_num,
-                                &Vec::new(),
+                                &[],
                                 p + line_start,
                                 l,
                                 show_code_change,
@@ -1951,7 +1951,7 @@ impl EmitterWriter {
                 self.draw_code_line(
                     &mut buffer,
                     &mut row_num,
-                    highlight_parts,
+                    &highlight_parts,
                     line_pos + line_start,
                     line,
                     show_code_change,
@@ -2176,7 +2176,7 @@ impl EmitterWriter {
         &self,
         buffer: &mut StyledBuffer,
         row_num: &mut usize,
-        highlight_parts: &Vec<SubstitutionHighlight>,
+        highlight_parts: &[SubstitutionHighlight],
         line_num: usize,
         line_to_add: &str,
         show_code_change: DisplaySuggestion,
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index cbf595089cc..99af872f07f 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -331,7 +331,7 @@ impl CodeSuggestion {
                     });
                     buf.push_str(&part.snippet);
                     let cur_hi = sm.lookup_char_pos(part.span.hi());
-                    if prev_hi.line == cur_lo.line && cur_hi.line == cur_lo.line {
+                    if cur_hi.line == cur_lo.line {
                         // Account for the difference between the width of the current code and the
                         // snippet being suggested, so that the *later* suggestions are correctly
                         // aligned on the screen.
diff --git a/compiler/rustc_expand/locales/en-US.ftl b/compiler/rustc_expand/locales/en-US.ftl
index b475d285f6b..cfae781bdee 100644
--- a/compiler/rustc_expand/locales/en-US.ftl
+++ b/compiler/rustc_expand/locales/en-US.ftl
@@ -133,3 +133,6 @@ expand_trace_macro = trace_macro
 expand_proc_macro_panicked =
     proc macro panicked
     .help = message: {$message}
+
+expand_proc_macro_derive_tokens =
+    proc-macro derive produced unparseable tokens
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 70ab222b484..e5102a952e7 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -390,3 +390,10 @@ pub(crate) struct ProcMacroPanicked {
 pub(crate) struct ProcMacroPanickedHelp {
     pub message: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(expand_proc_macro_derive_tokens)]
+pub struct ProcMacroDeriveTokens {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index b79835be73a..47a8b4bc488 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -282,7 +282,7 @@ pub(super) fn transcribe<'a>(
             }
 
             // There should be no meta-var declarations in the invocation of a macro.
-            mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"),
+            mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl`"),
         }
     }
 }
diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs
index cef64a10479..ddba1441719 100644
--- a/compiler/rustc_expand/src/proc_macro.rs
+++ b/compiler/rustc_expand/src/proc_macro.rs
@@ -176,7 +176,7 @@ impl MultiItemModifier for DeriveProcMacro {
 
         // fail if there have been errors emitted
         if ecx.sess.parse_sess.span_diagnostic.err_count() > error_count_before {
-            ecx.struct_span_err(span, "proc-macro derive produced unparseable tokens").emit();
+            ecx.sess.emit_err(errors::ProcMacroDeriveTokens { span });
         }
 
         ExpandResult::Ready(items)
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 14918d3c190..480d95b77e9 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -43,7 +43,6 @@ pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
         ps.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str),
         None,
     )
-    .0
 }
 
 /// Parses a string, returns a crate.
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index e064e87a59a..e7b2df34ccc 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -90,6 +90,8 @@ declare_features! (
     (accepted, clone_closures, "1.26.0", Some(44490), None),
     /// Allows coercing non capturing closures to function pointers.
     (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
+    /// Allows using `cmpxchg16b` from `core::arch::x86_64`.
+    (accepted, cmpxchg16b_target_feature, "CURRENT_RUSTC_VERSION", Some(44839), None),
     /// Allows usage of the `compile_error!` macro.
     (accepted, compile_error, "1.20.0", Some(40872), None),
     /// Allows `impl Trait` in function return types.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 6d8f7e4a0f6..a01914f969e 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -256,7 +256,6 @@ declare_features! (
     (active, arm_target_feature, "1.27.0", Some(44839), None),
     (active, avx512_target_feature, "1.27.0", Some(44839), None),
     (active, bpf_target_feature, "1.54.0", Some(44839), None),
-    (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None),
     (active, ermsb_target_feature, "1.49.0", Some(44839), None),
     (active, hexagon_target_feature, "1.27.0", Some(44839), None),
     (active, mips_target_feature, "1.27.0", Some(44839), None),
@@ -317,8 +316,6 @@ declare_features! (
     (active, c_unwind, "1.52.0", Some(74990), None),
     /// Allows using C-variadics.
     (active, c_variadic, "1.34.0", Some(44930), None),
-    /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
-    (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None),
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 79a12801de2..04d4f6cb14e 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -52,6 +52,8 @@ declare_features! (
     (removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")),
     (removed, await_macro, "1.38.0", Some(50547), None,
      Some("subsumed by `.await` syntax")),
+    /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
+    (removed, capture_disjoint_fields, "1.49.0", Some(53488), None, Some("stabilized in Rust 2021")),
     /// Allows comparing raw pointers during const eval.
     (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
      Some("cannot be allowed in const eval in any meaningful way")),
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 72e9f7c1343..19d3d41c984 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -498,6 +498,7 @@ pub struct GenericParam<'hir> {
     pub pure_wrt_drop: bool,
     pub kind: GenericParamKind<'hir>,
     pub colon_span: Option<Span>,
+    pub source: GenericParamSource,
 }
 
 impl<'hir> GenericParam<'hir> {
@@ -516,6 +517,20 @@ impl<'hir> GenericParam<'hir> {
     }
 }
 
+/// Records where the generic parameter originated from.
+///
+/// This can either be from an item's generics, in which case it's typically
+/// early-bound (but can be a late-bound lifetime in functions, for example),
+/// or from a `for<...>` binder, in which case it's late-bound (and notably,
+/// does not show up in the parent item's generics).
+#[derive(Debug, HashStable_Generic, PartialEq, Eq, Copy, Clone)]
+pub enum GenericParamSource {
+    // Early or late-bound parameters defined on an item
+    Generics,
+    // Late-bound parameters defined via a `for<...>`
+    Binder,
+}
+
 #[derive(Default)]
 pub struct GenericParamCount {
     pub lifetimes: usize,
diff --git a/compiler/rustc_hir_analysis/locales/en-US.ftl b/compiler/rustc_hir_analysis/locales/en-US.ftl
index 50b0816889b..1d313945b52 100644
--- a/compiler/rustc_hir_analysis/locales/en-US.ftl
+++ b/compiler/rustc_hir_analysis/locales/en-US.ftl
@@ -62,14 +62,6 @@ hir_analysis_manual_implementation =
 
 hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
 
-hir_analysis_unused_extern_crate =
-    unused extern crate
-    .suggestion = remove it
-
-hir_analysis_extern_crate_not_idiomatic =
-    `extern crate` is not idiomatic in the new edition
-    .suggestion = convert it to a `{$msg_code}`
-
 hir_analysis_trait_object_declared_with_no_traits =
     at least one trait is required for an object type
     .alias_span = this alias does not contain a trait
@@ -155,3 +147,11 @@ hir_analysis_main_function_generic_parameters = `main` function is not allowed t
 
 hir_analysis_variadic_function_compatible_convention = C-variadic function must have a compatible calling convention, like {$conventions}
     .label = C-variadic function must have a compatible calling convention
+
+hir_analysis_cannot_capture_late_bound_ty_in_anon_const =
+    cannot capture late-bound type parameter in a constant
+    .label = parameter defined here
+
+hir_analysis_cannot_capture_late_bound_const_in_anon_const =
+    cannot capture late-bound const parameter in a constant
+    .label = parameter defined here
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index a15cf454df7..899029d98e0 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -35,7 +35,7 @@ use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
 use rustc_middle::ty::DynKind;
 use rustc_middle::ty::GenericParamDefKind;
-use rustc_middle::ty::{self, Const, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
@@ -50,6 +50,7 @@ use rustc_trait_selection::traits::{self, astconv_object_safety_violations, Obli
 
 use smallvec::{smallvec, SmallVec};
 use std::collections::BTreeSet;
+use std::fmt::Display;
 use std::slice;
 
 #[derive(Debug)]
@@ -1095,11 +1096,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // those that do.
                 self.one_bound_for_assoc_type(
                     || traits::supertraits(tcx, trait_ref),
-                    || trait_ref.print_only_trait_path().to_string(),
+                    trait_ref.print_only_trait_path(),
                     binding.item_name,
                     path_span,
-                    || match binding.kind {
-                        ConvertedBindingKind::Equality(ty) => Some(ty.to_string()),
+                    match binding.kind {
+                        ConvertedBindingKind::Equality(term) => Some(term),
                         _ => None,
                     },
                 )?
@@ -1789,10 +1790,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     assoc_name,
                 )
             },
-            || param_name.to_string(),
+            param_name,
             assoc_name,
             span,
-            || None,
+            None,
         )
     }
 
@@ -1802,10 +1803,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     fn one_bound_for_assoc_type<I>(
         &self,
         all_candidates: impl Fn() -> I,
-        ty_param_name: impl Fn() -> String,
+        ty_param_name: impl Display,
         assoc_name: Ident,
         span: Span,
-        is_equality: impl Fn() -> Option<String>,
+        is_equality: Option<ty::Term<'tcx>>,
     ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed>
     where
         I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
@@ -1821,7 +1822,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             (None, None) => {
                 let reported = self.complain_about_assoc_type_not_found(
                     all_candidates,
-                    &ty_param_name(),
+                    &ty_param_name.to_string(),
                     assoc_name,
                     span,
                 );
@@ -1833,7 +1834,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         if let Some(bound2) = next_cand {
             debug!(?bound2);
 
-            let is_equality = is_equality();
             let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
             let mut err = if is_equality.is_some() {
                 // More specific Error Index entry.
@@ -1843,7 +1843,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     E0222,
                     "ambiguous associated type `{}` in bounds of `{}`",
                     assoc_name,
-                    ty_param_name()
+                    ty_param_name
                 )
             } else {
                 struct_span_err!(
@@ -1852,7 +1852,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     E0221,
                     "ambiguous associated type `{}` in bounds of `{}`",
                     assoc_name,
-                    ty_param_name()
+                    ty_param_name
                 )
             };
             err.span_label(span, format!("ambiguous associated type `{}`", assoc_name));
@@ -1886,18 +1886,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         err.span_suggestion_verbose(
                             span.with_hi(assoc_name.span.lo()),
                             "use fully qualified syntax to disambiguate",
-                            format!(
-                                "<{} as {}>::",
-                                ty_param_name(),
-                                bound.print_only_trait_path(),
-                            ),
+                            format!("<{} as {}>::", ty_param_name, bound.print_only_trait_path()),
                             Applicability::MaybeIncorrect,
                         );
                     }
                 } else {
                     err.note(&format!(
                         "associated type `{}` could derive from `{}`",
-                        ty_param_name(),
+                        ty_param_name,
                         bound.print_only_trait_path(),
                     ));
                 }
@@ -1906,7 +1902,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 err.help(&format!(
                     "consider introducing a new type parameter `T` and adding `where` constraints:\
                      \n    where\n        T: {},\n{}",
-                    ty_param_name(),
+                    ty_param_name,
                     where_bounds.join(",\n"),
                 ));
             }
@@ -2070,10 +2066,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
                 self.one_bound_for_assoc_type(
                     || traits::supertraits(tcx, ty::Binder::dummy(trait_ref.subst_identity())),
-                    || "Self".to_string(),
+                    kw::SelfUpper,
                     assoc_ident,
                     span,
-                    || None,
+                    None,
                 )?
             }
             (
@@ -2403,8 +2399,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 infcx
                                     .can_eq(
                                         ty::ParamEnv::empty(),
-                                        tcx.erase_regions(impl_.self_ty()),
-                                        tcx.erase_regions(qself_ty),
+                                        impl_.self_ty(),
+                                        // Must fold past escaping bound vars too,
+                                        // since we have those at this point in astconv.
+                                        tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased),
                                     )
                             })
                             && tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 4ea471f8f05..9693a59defb 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -22,8 +22,7 @@ use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::{
-    self, AdtDef, DefIdTree, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
-    TypeVisitableExt,
+    self, AdtDef, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
@@ -792,8 +791,10 @@ fn check_impl_items_against_trait<'tcx>(
             trait_def.must_implement_one_of.as_deref();
 
         for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) {
-            let is_implemented = ancestors
-                .leaf_def(tcx, trait_item_id)
+            let leaf_def = ancestors.leaf_def(tcx, trait_item_id);
+
+            let is_implemented = leaf_def
+                .as_ref()
                 .map_or(false, |node_item| node_item.item.defaultness(tcx).has_value());
 
             if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
@@ -801,8 +802,8 @@ fn check_impl_items_against_trait<'tcx>(
             }
 
             // true if this item is specifically implemented in this impl
-            let is_implemented_here = ancestors
-                .leaf_def(tcx, trait_item_id)
+            let is_implemented_here = leaf_def
+                .as_ref()
                 .map_or(false, |node_item| !node_item.defining_node.is_from_trait());
 
             if !is_implemented_here {
@@ -831,6 +832,36 @@ fn check_impl_items_against_trait<'tcx>(
                     }
                 }
             }
+
+            if let Some(leaf_def) = &leaf_def
+                && !leaf_def.is_final()
+                && let def_id = leaf_def.item.def_id
+                && tcx.impl_method_has_trait_impl_trait_tys(def_id)
+            {
+                let def_kind = tcx.def_kind(def_id);
+                let descr = tcx.def_kind_descr(def_kind, def_id);
+                let (msg, feature) = if tcx.asyncness(def_id).is_async() {
+                    (
+                        format!("async {descr} in trait cannot be specialized"),
+                        sym::async_fn_in_trait,
+                    )
+                } else {
+                    (
+                        format!(
+                            "{descr} with return-position `impl Trait` in trait cannot be specialized"
+                        ),
+                        sym::return_position_impl_trait_in_trait,
+                    )
+                };
+                tcx.sess
+                    .struct_span_err(tcx.def_span(def_id), msg)
+                    .note(format!(
+                        "specialization behaves in inconsistent and \
+                        surprising ways with `#![feature({feature})]`, \
+                        and for now is disallowed"
+                    ))
+                    .emit();
+            }
         }
 
         if !missing_items.is_empty() {
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 89b4e6227bd..5adc7a87323 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -16,8 +16,7 @@ use rustc_infer::traits::util;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::util::ExplicitSelf;
 use rustc_middle::ty::{
-    self, DefIdTree, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable,
-    TypeVisitableExt,
+    self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
 use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
 use rustc_span::Span;
@@ -648,6 +647,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
             tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
         )
         .fold_with(&mut collector);
+
+    debug_assert_ne!(
+        collector.types.len(),
+        0,
+        "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`"
+    );
+
     let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig);
     trait_sig.error_reported()?;
     let trait_return_ty = trait_sig.output();
@@ -1866,7 +1872,7 @@ pub(super) fn check_type_bounds<'tcx>(
     //     type Bar<C> =...
     // }
     //
-    // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>
+    // - `impl_trait_ref` would be `<(A, B) as Foo<u32>>`
     // - `impl_ty_substs` would be `[A, B, ^0.0]` (`^0.0` here is the bound var with db 0 and index 0)
     // - `rebased_substs` would be `[(A, B), u32, ^0.0]`, combining the substs from
     //    the *trait* with the generic associated type parameters (as bound vars).
diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index 5716be4f1a9..f3f5851d8f9 100644
--- a/compiler/rustc_hir_analysis/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -1,12 +1,8 @@
-use crate::errors::{ExternCrateNotIdiomatic, UnusedExternCrate};
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::unord::UnordSet;
-use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint;
-use rustc_span::{Span, Symbol};
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
     let mut used_trait_imports: UnordSet<LocalDefId> = Default::default();
@@ -43,131 +39,4 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
             |lint| lint,
         );
     }
-
-    unused_crates_lint(tcx);
-}
-
-fn unused_crates_lint(tcx: TyCtxt<'_>) {
-    let lint = lint::builtin::UNUSED_EXTERN_CRATES;
-
-    // Collect first the crates that are completely unused. These we
-    // can always suggest removing (no matter which edition we are
-    // in).
-    let unused_extern_crates: FxHashMap<LocalDefId, Span> = tcx
-        .maybe_unused_extern_crates(())
-        .iter()
-        .filter(|&&(def_id, _)| {
-            tcx.extern_mod_stmt_cnum(def_id).map_or(true, |cnum| {
-                !tcx.is_compiler_builtins(cnum)
-                    && !tcx.is_panic_runtime(cnum)
-                    && !tcx.has_global_allocator(cnum)
-                    && !tcx.has_panic_handler(cnum)
-            })
-        })
-        .cloned()
-        .collect();
-
-    // Collect all the extern crates (in a reliable order).
-    let mut crates_to_lint = vec![];
-
-    for id in tcx.hir().items() {
-        if matches!(tcx.def_kind(id.owner_id), DefKind::ExternCrate) {
-            let item = tcx.hir().item(id);
-            if let hir::ItemKind::ExternCrate(orig_name) = item.kind {
-                crates_to_lint.push(ExternCrateToLint {
-                    def_id: item.owner_id.to_def_id(),
-                    span: item.span,
-                    orig_name,
-                    warn_if_unused: !item.ident.as_str().starts_with('_'),
-                });
-            }
-        }
-    }
-
-    let extern_prelude = &tcx.resolutions(()).extern_prelude;
-
-    for extern_crate in &crates_to_lint {
-        let def_id = extern_crate.def_id.expect_local();
-        let item = tcx.hir().expect_item(def_id);
-
-        // If the crate is fully unused, we suggest removing it altogether.
-        // We do this in any edition.
-        if extern_crate.warn_if_unused {
-            if let Some(&span) = unused_extern_crates.get(&def_id) {
-                // Removal suggestion span needs to include attributes (Issue #54400)
-                let id = tcx.hir().local_def_id_to_hir_id(def_id);
-                let span_with_attrs = tcx
-                    .hir()
-                    .attrs(id)
-                    .iter()
-                    .map(|attr| attr.span)
-                    .fold(span, |acc, attr_span| acc.to(attr_span));
-
-                tcx.emit_spanned_lint(lint, id, span, UnusedExternCrate { span: span_with_attrs });
-                continue;
-            }
-        }
-
-        // If we are not in Rust 2018 edition, then we don't make any further
-        // suggestions.
-        if !tcx.sess.rust_2018() {
-            continue;
-        }
-
-        // If the extern crate isn't in the extern prelude,
-        // there is no way it can be written as a `use`.
-        let orig_name = extern_crate.orig_name.unwrap_or(item.ident.name);
-        if !extern_prelude.get(&orig_name).map_or(false, |from_item| !from_item) {
-            continue;
-        }
-
-        // If the extern crate is renamed, then we cannot suggest replacing it with a use as this
-        // would not insert the new name into the prelude, where other imports in the crate may be
-        // expecting it.
-        if extern_crate.orig_name.is_some() {
-            continue;
-        }
-
-        let id = tcx.hir().local_def_id_to_hir_id(def_id);
-        // If the extern crate has any attributes, they may have funky
-        // semantics we can't faithfully represent using `use` (most
-        // notably `#[macro_use]`). Ignore it.
-        if !tcx.hir().attrs(id).is_empty() {
-            continue;
-        }
-
-        let base_replacement = match extern_crate.orig_name {
-            Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name),
-            None => format!("use {};", item.ident.name),
-        };
-        let vis = tcx.sess.source_map().span_to_snippet(item.vis_span).unwrap_or_default();
-        let add_vis = |to| if vis.is_empty() { to } else { format!("{} {}", vis, to) };
-        tcx.emit_spanned_lint(
-            lint,
-            id,
-            extern_crate.span,
-            ExternCrateNotIdiomatic {
-                span: extern_crate.span,
-                msg_code: add_vis("use".to_string()),
-                suggestion_code: add_vis(base_replacement),
-            },
-        );
-    }
-}
-
-struct ExternCrateToLint {
-    /// `DefId` of the extern crate
-    def_id: DefId,
-
-    /// span from the item
-    span: Span,
-
-    /// if `Some`, then this is renamed (`extern crate orig_name as
-    /// crate_name`), and -- perhaps surprisingly -- this stores the
-    /// *original* name (`item.name` will contain the new name)
-    orig_name: Option<Symbol>,
-
-    /// if `false`, the original name started with `_`, so we shouldn't lint
-    /// about it going unused (but we should still emit idiom lints).
-    warn_if_unused: bool,
 }
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 875c5f1fd00..ffb68abf978 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -437,7 +437,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn
             }
 
             // Here we are considering a case of converting
-            // `S<P0...Pn>` to S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
+            // `S<P0...Pn>` to `S<Q0...Qn>`. As an example, let's imagine a struct `Foo<T, U>`,
             // which acts like a pointer to `U`, but carries along some extra data of type `T`:
             //
             //     struct Foo<T, U> {
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 9cf3ff65a91..6f6f993f727 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -3,7 +3,7 @@ use crate::astconv::AstConv;
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, DefIdTree, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 
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 6c00b8ff7bd..e9963e67741 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -17,13 +17,15 @@ use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeNa
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::*;
-use rustc_middle::ty::{self, DefIdTree, TyCtxt, TypeSuperVisitable, TypeVisitor};
+use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
 use rustc_session::lint;
 use rustc_span::def_id::DefId;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use std::fmt;
 
+use crate::errors;
+
 trait RegionExt {
     fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg);
 
@@ -161,6 +163,15 @@ enum Scope<'a> {
         s: ScopeRef<'a>,
     },
 
+    /// Disallows capturing non-lifetime binders from parent scopes.
+    ///
+    /// This is necessary for something like `for<T> [(); { /* references T */ }]:`,
+    /// since we don't do something more correct like replacing any captured
+    /// late-bound vars with early-bound params in the const's own generics.
+    AnonConstBoundary {
+        s: ScopeRef<'a>,
+    },
+
     Root {
         opt_parent_item: Option<LocalDefId>,
     },
@@ -211,6 +222,7 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> {
                 .field("s", &"..")
                 .finish(),
             Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(),
+            Scope::AnonConstBoundary { s: _ } => f.debug_struct("AnonConstBoundary").finish(),
             Scope::Root { opt_parent_item } => {
                 f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish()
             }
@@ -312,7 +324,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     break (vec![], BinderScopeType::Normal);
                 }
 
-                Scope::Elision { s, .. } | Scope::ObjectLifetimeDefault { s, .. } => {
+                Scope::Elision { s, .. }
+                | Scope::ObjectLifetimeDefault { s, .. }
+                | Scope::AnonConstBoundary { s } => {
                     scope = s;
                 }
 
@@ -1029,50 +1043,64 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
     fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) {
         self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow);
     }
+
+    fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+        self.with(Scope::AnonConstBoundary { s: self.scope }, |this| {
+            intravisit::walk_anon_const(this, c);
+        });
+    }
 }
 
 fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: DefId) -> ObjectLifetimeDefault {
     debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam);
     let param_def_id = param_def_id.expect_local();
-    let parent_def_id = tcx.local_parent(param_def_id);
-    let generics = tcx.hir().get_generics(parent_def_id).unwrap();
-    let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
-    let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
-
-    // Scan the bounds and where-clauses on parameters to extract bounds
-    // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
-    // for each type parameter.
-    match param.kind {
-        GenericParamKind::Type { .. } => {
-            let mut set = Set1::Empty;
-
-            // Look for `type: ...` where clauses.
-            for bound in generics.bounds_for_param(param_def_id) {
-                // Ignore `for<'a> type: ...` as they can change what
-                // lifetimes mean (although we could "just" handle it).
-                if !bound.bound_generic_params.is_empty() {
-                    continue;
-                }
+    let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(param_def_id) else {
+        bug!("expected GenericParam for object_lifetime_default");
+    };
+    match param.source {
+        hir::GenericParamSource::Generics => {
+            let parent_def_id = tcx.local_parent(param_def_id);
+            let generics = tcx.hir().get_generics(parent_def_id).unwrap();
+            let param_hir_id = tcx.local_def_id_to_hir_id(param_def_id);
+            let param = generics.params.iter().find(|p| p.hir_id == param_hir_id).unwrap();
+
+            // Scan the bounds and where-clauses on parameters to extract bounds
+            // of the form `T:'a` so as to determine the `ObjectLifetimeDefault`
+            // for each type parameter.
+            match param.kind {
+                GenericParamKind::Type { .. } => {
+                    let mut set = Set1::Empty;
+
+                    // Look for `type: ...` where clauses.
+                    for bound in generics.bounds_for_param(param_def_id) {
+                        // Ignore `for<'a> type: ...` as they can change what
+                        // lifetimes mean (although we could "just" handle it).
+                        if !bound.bound_generic_params.is_empty() {
+                            continue;
+                        }
 
-                for bound in bound.bounds {
-                    if let hir::GenericBound::Outlives(lifetime) = bound {
-                        set.insert(lifetime.res);
+                        for bound in bound.bounds {
+                            if let hir::GenericBound::Outlives(lifetime) = bound {
+                                set.insert(lifetime.res);
+                            }
+                        }
                     }
-                }
-            }
 
-            match set {
-                Set1::Empty => ObjectLifetimeDefault::Empty,
-                Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
-                Set1::One(hir::LifetimeName::Param(param_def_id)) => {
-                    ObjectLifetimeDefault::Param(param_def_id.to_def_id())
+                    match set {
+                        Set1::Empty => ObjectLifetimeDefault::Empty,
+                        Set1::One(hir::LifetimeName::Static) => ObjectLifetimeDefault::Static,
+                        Set1::One(hir::LifetimeName::Param(param_def_id)) => {
+                            ObjectLifetimeDefault::Param(param_def_id.to_def_id())
+                        }
+                        _ => ObjectLifetimeDefault::Ambiguous,
+                    }
+                }
+                _ => {
+                    bug!("object_lifetime_default_raw must only be called on a type parameter")
                 }
-                _ => ObjectLifetimeDefault::Ambiguous,
             }
         }
-        _ => {
-            bug!("object_lifetime_default_raw must only be called on a type parameter")
-        }
+        hir::GenericParamSource::Binder => ObjectLifetimeDefault::Empty,
     }
 }
 
@@ -1267,7 +1295,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 Scope::Elision { s, .. }
                 | Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
-                | Scope::TraitRefBoundary { s, .. } => {
+                | Scope::TraitRefBoundary { s, .. }
+                | Scope::AnonConstBoundary { s } => {
                     scope = s;
                 }
             }
@@ -1332,7 +1361,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 | Scope::Elision { s, .. }
                 | Scope::ObjectLifetimeDefault { s, .. }
                 | Scope::Supertrait { s, .. }
-                | Scope::TraitRefBoundary { s, .. } => {
+                | Scope::TraitRefBoundary { s, .. }
+                | Scope::AnonConstBoundary { s } => {
                     scope = s;
                 }
             }
@@ -1351,6 +1381,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         // search.
         let mut late_depth = 0;
         let mut scope = self.scope;
+        let mut crossed_anon_const = false;
         let result = loop {
             match *scope {
                 Scope::Body { s, .. } => {
@@ -1384,17 +1415,44 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 | Scope::TraitRefBoundary { s, .. } => {
                     scope = s;
                 }
+
+                Scope::AnonConstBoundary { s } => {
+                    crossed_anon_const = true;
+                    scope = s;
+                }
             }
         };
 
         if let Some(def) = result {
+            if let ResolvedArg::LateBound(..) = def && crossed_anon_const {
+                let use_span = self.tcx.hir().span(hir_id);
+                let def_span = self.tcx.def_span(param_def_id);
+                match self.tcx.def_kind(param_def_id) {
+                    DefKind::ConstParam => {
+                        self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Const {
+                            use_span,
+                            def_span,
+                        });
+                    }
+                    DefKind::TyParam => {
+                        self.tcx.sess.emit_err(errors::CannotCaptureLateBoundInAnonConst::Type {
+                            use_span,
+                            def_span,
+                        });
+                    }
+                    _ => unreachable!(),
+                }
+                return;
+            }
+
             self.map.defs.insert(hir_id, def);
             return;
         }
 
-        self.tcx
-            .sess
-            .delay_span_bug(self.tcx.hir().span(hir_id), "could not resolve {param_def_id:?}");
+        self.tcx.sess.delay_span_bug(
+            self.tcx.hir().span(hir_id),
+            format!("could not resolve {param_def_id:?}"),
+        );
     }
 
     #[instrument(level = "debug", skip(self))]
@@ -1465,7 +1523,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                         | Scope::Elision { s, .. }
                         | Scope::ObjectLifetimeDefault { s, .. }
                         | Scope::Supertrait { s, .. }
-                        | Scope::TraitRefBoundary { s, .. } => {
+                        | Scope::TraitRefBoundary { s, .. }
+                        | Scope::AnonConstBoundary { s } => {
                             scope = s;
                         }
                     }
@@ -1701,7 +1760,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
 
                 Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
 
-                Scope::Supertrait { s, .. } | Scope::TraitRefBoundary { s, .. } => {
+                Scope::Supertrait { s, .. }
+                | Scope::TraitRefBoundary { s, .. }
+                | Scope::AnonConstBoundary { s } => {
                     scope = s;
                 }
             }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 50073d94ea5..acd9f8a5c8e 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty::print::with_forced_trimmed_paths;
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{
-    self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+    self, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
 use rustc_span::symbol::Ident;
 use rustc_span::{Span, DUMMY_SP};
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index a566e73912e..3e069275775 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -5,7 +5,7 @@ use rustc_errors::{
     error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
     MultiSpan,
 };
-use rustc_macros::{Diagnostic, LintDiagnostic};
+use rustc_macros::Diagnostic;
 use rustc_middle::ty::Ty;
 use rustc_span::{symbol::Ident, Span, Symbol};
 
@@ -247,26 +247,6 @@ pub struct SubstsOnOverriddenImpl {
     pub span: Span,
 }
 
-#[derive(LintDiagnostic)]
-#[diag(hir_analysis_unused_extern_crate)]
-pub struct UnusedExternCrate {
-    #[suggestion(applicability = "machine-applicable", code = "")]
-    pub span: Span,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(hir_analysis_extern_crate_not_idiomatic)]
-pub struct ExternCrateNotIdiomatic {
-    #[suggestion(
-        style = "short",
-        applicability = "machine-applicable",
-        code = "{suggestion_code}"
-    )]
-    pub span: Span,
-    pub msg_code: String,
-    pub suggestion_code: String,
-}
-
 #[derive(Diagnostic)]
 #[diag(hir_analysis_const_impl_for_non_const_trait)]
 pub struct ConstImplForNonConstTrait {
@@ -401,3 +381,21 @@ pub(crate) struct VariadicFunctionCompatibleConvention<'a> {
     pub span: Span,
     pub conventions: &'a str,
 }
+
+#[derive(Diagnostic)]
+pub(crate) enum CannotCaptureLateBoundInAnonConst {
+    #[diag(hir_analysis_cannot_capture_late_bound_ty_in_anon_const)]
+    Type {
+        #[primary_span]
+        use_span: Span,
+        #[label]
+        def_span: Span,
+    },
+    #[diag(hir_analysis_cannot_capture_late_bound_const_in_anon_const)]
+    Const {
+        #[primary_span]
+        use_span: Span,
+        #[label]
+        def_span: Span,
+    },
+}
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index a8b33c74bc1..d53c429ca15 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -1,7 +1,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::Span;
 
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 5d5c8ca604a..a8b7699b667 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -8,7 +8,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
-use rustc_middle::ty::{DefIdTree, TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
 use std::ops::ControlFlow;
 
 /// Defines the `TermsContext` basically houses an arena where we can
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 34d62987c3b..7ba57b3b7a2 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -315,7 +315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     probe::ProbeScope::TraitsInScope,
                     None,
                 ) {
-                    Ok(pick) => pick.self_ty,
+                    Ok(pick) => eraser.fold_ty(pick.self_ty),
                     Err(_) => rcvr_ty,
                 };
                 // Remove one layer of references to account for `&mut self` and
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 60e55c7b0cf..a8f8121153f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -25,7 +25,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
 use rustc_middle::ty::{
-    self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, Ty, TyCtxt, UserType,
+    self, AdtKind, CanonicalUserType, GenericParamDefKind, Ty, TyCtxt, UserType,
 };
 use rustc_middle::ty::{GenericArgKind, SubstsRef, UserSelfTy, UserSubsts};
 use rustc_session::lint;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index d64492e503d..ec14bd3c6f4 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -3,9 +3,7 @@ use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
 use rustc_infer::traits::ObligationCauseCode;
-use rustc_middle::ty::{
-    self, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
-};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::{self, Span};
 use rustc_trait_selection::traits;
 
@@ -714,12 +712,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.tcx.parent(expr_ctor_def_id)
                 }
                 hir::def::DefKind::Ctor(hir::def::CtorOf::Variant, hir::def::CtorKind::Fn) => {
-                    // If this is a variant, its parent is the type definition.
-                    if in_ty_adt.did() != self.tcx.parent(expr_ctor_def_id) {
+                    // For a typical enum like
+                    // `enum Blah<T> { Variant(T) }`
+                    // we get the following resolutions:
+                    // - expr_ctor_def_id :::                                   DefId(0:29 ~ source_file[b442]::Blah::Variant::{constructor#0})
+                    // - self.tcx.parent(expr_ctor_def_id) :::                  DefId(0:28 ~ source_file[b442]::Blah::Variant)
+                    // - self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) ::: DefId(0:26 ~ source_file[b442]::Blah)
+
+                    // Therefore, we need to go up once to obtain the variant and up twice to obtain the type.
+                    // Note that this pattern still holds even when we `use` a variant or `use` an enum type to rename it, or chain `use` expressions
+                    // together; this resolution is handled automatically by `qpath_res`.
+
+                    // FIXME: Deal with type aliases?
+                    if in_ty_adt.did() == self.tcx.parent(self.tcx.parent(expr_ctor_def_id)) {
+                        // The constructor definition refers to the "constructor" of the variant:
+                        // For example, `Some(5)` triggers this case.
+                        self.tcx.parent(expr_ctor_def_id)
+                    } else {
                         // FIXME: Deal with type aliases?
                         return Err(expr);
                     }
-                    expr_ctor_def_id
                 }
                 _ => {
                     return Err(expr);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 2e62e13648c..ea54b76bdec 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -28,7 +28,7 @@ use rustc_infer::infer::InferOk;
 use rustc_infer::infer::TypeTrace;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::visit::TypeVisitableExt;
-use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty};
+use rustc_middle::ty::{self, IsSuggestable, Ty};
 use rustc_session::Session;
 use rustc_span::symbol::{kw, Ident};
 use rustc_span::{self, sym, Span};
@@ -36,7 +36,6 @@ use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext}
 
 use std::iter;
 use std::mem;
-use std::slice;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(in super::super) fn check_casts(&mut self) {
@@ -1507,11 +1506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let coerce = if blk.targeted_by_break {
             CoerceMany::new(coerce_to_ty)
         } else {
-            let tail_expr: &[&hir::Expr<'_>] = match tail_expr {
-                Some(e) => slice::from_ref(e),
-                None => &[],
-            };
-            CoerceMany::with_coercion_sites(coerce_to_ty, tail_expr)
+            CoerceMany::with_coercion_sites(coerce_to_ty, blk.expr.as_slice())
         };
 
         let prev_diverges = self.diverges.get();
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index c49621b7c24..c77251a156f 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -16,7 +16,7 @@ use rustc_infer::traits::{self, StatementAsExpression};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
-    self, suggest_constraining_type_params, Binder, DefIdTree, IsSuggestable, ToPredicate, Ty,
+    self, suggest_constraining_type_params, Binder, IsSuggestable, ToPredicate, Ty,
     TypeVisitableExt,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 91fd8fad73c..e397dfd4570 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -5,6 +5,7 @@
 #![feature(min_specialization)]
 #![feature(control_flow_enum)]
 #![feature(drain_filter)]
+#![feature(option_as_slice)]
 #![allow(rustc::potential_query_instability)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index bcfc61bffb2..4d3969d28aa 100644
--- a/compiler/rustc_hir_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -636,7 +636,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
         // `&&Some(x,)` `place_foo`
         //  `&Some(x,)` `deref { place_foo}`
         //   `Some(x,)` `deref { deref { place_foo }}`
-        //        (x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
+        //       `(x,)` `field0 { deref { deref { place_foo }}}` <- resulting place
         //
         // The above example has no adjustments. If the code were instead the (after adjustments,
         // equivalent) version
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 47a4d4e72df..4f4779d1543 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -27,7 +27,7 @@ use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::{with_crate_prefix, with_forced_trimmed_paths};
-use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
 use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
@@ -333,6 +333,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             rcvr_ty.prefix_string(self.tcx),
             ty_str_reported,
         );
+        if tcx.sess.source_map().is_multiline(sugg_span) {
+            err.span_label(sugg_span.with_hi(span.lo()), "");
+        }
         let ty_str = if short_ty_str.len() < ty_str.len() && ty_str.len() > 10 {
             short_ty_str
         } else {
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index a4b325a9b79..eecded557a5 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -13,7 +13,7 @@ use rustc_middle::ty::adjustment::{
 };
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{
-    self, DefIdTree, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
+    self, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
@@ -749,14 +749,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let opname = Ident::with_dummy_span(opname);
-        let input_types =
-            opt_rhs.as_ref().map(|(_, ty)| std::slice::from_ref(ty)).unwrap_or_default();
+        let (opt_rhs_expr, opt_rhs_ty) = opt_rhs.unzip();
+        let input_types = opt_rhs_ty.as_slice();
         let cause = self.cause(
             span,
             traits::BinOp {
-                rhs_span: opt_rhs.map(|(expr, _)| expr.span),
-                is_lit: opt_rhs
-                    .map_or(false, |(expr, _)| matches!(expr.kind, hir::ExprKind::Lit(_))),
+                rhs_span: opt_rhs_expr.map(|expr| expr.span),
+                is_lit: opt_rhs_expr
+                    .map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))),
                 output_ty: expected.only_has_type(self),
             },
         );
diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index 8fcec3363c0..2cca45de5e9 100644
--- a/compiler/rustc_hir_typeck/src/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -11,7 +11,6 @@ use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutabili
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
-use std::slice;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
@@ -393,11 +392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(self.typeck_results.borrow().node_substs(expr.hir_id).type_at(1))
             }
         };
-        let arg_tys = match arg_ty {
-            None => &[],
-            Some(ref ty) => slice::from_ref(ty),
-        };
-
+        let arg_tys = arg_ty.as_slice();
         let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
         let method = match method {
             Some(ok) => self.register_infer_ok_obligations(ok),
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index e94915c754e..4a432328c4d 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -231,7 +231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // We now fake capture information for all variables that are mentioned within the closure
         // We do this after handling migrations so that min_captures computes before
-        if !enable_precise_capture(self.tcx, span) {
+        if !enable_precise_capture(span) {
             let mut capture_information: InferredCaptureInformation<'tcx> = Default::default();
 
             if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
@@ -265,7 +265,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             // If we have an origin, store it.
             if let Some(origin) = origin {
-                let origin = if enable_precise_capture(self.tcx, span) {
+                let origin = if enable_precise_capture(span) {
                     (origin.0, origin.1)
                 } else {
                     (origin.0, Place { projections: vec![], ..origin.1 })
@@ -526,10 +526,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 PlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
                 base => bug!("Expected upvar, found={:?}", base),
             };
+            let var_ident = self.tcx.hir().ident(var_hir_id);
 
             let Some(min_cap_list) = root_var_min_capture_list.get_mut(&var_hir_id) else {
                 let mutability = self.determine_capture_mutability(&typeck_results, &place);
                 let min_cap_list = vec![ty::CapturedPlace {
+                    var_ident,
                     place,
                     info: capture_info,
                     mutability,
@@ -628,6 +630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if !ancestor_found {
                 let mutability = self.determine_capture_mutability(&typeck_results, &place);
                 let captured_place = ty::CapturedPlace {
+                    var_ident,
                     place,
                     info: updated_capture_info,
                     mutability,
@@ -1240,8 +1243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///
     /// This will make more sense with an example:
     ///
-    /// ```rust
-    /// #![feature(capture_disjoint_fields)]
+    /// ```rust,edition2021
     ///
     /// struct FancyInteger(i32); // This implements Drop
     ///
@@ -2221,7 +2223,7 @@ fn determine_place_ancestry_relation<'tcx>(
 ///     || drop(&*m.a.field_of_a)
 ///     // Here we really do want to capture `*m.a` because that outlives `'static`
 ///
-///     // If we capture `m`, then the closure no longer outlives `'static'
+///     // If we capture `m`, then the closure no longer outlives `'static`
 ///     // it is constrained to `'a`
 /// }
 /// ```
@@ -2247,12 +2249,10 @@ fn truncate_capture_for_optimization(
     (place, curr_mode)
 }
 
-/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
-/// user is using Rust Edition 2021 or higher.
-///
+/// Precise capture is enabled if user is using Rust Edition 2021 or higher.
 /// `span` is the span of the closure.
-fn enable_precise_capture(tcx: TyCtxt<'_>, span: Span) -> bool {
+fn enable_precise_capture(span: Span) -> bool {
     // We use span here to ensure that if the closure was generated by a macro with a different
     // edition.
-    tcx.features().capture_disjoint_fields || span.rust_2021()
+    span.rust_2021()
 }
diff --git a/compiler/rustc_incremental/src/assert_module_sources.rs b/compiler/rustc_incremental/src/assert_module_sources.rs
index b4b0ea00c50..c550e553bb0 100644
--- a/compiler/rustc_incremental/src/assert_module_sources.rs
+++ b/compiler/rustc_incremental/src/assert_module_sources.rs
@@ -18,7 +18,7 @@
 //! the HIR doesn't change as a result of the annotations, which might
 //! perturb the reuse results.
 //!
-//! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
+//! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]`
 //! allows for doing a more fine-grained check to see if pre- or post-lto data
 //! was re-used.
 
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 15179392c88..cbf169afb18 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -1870,7 +1870,7 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
         }
     }
 
-    /// Subtracts `set from `row`. `set` can be either `BitSet` or
+    /// Subtracts `set` from `row`. `set` can be either `BitSet` or
     /// `HybridBitSet`. Has no effect if `row` does not exist.
     ///
     /// Returns true if the row was changed.
diff --git a/compiler/rustc_infer/locales/en-US.ftl b/compiler/rustc_infer/locales/en-US.ftl
index c5b2b6c2d73..15780898dc6 100644
--- a/compiler/rustc_infer/locales/en-US.ftl
+++ b/compiler/rustc_infer/locales/en-US.ftl
@@ -79,7 +79,7 @@ infer_subtype = ...so that the {$requirement ->
     [if_else_different] `if` and `else` have incompatible types
     [no_else] `if` missing an `else` returns `()`
     [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] #[start]` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
     [intristic_correct_type] intrinsic has the correct type
     [method_correct_type] method receiver has the correct type
     *[other] types are compatible
@@ -92,7 +92,7 @@ infer_subtype_2 = ...so that {$requirement ->
     [if_else_different] `if` and `else` have incompatible types
     [no_else] `if` missing an `else` returns `()`
     [fn_main_correct_type] `main` function has the correct type
-    [fn_start_correct_type] #[start]` function has the correct type
+    [fn_start_correct_type] `#[start]` function has the correct type
     [intristic_correct_type] intrinsic has the correct type
     [method_correct_type] method receiver has the correct type
     *[other] types are compatible
@@ -277,7 +277,7 @@ infer_tid_consider_borrowing = consider borrowing this type parameter in the tra
 infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
 
 infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement
-infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s 'static` requirement
+infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement
 infer_dtcs_has_req_note = the used `impl` has a `'static` requirement
 infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement
 
@@ -313,7 +313,7 @@ infer_but_needs_to_satisfy = {$has_param_name ->
         [false] ...and is required to live as long as `'static` here
     }
     .used_here = ...is used here...
-    .introduced_by_bound = 'static` lifetime requirement introduced by this bound
+    .introduced_by_bound = `'static` lifetime requirement introduced by this bound
 
 infer_more_targeted = {$has_param_name ->
     [true] `{$param_name}`
@@ -345,3 +345,6 @@ infer_prlf_defined_without_sub = the lifetime defined here...
 infer_prlf_must_oultive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here
 infer_prlf_must_oultive_without_sup = ...must outlive the lifetime defined here
 infer_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information)
+
+infer_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds
+    .label = opaque type defined here
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index 7dccd0bb930..6bbd3fd3e6e 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1147,3 +1147,13 @@ pub enum PlaceholderRelationLfNotSatisfied {
         note: (),
     },
 }
+
+#[derive(Diagnostic)]
+#[diag(infer_opaque_captures_lifetime, code = "E0700")]
+pub struct OpaqueCapturesLifetime<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub opaque_ty_span: Span,
+    pub opaque_ty: Ty<'tcx>,
+}
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index c952ddc827a..7d9bae735e5 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -369,6 +369,34 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> {
     }
 }
 
+impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> {
+    fn to_trace(
+        _: TyCtxt<'tcx>,
+        cause: &ObligationCause<'tcx>,
+        a_is_expected: bool,
+        a: Self,
+        b: Self,
+    ) -> TypeTrace<'tcx> {
+        use GenericArgKind::*;
+        TypeTrace {
+            cause: cause.clone(),
+            values: match (a.unpack(), b.unpack()) {
+                (Lifetime(a), Lifetime(b)) => Regions(ExpectedFound::new(a_is_expected, a, b)),
+                (Type(a), Type(b)) => Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
+                (Const(a), Const(b)) => {
+                    Terms(ExpectedFound::new(a_is_expected, a.into(), b.into()))
+                }
+
+                (Lifetime(_), Type(_) | Const(_))
+                | (Type(_), Lifetime(_) | Const(_))
+                | (Const(_), Lifetime(_) | Type(_)) => {
+                    bug!("relating different kinds: {a:?} {b:?}")
+                }
+            },
+        }
+    }
+}
+
 impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> {
     fn to_trace(
         _: TyCtxt<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 7ffd39de781..678c4a0beb6 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -50,7 +50,7 @@ impl<'tcx> InferCtxt<'tcx> {
 
     /// Like [Self::canonicalize_query], but preserves distinct universes. For
     /// example, canonicalizing `&'?0: Trait<'?1>`, where `'?0` is in `U1` and
-    /// `'?1` is in `U3` would be canonicalized to have ?0` in `U1` and `'?1`
+    /// `'?1` is in `U3` would be canonicalized to have `?0` in `U1` and `'?1`
     /// in `U2`.
     ///
     /// This is used for Chalk integration.
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index 8c782a933a5..ce230afdab3 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -30,7 +30,7 @@ use rustc_middle::ty::{self, List, TyCtxt};
 use rustc_span::source_map::Span;
 
 pub use rustc_middle::infer::canonical::*;
-use substitute::CanonicalExt;
+pub use substitute::CanonicalExt;
 
 mod canonicalizer;
 pub mod query_response;
@@ -100,7 +100,11 @@ impl<'tcx> InferCtxt<'tcx> {
     /// variable for it. If this is an existentially quantified
     /// variable, then you'll get a new inference variable; if it is a
     /// universally quantified variable, you get a placeholder.
-    fn instantiate_canonical_var(
+    ///
+    /// FIXME(-Ztrait-solver=next): This is public because it's used by the
+    /// new trait solver which has a different canonicalization routine.
+    /// We should somehow deduplicate all of this.
+    pub fn instantiate_canonical_var(
         &self,
         span: Span,
         cv_info: CanonicalVarInfo<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 832af91a431..436d29c2449 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -151,11 +151,21 @@ impl<'tcx> InferCtxt<'tcx> {
         })
     }
 
-    /// FIXME: This method should only be used for canonical queries and therefore be private.
-    ///
-    /// As the new solver does canonicalization slightly differently, this is also used there
-    /// for now. This should hopefully change fairly soon.
-    pub fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+    /// Used by the new solver as that one takes the opaque types at the end of a probe
+    /// to deal with multiple candidates without having to recompute them.
+    pub fn clone_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
+        self.inner
+            .borrow()
+            .opaque_type_storage
+            .opaque_types
+            .iter()
+            .map(|&(k, ref v)| {
+                (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty)
+            })
+            .collect()
+    }
+
+    fn take_opaque_types_for_query_response(&self) -> Vec<(Ty<'tcx>, Ty<'tcx>)> {
         std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
             .into_iter()
             .map(|(k, v)| (self.tcx.mk_opaque(k.def_id.to_def_id(), k.substs), v.hidden_type.ty))
diff --git a/compiler/rustc_infer/src/infer/canonical/substitute.rs b/compiler/rustc_infer/src/infer/canonical/substitute.rs
index c5c6fc41b9e..cac3b407251 100644
--- a/compiler/rustc_infer/src/infer/canonical/substitute.rs
+++ b/compiler/rustc_infer/src/infer/canonical/substitute.rs
@@ -11,7 +11,9 @@ use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, TyCtxt};
 
-pub(super) trait CanonicalExt<'tcx, V> {
+/// FIXME(-Ztrait-solver=next): This or public because it is shared with the
+/// new trait solver implementation. We should deduplicate canonicalization.
+pub trait CanonicalExt<'tcx, V> {
     /// Instantiate the wrapped value, replacing each canonical value
     /// with the value given in `var_values`.
     fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 79efc1ce7bf..8a2b800af0e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -49,6 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError;
 use super::region_constraints::GenericKind;
 use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
 
+use crate::errors;
 use crate::infer;
 use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
 use crate::infer::ExpectedFound;
@@ -281,15 +282,13 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
     span: Span,
     hidden_ty: Ty<'tcx>,
     hidden_region: ty::Region<'tcx>,
-    opaque_ty: ty::OpaqueTypeKey<'tcx>,
+    opaque_ty_key: ty::OpaqueTypeKey<'tcx>,
 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-    let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs);
-    let mut err = struct_span_err!(
-        tcx.sess,
+    let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime {
         span,
-        E0700,
-        "hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds",
-    );
+        opaque_ty: tcx.mk_opaque(opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs),
+        opaque_ty_span: tcx.def_span(opaque_ty_key.def_id),
+    });
 
     // Explain the region we are capturing.
     match *hidden_region {
@@ -1690,7 +1689,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 format!("{name} is defined in the current crate")
                             } else {
                                 let crate_name = self.tcx.crate_name(defid.krate);
-                                format!("{name} is defined in crate `{crate_name}")
+                                format!("{name} is defined in crate `{crate_name}`")
                             };
                             diagnostic.span_note(def_span, msg);
                         };
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 e242900fd23..a3151d2d365 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
@@ -17,7 +17,7 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
-use rustc_middle::ty::{self, DefIdTree, InferConst};
+use rustc_middle::ty::{self, InferConst};
 use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
 use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
 use rustc_span::symbol::{kw, sym, Ident};
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
index db4b8af4683..c5ef48fe3da 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs
@@ -5,7 +5,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::TyCtxt;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Binder, Region, Ty, TypeVisitable};
 use rustc_span::Span;
 
 /// Information about the anonymous region we are searching for.
diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
index 335eb4c5406..2c480355085 100644
--- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
+++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs
@@ -70,7 +70,7 @@ pub enum RegionResolutionError<'tcx> {
     /// `o` requires that `a <= b`, but this does not hold
     ConcreteFailure(SubregionOrigin<'tcx>, Region<'tcx>, Region<'tcx>),
 
-    /// `GenericBoundFailure(p, s, a)
+    /// `GenericBoundFailure(p, s, a)`:
     ///
     /// The parameter/associated-type `p` must be known to outlive the lifetime
     /// `a` (but none of the known bounds are sufficient).
@@ -438,7 +438,11 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             }
             (VarValue::Value(a), VarValue::Empty(_)) => {
                 match *a {
-                    ReLateBound(..) | ReErased | ReError(_) => {
+                    // this is always on an error path,
+                    // so it doesn't really matter if it's shorter or longer than an empty region
+                    ReError(_) => false,
+
+                    ReLateBound(..) | ReErased => {
                         bug!("cannot relate region: {:?}", a);
                     }
 
@@ -467,7 +471,11 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
             }
             (VarValue::Empty(a_ui), VarValue::Value(b)) => {
                 match *b {
-                    ReLateBound(..) | ReErased | ReError(_) => {
+                    // this is always on an error path,
+                    // so it doesn't really matter if it's shorter or longer than an empty region
+                    ReError(_) => false,
+
+                    ReLateBound(..) | ReErased => {
                         bug!("cannot relate region: {:?}", b);
                     }
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index cf8007c964d..387843ee693 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -94,10 +94,10 @@ pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable<
 /// call to `start_snapshot` and `rollback_to`.
 #[derive(Clone)]
 pub struct InferCtxtInner<'tcx> {
-    /// Cache for projections. This cache is snapshotted along with the infcx.
+    /// Cache for projections.
     ///
-    /// Public so that `traits::project` can use it.
-    pub projection_cache: traits::ProjectionCacheStorage<'tcx>,
+    /// This cache is snapshotted along with the infcx.
+    projection_cache: traits::ProjectionCacheStorage<'tcx>,
 
     /// We instantiate `UnificationTable` with `bounds<Ty>` because the types
     /// that might instantiate a general type variable have an order,
@@ -156,7 +156,7 @@ pub struct InferCtxtInner<'tcx> {
     undo_log: InferCtxtUndoLogs<'tcx>,
 
     /// Caches for opaque type inference.
-    pub opaque_type_storage: OpaqueTypeStorage<'tcx>,
+    opaque_type_storage: OpaqueTypeStorage<'tcx>,
 }
 
 impl<'tcx> InferCtxtInner<'tcx> {
@@ -195,41 +195,17 @@ impl<'tcx> InferCtxtInner<'tcx> {
     }
 
     #[inline]
-    fn int_unification_table(
-        &mut self,
-    ) -> ut::UnificationTable<
-        ut::InPlace<
-            ty::IntVid,
-            &mut ut::UnificationStorage<ty::IntVid>,
-            &mut InferCtxtUndoLogs<'tcx>,
-        >,
-    > {
+    fn int_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::IntVid> {
         self.int_unification_storage.with_log(&mut self.undo_log)
     }
 
     #[inline]
-    fn float_unification_table(
-        &mut self,
-    ) -> ut::UnificationTable<
-        ut::InPlace<
-            ty::FloatVid,
-            &mut ut::UnificationStorage<ty::FloatVid>,
-            &mut InferCtxtUndoLogs<'tcx>,
-        >,
-    > {
+    fn float_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::FloatVid> {
         self.float_unification_storage.with_log(&mut self.undo_log)
     }
 
     #[inline]
-    fn const_unification_table(
-        &mut self,
-    ) -> ut::UnificationTable<
-        ut::InPlace<
-            ty::ConstVid<'tcx>,
-            &mut ut::UnificationStorage<ty::ConstVid<'tcx>>,
-            &mut InferCtxtUndoLogs<'tcx>,
-        >,
-    > {
+    fn const_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::ConstVid<'tcx>> {
         self.const_unification_storage.with_log(&mut self.undo_log)
     }
 
@@ -1429,17 +1405,14 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 
+    /// Attempts to resolve all type/region/const variables in
+    /// `value`. Region inference must have been run already (e.g.,
+    /// by calling `resolve_regions_and_report_errors`). If some
+    /// variable was never unified, an `Err` results.
+    ///
+    /// This method is idempotent, but it not typically not invoked
+    /// except during the writeback phase.
     pub fn fully_resolve<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> FixupResult<'tcx, T> {
-        /*!
-         * Attempts to resolve all type/region/const variables in
-         * `value`. Region inference must have been run already (e.g.,
-         * by calling `resolve_regions_and_report_errors`). If some
-         * variable was never unified, an `Err` results.
-         *
-         * This method is idempotent, but it not typically not invoked
-         * except during the writeback phase.
-         */
-
         let value = resolve::fully_resolve(self, value);
         assert!(
             value.as_ref().map_or(true, |value| !value.needs_infer()),
@@ -1754,7 +1727,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     // in this case. The typechecker should only ever report type errors involving mismatched
     // types using one of these methods, and should not call span_err directly for such
     // errors.
-
     pub fn type_error_struct_with_diag<M>(
         &self,
         sp: Span,
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 6e413a7f412..573cd91a2a2 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -50,7 +50,7 @@ where
     ///
     /// - Covariant means `a <: b`.
     /// - Contravariant means `b <: a`.
-    /// - Invariant means `a == b.
+    /// - Invariant means `a == b`.
     /// - Bivariant means that it doesn't matter.
     ambient_variance: ty::Variance,
 
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index 33514eedfc3..872f617474c 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -249,7 +249,7 @@ pub enum VerifyBound<'tcx> {
 /// in that case we can show `'b: 'c`. But if `'?x` winds up being something
 /// else, the bound isn't relevant.
 ///
-/// In the [`VerifyBound`], this struct is enclosed in `Binder to account
+/// In the [`VerifyBound`], this struct is enclosed in `Binder` to account
 /// for cases like
 ///
 /// ```rust
diff --git a/compiler/rustc_interface/locales/en-US.ftl b/compiler/rustc_interface/locales/en-US.ftl
index da58492ccf2..37994899a20 100644
--- a/compiler/rustc_interface/locales/en-US.ftl
+++ b/compiler/rustc_interface/locales/en-US.ftl
@@ -33,7 +33,7 @@ interface_rustc_error_fatal =
     fatal error triggered by #[rustc_error]
 
 interface_rustc_error_unexpected_annotation =
-    unexpected annotation used with `#[rustc_error(...)]!
+    unexpected annotation used with `#[rustc_error(...)]`!
 
 interface_failed_writing_file =
     failed to write file {$path}: {$error}"
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index e6f04fe0aaa..322ec31fb2c 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -166,15 +166,17 @@ pub enum DocStyle {
     Inner,
 }
 
-// Note that the suffix is *not* considered when deciding the `LiteralKind` in
-// this type. This means that float literals like `1f32` are classified by this
-// type as `Int`. (Compare against `rustc_ast::token::LitKind` and
-// `rustc_ast::ast::LitKind.)
+/// Enum representing the literal types supported by the lexer.
+///
+/// Note that the suffix is *not* considered when deciding the `LiteralKind` in
+/// this type. This means that float literals like `1f32` are classified by this
+/// type as `Int`. (Compare against `rustc_ast::token::LitKind` and
+/// `rustc_ast::ast::LitKind`).
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum LiteralKind {
     /// "12_u8", "0o100", "0b120i99", "1f32".
     Int { base: Base, empty_int: bool },
-    /// "12.34f32", "1e3", but not "1f32`.
+    /// "12.34f32", "1e3", but not "1f32".
     Float { base: Base, empty_exponent: bool },
     /// "'a'", "'\\'", "'''", "';"
     Char { terminated: bool },
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 59540aaf18f..5b2100b5da9 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1288,7 +1288,7 @@ declare_lint! {
 }
 
 declare_lint_pass!(
-    /// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
+    /// Explains corresponding feature flag must be enabled for the `#[track_caller]` attribute to
     /// do anything
     UngatedAsyncFnTrackCaller => [UNGATED_ASYNC_FN_TRACK_CALLER]
 );
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index aace4974cc9..f5a711315ea 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -893,6 +893,23 @@ pub trait LintContext: Sized {
                 BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive => {
                     db.help("consider implementing the trait by hand, or remove the `packed` attribute");
                 }
+                BuiltinLintDiagnostics::UnusedExternCrate { removal_span }=> {
+                    db.span_suggestion(
+                        removal_span,
+                        "remove it",
+                        "",
+                        Applicability::MachineApplicable,
+                    );
+                }
+                BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span }=> {
+                    let suggestion_span = vis_span.between(ident_span);
+                    db.span_suggestion_verbose(
+                        suggestion_span,
+                        "convert it to a `use`",
+                        if vis_span.is_empty() { "use " } else { " use " },
+                        Applicability::MachineApplicable,
+                    );
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(db)
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 85958c41705..7ca50f5a2db 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -17,7 +17,7 @@ use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
 use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{
-    self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+    self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
 use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map;
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 3a92f5806c9..c43162f6325 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -14,7 +14,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_infer::traits::util::elaborate_predicates_with_span;
 use rustc_middle::ty::adjustment;
-use rustc_middle::ty::{self, DefIdTree, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::Symbol;
 use rustc_span::symbol::{kw, sym};
 use rustc_span::{BytePos, Span};
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 6efbf5ce9ee..534aff7fb62 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -522,6 +522,13 @@ pub enum BuiltinLintDiagnostics {
         is_formatting_arg: bool,
     },
     ByteSliceInPackedStructWithDerive,
+    UnusedExternCrate {
+        removal_span: Span,
+    },
+    ExternCrateNotIdiomatic {
+        vis_span: Span,
+        ident_span: Span,
+    },
 }
 
 /// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
index 9146a3739b2..05890628378 100644
--- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
+++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
@@ -14,6 +14,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/JSON.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/Memory.h"
 #include "llvm/Support/SourceMgr.h"
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 0a42265a6ba..4761ce83fab 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -9,7 +9,6 @@
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
-#include "llvm/InitializePasses.h"
 #include "llvm/IR/AutoUpgrade.h"
 #include "llvm/IR/AssemblyAnnotationWriter.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -58,22 +57,6 @@ typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
 
-extern "C" void LLVMInitializePasses() {
-  PassRegistry &Registry = *PassRegistry::getPassRegistry();
-  initializeCore(Registry);
-  initializeCodeGen(Registry);
-  initializeScalarOpts(Registry);
-  initializeVectorization(Registry);
-  initializeIPO(Registry);
-  initializeAnalysis(Registry);
-  initializeTransformUtils(Registry);
-  initializeInstCombine(Registry);
-#if LLVM_VERSION_LT(16, 0)
-  initializeInstrumentation(Registry);
-#endif
-  initializeTarget(Registry);
-}
-
 extern "C" void LLVMTimeTraceProfilerInitialize() {
   timeTraceProfilerInitialize(
       /* TimeTraceGranularity */ 0,
@@ -1004,23 +987,8 @@ LLVMRustPrintModule(LLVMModuleRef M, const char *Path, DemangleFn Demangle) {
 }
 
 extern "C" void LLVMRustPrintPasses() {
-  LLVMInitializePasses();
-  struct MyListener : PassRegistrationListener {
-    void passEnumerate(const PassInfo *Info) {
-      StringRef PassArg = Info->getPassArgument();
-      StringRef PassName = Info->getPassName();
-      if (!PassArg.empty()) {
-        // These unsigned->signed casts could theoretically overflow, but
-        // realistically never will (and even if, the result is implementation
-        // defined rather plain UB).
-        printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
-               (int)PassName.size(), PassName.data());
-      }
-    }
-  } Listener;
-
-  PassRegistry *PR = PassRegistry::getPassRegistry();
-  PR->enumerateWith(&Listener);
+  PassBuilder PB;
+  PB.printPassNames(outs());
 }
 
 extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index b1e6534944d..e3493caaaf7 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1751,6 +1751,19 @@ LLVMRustModuleCost(LLVMModuleRef M) {
   return std::distance(std::begin(f), std::end(f));
 }
 
+extern "C" void
+LLVMRustModuleInstructionStats(LLVMModuleRef M, RustStringRef Str)
+{
+  RawRustStringOstream OS(Str);
+  llvm::json::OStream JOS(OS);
+  auto Module = unwrap(M);
+
+  JOS.object([&] {
+    JOS.attribute("module", Module->getName());
+    JOS.attribute("total", Module->getInstructionCount());
+  });
+}
+
 // Vector reductions:
 extern "C" LLVMValueRef
 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index 82e6972d027..8d017d149f6 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -42,6 +42,12 @@ fn decodable_body(
     }
     let ty_name = s.ast().ident.to_string();
     let decode_body = match s.variants() {
+        [] => {
+            let message = format!("`{}` has no variants to decode", ty_name);
+            quote! {
+                panic!(#message)
+            }
+        }
         [vi] => vi.construct(|field, _index| decode_field(field)),
         variants => {
             let match_inner: TokenStream = variants
@@ -139,6 +145,11 @@ fn encodable_body(
     });
 
     let encode_body = match s.variants() {
+        [] => {
+            quote! {
+                match *self {}
+            }
+        }
         [_] => {
             let encode_inner = s.each_variant(|vi| {
                 vi.bindings()
@@ -160,6 +171,23 @@ fn encodable_body(
             }
         }
         _ => {
+            let disc = {
+                let mut variant_idx = 0usize;
+                let encode_inner = s.each_variant(|_| {
+                    let result = quote! {
+                        #variant_idx
+                    };
+                    variant_idx += 1;
+                    result
+                });
+                quote! {
+                    let disc = match *self {
+                        #encode_inner
+                    };
+                    ::rustc_serialize::Encoder::emit_usize(__encoder, disc);
+                }
+            };
+
             let mut variant_idx = 0usize;
             let encode_inner = s.each_variant(|vi| {
                 let encode_fields: TokenStream = vi
@@ -176,26 +204,11 @@ fn encodable_body(
                         result
                     })
                     .collect();
-
-                let result = if !vi.bindings().is_empty() {
-                    quote! {
-                        ::rustc_serialize::Encoder::emit_enum_variant(
-                            __encoder,
-                            #variant_idx,
-                            |__encoder| { #encode_fields }
-                        )
-                    }
-                } else {
-                    quote! {
-                        ::rustc_serialize::Encoder::emit_fieldless_enum_variant::<#variant_idx>(
-                            __encoder,
-                        )
-                    }
-                };
                 variant_idx += 1;
-                result
+                encode_fields
             });
             quote! {
+                #disc
                 match *self {
                     #encode_inner
                 }
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 755a2425350..c48e681eb94 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -789,6 +789,9 @@ fn get_metadata_section<'p>(
                 loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?;
             // The header is uncompressed
             let header_len = METADATA_HEADER.len();
+            // header + u32 length of data
+            let data_start = header_len + 4;
+
             debug!("checking {} bytes of metadata-version stamp", header_len);
             let header = &buf[..cmp::min(header_len, buf.len())];
             if header != METADATA_HEADER {
@@ -798,8 +801,14 @@ fn get_metadata_section<'p>(
                 )));
             }
 
+            // Length of the compressed stream - this allows linkers to pad the section if they want
+            let Ok(len_bytes) = <[u8; 4]>::try_from(&buf[header_len..cmp::min(data_start, buf.len())]) else {
+                return Err(MetadataError::LoadFailure("invalid metadata length found".to_string()));
+            };
+            let compressed_len = u32::from_be_bytes(len_bytes) as usize;
+
             // Header is okay -> inflate the actual metadata
-            let compressed_bytes = &buf[header_len..];
+            let compressed_bytes = &buf[data_start..(data_start + compressed_len)];
             debug!("inflating {} bytes of compressed metadata", compressed_bytes.len());
             // Assume the decompressed data will be at least the size of the compressed data, so we
             // don't have to grow the buffer as much.
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index f0dafe73c00..3ab01f7809b 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1101,37 +1101,18 @@ fn should_encode_const(def_kind: DefKind) -> bool {
     }
 }
 
-fn should_encode_trait_impl_trait_tys(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
-    if tcx.def_kind(def_id) != DefKind::AssocFn {
-        return false;
-    }
-
-    let Some(item) = tcx.opt_associated_item(def_id) else { return false; };
-    if item.container != ty::AssocItemContainer::ImplContainer {
-        return false;
+// We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable
+// option.
+fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+    if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
+        && let Some(assoc_item) = tcx.opt_associated_item(def_id)
+        && assoc_item.container == ty::AssocItemContainer::TraitContainer
+        && assoc_item.kind == ty::AssocKind::Fn
+    {
+        true
+    } else {
+        false
     }
-
-    let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
-
-    // FIXME(RPITIT): This does a somewhat manual walk through the signature
-    // of the trait fn to look for any RPITITs, but that's kinda doing a lot
-    // of work. We can probably remove this when we refactor RPITITs to be
-    // associated types.
-    tcx.fn_sig(trait_item_def_id).subst_identity().skip_binder().output().walk().any(|arg| {
-        if let ty::GenericArgKind::Type(ty) = arg.unpack()
-            && let ty::Alias(ty::Projection, data) = ty.kind()
-            && tcx.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
-        {
-            true
-        } else {
-            false
-        }
-    })
-}
-
-// Return `false` to avoid encoding impl trait in trait, while we don't use the query.
-fn should_encode_fn_impl_trait_in_trait<'tcx>(_tcx: TyCtxt<'tcx>, _def_id: DefId) -> bool {
-    false
 }
 
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
@@ -1211,7 +1192,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
                 self.encode_info_for_adt(def_id);
             }
-            if should_encode_trait_impl_trait_tys(tcx, def_id)
+            if tcx.impl_method_has_trait_impl_trait_tys(def_id)
                 && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
             {
                 record!(self.tables.trait_impl_trait_tys[def_id] <- table);
@@ -1640,7 +1621,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     #[instrument(level = "debug", skip(self))]
     fn encode_info_for_closure(&mut self, def_id: LocalDefId) {
         // NOTE(eddyb) `tcx.type_of(def_id)` isn't used because it's fully generic,
-        // including on the signature, which is inferred in `typeck.
+        // including on the signature, which is inferred in `typeck`.
         let typeck_result: &'tcx ty::TypeckResults<'tcx> = self.tcx.typeck(def_id);
         let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
         let ty = typeck_result.node_type(hir_id);
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index a7ec2d790b7..1d2541a6788 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -55,13 +55,13 @@ pub(crate) fn rustc_version() -> String {
 /// Metadata encoding version.
 /// N.B., increment this if you change the format of metadata such that
 /// the rustc version can't be found to compare with `rustc_version()`.
-const METADATA_VERSION: u8 = 6;
+const METADATA_VERSION: u8 = 7;
 
 /// Metadata header which includes `METADATA_VERSION`.
 ///
-/// This header is followed by the position of the `CrateRoot`,
-/// which is encoded as a 32-bit big-endian unsigned integer,
-/// and further followed by the rustc version string.
+/// This header is followed by the length of the compressed data, then
+/// the position of the `CrateRoot`, which is encoded as a 32-bit big-endian
+/// unsigned integer, and further followed by the rustc version string.
 pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
 
 /// A value of type T referred to by its absolute position
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index d4019b5bf17..62e44b6298b 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -116,6 +116,7 @@ macro_rules! arena_types {
             [] bit_set_u32: rustc_index::bit_set::BitSet<u32>,
             [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>,
             [decode] doc_link_resolutions: rustc_hir::def::DocLinkResMap,
+            [] closure_kind_origin: (rustc_span::Span, rustc_middle::hir::place::Place<'tcx>),
         ]);
     )
 }
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 2df851a7857..43eef1c770c 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -1,5 +1,5 @@
 use crate::hir::{ModuleItems, Owner};
-use crate::ty::{DefIdTree, TyCtxt};
+use crate::ty::TyCtxt;
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -903,6 +903,11 @@ impl<'hir> Map<'hir> {
     }
 
     #[inline]
+    pub fn ident(self, id: HirId) -> Ident {
+        self.opt_ident(id).unwrap()
+    }
+
+    #[inline]
     pub fn opt_name(self, id: HirId) -> Option<Symbol> {
         self.opt_ident(id).map(|ident| ident.name)
     }
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 2e2ca6a2788..6706b9db3f5 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -7,7 +7,7 @@ pub mod nested_filter;
 pub mod place;
 
 use crate::ty::query::Providers;
-use crate::ty::{DefIdTree, ImplSubject, TyCtxt};
+use crate::ty::{ImplSubject, TyCtxt};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
@@ -64,13 +64,17 @@ impl ModuleItems {
         self.foreign_items.iter().copied()
     }
 
-    pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ {
+    pub fn owners(&self) -> impl Iterator<Item = OwnerId> + '_ {
         self.items
             .iter()
-            .map(|id| id.owner_id.def_id)
-            .chain(self.trait_items.iter().map(|id| id.owner_id.def_id))
-            .chain(self.impl_items.iter().map(|id| id.owner_id.def_id))
-            .chain(self.foreign_items.iter().map(|id| id.owner_id.def_id))
+            .map(|id| id.owner_id)
+            .chain(self.trait_items.iter().map(|id| id.owner_id))
+            .chain(self.impl_items.iter().map(|id| id.owner_id))
+            .chain(self.foreign_items.iter().map(|id| id.owner_id))
+    }
+
+    pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ {
+        self.owners().map(|id| id.def_id)
     }
 
     pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
@@ -173,6 +177,7 @@ pub fn provide(providers: &mut Providers) {
         }
     };
     providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
+    providers.opt_rpitit_info = |_, _| None;
     providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
     providers.expn_that_defined = |tcx, id| {
         let id = id.expect_local();
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 8712514a384..7f8fc17744d 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -123,6 +123,11 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
         self.kind.universe()
     }
 
+    #[must_use]
+    pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> {
+        CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
+    }
+
     pub fn is_existential(&self) -> bool {
         match self.kind {
             CanonicalVarKind::Ty(_) => true,
@@ -133,6 +138,28 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
             CanonicalVarKind::PlaceholderConst(_, _) => false,
         }
     }
+
+    pub fn is_region(&self) -> bool {
+        match self.kind {
+            CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
+            CanonicalVarKind::Ty(_)
+            | CanonicalVarKind::PlaceholderTy(_)
+            | CanonicalVarKind::Const(_, _)
+            | CanonicalVarKind::PlaceholderConst(_, _) => false,
+        }
+    }
+
+    pub fn expect_anon_placeholder(self) -> u32 {
+        match self.kind {
+            CanonicalVarKind::Ty(_)
+            | CanonicalVarKind::Region(_)
+            | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
+
+            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(),
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(),
+            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(),
+        }
+    }
 }
 
 /// Describes the "kind" of the canonical variable. This is a "kind"
@@ -177,6 +204,38 @@ impl<'tcx> CanonicalVarKind<'tcx> {
             CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe,
         }
     }
+
+    /// Replaces the universe of this canonical variable with `ui`.
+    ///
+    /// In case this is a float or int variable, this causes an ICE if
+    /// the updated universe is not the root.
+    pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
+        match self {
+            CanonicalVarKind::Ty(kind) => match kind {
+                CanonicalTyVarKind::General(_) => {
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
+                }
+                CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => {
+                    assert_eq!(ui, ty::UniverseIndex::ROOT);
+                    CanonicalVarKind::Ty(kind)
+                }
+            },
+            CanonicalVarKind::PlaceholderTy(placeholder) => {
+                CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
+            }
+            CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
+            CanonicalVarKind::PlaceholderRegion(placeholder) => {
+                CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder })
+            }
+            CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
+            CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
+                CanonicalVarKind::PlaceholderConst(
+                    ty::Placeholder { universe: ui, ..placeholder },
+                    ty,
+                )
+            }
+        }
+    }
 }
 
 /// Rust actually has more than one category of type variables;
@@ -213,7 +272,8 @@ pub struct QueryResponse<'tcx, R> {
     pub value: R,
 }
 
-#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct QueryRegionConstraints<'tcx> {
     pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
     pub member_constraints: Vec<MemberConstraint<'tcx>>,
diff --git a/compiler/rustc_middle/src/infer/mod.rs b/compiler/rustc_middle/src/infer/mod.rs
index 38868c21049..2db59f37f40 100644
--- a/compiler/rustc_middle/src/infer/mod.rs
+++ b/compiler/rustc_middle/src/infer/mod.rs
@@ -12,7 +12,8 @@ use rustc_span::Span;
 /// ```text
 /// R0 member of [O1..On]
 /// ```
-#[derive(Debug, Clone, HashStable, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
 pub struct MemberConstraint<'tcx> {
     /// The `DefId` and substs of the opaque type causing this constraint.
     /// Used for error reporting.
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 893bf54b866..171cf1c1ab1 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -1,7 +1,7 @@
 //! A pass that checks to make sure private fields and methods aren't used
 //! outside their scopes. This pass will also generate a set of exported items
 //! which are available for use externally when compiled as a library.
-use crate::ty::{DefIdTree, TyCtxt, Visibility};
+use crate::ty::{TyCtxt, Visibility};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable;
@@ -112,7 +112,7 @@ impl EffectiveVisibilities {
         &mut self,
         def_id: LocalDefId,
         eff_vis: &EffectiveVisibility,
-        tree: impl DefIdTree,
+        tcx: TyCtxt<'_>,
     ) {
         use std::collections::hash_map::Entry;
         match self.map.entry(def_id) {
@@ -122,7 +122,7 @@ impl EffectiveVisibilities {
                     let vis_at_level = eff_vis.at_level(l);
                     let old_vis_at_level = old_eff_vis.at_level_mut(l);
                     if vis_at_level != old_vis_at_level
-                        && vis_at_level.is_at_least(*old_vis_at_level, tree)
+                        && vis_at_level.is_at_least(*old_vis_at_level, tcx)
                     {
                         *old_vis_at_level = *vis_at_level
                     }
@@ -219,7 +219,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
         lazy_private_vis: impl FnOnce() -> Visibility,
         inherited_effective_vis: EffectiveVisibility,
         level: Level,
-        tree: impl DefIdTree,
+        tcx: TyCtxt<'_>,
     ) -> bool {
         let mut changed = false;
         let mut current_effective_vis = self
@@ -240,7 +240,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
                     && level != l)
                 {
                     calculated_effective_vis =
-                        if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {
+                        if nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
                             inherited_effective_vis_at_level
                         } else {
                             nominal_vis
@@ -249,7 +249,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
                 // effective visibility can't be decreased at next update call for the
                 // same id
                 if *current_effective_vis_at_level != calculated_effective_vis
-                    && calculated_effective_vis.is_at_least(*current_effective_vis_at_level, tree)
+                    && calculated_effective_vis.is_at_least(*current_effective_vis_at_level, tcx)
                 {
                     changed = true;
                     *current_effective_vis_at_level = calculated_effective_vis;
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index 354c84e2209..b61f7806b7a 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -3,7 +3,7 @@
 
 pub use self::StabilityLevel::*;
 
-use crate::ty::{self, DefIdTree, TyCtxt};
+use crate::ty::{self, TyCtxt};
 use rustc_ast::NodeId;
 use rustc_attr::{self as attr, ConstStability, DefaultBodyStability, Deprecation, Stability};
 use rustc_data_structures::fx::FxHashMap;
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 221105ac48f..48375ed301d 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -8,7 +8,8 @@ mod tests;
 use std::borrow::Cow;
 use std::fmt;
 use std::hash;
-use std::ops::Range;
+use std::hash::Hash;
+use std::ops::{Deref, DerefMut, Range};
 use std::ptr;
 
 use either::{Left, Right};
@@ -29,6 +30,39 @@ use provenance_map::*;
 
 pub use init_mask::{InitChunk, InitChunkIter};
 
+/// Functionality required for the bytes of an `Allocation`.
+pub trait AllocBytes:
+    Clone + fmt::Debug + Eq + PartialEq + Hash + Deref<Target = [u8]> + DerefMut<Target = [u8]>
+{
+    /// Adjust the bytes to the specified alignment -- by default, this is a no-op.
+    fn adjust_to_align(self, _align: Align) -> Self;
+
+    /// Create an `AllocBytes` from a slice of `u8`.
+    fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self;
+
+    /// Create a zeroed `AllocBytes` of the specified size and alignment;
+    /// call the callback error handler if there is an error in allocating the memory.
+    fn zeroed(size: Size, _align: Align) -> Option<Self>;
+}
+
+// Default `bytes` for `Allocation` is a `Box<[u8]>`.
+impl AllocBytes for Box<[u8]> {
+    fn adjust_to_align(self, _align: Align) -> Self {
+        self
+    }
+
+    fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, _align: Align) -> Self {
+        Box::<[u8]>::from(slice.into())
+    }
+
+    fn zeroed(size: Size, _align: Align) -> Option<Self> {
+        let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).ok()?;
+        // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
+        let bytes = unsafe { bytes.assume_init() };
+        Some(bytes)
+    }
+}
+
 /// This type represents an Allocation in the Miri/CTFE core engine.
 ///
 /// Its public API is rather low-level, working directly with allocation offsets and a custom error
@@ -38,10 +72,10 @@ pub use init_mask::{InitChunk, InitChunkIter};
 // hashed. (see the `Hash` impl below for more details), so the impl is not derived.
 #[derive(Clone, Eq, PartialEq, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
-pub struct Allocation<Prov: Provenance = AllocId, Extra = ()> {
+pub struct Allocation<Prov: Provenance = AllocId, Extra = (), Bytes = Box<[u8]>> {
     /// The actual bytes of the allocation.
     /// Note that the bytes of a pointer represent the offset of the pointer.
-    bytes: Box<[u8]>,
+    bytes: Bytes,
     /// Maps from byte addresses to extra provenance data for each pointer.
     /// Only the first byte of a pointer is inserted into the map; i.e.,
     /// every entry in this map applies to `pointer_size` consecutive bytes starting
@@ -220,14 +254,27 @@ impl AllocRange {
 }
 
 // The constructors are all without extra; the extra gets added by a machine hook later.
-impl<Prov: Provenance> Allocation<Prov> {
+impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
+    /// Creates an allocation from an existing `Bytes` value - this is needed for miri FFI support
+    pub fn from_raw_bytes(bytes: Bytes, align: Align, mutability: Mutability) -> Self {
+        let size = Size::from_bytes(bytes.len());
+        Self {
+            bytes,
+            provenance: ProvenanceMap::new(),
+            init_mask: InitMask::new(size, true),
+            align,
+            mutability,
+            extra: (),
+        }
+    }
+
     /// Creates an allocation initialized by the given bytes
     pub fn from_bytes<'a>(
         slice: impl Into<Cow<'a, [u8]>>,
         align: Align,
         mutability: Mutability,
     ) -> Self {
-        let bytes = Box::<[u8]>::from(slice.into());
+        let bytes = Bytes::from_bytes(slice, align);
         let size = Size::from_bytes(bytes.len());
         Self {
             bytes,
@@ -248,7 +295,7 @@ impl<Prov: Provenance> Allocation<Prov> {
     ///
     /// If `panic_on_fail` is true, this will never return `Err`.
     pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> {
-        let bytes = Box::<[u8]>::try_new_zeroed_slice(size.bytes_usize()).map_err(|_| {
+        let bytes = Bytes::zeroed(size, align).ok_or_else(|| {
             // This results in an error that can happen non-deterministically, since the memory
             // available to the compiler can change between runs. Normally queries are always
             // deterministic. However, we can be non-deterministic here because all uses of const
@@ -262,8 +309,7 @@ impl<Prov: Provenance> Allocation<Prov> {
             });
             InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
         })?;
-        // SAFETY: the box was zero-allocated, which is a valid initial value for Box<[u8]>
-        let bytes = unsafe { bytes.assume_init() };
+
         Ok(Allocation {
             bytes,
             provenance: ProvenanceMap::new(),
@@ -275,7 +321,7 @@ impl<Prov: Provenance> Allocation<Prov> {
     }
 }
 
-impl Allocation {
+impl<Bytes: AllocBytes> Allocation<AllocId, (), Bytes> {
     /// Adjust allocation from the ones in tcx to a custom Machine instance
     /// with a different Provenance and Extra type.
     pub fn adjust_from_tcx<Prov: Provenance, Extra, Err>(
@@ -283,9 +329,11 @@ impl Allocation {
         cx: &impl HasDataLayout,
         extra: Extra,
         mut adjust_ptr: impl FnMut(Pointer<AllocId>) -> Result<Pointer<Prov>, Err>,
-    ) -> Result<Allocation<Prov, Extra>, Err> {
-        // Compute new pointer provenance, which also adjusts the bytes.
-        let mut bytes = self.bytes;
+    ) -> Result<Allocation<Prov, Extra, Bytes>, Err> {
+        // Compute new pointer provenance, which also adjusts the bytes, and realign the pointer if
+        // necessary.
+        let mut bytes = self.bytes.adjust_to_align(self.align);
+
         let mut new_provenance = Vec::with_capacity(self.provenance.ptrs().len());
         let ptr_size = cx.data_layout().pointer_size.bytes_usize();
         let endian = cx.data_layout().endian;
@@ -311,7 +359,7 @@ impl Allocation {
 }
 
 /// Raw accessors. Provide access to otherwise private bytes.
-impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
+impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
     pub fn len(&self) -> usize {
         self.bytes.len()
     }
@@ -340,7 +388,11 @@ impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
 }
 
 /// Byte accessors.
-impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
+impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
+    pub fn base_addr(&self) -> *const u8 {
+        self.bytes.as_ptr()
+    }
+
     /// This is the entirely abstraction-violating way to just grab the raw bytes without
     /// caring about provenance or initialization.
     ///
@@ -412,7 +464,7 @@ impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
 }
 
 /// Reading and writing.
-impl<Prov: Provenance, Extra> Allocation<Prov, Extra> {
+impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes> {
     /// Sets the init bit for the given range.
     fn mark_init(&mut self, range: AllocRange, is_init: bool) {
         if range.size.bytes() == 0 {
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index b0975616b61..1766d7a6698 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -127,8 +127,8 @@ pub use self::error::{
 pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
 
 pub use self::allocation::{
-    alloc_range, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, InitChunk,
-    InitChunkIter,
+    alloc_range, AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation,
+    InitChunk, InitChunkIter,
 };
 
 pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 0d78c6135b3..6e6bb8ce95e 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -10,7 +10,7 @@ use crate::ty::codec::{TyDecoder, TyEncoder};
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor};
-use crate::ty::{self, DefIdTree, List, Ty, TyCtxt};
+use crate::ty::{self, List, Ty, TyCtxt};
 use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
 use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
 
@@ -2908,7 +2908,7 @@ fn pretty_print_const_value<'tcx>(
             // the `destructure_const` query with an empty `ty::ParamEnv` without
             // introducing ICEs (e.g. via `layout_of`) from missing bounds.
             // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
-            // to be able to destructure the tuple into `(0u8, *mut T)
+            // to be able to destructure the tuple into `(0u8, *mut T)`
             //
             // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
             // correct `ty::ParamEnv` to allow printing *all* constant values.
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 16daf63b82d..d8829e3e782 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -12,8 +12,8 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::Idx;
 use rustc_middle::mir::interpret::{
-    alloc_range, read_target_uint, AllocId, Allocation, ConstAllocation, ConstValue, GlobalAlloc,
-    Pointer, Provenance,
+    alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, ConstValue,
+    GlobalAlloc, Pointer, Provenance,
 };
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
@@ -787,21 +787,21 @@ pub fn write_allocations<'tcx>(
 /// After the hex dump, an ascii dump follows, replacing all unprintable characters (control
 /// characters or characters whose value is larger than 127) with a `.`
 /// This also prints provenance adequately.
-pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra>(
+pub fn display_allocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
     tcx: TyCtxt<'tcx>,
-    alloc: &'a Allocation<Prov, Extra>,
-) -> RenderAllocation<'a, 'tcx, Prov, Extra> {
+    alloc: &'a Allocation<Prov, Extra, Bytes>,
+) -> RenderAllocation<'a, 'tcx, Prov, Extra, Bytes> {
     RenderAllocation { tcx, alloc }
 }
 
 #[doc(hidden)]
-pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra> {
+pub struct RenderAllocation<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> {
     tcx: TyCtxt<'tcx>,
-    alloc: &'a Allocation<Prov, Extra>,
+    alloc: &'a Allocation<Prov, Extra, Bytes>,
 }
 
-impl<'a, 'tcx, Prov: Provenance, Extra> std::fmt::Display
-    for RenderAllocation<'a, 'tcx, Prov, Extra>
+impl<'a, 'tcx, Prov: Provenance, Extra, Bytes: AllocBytes> std::fmt::Display
+    for RenderAllocation<'a, 'tcx, Prov, Extra, Bytes>
 {
     fn fmt(&self, w: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         let RenderAllocation { tcx, alloc } = *self;
@@ -845,9 +845,9 @@ fn write_allocation_newline(
 /// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there
 /// is only one line). Note that your prefix should contain a trailing space as the lines are
 /// printed directly after it.
-fn write_allocation_bytes<'tcx, Prov: Provenance, Extra>(
+fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
     tcx: TyCtxt<'tcx>,
-    alloc: &Allocation<Prov, Extra>,
+    alloc: &Allocation<Prov, Extra, Bytes>,
     w: &mut dyn std::fmt::Write,
     prefix: &str,
 ) -> std::fmt::Result {
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 1610ae1ce14..28a3b51b7fc 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -11,7 +11,7 @@ use std::io::{self, Write};
 pub const TOOLTIP_INDENT: &str = "    ";
 
 const CARET: char = '\u{2038}'; // Unicode `CARET`
-const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET
+const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET`
 const ANNOTATION_RIGHT_BRACKET: char = '\u{2989}'; // Unicode `Z NOTATION LEFT BINDING BRACKET`
 const NEW_LINE_SPAN: &str = "</span>\n<span class=\"line\">";
 const HEADER: &str = r#"<!DOCTYPE html>
diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs
index dc02fd53ed0..78ee8a6a8fd 100644
--- a/compiler/rustc_middle/src/query/keys.rs
+++ b/compiler/rustc_middle/src/query/keys.rs
@@ -4,8 +4,9 @@ use crate::infer::canonical::Canonical;
 use crate::mir;
 use crate::traits;
 use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::layout::{TyAndLayout, ValidityRequirement};
 use crate::ty::subst::{GenericArg, SubstsRef};
-use crate::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::hir_id::{HirId, OwnerId};
 use rustc_query_system::query::{DefaultCacheSelector, SingleCacheSelector, VecCacheSelector};
@@ -696,3 +697,24 @@ impl Key for HirId {
         None
     }
 }
+
+impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
+    type CacheSelector = DefaultCacheSelector<Self>;
+
+    // Just forward to `Ty<'tcx>`
+    #[inline(always)]
+    fn query_crate_is_local(&self) -> bool {
+        true
+    }
+
+    fn default_span(&self, _: TyCtxt<'_>) -> Span {
+        DUMMY_SP
+    }
+
+    fn ty_adt_id(&self) -> Option<DefId> {
+        match self.1.value.kind() {
+            ty::Adt(adt, _) => Some(adt.did()),
+            _ => None,
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 6a34e5ede19..5133da3429a 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -90,6 +90,7 @@ rustc_queries! {
     /// Definitions that were generated with no HIR, would be feeded to return `None`.
     query opt_local_def_id_to_hir_id(key: LocalDefId) -> Option<hir::HirId>{
         desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
+        feedable
     }
 
     /// Gives access to the HIR node's parent for the HIR owner `key`.
@@ -166,6 +167,7 @@ rustc_queries! {
         }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
+        feedable
     }
 
     query collect_return_position_impl_trait_in_trait_tys(key: DefId)
@@ -222,6 +224,7 @@ rustc_queries! {
         arena_cache
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
+        feedable
     }
 
     /// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
@@ -264,6 +267,7 @@ rustc_queries! {
         desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
+        feedable
     }
 
     /// Elaborated version of the predicates from `explicit_item_bounds`.
@@ -475,14 +479,10 @@ rustc_queries! {
         }
     }
 
-    query symbols_for_closure_captures(
-        key: (LocalDefId, LocalDefId)
-    ) -> &'tcx Vec<rustc_span::Symbol> {
-        arena_cache
+    query closure_typeinfo(key: LocalDefId) -> ty::ClosureTypeInfo<'tcx> {
         desc {
-            |tcx| "finding symbols for captures of closure `{}` in `{}`",
-            tcx.def_path_str(key.1.to_def_id()),
-            tcx.def_path_str(key.0.to_def_id())
+            |tcx| "finding symbols for captures of closure `{}`",
+            tcx.def_path_str(key.to_def_id())
         }
     }
 
@@ -592,6 +592,7 @@ rustc_queries! {
         desc { |tcx| "computing explicit predicates of `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
+        feedable
     }
 
     /// Returns the inferred outlives predicates (e.g., for `struct
@@ -600,6 +601,7 @@ rustc_queries! {
         desc { |tcx| "computing inferred outlives predicates of `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
+        feedable
     }
 
     /// Maps from the `DefId` of a trait to the list of
@@ -732,6 +734,7 @@ rustc_queries! {
         desc { |tcx| "computing associated item data for `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { key.is_local() }
         separate_provide_extern
+        feedable
     }
 
     /// Collects the associated items defined on a trait or impl.
@@ -1146,6 +1149,15 @@ rustc_queries! {
         desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
         cache_on_disk_if { def_id.is_local() }
         separate_provide_extern
+        feedable
+    }
+
+    /// The `opt_rpitit_info` query returns the pair of the def id of the function where the RPIT
+    /// is defined and the opaque def id if any.
+    query opt_rpitit_info(def_id: DefId) -> Option<ty::ImplTraitInTraitData> {
+        desc { |tcx| "opt_rpitit_info `{}`", tcx.def_path_str(def_id) }
+        cache_on_disk_if { def_id.is_local() }
+        feedable
     }
 
     /// Gets the span for the definition.
@@ -1161,6 +1173,7 @@ rustc_queries! {
         desc { |tcx| "looking up span for `{}`'s identifier", tcx.def_path_str(def_id) }
         cache_on_disk_if { def_id.is_local() }
         separate_provide_extern
+        feedable
     }
 
     query lookup_stability(def_id: DefId) -> Option<attr::Stability> {
@@ -1502,6 +1515,7 @@ rustc_queries! {
         desc { |tcx| "looking up whether `{}` is a default impl", tcx.def_path_str(def_id) }
         cache_on_disk_if { def_id.is_local() }
         separate_provide_extern
+        feedable
     }
 
     query check_well_formed(key: hir::OwnerId) -> () {
@@ -1658,7 +1672,7 @@ rustc_queries! {
 
     /// Does lifetime resolution on items. Importantly, we can't resolve
     /// lifetimes directly on things like trait methods, because of trait params.
-    /// See `rustc_resolve::late::lifetimes for details.
+    /// See `rustc_resolve::late::lifetimes` for details.
     query resolve_bound_vars(_: hir::OwnerId) -> &'tcx ResolveBoundVars {
         arena_cache
         desc { "resolving lifetimes" }
@@ -1699,6 +1713,7 @@ rustc_queries! {
     query visibility(def_id: DefId) -> ty::Visibility<DefId> {
         desc { |tcx| "computing visibility of `{}`", tcx.def_path_str(def_id) }
         separate_provide_extern
+        feedable
     }
 
     query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
@@ -1830,9 +1845,6 @@ rustc_queries! {
     query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet<LocalDefId> {
         desc { "fetching potentially unused trait imports" }
     }
-    query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] {
-        desc { "looking up all possibly unused extern crates" }
-    }
     query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet<Symbol> {
         desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
@@ -2173,12 +2185,8 @@ rustc_queries! {
         separate_provide_extern
     }
 
-    query permits_uninit_init(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, ty::layout::LayoutError<'tcx>> {
-        desc { "checking to see if `{}` permits being left uninit", key.value }
-    }
-
-    query permits_zero_init(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, ty::layout::LayoutError<'tcx>> {
-        desc { "checking to see if `{}` permits being left zeroed", key.value }
+    query check_validity_requirement(key: (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>)) -> Result<bool, ty::layout::LayoutError<'tcx>> {
+        desc { "checking validity requirement for `{}`: {}", key.1.value, key.0 }
     }
 
     query compare_impl_const(
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 6f2dac46753..3b11fab8cdf 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
 use rustc_middle::ty::adjustment::PointerCast;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
+use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts};
 use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -29,11 +29,15 @@ use rustc_target::asm::InlineAsmRegOrRegClass;
 use std::fmt;
 use std::ops::Index;
 
-pub mod print;
 pub mod visit;
 
 macro_rules! thir_with_elements {
-    ($($name:ident: $id:ty => $value:ty => $format:literal,)*) => {
+    (
+        $($field_name:ident: $field_ty:ty,)*
+
+    @elements:
+        $($name:ident: $id:ty => $value:ty => $format:literal,)*
+    ) => {
         $(
             newtype_index! {
                 #[derive(HashStable)]
@@ -48,14 +52,20 @@ macro_rules! thir_with_elements {
         #[derive(Debug, HashStable, Clone)]
         pub struct Thir<'tcx> {
             $(
+                pub $field_name: $field_ty,
+            )*
+            $(
                 pub $name: IndexVec<$id, $value>,
             )*
         }
 
         impl<'tcx> Thir<'tcx> {
-            pub fn new() -> Thir<'tcx> {
+            pub fn new($($field_name: $field_ty,)*) -> Thir<'tcx> {
                 Thir {
                     $(
+                        $field_name,
+                    )*
+                    $(
                         $name: IndexVec::new(),
                     )*
                 }
@@ -76,6 +86,9 @@ macro_rules! thir_with_elements {
 pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
 
 thir_with_elements! {
+    body_type: BodyTy<'tcx>,
+
+@elements:
     arms: ArmId => Arm<'tcx> => "a{}",
     blocks: BlockId => Block => "b{}",
     exprs: ExprId => Expr<'tcx> => "e{}",
@@ -83,6 +96,12 @@ thir_with_elements! {
     params: ParamId => Param<'tcx> => "p{}",
 }
 
+#[derive(Debug, HashStable, Clone)]
+pub enum BodyTy<'tcx> {
+    Const(Ty<'tcx>),
+    Fn(FnSig<'tcx>),
+}
+
 /// Description of a type-checked function parameter.
 #[derive(Clone, Debug, HashStable)]
 pub struct Param<'tcx> {
@@ -218,6 +237,9 @@ pub struct LocalVarId(pub hir::HirId);
 /// A THIR expression.
 #[derive(Clone, Debug, HashStable)]
 pub struct Expr<'tcx> {
+    /// kind of expression
+    pub kind: ExprKind<'tcx>,
+
     /// The type of this expression
     pub ty: Ty<'tcx>,
 
@@ -227,9 +249,6 @@ pub struct Expr<'tcx> {
 
     /// span of the expression in the source
     pub span: Span,
-
-    /// kind of expression
-    pub kind: ExprKind<'tcx>,
 }
 
 #[derive(Clone, Debug, HashStable)]
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index c5bf9717f03..bd43867a3da 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -2,6 +2,7 @@ use std::ops::ControlFlow;
 
 use rustc_data_structures::intern::Interned;
 
+use crate::infer::canonical::QueryRegionConstraints;
 use crate::ty::{
     FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor,
 };
@@ -18,20 +19,25 @@ impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> {
 }
 
 /// Additional constraints returned on success.
-#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)]
+#[derive(Debug, PartialEq, Eq, Clone, Hash, Default, TypeFoldable, TypeVisitable)]
 pub struct ExternalConstraintsData<'tcx> {
     // FIXME: implement this.
-    pub regions: (),
+    pub region_constraints: QueryRegionConstraints<'tcx>,
     pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>,
 }
 
+// FIXME: Having to clone `region_constraints` for folding feels bad and
+// probably isn't great wrt performance.
+//
+// Not sure how to fix this, maybe we should also intern `opaque_types` and
+// `region_constraints` here or something.
 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
     fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
         self,
         folder: &mut F,
     ) -> Result<Self, F::Error> {
         Ok(FallibleTypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
-            regions: (),
+            region_constraints: self.region_constraints.clone().try_fold_with(folder)?,
             opaque_types: self
                 .opaque_types
                 .iter()
@@ -42,7 +48,7 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
 
     fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
         TypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData {
-            regions: (),
+            region_constraints: self.region_constraints.clone().fold_with(folder),
             opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(),
         })
     }
@@ -53,7 +59,7 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ExternalConstraints<'tcx> {
         &self,
         visitor: &mut V,
     ) -> std::ops::ControlFlow<V::BreakTy> {
-        self.regions.visit_with(visitor)?;
+        self.region_constraints.visit_with(visitor)?;
         self.opaque_types.visit_with(visitor)?;
         ControlFlow::Continue(())
     }
diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs
index f1a9e50a4f0..dfe23cf991f 100644
--- a/compiler/rustc_middle/src/ty/assoc.rs
+++ b/compiler/rustc_middle/src/ty/assoc.rs
@@ -1,6 +1,6 @@
 pub use self::AssocItemContainer::*;
 
-use crate::ty::{self, DefIdTree};
+use crate::ty;
 use rustc_data_structures::sorted_map::SortedIndexMultiMap;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Namespace};
diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs
index 6ade8935fc8..dc2bd54b7fe 100644
--- a/compiler/rustc_middle/src/ty/closure.rs
+++ b/compiler/rustc_middle/src/ty/closure.rs
@@ -5,10 +5,10 @@ use crate::{mir, ty};
 
 use std::fmt::Write;
 
-use hir::LangItem;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::{self as hir, LangItem};
+use rustc_span::symbol::Ident;
 use rustc_span::{Span, Symbol};
 
 use super::{Ty, TyCtxt};
@@ -129,6 +129,9 @@ impl<'tcx> ClosureKind {
 #[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
 #[derive(TypeFoldable, TypeVisitable)]
 pub struct CapturedPlace<'tcx> {
+    /// Name and span where the binding happens.
+    pub var_ident: Ident,
+
     /// The `Place` that is captured.
     pub place: HirPlace<'tcx>,
 
@@ -148,12 +151,8 @@ impl<'tcx> CapturedPlace<'tcx> {
     }
 
     /// Returns a symbol of the captured upvar, which looks like `name__field1__field2`.
-    fn to_symbol(&self, tcx: TyCtxt<'tcx>) -> Symbol {
-        let hir_id = match self.place.base {
-            HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
-            base => bug!("Expected an upvar, found {:?}", base),
-        };
-        let mut symbol = tcx.hir().name(hir_id).as_str().to_string();
+    pub fn to_symbol(&self) -> Symbol {
+        let mut symbol = self.var_ident.to_string();
 
         let mut ty = self.place.base_ty;
         for proj in self.place.projections.iter() {
@@ -169,11 +168,7 @@ impl<'tcx> CapturedPlace<'tcx> {
                         .unwrap();
                     }
                     ty => {
-                        span_bug!(
-                            self.get_capture_kind_span(tcx),
-                            "Unexpected type {:?} for `Field` projection",
-                            ty
-                        )
+                        bug!("Unexpected type {:?} for `Field` projection", ty)
                     }
                 },
 
@@ -238,10 +233,39 @@ impl<'tcx> CapturedPlace<'tcx> {
     }
 }
 
-fn symbols_for_closure_captures(tcx: TyCtxt<'_>, def_id: (LocalDefId, LocalDefId)) -> Vec<Symbol> {
-    let typeck_results = tcx.typeck(def_id.0);
-    let captures = typeck_results.closure_min_captures_flattened(def_id.1);
-    captures.into_iter().map(|captured_place| captured_place.to_symbol(tcx)).collect()
+#[derive(Copy, Clone, Debug, HashStable)]
+pub struct ClosureTypeInfo<'tcx> {
+    user_provided_sig: ty::CanonicalPolyFnSig<'tcx>,
+    captures: &'tcx [&'tcx ty::CapturedPlace<'tcx>],
+    kind_origin: Option<&'tcx (Span, HirPlace<'tcx>)>,
+}
+
+fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo<'tcx> {
+    debug_assert!(tcx.is_closure(def.to_def_id()));
+    let typeck_results = tcx.typeck(def);
+    let user_provided_sig = typeck_results.user_provided_sigs[&def];
+    let captures = typeck_results.closure_min_captures_flattened(def);
+    let captures = tcx.arena.alloc_from_iter(captures);
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def);
+    let kind_origin = typeck_results.closure_kind_origins().get(hir_id);
+    ClosureTypeInfo { user_provided_sig, captures, kind_origin }
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+    pub fn closure_kind_origin(self, def_id: LocalDefId) -> Option<&'tcx (Span, HirPlace<'tcx>)> {
+        self.closure_typeinfo(def_id).kind_origin
+    }
+
+    pub fn closure_user_provided_sig(self, def_id: LocalDefId) -> ty::CanonicalPolyFnSig<'tcx> {
+        self.closure_typeinfo(def_id).user_provided_sig
+    }
+
+    pub fn closure_captures(self, def_id: LocalDefId) -> &'tcx [&'tcx ty::CapturedPlace<'tcx>] {
+        if !self.is_closure(def_id.to_def_id()) {
+            return &[];
+        };
+        self.closure_typeinfo(def_id).captures
+    }
 }
 
 /// Return true if the `proj_possible_ancestor` represents an ancestor path
@@ -434,5 +458,5 @@ impl BorrowKind {
 }
 
 pub fn provide(providers: &mut ty::query::Providers) {
-    *providers = ty::query::Providers { symbols_for_closure_captures, ..*providers }
+    *providers = ty::query::Providers { closure_typeinfo, ..*providers }
 }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 884ae7f5da2..5d0cf23280b 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,6 +1,6 @@
 use crate::middle::resolve_bound_vars as rbv;
 use crate::mir::interpret::LitToConstInput;
-use crate::ty::{self, DefIdTree, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
 use rustc_data_structures::intern::Interned;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -16,7 +16,7 @@ pub use int::*;
 pub use kind::*;
 pub use valtree::*;
 
-/// Use this rather than `ConstData, whenever possible.
+/// Use this rather than `ConstData`, whenever possible.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable)]
 #[rustc_pass_by_value]
 pub struct Const<'tcx>(pub(super) Interned<'tcx, ConstData<'tcx>>);
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 433c9ab9aa2..70091477e39 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -20,11 +20,10 @@ use crate::traits;
 use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData};
 use crate::ty::query::{self, TyCtxtAt};
 use crate::ty::{
-    self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar,
-    FloatVid, GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst,
-    ParamTy, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind,
-    ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy,
-    Visibility,
+    self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, FloatTy, FloatVar, FloatVid,
+    GenericParamDefKind, ImplPolarity, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy,
+    PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, Region, RegionKind, ReprOptions,
+    TraitObjectVisitor, Ty, TyKind, TyVar, TyVid, TypeAndMut, TypeckResults, UintTy, Visibility,
 };
 use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
 use rustc_ast as ast;
@@ -310,7 +309,7 @@ pub struct CommonLifetimes<'tcx> {
     pub re_vars: Vec<Region<'tcx>>,
 
     /// Pre-interned values of the form:
-    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })
+    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })`
     /// for small values of `i` and `v`.
     pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
 }
@@ -794,8 +793,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     pub fn consider_optimizing<T: Fn() -> String>(self, msg: T) -> bool {
-        let cname = self.crate_name(LOCAL_CRATE);
-        self.sess.consider_optimizing(cname.as_str(), msg)
+        self.sess.consider_optimizing(|| self.crate_name(LOCAL_CRATE), msg)
     }
 
     /// Obtain all lang items of this crate and all dependencies (recursively)
@@ -2187,7 +2185,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // Actually intern type lists as lists of `GenericArg`s.
         //
         // Transmuting from `Ty<'tcx>` to `GenericArg<'tcx>` is sound
-        // as explained in ty_slice_as_generic_arg`. With this,
+        // as explained in `ty_slice_as_generic_arg`. With this,
         // we guarantee that even when transmuting between `List<Ty<'tcx>>`
         // and `List<GenericArg<'tcx>>`, the uniqueness requirement for
         // lists is upheld.
@@ -2450,7 +2448,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
         self.tcx.ty_error_with_message(self.span, "TyKind::Error constructed but no error reported")
     }
 
-    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
+    /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg` to
     /// ensure it gets used.
     #[track_caller]
     pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
@@ -2487,8 +2485,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
         |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]);
     providers.maybe_unused_trait_imports =
         |tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
-    providers.maybe_unused_extern_crates =
-        |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..];
     providers.names_imported_by_glob_use = |tcx, id| {
         tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
     };
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index e894e1aaf36..3ca17e7273e 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -3,9 +3,9 @@
 use std::ops::ControlFlow;
 
 use crate::ty::{
-    AliasTy, Const, ConstKind, DefIdTree, FallibleTypeFolder, InferConst, InferTy, Opaque,
-    PolyTraitPredicate, Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
-    TypeSuperVisitable, TypeVisitable, TypeVisitor,
+    AliasTy, Const, ConstKind, FallibleTypeFolder, InferConst, InferTy, Opaque, PolyTraitPredicate,
+    Projection, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
+    TypeVisitor,
 };
 
 use rustc_data_structures::fx::FxHashMap;
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
index e268553f826..ac42d6e0510 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -1,5 +1,5 @@
 use crate::ty::context::TyCtxt;
-use crate::ty::{self, DefId, DefIdTree, ParamEnv, Ty};
+use crate::ty::{self, DefId, ParamEnv, Ty};
 
 /// Represents whether some type is inhabited in a given context.
 /// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index 355b8d8b431..92a040068dd 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -105,7 +105,7 @@ impl<'tcx> VariantDef {
 impl<'tcx> Ty<'tcx> {
     pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> {
         match self.kind() {
-            // For now, union`s are always considered inhabited
+            // For now, unions are always considered inhabited
             Adt(adt, _) if adt.is_union() => InhabitedPredicate::True,
             // Non-exhaustive ADTs from other crates are always considered inhabited
             Adt(adt, _) if adt.is_variant_list_non_exhaustive() && !adt.did().is_local() => {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 6c59cde86e3..254ffc33c96 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -7,6 +7,7 @@ use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_index::vec::Idx;
 use rustc_session::config::OptLevel;
+use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::*;
@@ -92,7 +93,7 @@ impl IntegerExt for Integer {
             if discr < fit {
                 bug!(
                     "Integer::repr_discr: `#[repr]` hint too small for \
-                      discriminant range of enum `{}",
+                      discriminant range of enum `{}`",
                     ty
                 )
             }
@@ -169,6 +170,41 @@ pub const FAT_PTR_EXTRA: usize = 1;
 /// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
 pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
 
+/// Used in `check_validity_requirement` to indicate the kind of initialization
+/// that is checked to be valid
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
+pub enum ValidityRequirement {
+    Inhabited,
+    Zero,
+    /// The return value of mem::uninitialized, 0x01
+    /// (unless -Zstrict-init-checks is on, in which case it's the same as Uninit).
+    UninitMitigated0x01Fill,
+    /// True uninitialized memory.
+    Uninit,
+}
+
+impl ValidityRequirement {
+    pub fn from_intrinsic(intrinsic: Symbol) -> Option<Self> {
+        match intrinsic {
+            sym::assert_inhabited => Some(Self::Inhabited),
+            sym::assert_zero_valid => Some(Self::Zero),
+            sym::assert_mem_uninitialized_valid => Some(Self::UninitMitigated0x01Fill),
+            _ => None,
+        }
+    }
+}
+
+impl fmt::Display for ValidityRequirement {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Inhabited => f.write_str("is inhabited"),
+            Self::Zero => f.write_str("allows being left zeroed"),
+            Self::UninitMitigated0x01Fill => f.write_str("allows being filled with 0x01"),
+            Self::Uninit => f.write_str("allows being left uninitialized"),
+        }
+    }
+}
+
 #[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
 pub enum LayoutError<'tcx> {
     Unknown(Ty<'tcx>),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 17262a0be24..8cc8a0573bb 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -73,7 +73,7 @@ pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
 pub use self::closure::{
     is_ancestor_or_same_capture, place_to_string_for_capture, BorrowKind, CaptureInfo,
-    CapturedPlace, ClosureKind, MinCaptureInformationMap, MinCaptureList,
+    CapturedPlace, ClosureKind, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
     RootVariableMinCaptureList, UpvarCapture, UpvarCaptureMap, UpvarId, UpvarListMap, UpvarPath,
     CAPTURE_STRUCT_LOCAL,
 };
@@ -165,12 +165,8 @@ pub struct ResolverGlobalCtxt {
     pub effective_visibilities: EffectiveVisibilities,
     pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
     pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
-    pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
     pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>,
     pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
-    /// Extern prelude entries. The value is `true` if the entry was introduced
-    /// via `extern crate` item and not `--extern` option or compiler built-in.
-    pub extern_prelude: FxHashMap<Symbol, bool>,
     pub main_def: Option<MainDefinition>,
     pub trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
     /// A list of proc macro LocalDefIds, written out in the order in which
@@ -329,12 +325,15 @@ pub struct ClosureSizeProfileData<'tcx> {
     pub after_feature_tys: Ty<'tcx>,
 }
 
-pub trait DefIdTree: Copy {
-    fn opt_parent(self, id: DefId) -> Option<DefId>;
+impl TyCtxt<'_> {
+    #[inline]
+    pub fn opt_parent(self, id: DefId) -> Option<DefId> {
+        self.def_key(id).parent.map(|index| DefId { index, ..id })
+    }
 
     #[inline]
     #[track_caller]
-    fn parent(self, id: DefId) -> DefId {
+    pub fn parent(self, id: DefId) -> DefId {
         match self.opt_parent(id) {
             Some(id) => id,
             // not `unwrap_or_else` to avoid breaking caller tracking
@@ -344,17 +343,17 @@ pub trait DefIdTree: Copy {
 
     #[inline]
     #[track_caller]
-    fn opt_local_parent(self, id: LocalDefId) -> Option<LocalDefId> {
+    pub fn opt_local_parent(self, id: LocalDefId) -> Option<LocalDefId> {
         self.opt_parent(id.to_def_id()).map(DefId::expect_local)
     }
 
     #[inline]
     #[track_caller]
-    fn local_parent(self, id: LocalDefId) -> LocalDefId {
+    pub fn local_parent(self, id: LocalDefId) -> LocalDefId {
         self.parent(id.to_def_id()).expect_local()
     }
 
-    fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
+    pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
         if descendant.krate != ancestor.krate {
             return false;
         }
@@ -369,13 +368,6 @@ pub trait DefIdTree: Copy {
     }
 }
 
-impl<'tcx> DefIdTree for TyCtxt<'tcx> {
-    #[inline]
-    fn opt_parent(self, id: DefId) -> Option<DefId> {
-        self.def_key(id).parent.map(|index| DefId { index, ..id })
-    }
-}
-
 impl<Id> Visibility<Id> {
     pub fn is_public(self) -> bool {
         matches!(self, Visibility::Public)
@@ -395,19 +387,19 @@ impl<Id: Into<DefId>> Visibility<Id> {
     }
 
     /// Returns `true` if an item with this visibility is accessible from the given module.
-    pub fn is_accessible_from(self, module: impl Into<DefId>, tree: impl DefIdTree) -> bool {
+    pub fn is_accessible_from(self, module: impl Into<DefId>, tcx: TyCtxt<'_>) -> bool {
         match self {
             // Public items are visible everywhere.
             Visibility::Public => true,
-            Visibility::Restricted(id) => tree.is_descendant_of(module.into(), id.into()),
+            Visibility::Restricted(id) => tcx.is_descendant_of(module.into(), id.into()),
         }
     }
 
     /// Returns `true` if this visibility is at least as accessible as the given visibility
-    pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tree: impl DefIdTree) -> bool {
+    pub fn is_at_least(self, vis: Visibility<impl Into<DefId>>, tcx: TyCtxt<'_>) -> bool {
         match vis {
             Visibility::Public => self.is_public(),
-            Visibility::Restricted(id) => self.is_accessible_from(id, tree),
+            Visibility::Restricted(id) => self.is_accessible_from(id, tcx),
         }
     }
 }
@@ -714,7 +706,7 @@ impl<'tcx> Predicate<'tcx> {
         //   The substitution from the input trait-ref is therefore going to be
         //   `'a => 'x` (where `'x` has a DB index of 1).
         // - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
-        //   early-bound parameter and `'b' is a late-bound parameter with a
+        //   early-bound parameter and `'b` is a late-bound parameter with a
         //   DB index of 1.
         // - If we replace `'a` with `'x` from the input, it too will have
         //   a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
@@ -2075,6 +2067,12 @@ pub enum ImplOverlapKind {
     Issue33140,
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
+pub enum ImplTraitInTraitData {
+    Trait { fn_def_id: DefId, opaque_def_id: DefId },
+    Impl { fn_def_id: DefId },
+}
+
 impl<'tcx> TyCtxt<'tcx> {
     pub fn typeck_body(self, body: hir::BodyId) -> &'tcx TypeckResults<'tcx> {
         self.typeck(self.hir().body_owner_def_id(body))
@@ -2442,7 +2440,7 @@ impl<'tcx> TyCtxt<'tcx> {
         None
     }
 
-    /// Check if the given `DefId` is `#\[automatically_derived\], *and*
+    /// Check if the given `DefId` is `#\[automatically_derived\]`, *and*
     /// whether it was produced by expanding a builtin derive macro.
     pub fn is_builtin_derived(self, def_id: DefId) -> bool {
         if self.is_automatically_derived(def_id)
@@ -2545,6 +2543,34 @@ impl<'tcx> TyCtxt<'tcx> {
         }
         def_id
     }
+
+    pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
+        if self.def_kind(def_id) != DefKind::AssocFn {
+            return false;
+        }
+
+        let Some(item) = self.opt_associated_item(def_id) else { return false; };
+        if item.container != ty::AssocItemContainer::ImplContainer {
+            return false;
+        }
+
+        let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
+
+        // FIXME(RPITIT): This does a somewhat manual walk through the signature
+        // of the trait fn to look for any RPITITs, but that's kinda doing a lot
+        // of work. We can probably remove this when we refactor RPITITs to be
+        // associated types.
+        self.fn_sig(trait_item_def_id).subst_identity().skip_binder().output().walk().any(|arg| {
+            if let ty::GenericArgKind::Type(ty) = arg.unpack()
+                && let ty::Alias(ty::Projection, data) = ty.kind()
+                && self.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
+            {
+                true
+            } else {
+                false
+            }
+        })
+    }
 }
 
 /// Yields the parent function's `LocalDefId` if `def_id` is an `impl Trait` definition.
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index 57c8f3075b0..578cd82aa4c 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -7,7 +7,6 @@
 //! `normalize_generic_arg_after_erasing_regions` query for each type
 //! or constant found within. (This underlying query is what is cached.)
 
-use crate::mir;
 use crate::traits::query::NoSolution;
 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
 use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
@@ -16,7 +15,6 @@ use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
 pub enum NormalizationError<'tcx> {
     Type(Ty<'tcx>),
     Const(ty::Const<'tcx>),
-    ConstantKind(mir::ConstantKind<'tcx>),
 }
 
 impl<'tcx> NormalizationError<'tcx> {
@@ -24,7 +22,6 @@ impl<'tcx> NormalizationError<'tcx> {
         match self {
             NormalizationError::Type(t) => format!("{}", t),
             NormalizationError::Const(c) => format!("{}", c),
-            NormalizationError::ConstantKind(ck) => format!("{}", ck),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index 021c20b5854..d947d96041e 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -1,5 +1,5 @@
 use crate::ty::GenericArg;
-use crate::ty::{self, DefIdTree, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt};
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sso::SsoHashSet;
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 6a053c368d8..b3139d23d36 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,6 +1,6 @@
 use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
 use crate::ty::{
-    self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
+    self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
     TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
 use crate::ty::{GenericArg, GenericArgKind};
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index 3d9a5075d4a..2bc51baf879 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -32,6 +32,7 @@ use crate::traits::specialization_graph;
 use crate::traits::{self, ImplSource};
 use crate::ty::context::TyCtxtFeed;
 use crate::ty::fast_reject::SimplifiedType;
+use crate::ty::layout::ValidityRequirement;
 use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::util::AlwaysRequiresDrop;
 use crate::ty::GeneratorDiagnosticData;
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 1d4d76da572..ef643531bb2 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -263,6 +263,7 @@ TrivialTypeTraversalAndLiftImpls! {
     crate::ty::UniverseIndex,
     crate::ty::Variance,
     ::rustc_span::Span,
+    ::rustc_span::symbol::Ident,
     ::rustc_errors::ErrorGuaranteed,
     Field,
     interpret::Scalar,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index ba714541c9e..52d114bae30 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -7,7 +7,7 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use crate::ty::visit::ValidateBoundVars;
 use crate::ty::InferTy::*;
 use crate::ty::{
-    self, AdtDef, DefIdTree, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable,
+    self, AdtDef, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable,
     TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
 use crate::ty::{List, ParamEnv};
@@ -107,6 +107,15 @@ impl BoundRegionKind {
             _ => None,
         }
     }
+
+    pub fn expect_anon(&self) -> u32 {
+        match *self {
+            BoundRegionKind::BrNamed(_, _) | BoundRegionKind::BrEnv => {
+                bug!("expected anon region: {self:?}")
+            }
+            BoundRegionKind::BrAnon(idx, _) => idx,
+        }
+    }
 }
 
 pub trait Article {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 9beaac87183..586958247fc 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -569,7 +569,7 @@ impl<'a, V> LocalTableInContext<'a, V> {
         self.data.contains_key(&id.local_id)
     }
 
-    pub fn get(&self, id: hir::HirId) -> Option<&V> {
+    pub fn get(&self, id: hir::HirId) -> Option<&'a V> {
         validate_hir_id_for_typeck_results(self.hir_owner, id);
         self.data.get(&id.local_id)
     }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 90270e0ee9d..8b5469743da 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -4,8 +4,8 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::mir;
 use crate::ty::layout::IntegerExt;
 use crate::ty::{
-    self, DefIdTree, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder,
-    TypeSuperFoldable, TypeVisitableExt,
+    self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
+    TypeVisitableExt,
 };
 use crate::ty::{GenericArgKind, SubstsRef};
 use rustc_apfloat::Float as _;
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index c4f526dbdc8..55aa4fcff2c 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -4,7 +4,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_middle::ty::Representability;
-use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_query_system::query::QueryInfo;
 use rustc_query_system::Value;
 use rustc_span::def_id::LocalDefId;
diff --git a/compiler/rustc_mir_build/locales/en-US.ftl b/compiler/rustc_mir_build/locales/en-US.ftl
index f9bda721df3..93e7fb330e0 100644
--- a/compiler/rustc_mir_build/locales/en-US.ftl
+++ b/compiler/rustc_mir_build/locales/en-US.ftl
@@ -374,3 +374,9 @@ mir_build_suggest_let_else = you might want to use `let else` to handle the {$co
     } matched
 
 mir_build_suggest_attempted_int_lit = alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
+
+
+mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
+    .attributes = no other attributes may be applied
+    .not_box = `#[rustc_box]` may only be applied to a `Box::new()` call
+    .missing_box = `#[rustc_box]` requires the `owned_box` lang item
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 2f63333d46b..cfacb5ea327 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -55,7 +55,7 @@ pub fn as_constant_inner<'tcx>(
                         ConstantKind::Ty(tcx.const_error_with_guaranteed(ty, guar))
                     }
                     Err(LitToConstError::TypeError) => {
-                        bug!("encountered type error in `lit_to_mir_constant")
+                        bug!("encountered type error in `lit_to_mir_constant`")
                     }
                 };
 
diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs
index eb20b2308c0..33200b80a57 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -11,7 +11,7 @@ use rustc_middle::mir::AssertKind::BoundsCheck;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::AdtDef;
-use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance};
+use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, Variance};
 use rustc_span::Span;
 use rustc_target::abi::VariantIdx;
 
@@ -183,7 +183,7 @@ fn to_upvars_resolved_place_builder<'tcx>(
             &projection,
         ) else {
         let closure_span = cx.tcx.def_span(closure_def_id);
-        if !enable_precise_capture(cx.tcx, closure_span) {
+        if !enable_precise_capture(closure_span) {
             bug!(
                 "No associated capture found for {:?}[{:#?}] even though \
                     capture_disjoint_fields isn't enabled",
@@ -745,8 +745,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 }
 
-/// Precise capture is enabled if the feature gate `capture_disjoint_fields` is enabled or if
-/// user is using Rust Edition 2021 or higher.
-fn enable_precise_capture(tcx: TyCtxt<'_>, closure_span: Span) -> bool {
-    tcx.features().capture_disjoint_fields || closure_span.rust_2021()
+/// Precise capture is enabled if user is using Rust Edition 2021 or higher.
+fn enable_precise_capture(closure_span: Span) -> bool {
+    closure_span.rust_2021()
 }
diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs
index 78083685193..ea5aeb67d85 100644
--- a/compiler/rustc_mir_build/src/build/expr/stmt.rs
+++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs
@@ -40,7 +40,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // Generate better code for things that don't need to be
                 // dropped.
                 if lhs.ty.needs_drop(this.tcx, this.param_env) {
-                    let rhs = unpack!(block = this.as_local_operand(block, rhs));
+                    let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
                     let lhs = unpack!(block = this.as_place(block, lhs));
                     unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs));
                 } else {
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index a6de8684c0f..b3f9d82829f 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::*;
 use rustc_middle::thir::{
     self, BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
 };
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypeckResults};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_span::Symbol;
@@ -47,8 +47,6 @@ pub(crate) fn mir_built(
 
 /// Construct the MIR for a given `DefId`.
 fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
-    let body_owner_kind = tcx.hir().body_owner_kind(def.did);
-
     // Ensure unsafeck and abstract const building is ran before we steal the THIR.
     // We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query
     // if inputs are green. This can cause ICEs when calling `thir_abstract_const` after
@@ -65,16 +63,15 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
     }
 
     let body = match tcx.thir_body(def) {
-        Err(error_reported) => construct_error(tcx, def.did, body_owner_kind, error_reported),
+        Err(error_reported) => construct_error(tcx, def.did, error_reported),
         Ok((thir, expr)) => {
             // We ran all queries that depended on THIR at the beginning
             // of `mir_build`, so now we can steal it
             let thir = thir.steal();
 
-            if body_owner_kind.is_fn_or_closure() {
-                construct_fn(tcx, def, &thir, expr)
-            } else {
-                construct_const(tcx, def, &thir, expr)
+            match thir.body_type {
+                thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, &thir, expr, fn_sig),
+                thir::BodyTy::Const(ty) => construct_const(tcx, def, &thir, expr, ty),
             }
         }
     };
@@ -158,13 +155,13 @@ struct BlockContext(Vec<BlockFrame>);
 struct Builder<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     infcx: InferCtxt<'tcx>,
-    typeck_results: &'tcx TypeckResults<'tcx>,
     region_scope_tree: &'tcx region::ScopeTree,
     param_env: ty::ParamEnv<'tcx>,
 
     thir: &'a Thir<'tcx>,
     cfg: CFG<'tcx>,
 
+    def: ty::WithOptConstParam<LocalDefId>,
     def_id: DefId,
     hir_id: hir::HirId,
     parent_module: DefId,
@@ -434,6 +431,7 @@ fn construct_fn<'tcx>(
     fn_def: ty::WithOptConstParam<LocalDefId>,
     thir: &Thir<'tcx>,
     expr: ExprId,
+    fn_sig: ty::FnSig<'tcx>,
 ) -> Body<'tcx> {
     let span = tcx.def_span(fn_def.did);
     let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def.did);
@@ -453,11 +451,6 @@ fn construct_fn<'tcx>(
         .output
         .span();
 
-    // fetch the fully liberated fn signature (that is, all bound
-    // types/lifetimes replaced)
-    let typeck_results = tcx.typeck_opt_const_arg(fn_def);
-    let fn_sig = typeck_results.liberated_fn_sigs()[fn_id];
-
     let safety = match fn_sig.unsafety {
         hir::Unsafety::Normal => Safety::Safe,
         hir::Unsafety::Unsafe => Safety::FnUnsafe,
@@ -529,13 +522,7 @@ fn construct_fn<'tcx>(
         let return_block =
             unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
                 Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
-                    builder.args_and_body(
-                        START_BLOCK,
-                        fn_def.did,
-                        arguments,
-                        arg_scope,
-                        &thir[expr],
-                    )
+                    builder.args_and_body(START_BLOCK, arguments, arg_scope, &thir[expr])
                 }))
             }));
         let source_info = builder.source_info(fn_end);
@@ -563,6 +550,7 @@ fn construct_const<'a, 'tcx>(
     def: ty::WithOptConstParam<LocalDefId>,
     thir: &'a Thir<'tcx>,
     expr: ExprId,
+    const_ty: Ty<'tcx>,
 ) -> Body<'tcx> {
     let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
 
@@ -586,20 +574,6 @@ fn construct_const<'a, 'tcx>(
         _ => span_bug!(tcx.def_span(def.did), "can't build MIR for {:?}", def.did),
     };
 
-    // Get the revealed type of this const. This is *not* the adjusted
-    // type of its body, which may be a subtype of this type. For
-    // example:
-    //
-    // fn foo(_: &()) {}
-    // static X: fn(&'static ()) = foo;
-    //
-    // The adjusted type of the body of X is `for<'a> fn(&'a ())` which
-    // is not the same as the type of X. We need the type of the return
-    // place to be the type of the constant because NLL typeck will
-    // equate them.
-    let typeck_results = tcx.typeck_opt_const_arg(def);
-    let const_ty = typeck_results.node_type(hir_id);
-
     let infcx = tcx.infer_ctxt().build();
     let mut builder = Builder::new(
         thir,
@@ -629,15 +603,11 @@ fn construct_const<'a, 'tcx>(
 ///
 /// This is required because we may still want to run MIR passes on an item
 /// with type errors, but normal MIR construction can't handle that in general.
-fn construct_error(
-    tcx: TyCtxt<'_>,
-    def: LocalDefId,
-    body_owner_kind: hir::BodyOwnerKind,
-    err: ErrorGuaranteed,
-) -> Body<'_> {
+fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> {
     let span = tcx.def_span(def);
     let hir_id = tcx.hir().local_def_id_to_hir_id(def);
     let generator_kind = tcx.generator_kind(def);
+    let body_owner_kind = tcx.hir().body_owner_kind(def);
 
     let ty = tcx.ty_error(err);
     let num_params = match body_owner_kind {
@@ -728,9 +698,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             thir,
             tcx,
             infcx,
-            typeck_results: tcx.typeck_opt_const_arg(def),
             region_scope_tree: tcx.region_scope_tree(def.did),
             param_env,
+            def,
             def_id: def.did.to_def_id(),
             hir_id,
             parent_module: tcx.parent_module(hir_id).to_def_id(),
@@ -780,14 +750,78 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.var_debug_info,
             self.fn_span,
             self.generator_kind,
-            self.typeck_results.tainted_by_errors,
+            None,
         )
     }
 
+    fn insert_upvar_arg(&mut self) {
+        let Some(closure_arg) = self.local_decls.get(ty::CAPTURE_STRUCT_LOCAL) else { return };
+
+        let mut closure_ty = closure_arg.ty;
+        let mut closure_env_projs = vec![];
+        if let ty::Ref(_, ty, _) = closure_ty.kind() {
+            closure_env_projs.push(ProjectionElem::Deref);
+            closure_ty = *ty;
+        }
+
+        let upvar_substs = match closure_ty.kind() {
+            ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
+            ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
+            _ => return,
+        };
+
+        // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
+        // indexed closure and we stored in a map called closure_min_captures in TypeckResults
+        // with the closure's DefId. Here, we run through that vec of UpvarIds for
+        // the given closure and use the necessary information to create upvar
+        // debuginfo and to fill `self.upvars`.
+        let capture_tys = upvar_substs.upvar_tys();
+
+        let tcx = self.tcx;
+        self.upvars = tcx
+            .closure_captures(self.def.did)
+            .iter()
+            .zip(capture_tys)
+            .enumerate()
+            .map(|(i, (captured_place, ty))| {
+                let name = captured_place.to_symbol();
+
+                let capture = captured_place.info.capture_kind;
+                let var_id = match captured_place.place.base {
+                    HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
+                    _ => bug!("Expected an upvar"),
+                };
+
+                let mutability = captured_place.mutability;
+
+                let mut projs = closure_env_projs.clone();
+                projs.push(ProjectionElem::Field(Field::new(i), ty));
+                match capture {
+                    ty::UpvarCapture::ByValue => {}
+                    ty::UpvarCapture::ByRef(..) => {
+                        projs.push(ProjectionElem::Deref);
+                    }
+                };
+
+                let use_place = Place {
+                    local: ty::CAPTURE_STRUCT_LOCAL,
+                    projection: tcx.mk_place_elems(&projs),
+                };
+                self.var_debug_info.push(VarDebugInfo {
+                    name,
+                    source_info: SourceInfo::outermost(captured_place.var_ident.span),
+                    value: VarDebugInfoContents::Place(use_place),
+                });
+
+                let capture = Capture { captured_place, use_place, mutability };
+                (var_id, capture)
+            })
+            .collect();
+    }
+
     fn args_and_body(
         &mut self,
         mut block: BasicBlock,
-        fn_def_id: LocalDefId,
         arguments: &IndexVec<ParamId, Param<'tcx>>,
         argument_scope: region::Scope,
         expr: &Expr<'tcx>,
@@ -809,69 +843,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         }
 
-        let tcx = self.tcx;
-        let tcx_hir = tcx.hir();
-        let hir_typeck_results = self.typeck_results;
-
-        // In analyze_closure() in upvar.rs we gathered a list of upvars used by an
-        // indexed closure and we stored in a map called closure_min_captures in TypeckResults
-        // with the closure's DefId. Here, we run through that vec of UpvarIds for
-        // the given closure and use the necessary information to create upvar
-        // debuginfo and to fill `self.upvars`.
-        if hir_typeck_results.closure_min_captures.get(&fn_def_id).is_some() {
-            let mut closure_env_projs = vec![];
-            let mut closure_ty = self.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
-            if let ty::Ref(_, ty, _) = closure_ty.kind() {
-                closure_env_projs.push(ProjectionElem::Deref);
-                closure_ty = *ty;
-            }
-            let upvar_substs = match closure_ty.kind() {
-                ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
-                ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
-                _ => span_bug!(self.fn_span, "upvars with non-closure env ty {:?}", closure_ty),
-            };
-            let def_id = self.def_id.as_local().unwrap();
-            let capture_syms = tcx.symbols_for_closure_captures((def_id, fn_def_id));
-            let capture_tys = upvar_substs.upvar_tys();
-            let captures_with_tys = hir_typeck_results
-                .closure_min_captures_flattened(fn_def_id)
-                .zip(capture_tys.zip(capture_syms));
-
-            self.upvars = captures_with_tys
-                .enumerate()
-                .map(|(i, (captured_place, (ty, sym)))| {
-                    let capture = captured_place.info.capture_kind;
-                    let var_id = match captured_place.place.base {
-                        HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
-                        _ => bug!("Expected an upvar"),
-                    };
-
-                    let mutability = captured_place.mutability;
-
-                    let mut projs = closure_env_projs.clone();
-                    projs.push(ProjectionElem::Field(Field::new(i), ty));
-                    match capture {
-                        ty::UpvarCapture::ByValue => {}
-                        ty::UpvarCapture::ByRef(..) => {
-                            projs.push(ProjectionElem::Deref);
-                        }
-                    };
-
-                    let use_place = Place {
-                        local: ty::CAPTURE_STRUCT_LOCAL,
-                        projection: tcx.mk_place_elems(&projs),
-                    };
-                    self.var_debug_info.push(VarDebugInfo {
-                        name: *sym,
-                        source_info: SourceInfo::outermost(tcx_hir.span(var_id)),
-                        value: VarDebugInfoContents::Place(use_place),
-                    });
-
-                    let capture = Capture { captured_place, use_place, mutability };
-                    (var_id, capture)
-                })
-                .collect();
-        }
+        self.insert_upvar_arg();
 
         let mut scope = None;
         // Bind the argument patterns
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 591b416337b..770701b3750 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -91,7 +91,7 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::*;
 use rustc_middle::thir::{Expr, LintLevel};
 
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{DesugaringKind, Span, DUMMY_SP};
 
 #[derive(Debug)]
 pub struct Scopes<'tcx> {
@@ -1118,24 +1118,35 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     /// Utility function for *non*-scope code to build their own drops
+    /// Force a drop at this point in the MIR by creating a new block.
     pub(crate) fn build_drop_and_replace(
         &mut self,
         block: BasicBlock,
         span: Span,
         place: Place<'tcx>,
-        value: Operand<'tcx>,
+        value: Rvalue<'tcx>,
     ) -> BlockAnd<()> {
+        let span = self.tcx.with_stable_hashing_context(|hcx| {
+            span.mark_with_reason(None, DesugaringKind::Replace, self.tcx.sess.edition(), hcx)
+        });
         let source_info = self.source_info(span);
-        let next_target = self.cfg.start_new_block();
+
+        // create the new block for the assignment
+        let assign = self.cfg.start_new_block();
+        self.cfg.push_assign(assign, source_info, place, value.clone());
+
+        // create the new block for the assignment in the case of unwinding
+        let assign_unwind = self.cfg.start_new_cleanup_block();
+        self.cfg.push_assign(assign_unwind, source_info, place, value.clone());
 
         self.cfg.terminate(
             block,
             source_info,
-            TerminatorKind::DropAndReplace { place, value, target: next_target, unwind: None },
+            TerminatorKind::Drop { place, target: assign, unwind: Some(assign_unwind) },
         );
         self.diverge_from(block);
 
-        next_target.unit()
+        assign.unit()
     }
 
     /// Creates an `Assert` terminator and return the success block.
@@ -1413,8 +1424,15 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
     fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
         let term = &mut cfg.block_data_mut(from).terminator_mut();
         match &mut term.kind {
-            TerminatorKind::Drop { unwind, .. }
-            | TerminatorKind::DropAndReplace { unwind, .. }
+            TerminatorKind::Drop { unwind, .. } => {
+                if let Some(unwind) = *unwind {
+                    let source_info = term.source_info;
+                    cfg.terminate(unwind, source_info, TerminatorKind::Goto { target: to });
+                } else {
+                    *unwind = Some(to);
+                }
+            }
+            TerminatorKind::DropAndReplace { unwind, .. }
             | TerminatorKind::FalseUnwind { unwind, .. }
             | TerminatorKind::Call { cleanup: unwind, .. }
             | TerminatorKind::Assert { cleanup: unwind, .. }
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index c1f6b8b59ce..dc4d2276e4a 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -888,3 +888,22 @@ pub enum MiscPatternSuggestion {
         start_span: Span,
     },
 }
+
+#[derive(Diagnostic)]
+#[diag(mir_build_rustc_box_attribute_error)]
+pub struct RustcBoxAttributeError {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub reason: RustcBoxAttrReason,
+}
+
+#[derive(Subdiagnostic)]
+pub enum RustcBoxAttrReason {
+    #[note(mir_build_attributes)]
+    Attributes,
+    #[note(mir_build_not_box)]
+    NotBoxNew,
+    #[note(mir_build_missing_box)]
+    MissingBox,
+}
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index fbc130501f9..e10a264d385 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -38,6 +38,6 @@ pub fn provide(providers: &mut Providers) {
     providers.thir_check_unsafety = check_unsafety::thir_check_unsafety;
     providers.thir_check_unsafety_for_const_arg = check_unsafety::thir_check_unsafety_for_const_arg;
     providers.thir_body = thir::cx::thir_body;
-    providers.thir_tree = thir::cx::thir_tree;
-    providers.thir_flat = thir::cx::thir_flat;
+    providers.thir_tree = thir::print::thir_tree;
+    providers.thir_flat = thir::print::thir_flat;
 }
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index ae203233bd5..9086412c09a 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -1,3 +1,4 @@
+use crate::errors;
 use crate::thir::cx::region::Scope;
 use crate::thir::cx::Cx;
 use crate::thir::util::UserAnnotatedTyHelpers;
@@ -18,7 +19,7 @@ use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::{
     self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType,
 };
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 use rustc_target::abi::VariantIdx;
 
 impl<'tcx> Cx<'tcx> {
@@ -33,8 +34,6 @@ impl<'tcx> Cx<'tcx> {
 
     #[instrument(level = "trace", skip(self, hir_expr))]
     pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId {
-        let temp_lifetime =
-            self.rvalue_scopes.temporary_scope(self.region_scope_tree, hir_expr.hir_id.local_id);
         let expr_scope =
             region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node };
 
@@ -67,7 +66,7 @@ impl<'tcx> Cx<'tcx> {
 
         // Next, wrap this up in the expr's scope.
         expr = Expr {
-            temp_lifetime,
+            temp_lifetime: expr.temp_lifetime,
             ty: expr.ty,
             span: hir_expr.span,
             kind: ExprKind::Scope {
@@ -82,7 +81,7 @@ impl<'tcx> Cx<'tcx> {
             self.region_scope_tree.opt_destruction_scope(hir_expr.hir_id.local_id)
         {
             expr = Expr {
-                temp_lifetime,
+                temp_lifetime: expr.temp_lifetime,
                 ty: expr.ty,
                 span: hir_expr.span,
                 kind: ExprKind::Scope {
@@ -262,6 +261,7 @@ impl<'tcx> Cx<'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self), ret)]
     fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
         let tcx = self.tcx;
         let expr_ty = self.typeck_results().expr_ty(expr);
@@ -322,6 +322,34 @@ impl<'tcx> Cx<'tcx> {
                         fn_span: expr.span,
                     }
                 } else {
+                    let attrs = tcx.hir().attrs(expr.hir_id);
+                    if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_box) {
+                        if attrs.len() != 1 {
+                            tcx.sess.emit_err(errors::RustcBoxAttributeError {
+                                span: attrs[0].span,
+                                reason: errors::RustcBoxAttrReason::Attributes,
+                            });
+                        } else if let Some(box_item) = tcx.lang_items().owned_box() {
+                            if let hir::ExprKind::Path(hir::QPath::TypeRelative(ty, fn_path)) = fun.kind
+                                && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
+                                && path.res.opt_def_id().map_or(false, |did| did == box_item)
+                                && fn_path.ident.name == sym::new
+                                && let [value] = args
+                            {
+                                return Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: ExprKind::Box { value: self.mirror_expr(value) } }
+                            } else {
+                                tcx.sess.emit_err(errors::RustcBoxAttributeError {
+                                    span: expr.span,
+                                    reason: errors::RustcBoxAttrReason::NotBoxNew
+                                });
+                            }
+                        } else {
+                            tcx.sess.emit_err(errors::RustcBoxAttributeError {
+                                span: attrs[0].span,
+                                reason: errors::RustcBoxAttrReason::MissingBox,
+                            });
+                        }
+                    }
                     let adt_data =
                         if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind {
                             // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
@@ -541,8 +569,9 @@ impl<'tcx> Cx<'tcx> {
                 let def_id = def_id.expect_local();
 
                 let upvars = self
-                    .typeck_results
-                    .closure_min_captures_flattened(def_id)
+                    .tcx
+                    .closure_captures(def_id)
+                    .iter()
                     .zip(substs.upvar_tys())
                     .map(|(captured_place, ty)| {
                         let upvars = self.capture_upvar(expr, captured_place, ty);
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 20af60a511e..070544446e3 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -52,23 +52,6 @@ pub(crate) fn thir_body(
     Ok((tcx.alloc_steal_thir(cx.thir), expr))
 }
 
-pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
-    match thir_body(tcx, owner_def) {
-        Ok((thir, _)) => {
-            let thir = thir.steal();
-            tcx.thir_tree_representation(&thir)
-        }
-        Err(_) => "error".into(),
-    }
-}
-
-pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
-    match thir_body(tcx, owner_def) {
-        Ok((thir, _)) => format!("{:#?}", thir.steal()),
-        Err(_) => "error".into(),
-    }
-}
-
 struct Cx<'tcx> {
     tcx: TyCtxt<'tcx>,
     thir: Thir<'tcx>,
@@ -99,9 +82,30 @@ impl<'tcx> Cx<'tcx> {
         let typeck_results = tcx.typeck_opt_const_arg(def);
         let did = def.did;
         let hir = tcx.hir();
+        let hir_id = hir.local_def_id_to_hir_id(did);
+
+        let body_type = if hir.body_owner_kind(did).is_fn_or_closure() {
+            // fetch the fully liberated fn signature (that is, all bound
+            // types/lifetimes replaced)
+            BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
+        } else {
+            // Get the revealed type of this const. This is *not* the adjusted
+            // type of its body, which may be a subtype of this type. For
+            // example:
+            //
+            // fn foo(_: &()) {}
+            // static X: fn(&'static ()) = foo;
+            //
+            // The adjusted type of the body of X is `for<'a> fn(&'a ())` which
+            // is not the same as the type of X. We need the type of the return
+            // place to be the type of the constant because NLL typeck will
+            // equate them.
+            BodyTy::Const(typeck_results.node_type(hir_id))
+        };
+
         Cx {
             tcx,
-            thir: Thir::new(),
+            thir: Thir::new(body_type),
             param_env: tcx.param_env(def.did),
             region_scope_tree: tcx.region_scope_tree(def.did),
             typeck_results,
@@ -109,7 +113,7 @@ impl<'tcx> Cx<'tcx> {
             body_owner: did.to_def_id(),
             adjustment_span: None,
             apply_adjustments: hir
-                .attrs(hir.local_def_id_to_hir_id(did))
+                .attrs(hir_id)
                 .iter()
                 .all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
         }
diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs
index e0e6ac26654..ca26cc13b5e 100644
--- a/compiler/rustc_mir_build/src/thir/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/mod.rs
@@ -5,9 +5,7 @@
 //! structures.
 
 pub(crate) mod constant;
-
 pub(crate) mod cx;
-
 pub(crate) mod pattern;
-
+pub(crate) mod print;
 mod util;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 41306dd80fb..f356c8a6838 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -25,7 +25,7 @@ use rustc_middle::mir::{BorrowKind, Field, Mutability};
 use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange};
 use rustc_middle::ty::subst::{GenericArg, SubstsRef};
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
-use rustc_middle::ty::{self, AdtDef, ConstKind, DefIdTree, Region, Ty, TyCtxt, UserType};
+use rustc_middle::ty::{self, AdtDef, ConstKind, Region, Ty, TyCtxt, UserType};
 use rustc_span::{Span, Symbol};
 
 use std::cmp::Ordering;
diff --git a/compiler/rustc_middle/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 60b903e9906..8028227aafd 100644
--- a/compiler/rustc_middle/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -1,13 +1,24 @@
-use crate::thir::*;
-use crate::ty::{self, TyCtxt};
-
+use rustc_middle::thir::*;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::LocalDefId;
 use std::fmt::{self, Write};
 
-impl<'tcx> TyCtxt<'tcx> {
-    pub fn thir_tree_representation<'a>(self, thir: &'a Thir<'tcx>) -> String {
-        let mut printer = ThirPrinter::new(thir);
-        printer.print();
-        printer.into_buffer()
+pub(crate) fn thir_tree(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
+    match super::cx::thir_body(tcx, owner_def) {
+        Ok((thir, _)) => {
+            let thir = thir.steal();
+            let mut printer = ThirPrinter::new(&thir);
+            printer.print();
+            printer.into_buffer()
+        }
+        Err(_) => "error".into(),
+    }
+}
+
+pub(crate) fn thir_flat(tcx: TyCtxt<'_>, owner_def: ty::WithOptConstParam<LocalDefId>) -> String {
+    match super::cx::thir_body(tcx, owner_def) {
+        Ok((thir, _)) => format!("{:#?}", thir.steal()),
+        Err(_) => "error".into(),
     }
 }
 
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index fa5f392fa74..536745d2cfe 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -74,7 +74,7 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
         //
         // `unsafe { *FOO = 0; *BAR.field = 1; }`
         // `unsafe { &mut *FOO }`
-        // `unsafe { (*ARRAY)[0] = val; }
+        // `unsafe { (*ARRAY)[0] = val; }`
         if !place.projection.iter().any(|p| matches!(p, PlaceElem::Deref)) {
             let source_info = self.body.source_info(location);
             let lint_root = self.body.source_scopes[source_info.scope]
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index f973c1ed28f..8ee316773ae 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -407,7 +407,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
                 if self.prev().is_macro_expansion() && self.curr().is_macro_expansion() {
                     // Macros that expand to include branching (such as
                     // `assert_eq!()`, `assert_ne!()`, `info!()`, `debug!()`, or
-                    // `trace!()) typically generate callee spans with identical
+                    // `trace!()`) typically generate callee spans with identical
                     // ranges (typically the full span of the macro) for all
                     // `BasicBlocks`. This makes it impossible to distinguish
                     // the condition (`if val1 != val2`) from the optional
@@ -694,7 +694,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
     /// `prev.span.hi()` will be greater than (further right of) `prev_original_span.hi()`.
     /// If prev.span() was split off to the right of a closure, prev.span().lo() will be
     /// greater than prev_original_span.lo(). The actual span of `prev_original_span` is
-    /// not as important as knowing that `prev()` **used to have the same span** as `curr(),
+    /// not as important as knowing that `prev()` **used to have the same span** as `curr()`,
     /// which means their sort order is still meaningful for determining the dominator
     /// relationship.
     ///
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index bdfd8dc6e99..29424f09695 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -14,7 +14,7 @@ use rustc_mir_dataflow::un_derefer::UnDerefer;
 use rustc_mir_dataflow::MoveDataParamEnv;
 use rustc_mir_dataflow::{on_all_children_bits, on_all_drop_children_bits};
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
-use rustc_span::Span;
+use rustc_span::{DesugaringKind, Span};
 use rustc_target::abi::VariantIdx;
 use std::fmt;
 
@@ -425,10 +425,19 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                             bb,
                         ),
                         LookupResult::Parent(..) => {
-                            self.tcx.sess.delay_span_bug(
-                                terminator.source_info.span,
-                                &format!("drop of untracked value {:?}", bb),
-                            );
+                            if !matches!(
+                                terminator.source_info.span.desugaring_kind(),
+                                Some(DesugaringKind::Replace),
+                            ) {
+                                self.tcx.sess.delay_span_bug(
+                                    terminator.source_info.span,
+                                    &format!("drop of untracked value {:?}", bb),
+                                );
+                            }
+                            // A drop and replace behind a pointer/array/whatever.
+                            // The borrow checker requires that these locations are initialized before the assignment,
+                            // so we just leave an unconditional drop.
+                            assert!(!data.is_cleanup);
                         }
                     }
                 }
diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 14e644bc344..4182da1957e 100644
--- a/compiler/rustc_mir_transform/src/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -6,9 +6,9 @@ use rustc_middle::mir::{
     BinOp, Body, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem, Rvalue,
     SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UnOp,
 };
-use rustc_middle::ty::layout::LayoutError;
-use rustc_middle::ty::{self, ParamEnv, ParamEnvAnd, SubstsRef, Ty, TyCtxt};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_middle::ty::layout::ValidityRequirement;
+use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
+use rustc_span::symbol::Symbol;
 
 pub struct InstCombine;
 
@@ -234,16 +234,15 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
         }
         let ty = substs.type_at(0);
 
-        // Check this is a foldable intrinsic before we query the layout of our generic parameter
-        let Some(assert_panics) = intrinsic_assert_panics(intrinsic_name) else { return; };
-        match assert_panics(self.tcx, self.param_env.and(ty)) {
-            // We don't know the layout, don't touch the assertion
-            Err(_) => {}
-            Ok(true) => {
+        let known_is_valid = intrinsic_assert_panics(self.tcx, self.param_env, ty, intrinsic_name);
+        match known_is_valid {
+            // We don't know the layout or it's not validity assertion at all, don't touch it
+            None => {}
+            Some(true) => {
                 // If we know the assert panics, indicate to later opts that the call diverges
                 *target = None;
             }
-            Ok(false) => {
+            Some(false) => {
                 // If we know the assert does not panic, turn the call into a Goto
                 terminator.kind = TerminatorKind::Goto { target: *target_block };
             }
@@ -252,33 +251,13 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
 }
 
 fn intrinsic_assert_panics<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
     intrinsic_name: Symbol,
-) -> Option<fn(TyCtxt<'tcx>, ParamEnvAnd<'tcx, Ty<'tcx>>) -> Result<bool, LayoutError<'tcx>>> {
-    fn inhabited_predicate<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
-    ) -> Result<bool, LayoutError<'tcx>> {
-        Ok(tcx.layout_of(param_env_and_ty)?.abi.is_uninhabited())
-    }
-    fn zero_valid_predicate<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
-    ) -> Result<bool, LayoutError<'tcx>> {
-        Ok(!tcx.permits_zero_init(param_env_and_ty)?)
-    }
-    fn mem_uninitialized_valid_predicate<'tcx>(
-        tcx: TyCtxt<'tcx>,
-        param_env_and_ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
-    ) -> Result<bool, LayoutError<'tcx>> {
-        Ok(!tcx.permits_uninit_init(param_env_and_ty)?)
-    }
-
-    match intrinsic_name {
-        sym::assert_inhabited => Some(inhabited_predicate),
-        sym::assert_zero_valid => Some(zero_valid_predicate),
-        sym::assert_mem_uninitialized_valid => Some(mem_uninitialized_valid_predicate),
-        _ => None,
-    }
+) -> Option<bool> {
+    let requirement = ValidityRequirement::from_intrinsic(intrinsic_name)?;
+    Some(!tcx.check_validity_requirement((requirement, param_env.and(ty))).ok()?)
 }
 
 fn resolve_rust_intrinsic<'tcx>(
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 4193eb7d6e8..cdd28ae0c01 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -248,7 +248,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
 
     // N.B., this `borrow()` is guaranteed to be valid (i.e., the value
     // cannot yet be stolen), because `mir_promoted()`, which steals
-    // from `mir_const(), forces this query to execute before
+    // from `mir_const()`, forces this query to execute before
     // performing the steal.
     let body = &tcx.mir_const(def).borrow();
 
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 2f02d00ec9f..c6e7468aab4 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -68,8 +68,11 @@ fn lower_slice_len_call<'tcx>(
                 ty::FnDef(fn_def_id, _) if fn_def_id == &slice_len_fn_item_def_id => {
                     // perform modifications
                     // from something like `_5 = core::slice::<impl [u8]>::len(move _6) -> bb1`
-                    // into `_5 = Len(*_6)
+                    // into:
+                    // ```
+                    // _5 = Len(*_6)
                     // goto bb1
+                    // ```
 
                     // make new RValue for Len
                     let deref_arg = tcx.mk_place_deref(arg);
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 2c56edd89bc..3c7425d83c4 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -9,7 +9,7 @@ use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel
 use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility};
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
 use rustc_middle::ty::print::characteristic_def_id_of_type;
-use rustc_middle::ty::{self, visit::TypeVisitableExt, DefIdTree, InstanceDef, TyCtxt};
+use rustc_middle::ty::{self, visit::TypeVisitableExt, InstanceDef, TyCtxt};
 use rustc_span::symbol::Symbol;
 
 use super::PartitioningCx;
diff --git a/compiler/rustc_parse/locales/en-US.ftl b/compiler/rustc_parse/locales/en-US.ftl
index a31b1f6ac1a..e76e91fc1b1 100644
--- a/compiler/rustc_parse/locales/en-US.ftl
+++ b/compiler/rustc_parse/locales/en-US.ftl
@@ -151,6 +151,10 @@ parse_missing_in_in_for_loop = missing `in` in `for` loop
 parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
     .suggestion = try adding an expression to the `for` loop
 
+parse_loop_else = `{$loop_kind}...else` loops are not supported
+    .note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+    .loop_keyword = `else` is attached to this loop
+
 parse_missing_comma_after_match_arm = expected `,` following `match` arm
     .suggestion = missing a comma here to end this `match` arm
 
@@ -220,7 +224,7 @@ parse_match_arm_body_without_braces = `match` arm body without braces
             [one] statement
            *[other] statements
         } with a body
-    .suggestion_use_comma_not_semicolon = use a comma to end a `match` arm expression
+    .suggestion_use_comma_not_semicolon = replace `;` with `,` to end a `match` arm expression
 
 parse_inclusive_range_extra_equals = unexpected `=` after inclusive range
     .suggestion_remove_eq = use `..=` instead
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index c746a870964..1662db36d10 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -452,6 +452,17 @@ pub(crate) struct MissingExpressionInForLoop {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_loop_else)]
+#[note]
+pub(crate) struct LoopElseNotSupported {
+    #[primary_span]
+    pub span: Span,
+    pub loop_kind: &'static str,
+    #[label(parse_loop_keyword)]
+    pub loop_kw: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_missing_comma_after_match_arm)]
 pub(crate) struct MissingCommaAfterMatchArm {
     #[primary_span]
diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs
index 386bf026bb4..27f4428d306 100644
--- a/compiler/rustc_parse/src/lexer/diagnostics.rs
+++ b/compiler/rustc_parse/src/lexer/diagnostics.rs
@@ -1,4 +1,4 @@
-use super::UnmatchedBrace;
+use super::UnmatchedDelim;
 use rustc_ast::token::Delimiter;
 use rustc_errors::Diagnostic;
 use rustc_span::source_map::SourceMap;
@@ -8,7 +8,7 @@ use rustc_span::Span;
 pub struct TokenTreeDiagInfo {
     /// Stack of open delimiters and their spans. Used for error message.
     pub open_braces: Vec<(Delimiter, Span)>,
-    pub unmatched_braces: Vec<UnmatchedBrace>,
+    pub unmatched_delims: Vec<UnmatchedDelim>,
 
     /// Used only for error recovery when arriving to EOF with mismatched braces.
     pub last_unclosed_found_span: Option<Span>,
@@ -32,10 +32,10 @@ pub fn same_identation_level(sm: &SourceMap, open_sp: Span, close_sp: Span) -> b
 // it's more friendly compared to report `unmatched error` in later phase
 pub fn report_missing_open_delim(
     err: &mut Diagnostic,
-    unmatched_braces: &[UnmatchedBrace],
+    unmatched_delims: &[UnmatchedDelim],
 ) -> bool {
     let mut reported_missing_open = false;
-    for unmatch_brace in unmatched_braces.iter() {
+    for unmatch_brace in unmatched_delims.iter() {
         if let Some(delim) = unmatch_brace.found_delim
             && matches!(delim, Delimiter::Parenthesis | Delimiter::Bracket)
         {
@@ -60,7 +60,7 @@ pub fn report_suspicious_mismatch_block(
     sm: &SourceMap,
     delim: Delimiter,
 ) {
-    if report_missing_open_delim(err, &diag_info.unmatched_braces) {
+    if report_missing_open_delim(err, &diag_info.unmatched_delims) {
         return;
     }
 
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 37449aaabed..9dbddee5a56 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -1,10 +1,11 @@
 use crate::errors;
 use crate::lexer::unicode_chars::UNICODE_ARRAY;
+use crate::make_unclosed_delims_error;
 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, DiagnosticBuilder, PResult, StashKey};
+use rustc_errors::{error_code, Applicability, Diagnostic, DiagnosticBuilder, StashKey};
 use rustc_lexer::unescape::{self, Mode};
 use rustc_lexer::Cursor;
 use rustc_lexer::{Base, DocStyle, RawStrError};
@@ -31,7 +32,7 @@ use unescape_error_reporting::{emit_unescape_error, escaped_char};
 rustc_data_structures::static_assert_size!(rustc_lexer::Token, 12);
 
 #[derive(Clone, Debug)]
-pub struct UnmatchedBrace {
+pub struct UnmatchedDelim {
     pub expected_delim: Delimiter,
     pub found_delim: Option<Delimiter>,
     pub found_span: Span,
@@ -44,7 +45,7 @@ pub(crate) fn parse_token_trees<'a>(
     mut src: &'a str,
     mut start_pos: BytePos,
     override_span: Option<Span>,
-) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
+) -> Result<TokenStream, Vec<Diagnostic>> {
     // Skip `#!`, if present.
     if let Some(shebang_len) = rustc_lexer::strip_shebang(src) {
         src = &src[shebang_len..];
@@ -61,7 +62,29 @@ pub(crate) fn parse_token_trees<'a>(
         override_span,
         nbsp_is_whitespace: false,
     };
-    tokentrees::TokenTreesReader::parse_all_token_trees(string_reader)
+    let (token_trees, unmatched_delims) =
+        tokentrees::TokenTreesReader::parse_all_token_trees(string_reader);
+    match token_trees {
+        Ok(stream) if unmatched_delims.is_empty() => Ok(stream),
+        _ => {
+            // Return error if there are unmatched delimiters or unclosng delimiters.
+            // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
+            // because the delimiter mismatch is more likely to be the root cause of error
+
+            let mut buffer = Vec::with_capacity(1);
+            // Not using `emit_unclosed_delims` to use `db.buffer`
+            for unmatched in unmatched_delims {
+                if let Some(err) = make_unclosed_delims_error(unmatched, &sess) {
+                    err.buffer(&mut buffer);
+                }
+            }
+            if let Err(err) = token_trees {
+                // Add unclosing delimiter error
+                err.buffer(&mut buffer);
+            }
+            Err(buffer)
+        }
+    }
 }
 
 struct StringReader<'a> {
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index 0de8f79112c..36fd1e37d65 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -1,7 +1,7 @@
 use super::diagnostics::report_suspicious_mismatch_block;
 use super::diagnostics::same_identation_level;
 use super::diagnostics::TokenTreeDiagInfo;
-use super::{StringReader, UnmatchedBrace};
+use super::{StringReader, UnmatchedDelim};
 use rustc_ast::token::{self, Delimiter, Token};
 use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust::token_to_string;
@@ -18,14 +18,14 @@ pub(super) struct TokenTreesReader<'a> {
 impl<'a> TokenTreesReader<'a> {
     pub(super) fn parse_all_token_trees(
         string_reader: StringReader<'a>,
-    ) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
+    ) -> (PResult<'a, TokenStream>, Vec<UnmatchedDelim>) {
         let mut tt_reader = TokenTreesReader {
             string_reader,
             token: Token::dummy(),
             diag_info: TokenTreeDiagInfo::default(),
         };
         let res = tt_reader.parse_token_trees(/* is_delimited */ false);
-        (res, tt_reader.diag_info.unmatched_braces)
+        (res, tt_reader.diag_info.unmatched_delims)
     }
 
     // Parse a stream of tokens into a list of `TokenTree`s.
@@ -34,7 +34,7 @@ impl<'a> TokenTreesReader<'a> {
         let mut buf = Vec::new();
         loop {
             match self.token.kind {
-                token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)),
+                token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)?),
                 token::CloseDelim(delim) => {
                     return if is_delimited {
                         Ok(TokenStream::new(buf))
@@ -43,10 +43,11 @@ impl<'a> TokenTreesReader<'a> {
                     };
                 }
                 token::Eof => {
-                    if is_delimited {
-                        self.eof_err().emit();
-                    }
-                    return Ok(TokenStream::new(buf));
+                    return if is_delimited {
+                        Err(self.eof_err())
+                    } else {
+                        Ok(TokenStream::new(buf))
+                    };
                 }
                 _ => {
                     // Get the next normal token. This might require getting multiple adjacent
@@ -78,7 +79,7 @@ impl<'a> TokenTreesReader<'a> {
         let mut err = self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg);
         for &(_, sp) in &self.diag_info.open_braces {
             err.span_label(sp, "unclosed delimiter");
-            self.diag_info.unmatched_braces.push(UnmatchedBrace {
+            self.diag_info.unmatched_delims.push(UnmatchedDelim {
                 expected_delim: Delimiter::Brace,
                 found_delim: None,
                 found_span: self.token.span,
@@ -98,7 +99,7 @@ impl<'a> TokenTreesReader<'a> {
         err
     }
 
-    fn parse_token_tree_open_delim(&mut self, open_delim: Delimiter) -> TokenTree {
+    fn parse_token_tree_open_delim(&mut self, open_delim: Delimiter) -> PResult<'a, TokenTree> {
         // The span for beginning of the delimited section
         let pre_span = self.token.span;
 
@@ -107,7 +108,7 @@ impl<'a> TokenTreesReader<'a> {
         // Parse the token trees within the delimiters.
         // We stop at any delimiter so we can try to recover if the user
         // uses an incorrect delimiter.
-        let tts = self.parse_token_trees(/* is_delimited */ true).unwrap();
+        let tts = self.parse_token_trees(/* is_delimited */ true)?;
 
         // Expand to cover the entire delimited token tree
         let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
@@ -160,7 +161,7 @@ impl<'a> TokenTreesReader<'a> {
                         }
                     }
                     let (tok, _) = self.diag_info.open_braces.pop().unwrap();
-                    self.diag_info.unmatched_braces.push(UnmatchedBrace {
+                    self.diag_info.unmatched_delims.push(UnmatchedDelim {
                         expected_delim: tok,
                         found_delim: Some(close_delim),
                         found_span: self.token.span,
@@ -190,7 +191,7 @@ impl<'a> TokenTreesReader<'a> {
             _ => unreachable!(),
         }
 
-        TokenTree::Delimited(delim_span, open_delim, tts)
+        Ok(TokenTree::Delimited(delim_span, open_delim, tts))
     }
 
     fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> {
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 6f37e9758fc..d1c3fd0cd0f 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -30,7 +30,7 @@ pub const MACRO_ARGUMENTS: Option<&str> = Some("macro arguments");
 
 #[macro_use]
 pub mod parser;
-use parser::{emit_unclosed_delims, make_unclosed_delims_error, Parser};
+use parser::{make_unclosed_delims_error, Parser};
 pub mod lexer;
 pub mod validate_attr;
 
@@ -96,10 +96,7 @@ pub fn parse_stream_from_source_str(
     sess: &ParseSess,
     override_span: Option<Span>,
 ) -> TokenStream {
-    let (stream, mut errors) =
-        source_file_to_stream(sess, sess.source_map().new_source_file(name, source), override_span);
-    emit_unclosed_delims(&mut errors, &sess);
-    stream
+    source_file_to_stream(sess, sess.source_map().new_source_file(name, source), override_span)
 }
 
 /// Creates a new parser from a source string.
@@ -135,9 +132,8 @@ fn maybe_source_file_to_parser(
     source_file: Lrc<SourceFile>,
 ) -> Result<Parser<'_>, Vec<Diagnostic>> {
     let end_pos = source_file.end_pos;
-    let (stream, unclosed_delims) = maybe_file_to_stream(sess, source_file, None)?;
+    let stream = maybe_file_to_stream(sess, source_file, None)?;
     let mut parser = stream_to_parser(sess, stream, None);
-    parser.unclosed_delims = unclosed_delims;
     if parser.token == token::Eof {
         parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None);
     }
@@ -182,7 +178,7 @@ pub fn source_file_to_stream(
     sess: &ParseSess,
     source_file: Lrc<SourceFile>,
     override_span: Option<Span>,
-) -> (TokenStream, Vec<lexer::UnmatchedBrace>) {
+) -> TokenStream {
     panictry_buffer!(&sess.span_diagnostic, maybe_file_to_stream(sess, source_file, override_span))
 }
 
@@ -192,7 +188,7 @@ pub fn maybe_file_to_stream(
     sess: &ParseSess,
     source_file: Lrc<SourceFile>,
     override_span: Option<Span>,
-) -> Result<(TokenStream, Vec<lexer::UnmatchedBrace>), Vec<Diagnostic>> {
+) -> Result<TokenStream, Vec<Diagnostic>> {
     let src = source_file.src.as_ref().unwrap_or_else(|| {
         sess.span_diagnostic.bug(&format!(
             "cannot lex `source_file` without source: {}",
@@ -200,23 +196,7 @@ pub fn maybe_file_to_stream(
         ));
     });
 
-    let (token_trees, unmatched_braces) =
-        lexer::parse_token_trees(sess, src.as_str(), source_file.start_pos, override_span);
-
-    match token_trees {
-        Ok(stream) => Ok((stream, unmatched_braces)),
-        Err(err) => {
-            let mut buffer = Vec::with_capacity(1);
-            err.buffer(&mut buffer);
-            // Not using `emit_unclosed_delims` to use `db.buffer`
-            for unmatched in unmatched_braces {
-                if let Some(err) = make_unclosed_delims_error(unmatched, &sess) {
-                    err.buffer(&mut buffer);
-                }
-            }
-            Err(buffer)
-        }
-    }
+    lexer::parse_token_trees(sess, src.as_str(), source_file.start_pos, override_span)
 }
 
 /// Given a stream and the `ParseSess`, produces a parser.
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index dbd3b76786f..b0ab0f10624 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -134,11 +134,11 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
             // Process the replace ranges, starting from the highest start
             // position and working our way back. If have tokens like:
             //
-            // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }`
+            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
             //
             // Then we will generate replace ranges for both
             // the `#[cfg(FALSE)] field: bool` and the entire
-            // `#[cfg(FALSE)]` struct Foo { #[cfg(FALSE)] field: bool }`
+            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
             //
             // By starting processing from the replace range with the greatest
             // start position, we ensure that any replace range which encloses
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index b4948dddcc9..0a65c37ea7b 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -19,7 +19,6 @@ use crate::errors::{
 };
 
 use crate::fluent_generated as fluent;
-use crate::lexer::UnmatchedBrace;
 use crate::parser;
 use rustc_ast as ast;
 use rustc_ast::ptr::P;
@@ -165,8 +164,6 @@ enum IsStandalone {
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 enum IncOrDec {
     Inc,
-    // FIXME: `i--` recovery isn't implemented yet
-    #[allow(dead_code)]
     Dec,
 }
 
@@ -222,7 +219,6 @@ impl MultiSugg {
 /// is dropped.
 pub struct SnapshotParser<'a> {
     parser: Parser<'a>,
-    unclosed_delims: Vec<UnmatchedBrace>,
 }
 
 impl<'a> Deref for SnapshotParser<'a> {
@@ -257,27 +253,15 @@ impl<'a> Parser<'a> {
         &self.sess.span_diagnostic
     }
 
-    /// Replace `self` with `snapshot.parser` and extend `unclosed_delims` with `snapshot.unclosed_delims`.
-    /// This is to avoid losing unclosed delims errors `create_snapshot_for_diagnostic` clears.
+    /// Replace `self` with `snapshot.parser`.
     pub(super) fn restore_snapshot(&mut self, snapshot: SnapshotParser<'a>) {
         *self = snapshot.parser;
-        self.unclosed_delims.extend(snapshot.unclosed_delims);
-    }
-
-    pub fn unclosed_delims(&self) -> &[UnmatchedBrace] {
-        &self.unclosed_delims
     }
 
     /// Create a snapshot of the `Parser`.
     pub fn create_snapshot_for_diagnostic(&self) -> SnapshotParser<'a> {
-        let mut snapshot = self.clone();
-        let unclosed_delims = self.unclosed_delims.clone();
-        // Clear `unclosed_delims` in snapshot to avoid
-        // duplicate errors being emitted when the `Parser`
-        // is dropped (which may or may not happen, depending
-        // if the parsing the snapshot is created for is successful)
-        snapshot.unclosed_delims.clear();
-        SnapshotParser { parser: snapshot, unclosed_delims }
+        let snapshot = self.clone();
+        SnapshotParser { parser: snapshot }
     }
 
     pub(super) fn span_to_snippet(&self, span: Span) -> Result<String, SpanSnippetError> {
@@ -581,21 +565,6 @@ impl<'a> Parser<'a> {
         } else {
             label_sp
         };
-        match self.recover_closing_delimiter(
-            &expected
-                .iter()
-                .filter_map(|tt| match tt {
-                    TokenType::Token(t) => Some(t.clone()),
-                    _ => None,
-                })
-                .collect::<Vec<_>>(),
-            err,
-        ) {
-            Err(e) => err = e,
-            Ok(recovered) => {
-                return Ok(recovered);
-            }
-        }
 
         if self.check_too_many_raw_str_terminators(&mut err) {
             if expected.contains(&TokenType::Token(token::Semi)) && self.eat(&token::Semi) {
@@ -1357,6 +1326,20 @@ impl<'a> Parser<'a> {
         self.recover_from_inc_dec(operand_expr, kind, op_span)
     }
 
+    pub(super) fn recover_from_postfix_decrement(
+        &mut self,
+        operand_expr: P<Expr>,
+        op_span: Span,
+        start_stmt: bool,
+    ) -> PResult<'a, P<Expr>> {
+        let kind = IncDecRecovery {
+            standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr },
+            op: IncOrDec::Dec,
+            fixity: UnaryFixity::Post,
+        };
+        self.recover_from_inc_dec(operand_expr, kind, op_span)
+    }
+
     fn recover_from_inc_dec(
         &mut self,
         base: P<Expr>,
@@ -1561,12 +1544,6 @@ impl<'a> Parser<'a> {
         );
         let mut err = self.struct_span_err(sp, &msg);
         let label_exp = format!("expected `{token_str}`");
-        match self.recover_closing_delimiter(&[t.clone()], err) {
-            Err(e) => err = e,
-            Ok(recovered) => {
-                return Ok(recovered);
-            }
-        }
         let sm = self.sess.source_map();
         if !sm.is_multiline(prev_sp.until(sp)) {
             // When the spans are in the same line, it means that the only content
@@ -1783,81 +1760,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub(super) fn recover_closing_delimiter(
-        &mut self,
-        tokens: &[TokenKind],
-        mut err: DiagnosticBuilder<'a, ErrorGuaranteed>,
-    ) -> PResult<'a, bool> {
-        let mut pos = None;
-        // We want to use the last closing delim that would apply.
-        for (i, unmatched) in self.unclosed_delims.iter().enumerate().rev() {
-            if tokens.contains(&token::CloseDelim(unmatched.expected_delim))
-                && Some(self.token.span) > unmatched.unclosed_span
-            {
-                pos = Some(i);
-            }
-        }
-        match pos {
-            Some(pos) => {
-                // Recover and assume that the detected unclosed delimiter was meant for
-                // this location. Emit the diagnostic and act as if the delimiter was
-                // present for the parser's sake.
-
-                // Don't attempt to recover from this unclosed delimiter more than once.
-                let unmatched = self.unclosed_delims.remove(pos);
-                let delim = TokenType::Token(token::CloseDelim(unmatched.expected_delim));
-                if unmatched.found_delim.is_none() {
-                    // We encountered `Eof`, set this fact here to avoid complaining about missing
-                    // `fn main()` when we found place to suggest the closing brace.
-                    *self.sess.reached_eof.borrow_mut() = true;
-                }
-
-                // We want to suggest the inclusion of the closing delimiter where it makes
-                // the most sense, which is immediately after the last token:
-                //
-                //  {foo(bar {}}
-                //      ^      ^
-                //      |      |
-                //      |      help: `)` may belong here
-                //      |
-                //      unclosed delimiter
-                if let Some(sp) = unmatched.unclosed_span {
-                    let mut primary_span: Vec<Span> =
-                        err.span.primary_spans().iter().cloned().collect();
-                    primary_span.push(sp);
-                    let mut primary_span: MultiSpan = primary_span.into();
-                    for span_label in err.span.span_labels() {
-                        if let Some(label) = span_label.label {
-                            primary_span.push_span_label(span_label.span, label);
-                        }
-                    }
-                    err.set_span(primary_span);
-                    err.span_label(sp, "unclosed delimiter");
-                }
-                // Backticks should be removed to apply suggestions.
-                let mut delim = delim.to_string();
-                delim.retain(|c| c != '`');
-                err.span_suggestion_short(
-                    self.prev_token.span.shrink_to_hi(),
-                    &format!("`{delim}` may belong here"),
-                    delim,
-                    Applicability::MaybeIncorrect,
-                );
-                if unmatched.found_delim.is_none() {
-                    // Encountered `Eof` when lexing blocks. Do not recover here to avoid knockdown
-                    // errors which would be emitted elsewhere in the parser and let other error
-                    // recovery consume the rest of the file.
-                    Err(err)
-                } else {
-                    err.emit();
-                    self.expected_tokens.clear(); // Reduce the number of errors.
-                    Ok(true)
-                }
-            }
-            _ => Err(err),
-        }
-    }
-
     /// Eats tokens until we can be relatively sure we reached the end of the
     /// statement. This is something of a best-effort heuristic.
     ///
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 33254d034c9..e00eda47c66 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -282,6 +282,18 @@ impl<'a> Parser<'a> {
                 continue;
             }
 
+            if self.prev_token == token::BinOp(token::Minus)
+                && self.token == token::BinOp(token::Minus)
+                && self.prev_token.span.between(self.token.span).is_empty()
+                && !self.look_ahead(1, |tok| tok.can_begin_expr())
+            {
+                let op_span = self.prev_token.span.to(self.token.span);
+                // Eat the second `-`
+                self.bump();
+                lhs = self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)?;
+                continue;
+            }
+
             let op = op.node;
             // Special cases:
             if op == AssocOp::As {
@@ -1198,8 +1210,13 @@ impl<'a> Parser<'a> {
                         // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
                         self.restore_snapshot(snapshot);
                         let close_paren = self.prev_token.span;
-                        let span = lo.to(self.prev_token.span);
-                        if !fields.is_empty() {
+                        let span = lo.to(close_paren);
+                        if !fields.is_empty() &&
+                            // `token.kind` should not be compared here.
+                            // This is because the `snapshot.token.kind` is treated as the same as
+                            // that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different.
+                            self.span_to_snippet(close_paren).map_or(false, |snippet| snippet == ")")
+                        {
                             let mut replacement_err = errors::ParenthesesWithStructFields {
                                 span,
                                 r#type: path,
@@ -1377,19 +1394,6 @@ impl<'a> Parser<'a> {
             self.parse_expr_let()
         } else if self.eat_keyword(kw::Underscore) {
             Ok(self.mk_expr(self.prev_token.span, ExprKind::Underscore))
-        } else if !self.unclosed_delims.is_empty() && self.check(&token::Semi) {
-            // Don't complain about bare semicolons after unclosed braces
-            // recovery in order to keep the error count down. Fixing the
-            // delimiters will possibly also fix the bare semicolon found in
-            // expression context. For example, silence the following error:
-            //
-            //     error: expected expression, found `;`
-            //      --> file.rs:2:13
-            //       |
-            //     2 |     foo(bar(;
-            //       |             ^ expected expression
-            self.bump();
-            Ok(self.mk_expr_err(self.token.span))
         } else if self.token.uninterpolated_span().rust_2018() {
             // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly.
             if self.check_keyword(kw::Async) {
@@ -2491,9 +2495,27 @@ impl<'a> Parser<'a> {
         let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
 
         let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
+
+        self.recover_loop_else("for", lo)?;
+
         Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
     }
 
+    /// Recovers from an `else` clause after a loop (`for...else`, `while...else`)
+    fn recover_loop_else(&mut self, loop_kind: &'static str, loop_kw: Span) -> PResult<'a, ()> {
+        if self.token.is_keyword(kw::Else) && self.may_recover() {
+            let else_span = self.token.span;
+            self.bump();
+            let else_clause = self.parse_expr_else()?;
+            self.sess.emit_err(errors::LoopElseNotSupported {
+                span: else_span.to(else_clause.span),
+                loop_kind,
+                loop_kw,
+            });
+        }
+        Ok(())
+    }
+
     fn error_missing_in_for_loop(&mut self) {
         let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
             // Possibly using JS syntax (#75311).
@@ -2518,6 +2540,9 @@ impl<'a> Parser<'a> {
             err.span_label(cond.span, "this `while` condition successfully parsed");
             err
         })?;
+
+        self.recover_loop_else("while", lo)?;
+
         Ok(self.mk_expr_with_attrs(
             lo.to(self.prev_token.span),
             ExprKind::While(cond, body, opt_label),
@@ -2529,6 +2554,7 @@ impl<'a> Parser<'a> {
     fn parse_expr_loop(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
         let loop_span = self.prev_token.span;
         let (attrs, body) = self.parse_inner_attrs_and_block()?;
+        self.recover_loop_else("loop", lo)?;
         Ok(self.mk_expr_with_attrs(
             lo.to(self.prev_token.span),
             ExprKind::Loop(body, opt_label, loop_span),
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 9d9ae154ad4..85cc8ca02a9 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -125,16 +125,13 @@ impl<'a> Parser<'a> {
             return Ok(Some(item.into_inner()));
         };
 
-        let mut unclosed_delims = vec![];
         let item =
             self.collect_tokens_trailing_token(attrs, force_collect, |this: &mut Self, attrs| {
                 let item =
                     this.parse_item_common_(attrs, mac_allowed, attrs_allowed, fn_parse_mode);
-                unclosed_delims.append(&mut this.unclosed_delims);
                 Ok((item?, TrailingToken::None))
             })?;
 
-        self.unclosed_delims.append(&mut unclosed_delims);
         Ok(item)
     }
 
@@ -1960,21 +1957,12 @@ impl<'a> Parser<'a> {
         // FIXME: This will make us not emit the help even for declarative
         // macros within the same crate (that we can fix), which is sad.
         if !span.from_expansion() {
-            if self.unclosed_delims.is_empty() {
-                let DelimSpan { open, close } = args.dspan;
-                err.multipart_suggestion(
-                    "change the delimiters to curly braces",
-                    vec![(open, "{".to_string()), (close, '}'.to_string())],
-                    Applicability::MaybeIncorrect,
-                );
-            } else {
-                err.span_suggestion(
-                    span,
-                    "change the delimiters to curly braces",
-                    " { /* items */ }",
-                    Applicability::HasPlaceholders,
-                );
-            }
+            let DelimSpan { open, close } = args.dspan;
+            err.multipart_suggestion(
+                "change the delimiters to curly braces",
+                vec![(open, "{".to_string()), (close, '}'.to_string())],
+                Applicability::MaybeIncorrect,
+            );
             err.span_suggestion(
                 span.shrink_to_hi(),
                 "add a semicolon",
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index fda9151478f..6e9b447fa61 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -10,7 +10,7 @@ mod path;
 mod stmt;
 mod ty;
 
-use crate::lexer::UnmatchedBrace;
+use crate::lexer::UnmatchedDelim;
 pub use attr_wrapper::AttrWrapper;
 pub use diagnostics::AttemptLocalParseRecovery;
 pub(crate) use item::FnParseMode;
@@ -146,10 +146,7 @@ pub struct Parser<'a> {
     /// See the comments in the `parse_path_segment` function for more details.
     unmatched_angle_bracket_count: u32,
     max_angle_bracket_count: u32,
-    /// A list of all unclosed delimiters found by the lexer. If an entry is used for error recovery
-    /// it gets removed from here. Every entry left at the end gets emitted as an independent
-    /// error.
-    pub(super) unclosed_delims: Vec<UnmatchedBrace>,
+
     last_unexpected_token_span: Option<Span>,
     /// Span pointing at the `:` for the last type ascription the parser has seen, and whether it
     /// looked like it could have been a mistyped path or literal `Option:Some(42)`).
@@ -168,7 +165,7 @@ pub struct Parser<'a> {
 // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with nonterminals. Make sure
 // it doesn't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Parser<'_>, 312);
+rustc_data_structures::static_assert_size!(Parser<'_>, 288);
 
 /// Stores span information about a closure.
 #[derive(Clone)]
@@ -215,12 +212,6 @@ struct CaptureState {
     inner_attr_ranges: FxHashMap<AttrId, ReplaceRange>,
 }
 
-impl<'a> Drop for Parser<'a> {
-    fn drop(&mut self) {
-        emit_unclosed_delims(&mut self.unclosed_delims, &self.sess);
-    }
-}
-
 /// Iterator over a `TokenStream` that produces `Token`s. It's a bit odd that
 /// we (a) lex tokens into a nice tree structure (`TokenStream`), and then (b)
 /// use this type to emit them as a linear sequence. But a linear sequence is
@@ -335,7 +326,7 @@ impl TokenCursor {
             num_of_hashes = cmp::max(num_of_hashes, count);
         }
 
-        // `/// foo` becomes `doc = r"foo".
+        // `/// foo` becomes `doc = r"foo"`.
         let delim_span = DelimSpan::from_single(span);
         let body = TokenTree::Delimited(
             delim_span,
@@ -478,7 +469,6 @@ impl<'a> Parser<'a> {
             desugar_doc_comments,
             unmatched_angle_bracket_count: 0,
             max_angle_bracket_count: 0,
-            unclosed_delims: Vec::new(),
             last_unexpected_token_span: None,
             last_type_ascription: None,
             subparser_name,
@@ -859,7 +849,6 @@ impl<'a> Parser<'a> {
         let mut recovered = false;
         let mut trailing = false;
         let mut v = ThinVec::new();
-        let unclosed_delims = !self.unclosed_delims.is_empty();
 
         while !self.expect_any_with_type(kets, expect) {
             if let token::CloseDelim(..) | token::Eof = self.token.kind {
@@ -901,7 +890,7 @@ impl<'a> Parser<'a> {
                                 _ => {
                                     // Attempt to keep parsing if it was a similar separator.
                                     if let Some(tokens) = t.similar_tokens() {
-                                        if tokens.contains(&self.token.kind) && !unclosed_delims {
+                                        if tokens.contains(&self.token.kind) {
                                             self.bump();
                                         }
                                     }
@@ -1521,11 +1510,11 @@ impl<'a> Parser<'a> {
 }
 
 pub(crate) fn make_unclosed_delims_error(
-    unmatched: UnmatchedBrace,
+    unmatched: UnmatchedDelim,
     sess: &ParseSess,
 ) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> {
     // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to
-    // `unmatched_braces` only for error recovery in the `Parser`.
+    // `unmatched_delims` only for error recovery in the `Parser`.
     let found_delim = unmatched.found_delim?;
     let mut spans = vec![unmatched.found_span];
     if let Some(sp) = unmatched.unclosed_span {
@@ -1542,7 +1531,7 @@ pub(crate) fn make_unclosed_delims_error(
     Some(err)
 }
 
-pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, sess: &ParseSess) {
+pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedDelim>, sess: &ParseSess) {
     *sess.reached_eof.borrow_mut() |=
         unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none());
     for unmatched in unclosed_delims.drain(..) {
diff --git a/compiler/rustc_passes/locales/en-US.ftl b/compiler/rustc_passes/locales/en-US.ftl
index 0ed29ce0d47..3fa78efc290 100644
--- a/compiler/rustc_passes/locales/en-US.ftl
+++ b/compiler/rustc_passes/locales/en-US.ftl
@@ -402,9 +402,6 @@ passes_invalid_attr_at_crate_level =
     `{$name}` attribute cannot be used at crate level
     .suggestion = perhaps you meant to use an outer attribute
 
-passes_duplicate_diagnostic_item =
-    duplicate diagnostic item found: `{$name}`.
-
 passes_duplicate_diagnostic_item_in_crate =
     duplicate diagnostic item in crate `{$crate_name}`: `{$name}`.
     .note = the diagnostic item is first defined in crate `{$orig_crate_name}`.
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index e2f858a34b6..28e06e5bb3e 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -13,7 +13,7 @@ use rustc_hir::{Node, PatKind, TyKind};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::privacy::Level;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, DefIdTree, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{sym, Symbol};
 use std::mem;
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index 0ae7096642c..110eb210df9 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -11,19 +11,19 @@
 
 use rustc_ast as ast;
 use rustc_hir::diagnostic_items::DiagnosticItems;
+use rustc_hir::OwnerId;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_span::symbol::{kw::Empty, sym, Symbol};
+use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_span::symbol::{sym, Symbol};
 
-use crate::errors::{DuplicateDiagnosticItem, DuplicateDiagnosticItemInCrate};
+use crate::errors::DuplicateDiagnosticItemInCrate;
 
-fn observe_item(tcx: TyCtxt<'_>, diagnostic_items: &mut DiagnosticItems, def_id: LocalDefId) {
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-    let attrs = tcx.hir().attrs(hir_id);
+fn observe_item<'tcx>(tcx: TyCtxt<'tcx>, diagnostic_items: &mut DiagnosticItems, owner: OwnerId) {
+    let attrs = tcx.hir().attrs(owner.into());
     if let Some(name) = extract(attrs) {
         // insert into our table
-        collect_item(tcx, diagnostic_items, name, def_id.to_def_id());
+        collect_item(tcx, diagnostic_items, name, owner.to_def_id());
     }
 }
 
@@ -31,23 +31,29 @@ fn collect_item(tcx: TyCtxt<'_>, items: &mut DiagnosticItems, name: Symbol, item
     items.id_to_name.insert(item_def_id, name);
     if let Some(original_def_id) = items.name_to_id.insert(name, item_def_id) {
         if original_def_id != item_def_id {
-            let orig_span = tcx.hir().span_if_local(original_def_id);
-            let orig_crate_name =
-                orig_span.is_none().then(|| tcx.crate_name(original_def_id.krate));
-            match tcx.hir().span_if_local(item_def_id) {
-                Some(span) => tcx.sess.emit_err(DuplicateDiagnosticItem { span, name }),
-                None => tcx.sess.emit_err(DuplicateDiagnosticItemInCrate {
-                    span: orig_span,
-                    orig_crate_name: orig_crate_name.unwrap_or(Empty),
-                    have_orig_crate_name: orig_crate_name.map(|_| ()),
-                    crate_name: tcx.crate_name(item_def_id.krate),
-                    name,
-                }),
-            };
+            report_duplicate_item(tcx, name, original_def_id, item_def_id);
         }
     }
 }
 
+fn report_duplicate_item(
+    tcx: TyCtxt<'_>,
+    name: Symbol,
+    original_def_id: DefId,
+    item_def_id: DefId,
+) {
+    let orig_span = tcx.hir().span_if_local(original_def_id);
+    let duplicate_span = tcx.hir().span_if_local(item_def_id);
+    tcx.sess.emit_err(DuplicateDiagnosticItemInCrate {
+        duplicate_span,
+        orig_span,
+        crate_name: tcx.crate_name(item_def_id.krate),
+        orig_crate_name: tcx.crate_name(original_def_id.krate),
+        different_crates: (item_def_id.krate != original_def_id.krate).then_some(()),
+        name,
+    });
+}
+
 /// Extract the first `rustc_diagnostic_item = "$name"` out of a list of attributes.
 fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
     attrs.iter().find_map(|attr| {
@@ -64,21 +70,8 @@ fn diagnostic_items(tcx: TyCtxt<'_>, cnum: CrateNum) -> DiagnosticItems {
 
     // Collect diagnostic items in this crate.
     let crate_items = tcx.hir_crate_items(());
-
-    for id in crate_items.items() {
-        observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
-    }
-
-    for id in crate_items.trait_items() {
-        observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
-    }
-
-    for id in crate_items.impl_items() {
-        observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
-    }
-
-    for id in crate_items.foreign_items() {
-        observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
+    for id in crate_items.owners() {
+        observe_item(tcx, &mut diagnostic_items, id);
     }
 
     diagnostic_items
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index b327ba63330..b7e6a11998b 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -4,7 +4,7 @@ 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};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{DefIdTree, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{sigpipe, CrateType, EntryFnType};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 2c0d21b4798..9f1c0b5a0b7 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -810,22 +810,16 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
 }
 
 #[derive(Diagnostic)]
-#[diag(passes_duplicate_diagnostic_item)]
-pub struct DuplicateDiagnosticItem {
-    #[primary_span]
-    pub span: Span,
-    pub name: Symbol,
-}
-
-#[derive(Diagnostic)]
 #[diag(passes_duplicate_diagnostic_item_in_crate)]
 pub struct DuplicateDiagnosticItemInCrate {
+    #[primary_span]
+    pub duplicate_span: Option<Span>,
     #[note(passes_diagnostic_item_first_defined)]
-    pub span: Option<Span>,
-    pub orig_crate_name: Symbol,
+    pub orig_span: Option<Span>,
     #[note]
-    pub have_orig_crate_name: Option<()>,
+    pub different_crates: Option<()>,
     pub crate_name: Symbol,
+    pub orig_crate_name: Symbol,
     pub name: Symbol,
 }
 
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index de0e50a65de..9418f3cd322 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -5,7 +5,7 @@ use rustc_hir::intravisit;
 use rustc_hir::{HirId, ItemLocalId};
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{DefIdTree, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 
 pub fn check_crate(tcx: TyCtxt<'_>) {
     tcx.dep_graph.assert_ignored();
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 51a19c8e3c0..5e2d2d3e5a7 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -646,7 +646,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
     }
 
     // `UseTree` has one inline use (in `ast::ItemKind::Use`) and one
-    // non-inline use (in `ast::UseTreeKind::Nested). The former case is more
+    // non-inline use (in `ast::UseTreeKind::Nested`). The former case is more
     // common, so we don't implement `visit_use_tree` and tolerate the missed
     // coverage in the latter case.
 
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index df5c8f53ec1..db9d0dcc300 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -95,7 +95,7 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet};
 use rustc_index::vec::IndexVec;
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, DefIdTree, RootVariableMinCaptureList, Ty, TyCtxt};
+use rustc_middle::ty::{self, RootVariableMinCaptureList, Ty, TyCtxt};
 use rustc_session::lint;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{BytePos, Span};
diff --git a/compiler/rustc_passes/src/liveness/rwu_table.rs b/compiler/rustc_passes/src/liveness/rwu_table.rs
index 6d5983f53dc..053bf5c234a 100644
--- a/compiler/rustc_passes/src/liveness/rwu_table.rs
+++ b/compiler/rustc_passes/src/liveness/rwu_table.rs
@@ -9,7 +9,7 @@ pub(super) struct RWU {
 }
 
 /// Conceptually, this is like a `Vec<Vec<RWU>>`. But the number of
-/// RWU`s can get very large, so it uses a more compact representation.
+/// RWU's can get very large, so it uses a more compact representation.
 pub(super) struct RWUTable {
     /// Total number of live nodes.
     live_nodes: usize,
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 051100c56f8..d6cb68a9c20 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -14,7 +14,7 @@ use rustc_hir::Node;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::middle::privacy::{self, Level};
 use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, DefIdTree, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::config::CrateType;
 use rustc_target::spec::abi::Abi;
 
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 50176c80232..99a44b0ca4d 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -29,7 +29,7 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
 use rustc_middle::span_bug;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind};
+use rustc_middle::ty::{self, Const, GenericParamDefKind};
 use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_session::lint;
 use rustc_span::hygiene::Transparency;
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 70c481fb0ee..46e34462cf2 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -333,7 +333,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
                 },
             );
 
-            // `Encode the file footer.
+            // Encode the file footer.
             let footer_pos = encoder.position() as u64;
             encoder.encode_tagged(
                 TAG_FILE_FOOTER,
diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs
index 586bd38fbb8..5f003fa70e1 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -25,7 +25,6 @@ use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::mem;
-use std::ptr;
 use thin_vec::ThinVec;
 
 use super::QueryConfig;
@@ -250,13 +249,16 @@ where
     where
         C: QueryCache<Key = K>,
     {
-        // We can move out of `self` here because we `mem::forget` it below
-        let key = unsafe { ptr::read(&self.key) };
+        let key = self.key;
         let state = self.state;
 
         // Forget ourself so our destructor won't poison the query
         mem::forget(self);
 
+        // Mark as complete before we remove the job from the active state
+        // so no other thread can re-execute this query.
+        cache.complete(key, result, dep_node_index);
+
         let job = {
             #[cfg(parallel_compiler)]
             let mut lock = state.active.get_shard_by_value(&key).lock();
@@ -267,7 +269,6 @@ where
                 QueryResult::Poisoned => panic!(),
             }
         };
-        cache.complete(key, result, dep_node_index);
 
         job.signal_complete();
     }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index b1e023f2caa..9526bca3df2 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -25,9 +25,8 @@ use rustc_expand::expand::AstFragment;
 use rustc_hir::def::{self, *};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_metadata::creader::LoadedMacro;
-use rustc_middle::bug;
 use rustc_middle::metadata::ModChild;
-use rustc_middle::ty::{self, DefIdTree};
+use rustc_middle::{bug, ty};
 use rustc_session::cstore::CrateStore;
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
 use rustc_span::source_map::respan;
@@ -99,7 +98,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         loop {
             match self.get_module(def_id) {
                 Some(module) => return module,
-                None => def_id = self.parent(def_id),
+                None => def_id = self.tcx.parent(def_id),
             }
         }
     }
@@ -775,7 +774,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                         let field_vis = self
                             .try_resolve_visibility(&field.vis, false)
                             .unwrap_or(ty::Visibility::Public);
-                        if ctor_vis.is_at_least(field_vis, &*self.r) {
+                        if ctor_vis.is_at_least(field_vis, self.r.tcx) {
                             ctor_vis = field_vis;
                         }
                         ret_fields.push(field_vis.to_def_id());
@@ -1414,10 +1413,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
         if !(ctxt == AssocCtxt::Impl
             && matches!(item.vis.kind, ast::VisibilityKind::Inherited)
-            && self
-                .r
-                .trait_impl_items
-                .contains(&ty::DefIdTree::local_parent(&*self.r, local_def_id)))
+            && self.r.trait_impl_items.contains(&self.r.tcx.local_parent(local_def_id)))
         {
             // Trait impl item visibility is inherited from its trait when not specified
             // explicitly. In that case we cannot determine it here in early resolve,
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 0114e116386..b2578e4c4b4 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -29,11 +29,12 @@ use crate::Resolver;
 
 use rustc_ast as ast;
 use rustc_ast::visit::{self, Visitor};
-use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_data_structures::unord::UnordSet;
 use rustc_errors::{pluralize, MultiSpan};
-use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS};
+use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS};
 use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_span::symbol::Ident;
 use rustc_span::{Span, DUMMY_SP};
 
 struct UnusedImport<'a> {
@@ -53,11 +54,28 @@ struct UnusedImportCheckVisitor<'a, 'b, 'tcx> {
     r: &'a mut Resolver<'b, 'tcx>,
     /// All the (so far) unused imports, grouped path list
     unused_imports: FxIndexMap<ast::NodeId, UnusedImport<'a>>,
+    extern_crate_items: Vec<ExternCrateToLint>,
     base_use_tree: Option<&'a ast::UseTree>,
     base_id: ast::NodeId,
     item_span: Span,
 }
 
+struct ExternCrateToLint {
+    id: ast::NodeId,
+    /// Span from the item
+    span: Span,
+    /// Span to use to suggest complete removal.
+    span_with_attributes: Span,
+    /// Span of the visibility, if any.
+    vis_span: Span,
+    /// Whether the item has attrs.
+    has_attrs: bool,
+    /// Name used to refer to the crate.
+    ident: Ident,
+    /// Whether the statement renames the crate `extern crate orig_name as new_name;`.
+    renames: bool,
+}
+
 impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
     // We have information about whether `use` (import) items are actually
     // used now. If an import is not used at all, we signal a lint error.
@@ -96,18 +114,27 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
 
 impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
     fn visit_item(&mut self, item: &'a ast::Item) {
-        self.item_span = item.span_with_attributes();
-
-        // Ignore is_public import statements because there's no way to be sure
-        // whether they're used or not. Also ignore imports with a dummy span
-        // because this means that they were generated in some fashion by the
-        // compiler and we don't need to consider them.
-        if let ast::ItemKind::Use(..) = item.kind {
-            if item.vis.kind.is_pub() || item.span.is_dummy() {
-                return;
+        match item.kind {
+            // Ignore is_public import statements because there's no way to be sure
+            // whether they're used or not. Also ignore imports with a dummy span
+            // because this means that they were generated in some fashion by the
+            // compiler and we don't need to consider them.
+            ast::ItemKind::Use(..) if item.vis.kind.is_pub() || item.span.is_dummy() => return,
+            ast::ItemKind::ExternCrate(orig_name) => {
+                self.extern_crate_items.push(ExternCrateToLint {
+                    id: item.id,
+                    span: item.span,
+                    vis_span: item.vis.span,
+                    span_with_attributes: item.span_with_attributes(),
+                    has_attrs: !item.attrs.is_empty(),
+                    ident: item.ident,
+                    renames: orig_name.is_some(),
+                });
             }
+            _ => {}
         }
 
+        self.item_span = item.span_with_attributes();
         visit::walk_item(self, item);
     }
 
@@ -224,6 +251,9 @@ fn calc_unused_spans(
 
 impl Resolver<'_, '_> {
     pub(crate) fn check_unused(&mut self, krate: &ast::Crate) {
+        let tcx = self.tcx;
+        let mut maybe_unused_extern_crates = FxHashMap::default();
+
         for import in self.potentially_unused_imports.iter() {
             match import.kind {
                 _ if import.used.get()
@@ -246,7 +276,14 @@ impl Resolver<'_, '_> {
                 }
                 ImportKind::ExternCrate { id, .. } => {
                     let def_id = self.local_def_id(id);
-                    self.maybe_unused_extern_crates.push((def_id, import.span));
+                    if self.extern_crate_map.get(&def_id).map_or(true, |&cnum| {
+                        !tcx.is_compiler_builtins(cnum)
+                            && !tcx.is_panic_runtime(cnum)
+                            && !tcx.has_global_allocator(cnum)
+                            && !tcx.has_panic_handler(cnum)
+                    }) {
+                        maybe_unused_extern_crates.insert(id, import.span);
+                    }
                 }
                 ImportKind::MacroUse => {
                     let msg = "unused `#[macro_use]` import";
@@ -259,6 +296,7 @@ impl Resolver<'_, '_> {
         let mut visitor = UnusedImportCheckVisitor {
             r: self,
             unused_imports: Default::default(),
+            extern_crate_items: Default::default(),
             base_use_tree: None,
             base_id: ast::DUMMY_NODE_ID,
             item_span: DUMMY_SP,
@@ -290,7 +328,7 @@ impl Resolver<'_, '_> {
             let ms = MultiSpan::from_spans(spans.clone());
             let mut span_snippets = spans
                 .iter()
-                .filter_map(|s| match visitor.r.tcx.sess.source_map().span_to_snippet(*s) {
+                .filter_map(|s| match tcx.sess.source_map().span_to_snippet(*s) {
                     Ok(s) => Some(format!("`{}`", s)),
                     _ => None,
                 })
@@ -317,7 +355,7 @@ impl Resolver<'_, '_> {
             // If we are in the `--test` mode, suppress a help that adds the `#[cfg(test)]`
             // attribute; however, if not, suggest adding the attribute. There is no way to
             // retrieve attributes here because we do not have a `TyCtxt` yet.
-            let test_module_span = if visitor.r.tcx.sess.opts.test {
+            let test_module_span = if tcx.sess.opts.test {
                 None
             } else {
                 let parent_module = visitor.r.get_nearest_non_block_module(
@@ -346,5 +384,74 @@ impl Resolver<'_, '_> {
                 BuiltinLintDiagnostics::UnusedImports(fix_msg.into(), fixes, test_module_span),
             );
         }
+
+        for extern_crate in visitor.extern_crate_items {
+            let warn_if_unused = !extern_crate.ident.name.as_str().starts_with('_');
+
+            // If the crate is fully unused, we suggest removing it altogether.
+            // We do this in any edition.
+            if warn_if_unused {
+                if let Some(&span) = maybe_unused_extern_crates.get(&extern_crate.id) {
+                    visitor.r.lint_buffer.buffer_lint_with_diagnostic(
+                        UNUSED_EXTERN_CRATES,
+                        extern_crate.id,
+                        span,
+                        "unused extern crate",
+                        BuiltinLintDiagnostics::UnusedExternCrate {
+                            removal_span: extern_crate.span_with_attributes,
+                        },
+                    );
+                    continue;
+                }
+            }
+
+            // If we are not in Rust 2018 edition, then we don't make any further
+            // suggestions.
+            if !tcx.sess.rust_2018() {
+                continue;
+            }
+
+            // If the extern crate has any attributes, they may have funky
+            // semantics we can't faithfully represent using `use` (most
+            // notably `#[macro_use]`). Ignore it.
+            if extern_crate.has_attrs {
+                continue;
+            }
+
+            // If the extern crate is renamed, then we cannot suggest replacing it with a use as this
+            // would not insert the new name into the prelude, where other imports in the crate may be
+            // expecting it.
+            if extern_crate.renames {
+                continue;
+            }
+
+            // If the extern crate isn't in the extern prelude,
+            // there is no way it can be written as a `use`.
+            if !visitor
+                .r
+                .extern_prelude
+                .get(&extern_crate.ident)
+                .map_or(false, |entry| !entry.introduced_by_item)
+            {
+                continue;
+            }
+
+            let vis_span = extern_crate
+                .vis_span
+                .find_ancestor_inside(extern_crate.span)
+                .unwrap_or(extern_crate.vis_span);
+            let ident_span = extern_crate
+                .ident
+                .span
+                .find_ancestor_inside(extern_crate.span)
+                .unwrap_or(extern_crate.ident.span);
+            visitor.r.lint_buffer.buffer_lint_with_diagnostic(
+                UNUSED_EXTERN_CRATES,
+                extern_crate.id,
+                extern_crate.span,
+                "`extern crate` is not idiomatic in the new edition",
+                BuiltinLintDiagnostics::ExternCrateNotIdiomatic { vis_span, ident_span },
+            );
+        }
     }
 }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index ee2d2301399..adec7973671 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -15,7 +15,7 @@ use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::PrimTy;
 use rustc_middle::bug;
-use rustc_middle::ty::{DefIdTree, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE;
 use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS;
 use rustc_session::lint::BuiltinLintDiagnostics;
@@ -189,7 +189,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         let container = match parent.kind {
-            ModuleKind::Def(kind, _, _) => self.tcx.def_kind_descr(kind, parent.def_id()),
+            // Avoid using TyCtxt::def_kind_descr in the resolver, because it
+            // indirectly *calls* the resolver, and would cause a query cycle.
+            ModuleKind::Def(kind, _, _) => kind.descr(parent.def_id()),
             ModuleKind::Block => "block",
         };
 
@@ -1195,7 +1197,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         segms.push(ast::PathSegment::from_ident(ident));
                         let path = Path { span: name_binding.span, segments: segms, tokens: None };
                         let did = match res {
-                            Res::Def(DefKind::Ctor(..), did) => this.opt_parent(did),
+                            Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did),
                             _ => res.opt_def_id(),
                         };
 
@@ -1589,7 +1591,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             ctor_def_id,
         )) = binding.kind
         {
-            let def_id = self.parent(ctor_def_id);
+            let def_id = self.tcx.parent(ctor_def_id);
             let fields = self.field_names.get(&def_id)?;
             return fields.iter().map(|name| name.span).reduce(Span::to); // None for `struct Foo()`
         }
@@ -1804,7 +1806,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         found("module")
                     } else {
                         match binding.res() {
-                            Res::Def(kind, id) => found(self.tcx.def_kind_descr(kind, id)),
+                            // Avoid using TyCtxt::def_kind_descr in the resolver, because it
+                            // indirectly *calls* the resolver, and would cause a query cycle.
+                            Res::Def(kind, id) => found(kind.descr(id)),
                             _ => found(ns_to_try.descr()),
                         }
                     }
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 7bd90d7e345..4bb252bfb29 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -9,7 +9,7 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_middle::middle::privacy::Level;
 use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility};
-use rustc_middle::ty::{DefIdTree, Visibility};
+use rustc_middle::ty::Visibility;
 use std::mem;
 
 type ImportId<'a> = Interned<'a, NameBinding<'a>>;
@@ -60,7 +60,7 @@ impl Resolver<'_, '_> {
         // For mod items `nearest_normal_mod` returns its argument, but we actually need its parent.
         let normal_mod_id = self.nearest_normal_mod(def_id);
         if normal_mod_id == def_id {
-            self.opt_local_parent(def_id).map_or(Visibility::Public, Visibility::Restricted)
+            self.tcx.opt_local_parent(def_id).map_or(Visibility::Public, Visibility::Restricted)
         } else {
             Visibility::Restricted(normal_mod_id)
         }
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index ba7f04239c3..52f0b65fad6 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -368,7 +368,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     /// This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
     /// expansion and import resolution (perhaps they can be merged in the future).
     /// The function is used for resolving initial segments of macro paths (e.g., `foo` in
-    /// `foo::bar!(); or `foo!();`) and also for import paths on 2018 edition.
+    /// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
     #[instrument(level = "debug", skip(self, scope_set))]
     pub(crate) fn early_resolve_ident_in_lexical_scope(
         &mut self,
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 4dab0836d28..5d40c6e4e48 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -245,7 +245,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         import: &'a Import<'a>,
     ) -> &'a NameBinding<'a> {
         let import_vis = import.expect_vis().to_def_id();
-        let vis = if binding.vis.is_at_least(import_vis, self)
+        let vis = if binding.vis.is_at_least(import_vis, self.tcx)
             || pub_use_of_private_extern_crate_hack(import, binding)
         {
             import_vis
@@ -255,7 +255,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
         if let ImportKind::Glob { ref max_vis, .. } = import.kind {
             if vis == import_vis
-                || max_vis.get().map_or(true, |max_vis| vis.is_at_least(max_vis, self))
+                || max_vis.get().map_or(true, |max_vis| vis.is_at_least(max_vis, self.tcx))
             {
                 max_vis.set(Some(vis.expect_local()))
             }
@@ -294,7 +294,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 old_binding,
                                 binding,
                             ));
-                        } else if !old_binding.vis.is_at_least(binding.vis, &*this) {
+                        } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
                             // We are glob-importing the same item but with greater visibility.
                             resolution.binding = Some(binding);
                         }
@@ -786,7 +786,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     }
                     if !is_prelude
                     && let Some(max_vis) = max_vis.get()
-                    && !max_vis.is_at_least(import.expect_vis(), &*self)
+                    && !max_vis.is_at_least(import.expect_vis(), self.tcx)
                 {
                     let msg = "glob import doesn't reexport anything because no candidate is public enough";
                     self.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, msg);
@@ -977,7 +977,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut crate_private_reexport = false;
         self.per_ns(|this, ns| {
             if let Ok(binding) = source_bindings[ns].get() {
-                if !binding.vis.is_at_least(import.expect_vis(), &*this) {
+                if !binding.vis.is_at_least(import.expect_vis(), this.tcx) {
                     reexport_error = Some((ns, binding));
                     if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
                         if binding_def_id.is_top_level_module() {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 7df17376b3e..cc3e142a5fd 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -22,7 +22,6 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, PartialRes, PerNS};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::{BindingAnnotation, PrimTy, TraitCandidate};
 use rustc_middle::middle::resolve_bound_vars::Set1;
-use rustc_middle::ty::DefIdTree;
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
 use rustc_session::lint;
@@ -1671,8 +1670,12 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             // Figure out if this is a type/trait segment,
             // which may need lifetime elision performed.
             let type_def_id = match partial_res.base_res() {
-                Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => self.r.parent(def_id),
-                Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => self.r.parent(def_id),
+                Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
+                    self.r.tcx.parent(def_id)
+                }
+                Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
+                    self.r.tcx.parent(def_id)
+                }
                 Res::Def(DefKind::Struct, def_id)
                 | Res::Def(DefKind::Union, def_id)
                 | Res::Def(DefKind::Enum, def_id)
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 36415936bdc..206c43f6902 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -21,7 +21,6 @@ use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_hir::PrimTy;
-use rustc_middle::ty::DefIdTree;
 use rustc_session::lint;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
@@ -878,7 +877,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         );
         let is_assoc_fn = self.self_type_is_available();
         if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function {
-            // The current function has a `self' parameter, but we were unable to resolve
+            // The current function has a `self` parameter, but we were unable to resolve
             // a reference to `self`. This can only happen if the `self` identifier we
             // are resolving came from a different hygiene context.
             if fn_kind.decl().inputs.get(0).map_or(false, |p| p.is_self()) {
@@ -1508,7 +1507,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 }
             }
             (Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => {
-                let def_id = self.r.parent(ctor_def_id);
+                let def_id = self.r.tcx.parent(ctor_def_id);
                 if let Some(span) = self.def_span(def_id) {
                     err.span_label(span, &format!("`{}` defined here", path_str));
                 }
@@ -1999,7 +1998,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             }
         } else {
             let needs_placeholder = |ctor_def_id: DefId, kind: CtorKind| {
-                let def_id = self.r.parent(ctor_def_id);
+                let def_id = self.r.tcx.parent(ctor_def_id);
                 let has_no_fields = self.r.field_names.get(&def_id).map_or(false, |f| f.is_empty());
                 match kind {
                     CtorKind::Const => false,
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 7a1f14f71f2..5eba208e3ed 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -44,7 +44,7 @@ use rustc_metadata::creader::{CStore, CrateLoader};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::span_bug;
-use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools, TyCtxt};
+use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
 use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::cstore::CrateStore;
@@ -946,7 +946,6 @@ pub struct Resolver<'a, 'tcx> {
     has_pub_restricted: bool,
     used_imports: FxHashSet<NodeId>,
     maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
-    maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
 
     /// Privacy errors are delayed until the end in order to deduplicate them.
     privacy_errors: Vec<PrivacyError<'a>>,
@@ -1118,13 +1117,6 @@ impl<'a, 'tcx> AsMut<Resolver<'a, 'tcx>> for Resolver<'a, 'tcx> {
     }
 }
 
-impl<'a, 'b, 'tcx> DefIdTree for &'a Resolver<'b, 'tcx> {
-    #[inline]
-    fn opt_parent(self, id: DefId) -> Option<DefId> {
-        self.tcx.opt_parent(id)
-    }
-}
-
 impl<'tcx> Resolver<'_, 'tcx> {
     fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
         self.node_id_to_def_id.get(&node).copied()
@@ -1284,7 +1276,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             has_pub_restricted: false,
             used_imports: FxHashSet::default(),
             maybe_unused_trait_imports: Default::default(),
-            maybe_unused_extern_crates: Vec::new(),
 
             privacy_errors: Vec::new(),
             ambiguity_errors: Vec::new(),
@@ -1400,7 +1391,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let extern_crate_map = self.extern_crate_map;
         let reexport_map = self.reexport_map;
         let maybe_unused_trait_imports = self.maybe_unused_trait_imports;
-        let maybe_unused_extern_crates = self.maybe_unused_extern_crates;
         let glob_map = self.glob_map;
         let main_def = self.main_def;
         let confused_type_with_std_module = self.confused_type_with_std_module;
@@ -1414,12 +1404,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             reexport_map,
             glob_map,
             maybe_unused_trait_imports,
-            maybe_unused_extern_crates,
-            extern_prelude: self
-                .extern_prelude
-                .iter()
-                .map(|(ident, entry)| (ident.name, entry.introduced_by_item))
-                .collect(),
             main_def,
             trait_impls: self.trait_impls,
             proc_macros,
@@ -1798,7 +1782,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         vis: ty::Visibility<impl Into<DefId>>,
         module: Module<'a>,
     ) -> bool {
-        vis.is_accessible_from(module.nearest_parent_mod(), self)
+        vis.is_accessible_from(module.nearest_parent_mod(), self.tcx)
     }
 
     fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) {
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 5e4b66018e4..b8853c1744c 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -265,9 +265,9 @@ fn strip_generics_from_path_segment(segment: Vec<char>) -> Result<String, Malfor
     }
 }
 
-pub fn strip_generics_from_path(path_str: &str) -> Result<String, MalformedGenerics> {
+pub fn strip_generics_from_path(path_str: &str) -> Result<Box<str>, MalformedGenerics> {
     if !path_str.contains(['<', '>']) {
-        return Ok(path_str.to_string());
+        return Ok(path_str.into());
     }
     let mut stripped_segments = vec![];
     let mut path = path_str.chars().peekable();
@@ -322,7 +322,11 @@ pub fn strip_generics_from_path(path_str: &str) -> Result<String, MalformedGener
 
     let stripped_path = stripped_segments.join("::");
 
-    if !stripped_path.is_empty() { Ok(stripped_path) } else { Err(MalformedGenerics::MissingType) }
+    if !stripped_path.is_empty() {
+        Ok(stripped_path.into())
+    } else {
+        Err(MalformedGenerics::MissingType)
+    }
 }
 
 /// Returns whether the first doc-comment is an inner attribute.
@@ -336,7 +340,7 @@ pub fn inner_docs(attrs: &[ast::Attribute]) -> bool {
 /// Simplified version of the corresponding function in rustdoc.
 /// If the rustdoc version returns a successful result, this function must return the same result.
 /// Otherwise this function may return anything.
-fn preprocess_link(link: &str) -> String {
+fn preprocess_link(link: &str) -> Box<str> {
     let link = link.replace('`', "");
     let link = link.split('#').next().unwrap();
     let link = link.trim();
@@ -345,7 +349,7 @@ fn preprocess_link(link: &str) -> String {
     let link = link.strip_suffix("{}").unwrap_or(link);
     let link = link.strip_suffix("[]").unwrap_or(link);
     let link = if link != "!" { link.strip_suffix('!').unwrap_or(link) } else { link };
-    strip_generics_from_path(link).unwrap_or_else(|_| link.to_string())
+    strip_generics_from_path(link).unwrap_or_else(|_| link.into())
 }
 
 /// Keep inline and reference links `[]`,
@@ -365,7 +369,7 @@ pub fn may_be_doc_link(link_type: LinkType) -> bool {
 
 /// Simplified version of `preprocessed_markdown_links` from rustdoc.
 /// Must return at least the same links as it, but may add some more links on top of that.
-pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<String> {
+pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<str>> {
     let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
     let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();
 
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index 377c364961b..567fe06109b 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -43,7 +43,6 @@ pub trait Encoder {
     fn emit_str(&mut self, v: &str);
     fn emit_raw_bytes(&mut self, s: &[u8]);
 
-    // Convenience for the derive macro:
     fn emit_enum_variant<F>(&mut self, v_id: usize, f: F)
     where
         F: FnOnce(&mut Self),
@@ -51,17 +50,6 @@ pub trait Encoder {
         self.emit_usize(v_id);
         f(self);
     }
-
-    // We put the field index in a const generic to allow the emit_usize to be
-    // compiled into a more efficient form. In practice, the variant index is
-    // known at compile-time, and that knowledge allows much more efficient
-    // codegen than we'd otherwise get. LLVM isn't always able to make the
-    // optimization that would otherwise be necessary here, likely due to the
-    // multiple levels of inlining and const-prop that are needed.
-    #[inline]
-    fn emit_fieldless_enum_variant<const ID: usize>(&mut self) {
-        self.emit_usize(ID)
-    }
 }
 
 // Note: all the methods in this trait are infallible, which may be surprising.
diff --git a/compiler/rustc_session/locales/en-US.ftl b/compiler/rustc_session/locales/en-US.ftl
index fe553edab42..ff53f22d43f 100644
--- a/compiler/rustc_session/locales/en-US.ftl
+++ b/compiler/rustc_session/locales/en-US.ftl
@@ -5,7 +5,7 @@ session_incorrect_cgu_reuse_type =
     }`{$expected_reuse}`
 
 session_cgu_not_recorded =
-    CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded`
+    CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
 
 session_feature_gate_error = {$explain}
 
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 295e93f6103..d4e4ace889b 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2245,7 +2245,7 @@ pub fn parse_externs(
                 early_error(
                     error_format,
                     "the `-Z unstable-options` flag must also be passed to \
-                     enable `--extern options",
+                     enable `--extern` options",
                 );
             }
             for opt in opts.split(',') {
@@ -2792,7 +2792,7 @@ pub enum PpMode {
     HirTree,
     /// `-Zunpretty=thir-tree`
     ThirTree,
-    /// `-Zunpretty=`thir-flat`
+    /// `-Zunpretty=thir-flat`
     ThirFlat,
     /// `-Zunpretty=mir`
     Mir,
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 2075ed57a94..f1fbf38217d 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -182,7 +182,17 @@ pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
         if dir.ends_with(crate::config::host_triple()) {
             dir.parent() // chop off `$target`
                 .and_then(|p| p.parent()) // chop off `rustlib`
-                .and_then(|p| p.parent()) // chop off `lib`
+                .and_then(|p| {
+                    // chop off `lib` (this could be also $arch dir if the host sysroot uses a
+                    // multi-arch layout like Debian or Ubuntu)
+                    match p.parent() {
+                        Some(p) => match p.file_name() {
+                            Some(f) if f == "lib" => p.parent(), // first chop went for $arch, so chop again for `lib`
+                            _ => Some(p),
+                        },
+                        None => None,
+                    }
+                })
                 .map(|s| s.to_owned())
                 .ok_or(format!(
                     "Could not move 3 levels upper using `parent()` on {}",
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 4beac931632..b466a3fcdee 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1503,6 +1503,9 @@ options! {
         "what location details should be tracked when using caller_location, either \
         `none`, or a comma separated list of location details, for which \
         valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
+    lower_impl_trait_in_trait_to_assoc_ty: bool = (false, parse_bool, [TRACKED],
+        "modify the lowering strategy for `impl Trait` in traits so that they are lowered to \
+        generic associated types"),
     ls: bool = (false, parse_bool, [UNTRACKED],
         "list the symbols defined by a library crate (default: no)"),
     macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 446ba63ed1c..12634f67185 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -882,10 +882,14 @@ impl Session {
 
     /// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
     /// This expends fuel if applicable, and records fuel if applicable.
-    pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
+    pub fn consider_optimizing(
+        &self,
+        get_crate_name: impl Fn() -> Symbol,
+        msg: impl Fn() -> String,
+    ) -> bool {
         let mut ret = true;
         if let Some((ref c, _)) = self.opts.unstable_opts.fuel {
-            if c == crate_name {
+            if c == get_crate_name().as_str() {
                 assert_eq!(self.threads(), 1);
                 let mut fuel = self.optimization_fuel.lock();
                 ret = fuel.remaining != 0;
@@ -903,7 +907,7 @@ impl Session {
             }
         }
         if let Some(ref c) = self.opts.unstable_opts.print_fuel {
-            if c == crate_name {
+            if c == get_crate_name().as_str() {
                 assert_eq!(self.threads(), 1);
                 self.print_fuel.fetch_add(1, SeqCst);
             }
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 2340d501d5a..162c15574b5 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -235,7 +235,7 @@ impl<D: Decoder> Decodable<D> for DefIndex {
 pub struct DefId {
     // cfg-ing the order of fields so that the `DefIndex` which is high entropy always ends up in
     // the lower bits no matter the endianness. This allows the compiler to turn that `Hash` impl
-    // into a direct call to 'u64::hash(_)`.
+    // into a direct call to `u64::hash(_)`.
     #[cfg(not(all(target_pointer_width = "64", target_endian = "big")))]
     pub index: DefIndex,
     pub krate: CrateNum,
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index dee823eefde..9f22e9776d4 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1151,6 +1151,7 @@ pub enum DesugaringKind {
     Await,
     ForLoop,
     WhileLoop,
+    Replace,
 }
 
 impl DesugaringKind {
@@ -1166,6 +1167,7 @@ impl DesugaringKind {
             DesugaringKind::OpaqueTy => "`impl Trait`",
             DesugaringKind::ForLoop => "`for` loop",
             DesugaringKind::WhileLoop => "`while` loop",
+            DesugaringKind::Replace => "drop and replace",
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index fb579e4ff77..6272bf7f25e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1954,7 +1954,7 @@ impl Interner {
         let name = Symbol::new(inner.strings.len() as u32);
 
         // SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
-        // and immediately convert the clone back to `&[u8], all because there
+        // and immediately convert the clone back to `&[u8]`, all because there
         // is no `inner.arena.alloc_str()` method. This is clearly safe.
         let string: &str =
             unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) };
diff --git a/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
new file mode 100644
index 00000000000..c048d4a2aad
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/canonical/canonicalize.rs
@@ -0,0 +1,390 @@
+use std::cmp::Ordering;
+
+use crate::infer::InferCtxt;
+use rustc_middle::infer::canonical::Canonical;
+use rustc_middle::infer::canonical::CanonicalTyVarKind;
+use rustc_middle::infer::canonical::CanonicalVarInfo;
+use rustc_middle::infer::canonical::CanonicalVarInfos;
+use rustc_middle::infer::canonical::CanonicalVarKind;
+use rustc_middle::ty::BoundRegionKind::BrAnon;
+use rustc_middle::ty::BoundTyKind;
+use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::TypeVisitableExt;
+use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
+
+/// Whether we're canonicalizing a query input or the query reponse.
+///
+/// When canonicalizing an input we're in the context of the caller
+/// while canonicalizing the response happens in the context of the
+/// query.
+#[derive(Debug, Clone, Copy)]
+pub enum CanonicalizeMode {
+    Input,
+    /// FIXME: We currently return region constraints refering to
+    /// placeholders and inference variables from a binder instantiated
+    /// inside of the query.
+    ///
+    /// In the long term we should eagerly deal with these constraints
+    /// inside of the query and only propagate constraints which are
+    /// actually nameable by the caller.
+    Response {
+        /// The highest universe nameable by the caller.
+        ///
+        /// All variables in a universe nameable by the caller get mapped
+        /// to the root universe in the response and then mapped back to
+        /// their correct universe when applying the query response in the
+        /// context of the caller.
+        ///
+        /// This doesn't work for universes created inside of the query so
+        /// we do remember their universe in the response.
+        max_input_universe: ty::UniverseIndex,
+    },
+}
+
+pub struct Canonicalizer<'a, 'tcx> {
+    infcx: &'a InferCtxt<'tcx>,
+    canonicalize_mode: CanonicalizeMode,
+
+    variables: &'a mut Vec<ty::GenericArg<'tcx>>,
+    primitive_var_infos: Vec<CanonicalVarInfo<'tcx>>,
+    binder_index: ty::DebruijnIndex,
+}
+
+impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
+    #[instrument(level = "debug", skip(infcx), ret)]
+    pub fn canonicalize<T: TypeFoldable<TyCtxt<'tcx>>>(
+        infcx: &'a InferCtxt<'tcx>,
+        canonicalize_mode: CanonicalizeMode,
+        variables: &'a mut Vec<ty::GenericArg<'tcx>>,
+        value: T,
+    ) -> Canonical<'tcx, T> {
+        let mut canonicalizer = Canonicalizer {
+            infcx,
+            canonicalize_mode,
+
+            variables,
+            primitive_var_infos: Vec::new(),
+            binder_index: ty::INNERMOST,
+        };
+
+        let value = value.fold_with(&mut canonicalizer);
+        assert!(!value.needs_infer());
+        assert!(!value.has_placeholders());
+
+        let (max_universe, variables) = canonicalizer.finalize();
+
+        Canonical { max_universe, variables, value }
+    }
+
+    fn finalize(self) -> (ty::UniverseIndex, CanonicalVarInfos<'tcx>) {
+        let mut var_infos = self.primitive_var_infos;
+        // See the rustc-dev-guide section about how we deal with universes
+        // during canonicalization in the new solver.
+        match self.canonicalize_mode {
+            // We try to deduplicate as many query calls as possible and hide
+            // all information which should not matter for the solver.
+            //
+            // For this we compress universes as much as possible.
+            CanonicalizeMode::Input => {}
+            // When canonicalizing a response we map a universes already entered
+            // by the caller to the root universe and only return useful universe
+            // information for placeholders and inference variables created inside
+            // of the query.
+            CanonicalizeMode::Response { max_input_universe } => {
+                for var in var_infos.iter_mut() {
+                    let uv = var.universe();
+                    let new_uv = ty::UniverseIndex::from(
+                        uv.index().saturating_sub(max_input_universe.index()),
+                    );
+                    *var = var.with_updated_universe(new_uv);
+                }
+                let max_universe = var_infos
+                    .iter()
+                    .map(|info| info.universe())
+                    .max()
+                    .unwrap_or(ty::UniverseIndex::ROOT);
+
+                let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
+                return (max_universe, var_infos);
+            }
+        }
+
+        // Given a `var_infos` with existentials `En` and universals `Un` in
+        // universes `n`, this algorithm compresses them in place so that:
+        //
+        // - the new universe indices are as small as possible
+        // - we only create a new universe if we would otherwise put a placeholder in
+        //   the same compressed universe as an existential which cannot name it
+        //
+        // Let's walk through an example:
+        // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 0
+        // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 1
+        // - var_infos: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 1, next_orig_uv: 2
+        // - var_infos: [E0, U1, E5, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 5
+        // - var_infos: [E0, U1, E1, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 6
+        // - var_infos: [E0, U1, E1, U1, E1, E2, U2], curr_compressed_uv: 2, next_orig_uv: -
+        //
+        // This algorithm runs in `O(n²)` where `n` is the number of different universe
+        // indices in the input. This should be fine as `n` is expected to be small.
+        let mut curr_compressed_uv = ty::UniverseIndex::ROOT;
+        let mut existential_in_new_uv = false;
+        let mut next_orig_uv = Some(ty::UniverseIndex::ROOT);
+        while let Some(orig_uv) = next_orig_uv.take() {
+            let mut update_uv = |var: &mut CanonicalVarInfo<'tcx>, orig_uv, is_existential| {
+                let uv = var.universe();
+                match uv.cmp(&orig_uv) {
+                    Ordering::Less => (), // Already updated
+                    Ordering::Equal => {
+                        if is_existential {
+                            existential_in_new_uv = true;
+                        } else if existential_in_new_uv {
+                            //  `var` is a placeholder from a universe which is not nameable
+                            // by an existential which we already put into the compressed
+                            // universe `curr_compressed_uv`. We therefore have to create a
+                            // new universe for `var`.
+                            curr_compressed_uv = curr_compressed_uv.next_universe();
+                            existential_in_new_uv = false;
+                        }
+
+                        *var = var.with_updated_universe(curr_compressed_uv);
+                    }
+                    Ordering::Greater => {
+                        // We can ignore this variable in this iteration. We only look at
+                        // universes which actually occur in the input for performance.
+                        //
+                        // For this we set `next_orig_uv` to the next smallest, not yet compressed,
+                        // universe of the input.
+                        if next_orig_uv.map_or(true, |curr_next_uv| uv.cannot_name(curr_next_uv)) {
+                            next_orig_uv = Some(uv);
+                        }
+                    }
+                }
+            };
+
+            // For each universe which occurs in the input, we first iterate over all
+            // placeholders and then over all inference variables.
+            //
+            // Whenever we compress the universe of a placeholder, no existential with
+            // an already compressed universe can name that placeholder.
+            for is_existential in [false, true] {
+                for var in var_infos.iter_mut() {
+                    // We simply put all regions from the input into the highest
+                    // compressed universe, so we only deal with them at the end.
+                    if !var.is_region() {
+                        if is_existential == var.is_existential() {
+                            update_uv(var, orig_uv, is_existential)
+                        }
+                    }
+                }
+            }
+        }
+
+        for var in var_infos.iter_mut() {
+            if var.is_region() {
+                assert!(var.is_existential());
+                *var = var.with_updated_universe(curr_compressed_uv);
+            }
+        }
+
+        let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
+        (curr_compressed_uv, var_infos)
+    }
+}
+
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
+    fn interner(&self) -> TyCtxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
+    where
+        T: TypeFoldable<TyCtxt<'tcx>>,
+    {
+        self.binder_index.shift_in(1);
+        let t = t.super_fold_with(self);
+        self.binder_index.shift_out(1);
+        t
+    }
+
+    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        let r = self.infcx.shallow_resolve(r);
+        let kind = match *r {
+            ty::ReLateBound(..) => return r,
+
+            ty::ReStatic => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+                CanonicalizeMode::Response { .. } => return r,
+            },
+
+            ty::ReErased | ty::ReFree(_) | ty::ReEarlyBound(_) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+                CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"),
+            },
+
+            ty::RePlaceholder(placeholder) => match self.canonicalize_mode {
+                // We canonicalize placeholder regions as existentials in query inputs.
+                CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+                CanonicalizeMode::Response { max_input_universe } => {
+                    // If we have a placeholder region inside of a query, it must be from
+                    // a new universe.
+                    if max_input_universe.can_name(placeholder.universe) {
+                        bug!("new placeholder in universe {max_input_universe:?}: {r:?}");
+                    }
+                    CanonicalVarKind::PlaceholderRegion(placeholder)
+                }
+            },
+
+            ty::ReVar(_) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
+                CanonicalizeMode::Response { .. } => {
+                    CanonicalVarKind::Region(self.infcx.universe_of_region(r))
+                }
+            },
+
+            ty::ReError(_) => return r,
+        };
+
+        let existing_bound_var = match self.canonicalize_mode {
+            CanonicalizeMode::Input => None,
+            CanonicalizeMode::Response { .. } => {
+                self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from)
+            }
+        };
+        let var = existing_bound_var.unwrap_or_else(|| {
+            let var = ty::BoundVar::from(self.variables.len());
+            self.variables.push(r.into());
+            self.primitive_var_infos.push(CanonicalVarInfo { kind });
+            var
+        });
+        let br = ty::BoundRegion { var, kind: BrAnon(var.as_u32(), None) };
+        self.interner().mk_re_late_bound(self.binder_index, br)
+    }
+
+    fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        let kind = match *t.kind() {
+            ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
+                Ok(t) => return self.fold_ty(t),
+                Err(ui) => CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
+            },
+            ty::Infer(ty::IntVar(_)) => {
+                let nt = self.infcx.shallow_resolve(t);
+                if nt != t {
+                    return self.fold_ty(nt);
+                } else {
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+                }
+            }
+            ty::Infer(ty::FloatVar(_)) => {
+                let nt = self.infcx.shallow_resolve(t);
+                if nt != t {
+                    return self.fold_ty(nt);
+                } else {
+                    CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+                }
+            }
+            ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+                bug!("fresh var during canonicalization: {t:?}")
+            }
+            ty::Placeholder(placeholder) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
+                    universe: placeholder.universe,
+                    name: BoundTyKind::Anon(self.variables.len() as u32),
+                }),
+                CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
+            },
+            ty::Param(_) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
+                    universe: ty::UniverseIndex::ROOT,
+                    name: ty::BoundTyKind::Anon(self.variables.len() as u32),
+                }),
+                CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"),
+            },
+            ty::Bool
+            | ty::Char
+            | ty::Int(_)
+            | ty::Uint(_)
+            | ty::Float(_)
+            | ty::Adt(_, _)
+            | ty::Foreign(_)
+            | ty::Str
+            | ty::Array(_, _)
+            | ty::Slice(_)
+            | ty::RawPtr(_)
+            | ty::Ref(_, _, _)
+            | ty::FnDef(_, _)
+            | ty::FnPtr(_)
+            | ty::Dynamic(_, _, _)
+            | ty::Closure(_, _)
+            | ty::Generator(_, _, _)
+            | ty::GeneratorWitness(_)
+            | ty::GeneratorWitnessMIR(..)
+            | ty::Never
+            | ty::Tuple(_)
+            | ty::Alias(_, _)
+            | ty::Bound(_, _)
+            | ty::Error(_) => return t.super_fold_with(self),
+        };
+
+        let var = ty::BoundVar::from(
+            self.variables.iter().position(|&v| v == t.into()).unwrap_or_else(|| {
+                let var = self.variables.len();
+                self.variables.push(t.into());
+                self.primitive_var_infos.push(CanonicalVarInfo { kind });
+                var
+            }),
+        );
+        let bt = ty::BoundTy { var, kind: BoundTyKind::Anon(var.index() as u32) };
+        self.interner().mk_bound(self.binder_index, bt)
+    }
+
+    fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
+        let kind = match c.kind() {
+            ty::ConstKind::Infer(ty::InferConst::Var(vid)) => match self.infcx.probe_const_var(vid)
+            {
+                Ok(c) => return self.fold_const(c),
+                Err(universe) => CanonicalVarKind::Const(universe, c.ty()),
+            },
+            ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => {
+                bug!("fresh var during canonicalization: {c:?}")
+            }
+            ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
+                    ty::Placeholder {
+                        universe: placeholder.universe,
+                        name: ty::BoundVar::from(self.variables.len()),
+                    },
+                    c.ty(),
+                ),
+                CanonicalizeMode::Response { .. } => {
+                    CanonicalVarKind::PlaceholderConst(placeholder, c.ty())
+                }
+            },
+            ty::ConstKind::Param(_) => match self.canonicalize_mode {
+                CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
+                    ty::Placeholder {
+                        universe: ty::UniverseIndex::ROOT,
+                        name: ty::BoundVar::from(self.variables.len()),
+                    },
+                    c.ty(),
+                ),
+                CanonicalizeMode::Response { .. } => bug!("param ty in response: {c:?}"),
+            },
+            ty::ConstKind::Bound(_, _)
+            | ty::ConstKind::Unevaluated(_)
+            | ty::ConstKind::Value(_)
+            | ty::ConstKind::Error(_)
+            | ty::ConstKind::Expr(_) => return c.super_fold_with(self),
+        };
+
+        let var = ty::BoundVar::from(
+            self.variables.iter().position(|&v| v == c.into()).unwrap_or_else(|| {
+                let var = self.variables.len();
+                self.variables.push(c.into());
+                self.primitive_var_infos.push(CanonicalVarInfo { kind });
+                var
+            }),
+        );
+        self.interner().mk_const(ty::ConstKind::Bound(self.binder_index, var), c.ty())
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/canonical/mod.rs b/compiler/rustc_trait_selection/src/solve/canonical/mod.rs
new file mode 100644
index 00000000000..8c3be8da16b
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/solve/canonical/mod.rs
@@ -0,0 +1,240 @@
+/// Canonicalization is used to separate some goal from its context,
+/// throwing away unnecessary information in the process.
+///
+/// This is necessary to cache goals containing inference variables
+/// and placeholders without restricting them to the current `InferCtxt`.
+///
+/// Canonicalization is fairly involved, for more details see the relevant
+/// section of the [rustc-dev-guide][c].
+///
+/// [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
+use self::canonicalize::{CanonicalizeMode, Canonicalizer};
+use super::{CanonicalGoal, Certainty, EvalCtxt, Goal};
+use super::{CanonicalResponse, ExternalConstraints, QueryResult, Response};
+use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
+use rustc_infer::infer::canonical::CanonicalVarValues;
+use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::solve::ExternalConstraintsData;
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::ty::{self, GenericArgKind};
+use rustc_span::DUMMY_SP;
+use std::iter;
+use std::ops::Deref;
+
+mod canonicalize;
+
+impl<'tcx> EvalCtxt<'_, 'tcx> {
+    /// Canonicalizes the goal remembering the original values
+    /// for each bound variable.
+    pub(super) fn canonicalize_goal(
+        &self,
+        goal: Goal<'tcx, ty::Predicate<'tcx>>,
+    ) -> (Vec<ty::GenericArg<'tcx>>, CanonicalGoal<'tcx>) {
+        let mut orig_values = Default::default();
+        let canonical_goal = Canonicalizer::canonicalize(
+            self.infcx,
+            CanonicalizeMode::Input,
+            &mut orig_values,
+            goal,
+        );
+        (orig_values, canonical_goal)
+    }
+
+    /// To return the constraints of a canonical query to the caller, we canonicalize:
+    ///
+    /// - `var_values`: a map from bound variables in the canonical goal to
+    ///   the values inferred while solving the instantiated goal.
+    /// - `external_constraints`: additional constraints which aren't expressable
+    ///   using simple unification of inference variables.
+    #[instrument(level = "debug", skip(self))]
+    pub(super) fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> {
+        let external_constraints = self.compute_external_query_constraints()?;
+
+        let response = Response { var_values: self.var_values, external_constraints, certainty };
+        let canonical = Canonicalizer::canonicalize(
+            self.infcx,
+            CanonicalizeMode::Response { max_input_universe: self.max_input_universe },
+            &mut Default::default(),
+            response,
+        );
+        Ok(canonical)
+    }
+
+    #[instrument(level = "debug", skip(self), ret)]
+    fn compute_external_query_constraints(&self) -> Result<ExternalConstraints<'tcx>, NoSolution> {
+        // Cannot use `take_registered_region_obligations` as we may compute the response
+        // inside of a `probe` whenever we have multiple choices inside of the solver.
+        let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
+        let region_constraints = self.infcx.with_region_constraints(|region_constraints| {
+            make_query_region_constraints(
+                self.tcx(),
+                region_obligations
+                    .iter()
+                    .map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
+                region_constraints,
+            )
+        });
+        let opaque_types = self.infcx.clone_opaque_types_for_query_response();
+        Ok(self
+            .tcx()
+            .mk_external_constraints(ExternalConstraintsData { region_constraints, opaque_types }))
+    }
+
+    /// After calling a canonical query, we apply the constraints returned
+    /// by the query using this function.
+    ///
+    /// This happens in three steps:
+    /// - we instantiate the bound variables of the query response
+    /// - we unify the `var_values` of the response with the `original_values`
+    /// - we apply the `external_constraints` returned by the query
+    pub(super) fn instantiate_and_apply_query_response(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        original_values: Vec<ty::GenericArg<'tcx>>,
+        response: CanonicalResponse<'tcx>,
+    ) -> Result<Certainty, NoSolution> {
+        let substitution = self.compute_query_response_substitution(&original_values, &response);
+
+        let Response { var_values, external_constraints, certainty } =
+            response.substitute(self.tcx(), &substitution);
+
+        self.unify_query_var_values(param_env, &original_values, var_values)?;
+
+        // FIXME: implement external constraints.
+        let ExternalConstraintsData { region_constraints, opaque_types: _ } =
+            external_constraints.deref();
+        self.register_region_constraints(region_constraints);
+
+        Ok(certainty)
+    }
+
+    /// This returns the substitutions to instantiate the bound variables of
+    /// the canonical reponse. This depends on the `original_values` for the
+    /// bound variables.
+    fn compute_query_response_substitution(
+        &self,
+        original_values: &[ty::GenericArg<'tcx>],
+        response: &CanonicalResponse<'tcx>,
+    ) -> CanonicalVarValues<'tcx> {
+        // FIXME: Longterm canonical queries should deal with all placeholders
+        // created inside of the query directly instead of returning them to the
+        // caller.
+        let prev_universe = self.infcx.universe();
+        let universes_created_in_query = response.max_universe.index() + 1;
+        for _ in 0..universes_created_in_query {
+            self.infcx.create_next_universe();
+        }
+
+        let var_values = response.value.var_values;
+        assert_eq!(original_values.len(), var_values.len());
+
+        // If the query did not make progress with constraining inference variables,
+        // we would normally create a new inference variables for bound existential variables
+        // only then unify this new inference variable with the inference variable from
+        // the input.
+        //
+        // We therefore instantiate the existential variable in the canonical response with the
+        // inference variable of the input right away, which is more performant.
+        let mut opt_values = vec![None; response.variables.len()];
+        for (original_value, result_value) in iter::zip(original_values, var_values.var_values) {
+            match result_value.unpack() {
+                GenericArgKind::Type(t) => {
+                    if let &ty::Bound(debruijn, b) = t.kind() {
+                        assert_eq!(debruijn, ty::INNERMOST);
+                        opt_values[b.var.index()] = Some(*original_value);
+                    }
+                }
+                GenericArgKind::Lifetime(r) => {
+                    if let ty::ReLateBound(debruijn, br) = *r {
+                        assert_eq!(debruijn, ty::INNERMOST);
+                        opt_values[br.var.index()] = Some(*original_value);
+                    }
+                }
+                GenericArgKind::Const(c) => {
+                    if let ty::ConstKind::Bound(debrujin, b) = c.kind() {
+                        assert_eq!(debrujin, ty::INNERMOST);
+                        opt_values[b.index()] = Some(*original_value);
+                    }
+                }
+            }
+        }
+
+        let var_values = self.tcx().mk_substs_from_iter(response.variables.iter().enumerate().map(
+            |(index, info)| {
+                if info.universe() != ty::UniverseIndex::ROOT {
+                    // A variable from inside a binder of the query. While ideally these shouldn't
+                    // exist at all (see the FIXME at the start of this method), we have to deal with
+                    // them for now.
+                    self.infcx.instantiate_canonical_var(DUMMY_SP, info, |idx| {
+                        ty::UniverseIndex::from(prev_universe.index() + idx.index())
+                    })
+                } else if info.is_existential() {
+                    // As an optimization we sometimes avoid creating a new inference variable here.
+                    //
+                    // All new inference variables we create start out in the current universe of the caller.
+                    // This is conceptionally wrong as these inference variables would be able to name
+                    // more placeholders then they should be able to. However the inference variables have
+                    // to "come from somewhere", so by equating them with the original values of the caller
+                    // later on, we pull them down into their correct universe again.
+                    if let Some(v) = opt_values[index] {
+                        v
+                    } else {
+                        self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe)
+                    }
+                } else {
+                    // For placeholders which were already part of the input, we simply map this
+                    // universal bound variable back the placeholder of the input.
+                    original_values[info.expect_anon_placeholder() as usize]
+                }
+            },
+        ));
+
+        CanonicalVarValues { var_values }
+    }
+
+    #[instrument(level = "debug", skip(self, param_env), ret)]
+    fn unify_query_var_values(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        original_values: &[ty::GenericArg<'tcx>],
+        var_values: CanonicalVarValues<'tcx>,
+    ) -> Result<(), NoSolution> {
+        assert_eq!(original_values.len(), var_values.len());
+        for (&orig, response) in iter::zip(original_values, var_values.var_values) {
+            // This can fail due to the occurs check, see
+            // `tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs` for an example
+            // where that can happen.
+            //
+            // FIXME: To deal with #105787 I also expect us to emit nested obligations here at
+            // some point. We can figure out how to deal with this once we actually have
+            // an ICE.
+            let nested_goals = self.eq(param_env, orig, response)?;
+            assert!(nested_goals.is_empty(), "{nested_goals:?}");
+        }
+
+        Ok(())
+    }
+
+    fn register_region_constraints(&mut self, region_constraints: &QueryRegionConstraints<'tcx>) {
+        for &(ty::OutlivesPredicate(lhs, rhs), _) in &region_constraints.outlives {
+            match lhs.unpack() {
+                GenericArgKind::Lifetime(lhs) => self.infcx.region_outlives_predicate(
+                    &ObligationCause::dummy(),
+                    ty::Binder::dummy(ty::OutlivesPredicate(lhs, rhs)),
+                ),
+                GenericArgKind::Type(lhs) => self.infcx.register_region_obligation_with_cause(
+                    lhs,
+                    rhs,
+                    &ObligationCause::dummy(),
+                ),
+                GenericArgKind::Const(_) => bug!("const outlives: {lhs:?}: {rhs:?}"),
+            }
+        }
+
+        for member_constraint in &region_constraints.member_constraints {
+            // FIXME: Deal with member constraints :<
+            let _ = member_constraint;
+        }
+    }
+}
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
index c8097e81953..95612674eb9 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs
@@ -19,8 +19,17 @@ use super::Goal;
 pub struct EvalCtxt<'a, 'tcx> {
     // FIXME: should be private.
     pub(super) infcx: &'a InferCtxt<'tcx>,
-
     pub(super) var_values: CanonicalVarValues<'tcx>,
+    /// The highest universe index nameable by the caller.
+    ///
+    /// When we enter a new binder inside of the query we create new universes
+    /// which the caller cannot name. We have to be careful with variables from
+    /// these new universes when creating the query response.
+    ///
+    /// Both because these new universes can prevent us from reaching a fixpoint
+    /// if we have a coinductive cycle and because that's the only way we can return
+    /// new placeholders to the caller.
+    pub(super) max_input_universe: ty::UniverseIndex,
 
     pub(super) search_graph: &'a mut SearchGraph<'tcx>,
 
diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs
index 71f536dd3cb..57b6a452737 100644
--- a/compiler/rustc_trait_selection/src/solve/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/mod.rs
@@ -19,11 +19,9 @@ use std::mem;
 
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues};
-use rustc_infer::infer::canonical::{OriginalQueryValues, QueryRegionConstraints, QueryResponse};
 use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
 use rustc_infer::traits::query::NoSolution;
 use rustc_infer::traits::Obligation;
-use rustc_middle::infer::canonical::Certainty as OldCertainty;
 use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::ty::{
@@ -35,6 +33,7 @@ use crate::solve::search_graph::OverflowHandler;
 use crate::traits::ObligationCause;
 
 mod assembly;
+mod canonical;
 mod eval_ctxt;
 mod fulfill;
 mod project_goals;
@@ -89,11 +88,8 @@ trait CanonicalResponseExt {
 
 impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> {
     fn has_no_inference_or_external_constraints(&self) -> bool {
-        // so that we get a compile error when regions are supported
-        // so this code can be checked for being correct
-        let _: () = self.value.external_constraints.regions;
-
-        self.value.var_values.is_identity()
+        self.value.external_constraints.region_constraints.is_empty()
+            && self.value.var_values.is_identity()
             && self.value.external_constraints.opaque_types.is_empty()
     }
 }
@@ -169,6 +165,8 @@ impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> {
         let result = EvalCtxt {
             search_graph: &mut search_graph,
             infcx: self,
+            // Only relevant when canonicalizing the response.
+            max_input_universe: ty::UniverseIndex::ROOT,
             var_values: CanonicalVarValues::dummy(),
             in_projection_eq_hack: false,
         }
@@ -201,36 +199,33 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         search_graph.with_new_goal(tcx, canonical_goal, |search_graph| {
             let (ref infcx, goal, var_values) =
                 tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
-            let mut ecx =
-                EvalCtxt { infcx, var_values, search_graph, in_projection_eq_hack: false };
+            let mut ecx = EvalCtxt {
+                infcx,
+                var_values,
+                max_input_universe: canonical_goal.max_universe,
+                search_graph,
+                in_projection_eq_hack: false,
+            };
             ecx.compute_goal(goal)
         })
     }
 
-    fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> {
-        let external_constraints = compute_external_query_constraints(self.infcx)?;
-
-        Ok(self.infcx.canonicalize_response(Response {
-            var_values: self.var_values,
-            external_constraints,
-            certainty,
-        }))
-    }
-
     /// Recursively evaluates `goal`, returning whether any inference vars have
     /// been constrained and the certainty of the result.
     fn evaluate_goal(
         &mut self,
         goal: Goal<'tcx, ty::Predicate<'tcx>>,
     ) -> Result<(bool, Certainty), NoSolution> {
-        let mut orig_values = OriginalQueryValues::default();
-        let canonical_goal = self.infcx.canonicalize_query(goal, &mut orig_values);
+        let (orig_values, canonical_goal) = self.canonicalize_goal(goal);
         let canonical_response =
             EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
 
         let has_changed = !canonical_response.value.var_values.is_identity();
-        let certainty =
-            instantiate_canonical_query_response(self.infcx, &orig_values, canonical_response);
+        let certainty = self.instantiate_and_apply_query_response(
+            goal.param_env,
+            orig_values,
+            canonical_response,
+        )?;
 
         // Check that rerunning this query with its inference constraints applied
         // doesn't result in new inference constraints and has the same result.
@@ -244,8 +239,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
             && !self.in_projection_eq_hack
             && !self.search_graph.in_cycle()
         {
-            let mut orig_values = OriginalQueryValues::default();
-            let canonical_goal = self.infcx.canonicalize_query(goal, &mut orig_values);
+            let (_orig_values, canonical_goal) = self.canonicalize_goal(goal);
             let canonical_response =
                 EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?;
             if !canonical_response.value.var_values.is_identity() {
@@ -316,15 +310,21 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
 
     fn compute_type_outlives_goal(
         &mut self,
-        _goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>>,
+        goal: Goal<'tcx, TypeOutlivesPredicate<'tcx>>,
     ) -> QueryResult<'tcx> {
+        let ty::OutlivesPredicate(ty, lt) = goal.predicate;
+        self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy());
         self.make_canonical_response(Certainty::Yes)
     }
 
     fn compute_region_outlives_goal(
         &mut self,
-        _goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>>,
+        goal: Goal<'tcx, RegionOutlivesPredicate<'tcx>>,
     ) -> QueryResult<'tcx> {
+        self.infcx.region_outlives_predicate(
+            &ObligationCause::dummy(),
+            ty::Binder::dummy(goal.predicate),
+        );
         self.make_canonical_response(Certainty::Yes)
     }
 
@@ -561,49 +561,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
     }
 }
 
-#[instrument(level = "debug", skip(infcx), ret)]
-fn compute_external_query_constraints<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-) -> Result<ExternalConstraints<'tcx>, NoSolution> {
-    let region_obligations = infcx.take_registered_region_obligations();
-    let opaque_types = infcx.take_opaque_types_for_query_response();
-    Ok(infcx.tcx.mk_external_constraints(ExternalConstraintsData {
-        // FIXME: Now that's definitely wrong :)
-        //
-        // Should also do the leak check here I think
-        regions: drop(region_obligations),
-        opaque_types,
-    }))
-}
-
-fn instantiate_canonical_query_response<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-    original_values: &OriginalQueryValues<'tcx>,
-    response: CanonicalResponse<'tcx>,
-) -> Certainty {
-    let Ok(InferOk { value, obligations }) = infcx
-        .instantiate_query_response_and_region_obligations(
-            &ObligationCause::dummy(),
-            ty::ParamEnv::empty(),
-            original_values,
-            &response.unchecked_map(|resp| QueryResponse {
-                var_values: resp.var_values,
-                region_constraints: QueryRegionConstraints::default(),
-                certainty: match resp.certainty {
-                    Certainty::Yes => OldCertainty::Proven,
-                    Certainty::Maybe(_) => OldCertainty::Ambiguous,
-                },
-                // FIXME: This to_owned makes me sad, but we should eventually impl
-                // `instantiate_query_response_and_region_obligations` separately
-                // instead of piggybacking off of the old implementation.
-                opaque_types: resp.external_constraints.opaque_types.to_owned(),
-                value: resp.certainty,
-            }),
-        ) else { bug!(); };
-    assert!(obligations.is_empty());
-    value
-}
-
 pub(super) fn response_no_constraints<'tcx>(
     tcx: TyCtxt<'tcx>,
     goal: Canonical<'tcx, impl Sized>,
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 88fd8bb8bd0..33c66d072e9 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -77,10 +77,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         let nested_goals = self
             .eq(goal.param_env, goal.predicate.term, normalized_alias.into())
             .expect("failed to unify with unconstrained term");
-        let rhs_certainty =
+
+        let unify_certainty =
             self.evaluate_all(nested_goals).expect("failed to unify with unconstrained term");
 
-        self.make_canonical_response(normalization_certainty.unify_and(rhs_certainty))
+        self.make_canonical_response(normalization_certainty.unify_and(unify_certainty))
     }
 }
 
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 66d74fd05a6..9ab753c5a48 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -30,7 +30,7 @@ use rustc_middle::hir::map;
 use rustc_middle::ty::error::TypeError::{self, Sorts};
 use rustc_middle::ty::relate::TypeRelation;
 use rustc_middle::ty::{
-    self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
+    self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind,
     GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
     IsSuggestable, ToPredicate, Ty, TyCtxt, TypeAndMut, TypeFoldable, TypeFolder,
     TypeSuperFoldable, TypeVisitableExt, TypeckResults,
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index da2416b9646..944436ab82f 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -212,36 +212,44 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
 
     /// Identifies whether a predicate obligation needs processing.
     ///
-    /// This is always inlined, despite its size, because it has a single
-    /// callsite and it is called *very* frequently.
+    /// This is always inlined because it has a single callsite and it is
+    /// called *very* frequently. Be careful modifying this code! Several
+    /// compile-time benchmarks are very sensitive to even small changes.
     #[inline(always)]
     fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
         // If we were stalled on some unresolved variables, first check whether
         // any of them have been resolved; if not, don't bother doing more work
         // yet.
-        match pending_obligation.stalled_on.len() {
-            // Match arms are in order of frequency, which matters because this
-            // code is so hot. 1 and 0 dominate; 2+ is fairly rare.
-            1 => {
-                let infer_var = pending_obligation.stalled_on[0];
-                self.selcx.infcx.ty_or_const_infer_var_changed(infer_var)
-            }
-            0 => {
-                // In this case we haven't changed, but wish to make a change.
-                true
-            }
-            _ => {
-                // This `for` loop was once a call to `all()`, but this lower-level
-                // form was a perf win. See #64545 for details.
-                (|| {
-                    for &infer_var in &pending_obligation.stalled_on {
-                        if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
-                            return true;
-                        }
+        let stalled_on = &pending_obligation.stalled_on;
+        match stalled_on.len() {
+            // This case is the hottest most of the time, being hit up to 99%
+            // of the time. `keccak` and `cranelift-codegen-0.82.1` are
+            // benchmarks that particularly stress this path.
+            1 => self.selcx.infcx.ty_or_const_infer_var_changed(stalled_on[0]),
+
+            // In this case we haven't changed, but wish to make a change. Note
+            // that this is a special case, and is not equivalent to the `_`
+            // case below, which would return `false` for an empty `stalled_on`
+            // vector.
+            //
+            // This case is usually hit only 1% of the time or less, though it
+            // reaches 20% in `wasmparser-0.101.0`.
+            0 => true,
+
+            // This case is usually hit only 1% of the time or less, though it
+            // reaches 95% in `mime-0.3.16`, 64% in `wast-54.0.0`, and 12% in
+            // `inflate-0.4.5`.
+            //
+            // The obvious way of writing this, with a call to `any()` and no
+            // closure, is currently slower than this version.
+            _ => (|| {
+                for &infer_var in stalled_on {
+                    if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
+                        return true;
                     }
-                    false
-                })()
-            }
+                }
+                false
+            })(),
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index b2317f55d25..0e047977caa 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -28,7 +28,7 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_errors::ErrorGuaranteed;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::{TypeVisitable, TypeVisitableExt};
-use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
+use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
 use rustc_span::def_id::{DefId, CRATE_DEF_ID};
 use rustc_span::Span;
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index e5b0f9d3300..00acbf751f0 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -32,7 +32,6 @@ use rustc_infer::traits::ImplSourceBuiltinData;
 use rustc_middle::traits::select::OverflowError;
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
-use rustc_middle::ty::DefIdTree;
 use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 
@@ -1175,7 +1174,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
 /// paths you want to take. To make things worse, it was possible for
 /// cycles to arise, where you basically had a setup like `<MyType<$0>
 /// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
-/// Trait>::Foo> to `[type error]` would lead to an obligation of
+/// Trait>::Foo>` to `[type error]` would lead to an obligation of
 /// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
 /// an error for this obligation, but we legitimately should not,
 /// because it contains `[type error]`. Yuck! (See issue #29857 for
@@ -1312,16 +1311,16 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
                 }
                 Ok(None) => {
                     candidate_set.mark_ambiguous();
-                    return Err(());
+                    Err(())
                 }
                 Ok(Some(_)) => {
                     // Don't know enough about the impl to provide a useful signature
-                    return Err(());
+                    Err(())
                 }
                 Err(e) => {
                     debug!(error = ?e, "selection error");
                     candidate_set.mark_error(e);
-                    return Err(());
+                    Err(())
                 }
             }
         });
@@ -2199,7 +2198,8 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
         Ok(assoc_ty) => assoc_ty,
         Err(guar) => return Progress::error(tcx, guar),
     };
-    if !leaf_def.item.defaultness(tcx).has_value() {
+    // We don't support specialization for RPITITs anyways... yet.
+    if !leaf_def.is_final() {
         return Progress { term: tcx.ty_error_misc().into(), obligations };
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 4ad13dcb645..e91057356a2 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -339,7 +339,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // Essentially any user-written impl will match with an error type,
         // so creating `ImplCandidates` isn't useful. However, we might
-        // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized)
+        // end up finding a candidate elsewhere (e.g. a `BuiltinCandidate` for `Sized`)
         // This helps us avoid overflow: see issue #72839
         // Since compilation is already guaranteed to fail, this is just
         // to try to show the 'nicest' possible errors to the user.
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 01c1ad3a4ce..4377de15829 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -151,7 +151,7 @@ struct TraitObligationStack<'prev, 'tcx> {
     /// you don't want to cache that `B: AutoTrait` or `A: AutoTrait`
     /// is `EvaluatedToOk`; this is because they were only considered
     /// ok on the premise that if `A: AutoTrait` held, but we indeed
-    /// encountered a problem (later on) with `A: AutoTrait. So we
+    /// encountered a problem (later on) with `A: AutoTrait`. So we
     /// currently set a flag on the stack node for `B: AutoTrait` (as
     /// well as the second instance of `A: AutoTrait`) to suppress
     /// caching.
@@ -727,7 +727,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             // Otherwise, we can say that `T: NonAutoTrait` is
                             // true.
                             // Let's imagine we have a predicate stack like
-                            //         `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto
+                            //         `Foo: Bar -> WF(T) -> T: NonAutoTrait -> T: Auto`
                             // depth   ^1                    ^2                 ^3
                             // and the current predicate is `WF(T)`. `wf_args`
                             // would contain `(T, 1)`. We want to check all
diff --git a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
index e4f3e7928da..0cae0377ee8 100644
--- a/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
+++ b/compiler/rustc_transmute/src/maybe_transmutable/query_context.rs
@@ -58,9 +58,7 @@ mod rustc {
             use rustc_middle::ty;
 
             let parent = if let ty::Adt(adt_def, ..) = scope.kind() {
-                use rustc_middle::ty::DefIdTree;
-                let parent = self.parent(adt_def.did());
-                parent
+                self.parent(adt_def.did())
             } else {
                 // Is this always how we want to handle a non-ADT scope?
                 return false;
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index d4866b5dbdd..2fc55a2527d 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -4,7 +4,8 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_middle::ty::{self, DefIdTree, TyCtxt};
+use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, TyCtxt};
+use rustc_span::symbol::kw;
 
 pub fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
@@ -21,12 +22,68 @@ pub fn provide(providers: &mut ty::query::Providers) {
 fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
     let item = tcx.hir().expect_item(def_id.expect_local());
     match item.kind {
-        hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter(
-            trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
-        ),
-        hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter(
-            impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
-        ),
+        hir::ItemKind::Trait(.., ref trait_item_refs) => {
+            if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
+                // We collect RPITITs for each trait method's return type and create a
+                // corresponding associated item using associated_items_for_impl_trait_in_trait
+                // query.
+                tcx.arena.alloc_from_iter(
+                    trait_item_refs
+                        .iter()
+                        .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
+                        .chain(
+                            trait_item_refs
+                                .iter()
+                                .filter(|trait_item_ref| {
+                                    matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
+                                })
+                                .flat_map(|trait_item_ref| {
+                                    let trait_fn_def_id =
+                                        trait_item_ref.id.owner_id.def_id.to_def_id();
+                                    tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id)
+                                })
+                                .map(|def_id| *def_id),
+                        ),
+                )
+            } else {
+                tcx.arena.alloc_from_iter(
+                    trait_item_refs
+                        .iter()
+                        .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
+                )
+            }
+        }
+        hir::ItemKind::Impl(ref impl_) => {
+            if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
+                // We collect RPITITs for each trait method's return type, on the impl side too and
+                // create a corresponding associated item using
+                // associated_items_for_impl_trait_in_trait query.
+                tcx.arena.alloc_from_iter(
+                    impl_
+                        .items
+                        .iter()
+                        .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id())
+                        .chain(impl_.of_trait.iter().flat_map(|_| {
+                            impl_
+                                .items
+                                .iter()
+                                .filter(|impl_item_ref| {
+                                    matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. })
+                                })
+                                .flat_map(|impl_item_ref| {
+                                    let impl_fn_def_id =
+                                        impl_item_ref.id.owner_id.def_id.to_def_id();
+                                    tcx.associated_items_for_impl_trait_in_trait(impl_fn_def_id)
+                                })
+                                .map(|def_id| *def_id)
+                        })),
+                )
+            } else {
+                tcx.arena.alloc_from_iter(
+                    impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
+                )
+            }
+        }
         _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
     }
 }
@@ -193,10 +250,65 @@ fn associated_item_for_impl_trait_in_trait(
     let span = tcx.def_span(opaque_ty_def_id);
     let trait_assoc_ty =
         tcx.at(span).create_def(trait_def_id.expect_local(), DefPathData::ImplTraitAssocTy);
-    trait_assoc_ty.def_id()
+
+    let local_def_id = trait_assoc_ty.def_id();
+    let def_id = local_def_id.to_def_id();
+
+    trait_assoc_ty.opt_def_kind(Some(DefKind::AssocTy));
+
+    // There's no HIR associated with this new synthesized `def_id`, so feed
+    // `opt_local_def_id_to_hir_id` with `None`.
+    trait_assoc_ty.opt_local_def_id_to_hir_id(None);
+
+    // Copy span of the opaque.
+    trait_assoc_ty.def_ident_span(Some(span));
+
+    // Add the def_id of the function and opaque that generated this synthesized associated type.
+    trait_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Trait {
+        fn_def_id,
+        opaque_def_id: opaque_ty_def_id.to_def_id(),
+    }));
+
+    trait_assoc_ty.associated_item(ty::AssocItem {
+        name: kw::Empty,
+        kind: ty::AssocKind::Type,
+        def_id,
+        trait_item_def_id: None,
+        container: ty::TraitContainer,
+        fn_has_self_parameter: false,
+    });
+
+    // Copy visility of the containing function.
+    trait_assoc_ty.visibility(tcx.visibility(fn_def_id));
+
+    // Copy impl_defaultness of the containing function.
+    trait_assoc_ty.impl_defaultness(tcx.impl_defaultness(fn_def_id));
+
+    // Copy type_of of the opaque.
+    trait_assoc_ty.type_of(ty::EarlyBinder(tcx.mk_opaque(
+        opaque_ty_def_id.to_def_id(),
+        InternalSubsts::identity_for_item(tcx, opaque_ty_def_id.to_def_id()),
+    )));
+
+    // Copy generics_of of the opaque.
+    trait_assoc_ty.generics_of(tcx.generics_of(opaque_ty_def_id).clone());
+
+    // There are no predicates for the synthesized associated type.
+    trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
+        parent: Some(trait_def_id),
+        predicates: &[],
+    });
+
+    // There are no inferred outlives for the synthesized associated type.
+    trait_assoc_ty.inferred_outlives_of(&[]);
+
+    // FIXME implement this.
+    trait_assoc_ty.explicit_item_bounds(&[]);
+
+    local_def_id
 }
 
-/// Given an `trait_assoc_def_id` that corresponds to a previously synthethized impl trait in trait
+/// Given an `trait_assoc_def_id` that corresponds to a previously synthesized impl trait in trait
 /// into an associated type and an `impl_def_id` corresponding to an impl block, create and return
 /// the corresponding associated item inside the impl block.
 fn impl_associated_item_for_impl_trait_in_trait(
@@ -206,8 +318,40 @@ fn impl_associated_item_for_impl_trait_in_trait(
 ) -> LocalDefId {
     let impl_def_id = tcx.local_parent(impl_fn_def_id);
 
-    let span = tcx.def_span(trait_assoc_def_id);
+    // FIXME fix the span, we probably want the def_id of the return type of the function
+    let span = tcx.def_span(impl_fn_def_id);
     let impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy);
 
-    impl_assoc_ty.def_id()
+    let local_def_id = impl_assoc_ty.def_id();
+    let def_id = local_def_id.to_def_id();
+
+    impl_assoc_ty.opt_def_kind(Some(DefKind::AssocTy));
+
+    // There's no HIR associated with this new synthesized `def_id`, so feed
+    // `opt_local_def_id_to_hir_id` with `None`.
+    impl_assoc_ty.opt_local_def_id_to_hir_id(None);
+
+    // Add the def_id of the function that generated this synthesized associated type.
+    impl_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Impl {
+        fn_def_id: impl_fn_def_id.to_def_id(),
+    }));
+
+    impl_assoc_ty.associated_item(ty::AssocItem {
+        name: kw::Empty,
+        kind: ty::AssocKind::Type,
+        def_id,
+        trait_item_def_id: Some(trait_assoc_def_id.to_def_id()),
+        container: ty::ImplContainer,
+        fn_has_self_parameter: false,
+    });
+
+    // Copy impl_defaultness of the containing function.
+    impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id));
+
+    // Copy generics_of the trait's associated item.
+    // FIXME: This is not correct, in particular the parent is going to be wrong. So we would need
+    // to copy from trait_assoc_def_id and adjust things.
+    impl_assoc_ty.generics_of(tcx.generics_of(trait_assoc_def_id).clone());
+
+    local_def_id
 }
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 7fecee2a38b..56d6cc28bc8 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -1,4 +1,3 @@
-use crate::rustc_middle::ty::DefIdTree;
 use rustc_hir::{def::DefKind, def_id::DefId};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
diff --git a/config.toml.example b/config.toml.example
index 69eb228a2d5..3aaeb09d4c0 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -164,6 +164,7 @@ changelog-seen = 2
 # General build configuration options
 # =============================================================================
 [build]
+
 # The default stage to use for the `check` subcommand
 #check-stage = 0
 
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index a563b258723..44a37899007 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -283,9 +283,7 @@ impl<T> Box<T> {
     #[must_use]
     #[inline(always)]
     pub fn pin(x: T) -> Pin<Box<T>> {
-        (#[rustc_box]
-        Box::new(x))
-        .into()
+        Box::new(x).into()
     }
 
     /// Allocates memory on the heap then places `x` into it,
@@ -1242,8 +1240,8 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Box<T, A> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Default> Default for Box<T> {
     /// Creates a `Box<T>`, with the `Default` value for T.
+    #[inline]
     fn default() -> Self {
-        #[rustc_box]
         Box::new(T::default())
     }
 }
@@ -1252,6 +1250,7 @@ impl<T: Default> Default for Box<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
 impl<T> const Default for Box<[T]> {
+    #[inline]
     fn default() -> Self {
         let ptr: Unique<[T]> = Unique::<[T; 0]>::dangling();
         Box(ptr, Global)
@@ -1262,6 +1261,7 @@ impl<T> const Default for Box<[T]> {
 #[stable(feature = "default_box_extra", since = "1.17.0")]
 #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
 impl const Default for Box<str> {
+    #[inline]
     fn default() -> Self {
         // SAFETY: This is the same as `Unique::cast<U>` but with an unsized `U = str`.
         let ptr: Unique<str> = unsafe {
@@ -1616,7 +1616,6 @@ impl<T, const N: usize> From<[T; N]> for Box<[T]> {
     /// println!("{boxed:?}");
     /// ```
     fn from(array: [T; N]) -> Box<[T]> {
-        #[rustc_box]
         Box::new(array)
     }
 }
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index d4a12509b1c..8317ac431a5 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -1924,7 +1924,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     #[stable(feature = "append", since = "1.4.0")]
     pub fn append(&mut self, other: &mut Self) {
         if T::IS_ZST {
-            self.len += other.len;
+            self.len = self.len.checked_add(other.len).expect("capacity overflow");
             other.len = 0;
             other.head = 0;
             return;
diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs
index 5198bf297d9..4c6ae8f2579 100644
--- a/library/alloc/src/macros.rs
+++ b/library/alloc/src/macros.rs
@@ -48,6 +48,8 @@ macro_rules! vec {
     );
     ($($x:expr),+ $(,)?) => (
         $crate::__rust_force_expr!(<[_]>::into_vec(
+            // This rustc_box is not required, but it produces a dramatic improvement in compile
+            // time when constructing arrays with many elements.
             #[rustc_box]
             $crate::boxed::Box::new([$($x),+])
         ))
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index fd1e3e0f75b..932a537c598 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -2145,7 +2145,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I {
                 Rc::from_iter_exact(self, low)
             }
         } else {
-            // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator
+            // TrustedLen contract guarantees that `upper_bound == None` implies an iterator
             // length exceeding `usize::MAX`.
             // The default implementation would collect into a vec which would panic.
             // Thus we panic here immediately without invoking `Vec` code.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 2b843647dd5..c7e7ed3e95e 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2213,10 +2213,6 @@ impl PartialEq for String {
     fn eq(&self, other: &String) -> bool {
         PartialEq::eq(&self[..], &other[..])
     }
-    #[inline]
-    fn ne(&self, other: &String) -> bool {
-        PartialEq::ne(&self[..], &other[..])
-    }
 }
 
 macro_rules! impl_eq {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index f20486ca9e4..fdd341a06ef 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -2895,7 +2895,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToArcSlice<T> for I {
                 Arc::from_iter_exact(self, low)
             }
         } else {
-            // TrustedLen contract guarantees that `upper_bound == `None` implies an iterator
+            // TrustedLen contract guarantees that `upper_bound == None` implies an iterator
             // length exceeding `usize::MAX`.
             // The default implementation would collect into a vec which would panic.
             // Thus we panic here immediately without invoking `Vec` code.
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index b279f21b524..f2aa30f18fc 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -3131,10 +3131,7 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> {
     /// ```
     #[cfg(not(test))]
     fn from(s: [T; N]) -> Vec<T> {
-        <[T]>::into_vec(
-            #[rustc_box]
-            Box::new(s),
-        )
+        <[T]>::into_vec(Box::new(s))
     }
 
     #[cfg(test)]
diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs
index 0b8f5281b78..5a0b852e8d5 100644
--- a/library/alloc/tests/vec_deque.rs
+++ b/library/alloc/tests/vec_deque.rs
@@ -1046,6 +1046,20 @@ fn test_append_double_drop() {
 }
 
 #[test]
+#[should_panic]
+fn test_append_zst_capacity_overflow() {
+    let mut v = Vec::with_capacity(usize::MAX);
+    // note: using resize instead of set_len here would
+    //       be *extremely* slow in unoptimized builds.
+    // SAFETY: `v` has capacity `usize::MAX`, and no initialization
+    //         is needed for empty tuples.
+    unsafe { v.set_len(usize::MAX) };
+    let mut v = VecDeque::from(v);
+    let mut w = vec![()].into();
+    v.append(&mut w);
+}
+
+#[test]
 fn test_retain() {
     let mut buf = VecDeque::new();
     buf.extend(1..5);
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index c0fb0d993c3..c27646b8f33 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -56,7 +56,7 @@
 //!     let value_any = value as &dyn Any;
 //!
 //!     // Try to convert our value to a `String`. If successful, we want to
-//!     // output the String`'s length as well as its value. If not, it's a
+//!     // output the `String`'s length as well as its value. If not, it's a
 //!     // different type: just print it out unadorned.
 //!     match value_any.downcast_ref::<String>() {
 //!         Some(as_string) => {
diff --git a/library/core/src/array/equality.rs b/library/core/src/array/equality.rs
index b2c895f882c..d749865f76f 100644
--- a/library/core/src/array/equality.rs
+++ b/library/core/src/array/equality.rs
@@ -1,6 +1,5 @@
+use crate::cmp::BytewiseEq;
 use crate::convert::TryInto;
-use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
-use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
@@ -144,74 +143,14 @@ impl<T: PartialEq<Other>, Other, const N: usize> SpecArrayEq<Other, N> for T {
     }
 }
 
-impl<T: IsRawEqComparable<U>, U, const N: usize> SpecArrayEq<U, N> for T {
+impl<T: BytewiseEq<U>, U, const N: usize> SpecArrayEq<U, N> for T {
     fn spec_eq(a: &[T; N], b: &[U; N]) -> bool {
-        // SAFETY: This is why `IsRawEqComparable` is an `unsafe trait`.
-        unsafe {
-            let b = &*b.as_ptr().cast::<[T; N]>();
-            crate::intrinsics::raw_eq(a, b)
-        }
+        // SAFETY: Arrays are compared element-wise, and don't add any padding
+        // between elements, so when the elements are `BytewiseEq`, we can
+        // compare the entire array at once.
+        unsafe { crate::intrinsics::raw_eq(a, crate::mem::transmute(b)) }
     }
     fn spec_ne(a: &[T; N], b: &[U; N]) -> bool {
         !Self::spec_eq(a, b)
     }
 }
-
-/// `U` exists on here mostly because `min_specialization` didn't let me
-/// repeat the `T` type parameter in the above specialization, so instead
-/// the `T == U` constraint comes from the impls on this.
-/// # Safety
-/// - Neither `Self` nor `U` has any padding.
-/// - `Self` and `U` have the same layout.
-/// - `Self: PartialEq<U>` is byte-wise (this means no floats, among other things)
-#[rustc_specialization_trait]
-unsafe trait IsRawEqComparable<U>: PartialEq<U> {}
-
-macro_rules! is_raw_eq_comparable {
-    ($($t:ty),+ $(,)?) => {$(
-        unsafe impl IsRawEqComparable<$t> for $t {}
-    )+};
-}
-
-// SAFETY: All the ordinary integer types have no padding, and are not pointers.
-is_raw_eq_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
-
-// SAFETY: bool and char have *niches*, but no *padding* (and these are not pointer types), so this
-// is sound
-is_raw_eq_comparable!(bool, char);
-
-// SAFETY: Similarly, the non-zero types have a niche, but no undef and no pointers,
-// and they compare like their underlying numeric type.
-is_raw_eq_comparable!(
-    NonZeroU8,
-    NonZeroU16,
-    NonZeroU32,
-    NonZeroU64,
-    NonZeroU128,
-    NonZeroUsize,
-    NonZeroI8,
-    NonZeroI16,
-    NonZeroI32,
-    NonZeroI64,
-    NonZeroI128,
-    NonZeroIsize,
-);
-
-// SAFETY: The NonZero types have the "null" optimization guaranteed, and thus
-// are also safe to equality-compare bitwise inside an `Option`.
-// The way `PartialOrd` is defined for `Option` means that this wouldn't work
-// for `<` or `>` on the signed types, but since we only do `==` it's fine.
-is_raw_eq_comparable!(
-    Option<NonZeroU8>,
-    Option<NonZeroU16>,
-    Option<NonZeroU32>,
-    Option<NonZeroU64>,
-    Option<NonZeroU128>,
-    Option<NonZeroUsize>,
-    Option<NonZeroI8>,
-    Option<NonZeroI16>,
-    Option<NonZeroI32>,
-    Option<NonZeroI64>,
-    Option<NonZeroI128>,
-    Option<NonZeroIsize>,
-);
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 7f109491350..897d03595d7 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -632,7 +632,7 @@ pub struct RefCell<T: ?Sized> {
     // Stores the location of the earliest currently active borrow.
     // This gets updated whenever we go from having zero borrows
     // to having a single borrow. When a borrow occurs, this gets included
-    // in the generated `BorrowError/`BorrowMutError`
+    // in the generated `BorrowError`/`BorrowMutError`
     #[cfg(feature = "debug_refcell")]
     borrowed_at: Cell<Option<&'static crate::panic::Location<'static>>>,
     value: UnsafeCell<T>,
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index b4d58376aea..5b5f55d0e65 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -22,6 +22,9 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+mod bytewise;
+pub(crate) use bytewise::BytewiseEq;
+
 use crate::marker::Destruct;
 
 use self::Ordering::*;
diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs
new file mode 100644
index 00000000000..2548d9e24c9
--- /dev/null
+++ b/library/core/src/cmp/bytewise.rs
@@ -0,0 +1,83 @@
+use crate::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
+use crate::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
+
+/// Types where `==` & `!=` are equivalent to comparing their underlying bytes.
+///
+/// Importantly, this means no floating-point types, as those have different
+/// byte representations (like `-0` and `+0`) which compare as the same.
+/// Since byte arrays are `Eq`, that implies that these types are probably also
+/// `Eq`, but that's not technically required to use this trait.
+///
+/// `Rhs` is *de facto* always `Self`, but the separate parameter is important
+/// to avoid the `specializing impl repeats parameter` error when consuming this.
+///
+/// # Safety
+///
+/// - `Self` and `Rhs` have no padding.
+/// - `Self` and `Rhs` have the same layout (size and alignment).
+/// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct.
+/// - `<Self as PartialEq<Rhs>>::{eq,ne}` are equivalent to comparing the bytes.
+#[rustc_specialization_trait]
+pub(crate) unsafe trait BytewiseEq<Rhs = Self>: PartialEq<Rhs> + Sized {}
+
+macro_rules! is_bytewise_comparable {
+    ($($t:ty),+ $(,)?) => {$(
+        unsafe impl BytewiseEq for $t {}
+    )+};
+}
+
+// SAFETY: All the ordinary integer types have no padding, and are not pointers.
+is_bytewise_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
+
+// SAFETY: These have *niches*, but no *padding* and no *provenance*,
+// so we can compare them directly.
+is_bytewise_comparable!(bool, char, super::Ordering);
+
+// SAFETY: Similarly, the non-zero types have a niche, but no undef and no pointers,
+// and they compare like their underlying numeric type.
+is_bytewise_comparable!(
+    NonZeroU8,
+    NonZeroU16,
+    NonZeroU32,
+    NonZeroU64,
+    NonZeroU128,
+    NonZeroUsize,
+    NonZeroI8,
+    NonZeroI16,
+    NonZeroI32,
+    NonZeroI64,
+    NonZeroI128,
+    NonZeroIsize,
+);
+
+// SAFETY: The NonZero types have the "null" optimization guaranteed, and thus
+// are also safe to equality-compare bitwise inside an `Option`.
+// The way `PartialOrd` is defined for `Option` means that this wouldn't work
+// for `<` or `>` on the signed types, but since we only do `==` it's fine.
+is_bytewise_comparable!(
+    Option<NonZeroU8>,
+    Option<NonZeroU16>,
+    Option<NonZeroU32>,
+    Option<NonZeroU64>,
+    Option<NonZeroU128>,
+    Option<NonZeroUsize>,
+    Option<NonZeroI8>,
+    Option<NonZeroI16>,
+    Option<NonZeroI32>,
+    Option<NonZeroI64>,
+    Option<NonZeroI128>,
+    Option<NonZeroIsize>,
+);
+
+macro_rules! is_bytewise_comparable_array_length {
+    ($($n:literal),+ $(,)?) => {$(
+        // SAFETY: Arrays have no padding between elements, so if the elements are
+        // `BytewiseEq`, then the whole array can be too.
+        unsafe impl<T: BytewiseEq<U>, U> BytewiseEq<[U; $n]> for [T; $n] {}
+    )+};
+}
+
+// Frustratingly, this can't be made const-generic as it gets
+//    error: specializing impl repeats parameter `N`
+// so just do it for a couple of plausibly-common ones.
+is_bytewise_comparable_array_length!(0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64);
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index 76daceecd7b..27f6659049c 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -144,6 +144,7 @@ mod c_char_definition {
                 )
             ),
             all(target_os = "fuchsia", target_arch = "aarch64"),
+            all(target_os = "nto", target_arch = "aarch64"),
             target_os = "horizon"
         ))] {
             pub type c_char = u8;
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index b1ed3b31e43..18a90599c4d 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2093,6 +2093,10 @@ extern "rust-intrinsic" {
     /// Above some backend-decided threshold this will emit calls to `memcmp`,
     /// like slice equality does, instead of causing massive code size.
     ///
+    /// Since this works by comparing the underlying bytes, the actual `T` is
+    /// not particularly important.  It will be used for its size and alignment,
+    /// but any validity restrictions will be ignored, not enforced.
+    ///
     /// # Safety
     ///
     /// It's UB to call this if any of the *bytes* in `*a` or `*b` are uninitialized or carry a
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index 995d66dca56..72db1d87ca3 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -42,7 +42,7 @@
 //! another function. The `dialect` and `phase` parameters indicate which [version of MIR][dialect
 //! docs] you are inserting here. Generally you'll want to use `#![custom_mir(dialect = "built")]`
 //! if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
-//! "runtime", phase = "optimized")] if you don't.
+//! "runtime", phase = "optimized")]` if you don't.
 //!
 //! [dialect docs]:
 //!     https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.MirPhase.html
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index d3727a824b5..24bad799fc8 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -124,6 +124,8 @@
 #![feature(const_inherent_unchecked_arith)]
 #![feature(const_int_unchecked_arith)]
 #![feature(const_intrinsic_forget)]
+#![feature(const_ipv4)]
+#![feature(const_ipv6)]
 #![feature(const_likely)]
 #![feature(const_maybe_uninit_uninit_array)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
@@ -134,6 +136,7 @@
 #![feature(const_option)]
 #![feature(const_option_ext)]
 #![feature(const_pin)]
+#![feature(const_pointer_byte_offsets)]
 #![feature(const_pointer_is_aligned)]
 #![feature(const_ptr_sub_ptr)]
 #![feature(const_replace)]
@@ -179,6 +182,7 @@
 #![feature(const_slice_index)]
 #![feature(const_is_char_boundary)]
 #![feature(const_cstr_methods)]
+#![feature(ip)]
 #![feature(is_ascii_octdigit)]
 //
 // Language features:
@@ -242,7 +246,6 @@
 // Target features:
 #![feature(arm_target_feature)]
 #![feature(avx512_target_feature)]
-#![feature(cmpxchg16b_target_feature)]
 #![feature(hexagon_target_feature)]
 #![feature(mips_target_feature)]
 #![feature(powerpc_target_feature)]
@@ -251,6 +254,7 @@
 #![feature(sse4a_target_feature)]
 #![feature(tbm_target_feature)]
 #![feature(wasm_target_feature)]
+#![cfg_attr(bootstrap, feature(cmpxchg16b_target_feature))]
 
 // allow using `core::` in intra-doc links
 #[allow(unused_extern_crates)]
@@ -349,6 +353,7 @@ pub mod cell;
 pub mod char;
 pub mod ffi;
 pub mod iter;
+pub mod net;
 pub mod option;
 pub mod panic;
 pub mod panicking;
diff --git a/library/std/src/net/display_buffer.rs b/library/core/src/net/display_buffer.rs
index 7aadf06e92f..7aadf06e92f 100644
--- a/library/std/src/net/display_buffer.rs
+++ b/library/core/src/net/display_buffer.rs
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
new file mode 100644
index 00000000000..954d88d548e
--- /dev/null
+++ b/library/core/src/net/ip_addr.rs
@@ -0,0 +1,2070 @@
+use crate::cmp::Ordering;
+use crate::fmt::{self, Write};
+use crate::mem::transmute;
+
+use super::display_buffer::DisplayBuffer;
+
+/// An IP address, either IPv4 or IPv6.
+///
+/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
+/// respective documentation for more details.
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+///
+/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
+/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+///
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
+/// assert_eq!("::1".parse(), Ok(localhost_v6));
+///
+/// assert_eq!(localhost_v4.is_ipv6(), false);
+/// assert_eq!(localhost_v4.is_ipv4(), true);
+/// ```
+#[cfg_attr(not(test), rustc_diagnostic_item = "IpAddr")]
+#[stable(feature = "ip_addr", since = "1.7.0")]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
+pub enum IpAddr {
+    /// An IPv4 address.
+    #[stable(feature = "ip_addr", since = "1.7.0")]
+    V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
+    /// An IPv6 address.
+    #[stable(feature = "ip_addr", since = "1.7.0")]
+    V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
+}
+
+/// An IPv4 address.
+///
+/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
+/// They are usually represented as four octets.
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
+///
+/// # Textual representation
+///
+/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
+/// notation, divided by `.` (this is called "dot-decimal notation").
+/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which
+/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943].
+///
+/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1
+/// [`FromStr`]: crate::str::FromStr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv4Addr;
+///
+/// let localhost = Ipv4Addr::new(127, 0, 0, 1);
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// assert!("012.004.002.000".parse::<Ipv4Addr>().is_err()); // all octets are in octal
+/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
+/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Ipv4Addr {
+    octets: [u8; 4],
+}
+
+/// An IPv6 address.
+///
+/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
+/// They are usually represented as eight 16-bit segments.
+///
+/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+///
+/// # Embedding IPv4 Addresses
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined:
+/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated.
+///
+/// Both types of addresses are not assigned any special meaning by this implementation,
+/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`,
+/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is.
+/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address.
+///
+/// ### IPv4-Compatible IPv6 Addresses
+///
+/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated.
+/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows:
+///
+/// ```text
+/// |                80 bits               | 16 |      32 bits        |
+/// +--------------------------------------+--------------------------+
+/// |0000..............................0000|0000|    IPv4 address     |
+/// +--------------------------------------+----+---------------------+
+/// ```
+/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`.
+///
+/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`].
+/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address.
+///
+/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1
+///
+/// ### IPv4-Mapped IPv6 Addresses
+///
+/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2].
+/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows:
+///
+/// ```text
+/// |                80 bits               | 16 |      32 bits        |
+/// +--------------------------------------+--------------------------+
+/// |0000..............................0000|FFFF|    IPv4 address     |
+/// +--------------------------------------+----+---------------------+
+/// ```
+/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`.
+///
+/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`].
+/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address.
+/// Note that this will also convert the IPv6 loopback address `::1` to `0.0.0.1`. Use
+/// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
+///
+/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2
+///
+/// # Textual representation
+///
+/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
+/// an IPv6 address in text, but in general, each segments is written in hexadecimal
+/// notation, and segments are separated by `:`. For more information, see
+/// [IETF RFC 5952].
+///
+/// [`FromStr`]: crate::str::FromStr
+/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv6Addr;
+///
+/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+/// assert_eq!("::1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Ipv6Addr {
+    octets: [u8; 16],
+}
+
+/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2].
+///
+/// # Stability Guarantees
+///
+/// Not all possible values for a multicast scope have been assigned.
+/// Future RFCs may introduce new scopes, which will be added as variants to this enum;
+/// because of this the enum is marked as `#[non_exhaustive]`.
+///
+/// # Examples
+/// ```
+/// #![feature(ip)]
+///
+/// use std::net::Ipv6Addr;
+/// use std::net::Ipv6MulticastScope::*;
+///
+/// // An IPv6 multicast address with global scope (`ff0e::`).
+/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0);
+///
+/// // Will print "Global scope".
+/// match address.multicast_scope() {
+///     Some(InterfaceLocal) => println!("Interface-Local scope"),
+///     Some(LinkLocal) => println!("Link-Local scope"),
+///     Some(RealmLocal) => println!("Realm-Local scope"),
+///     Some(AdminLocal) => println!("Admin-Local scope"),
+///     Some(SiteLocal) => println!("Site-Local scope"),
+///     Some(OrganizationLocal) => println!("Organization-Local scope"),
+///     Some(Global) => println!("Global scope"),
+///     Some(_) => println!("Unknown scope"),
+///     None => println!("Not a multicast address!")
+/// }
+///
+/// ```
+///
+/// [IPv6 multicast address]: Ipv6Addr
+/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2
+#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
+#[unstable(feature = "ip", issue = "27709")]
+#[non_exhaustive]
+pub enum Ipv6MulticastScope {
+    /// Interface-Local scope.
+    InterfaceLocal,
+    /// Link-Local scope.
+    LinkLocal,
+    /// Realm-Local scope.
+    RealmLocal,
+    /// Admin-Local scope.
+    AdminLocal,
+    /// Site-Local scope.
+    SiteLocal,
+    /// Organization-Local scope.
+    OrganizationLocal,
+    /// Global scope.
+    Global,
+}
+
+impl IpAddr {
+    /// Returns [`true`] for the special 'unspecified' address.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_unspecified()`] and
+    /// [`Ipv6Addr::is_unspecified()`] for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
+    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "ip_shared", since = "1.12.0")]
+    #[must_use]
+    #[inline]
+    pub const fn is_unspecified(&self) -> bool {
+        match self {
+            IpAddr::V4(ip) => ip.is_unspecified(),
+            IpAddr::V6(ip) => ip.is_unspecified(),
+        }
+    }
+
+    /// Returns [`true`] if this is a loopback address.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_loopback()`] and
+    /// [`Ipv6Addr::is_loopback()`] for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
+    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "ip_shared", since = "1.12.0")]
+    #[must_use]
+    #[inline]
+    pub const fn is_loopback(&self) -> bool {
+        match self {
+            IpAddr::V4(ip) => ip.is_loopback(),
+            IpAddr::V6(ip) => ip.is_loopback(),
+        }
+    }
+
+    /// Returns [`true`] if the address appears to be globally routable.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_global()`] and
+    /// [`Ipv6Addr::is_global()`] for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
+    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_global(&self) -> bool {
+        match self {
+            IpAddr::V4(ip) => ip.is_global(),
+            IpAddr::V6(ip) => ip.is_global(),
+        }
+    }
+
+    /// Returns [`true`] if this is a multicast address.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_multicast()`] and
+    /// [`Ipv6Addr::is_multicast()`] for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
+    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "ip_shared", since = "1.12.0")]
+    #[must_use]
+    #[inline]
+    pub const fn is_multicast(&self) -> bool {
+        match self {
+            IpAddr::V4(ip) => ip.is_multicast(),
+            IpAddr::V6(ip) => ip.is_multicast(),
+        }
+    }
+
+    /// Returns [`true`] if this address is in a range designated for documentation.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_documentation()`] and
+    /// [`Ipv6Addr::is_documentation()`] for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
+    /// assert_eq!(
+    ///     IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(),
+    ///     true
+    /// );
+    /// ```
+    #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_documentation(&self) -> bool {
+        match self {
+            IpAddr::V4(ip) => ip.is_documentation(),
+            IpAddr::V6(ip) => ip.is_documentation(),
+        }
+    }
+
+    /// Returns [`true`] if this address is in a range designated for benchmarking.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_benchmarking()`] and
+    /// [`Ipv6Addr::is_benchmarking()`] for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true);
+    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true);
+    /// ```
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_benchmarking(&self) -> bool {
+        match self {
+            IpAddr::V4(ip) => ip.is_benchmarking(),
+            IpAddr::V6(ip) => ip.is_benchmarking(),
+        }
+    }
+
+    /// Returns [`true`] if this address is an [`IPv4` address], and [`false`]
+    /// otherwise.
+    ///
+    /// [`IPv4` address]: IpAddr::V4
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
+    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "ipaddr_checker", since = "1.16.0")]
+    #[must_use]
+    #[inline]
+    pub const fn is_ipv4(&self) -> bool {
+        matches!(self, IpAddr::V4(_))
+    }
+
+    /// Returns [`true`] if this address is an [`IPv6` address], and [`false`]
+    /// otherwise.
+    ///
+    /// [`IPv6` address]: IpAddr::V6
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
+    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "ipaddr_checker", since = "1.16.0")]
+    #[must_use]
+    #[inline]
+    pub const fn is_ipv6(&self) -> bool {
+        matches!(self, IpAddr::V6(_))
+    }
+
+    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it
+    /// return `self` as-is.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true);
+    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false);
+    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true);
+    /// ```
+    #[inline]
+    #[must_use = "this returns the result of the operation, \
+                  without modifying the original"]
+    #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    pub const fn to_canonical(&self) -> IpAddr {
+        match self {
+            &v4 @ IpAddr::V4(_) => v4,
+            IpAddr::V6(v6) => v6.to_canonical(),
+        }
+    }
+}
+
+impl Ipv4Addr {
+    /// Creates a new IPv4 address from four eight-bit octets.
+    ///
+    /// The result will represent the IP address `a`.`b`.`c`.`d`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
+    #[inline]
+    pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
+        Ipv4Addr { octets: [a, b, c, d] }
+    }
+
+    /// An IPv4 address with the address pointing to localhost: `127.0.0.1`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::LOCALHOST;
+    /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
+    /// ```
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
+    pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
+
+    /// An IPv4 address representing an unspecified address: `0.0.0.0`
+    ///
+    /// This corresponds to the constant `INADDR_ANY` in other languages.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::UNSPECIFIED;
+    /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
+    /// ```
+    #[doc(alias = "INADDR_ANY")]
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
+    pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
+
+    /// An IPv4 address representing the broadcast address: `255.255.255.255`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::BROADCAST;
+    /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
+    /// ```
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
+    pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
+
+    /// Returns the four eight-bit integers that make up this address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
+    /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
+    #[inline]
+    pub const fn octets(&self) -> [u8; 4] {
+        self.octets
+    }
+
+    /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
+    ///
+    /// This property is defined in _UNIX Network Programming, Second Edition_,
+    /// W. Richard Stevens, p. 891; see also [ip7].
+    ///
+    /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
+    /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
+    #[stable(feature = "ip_shared", since = "1.12.0")]
+    #[must_use]
+    #[inline]
+    pub const fn is_unspecified(&self) -> bool {
+        u32::from_be_bytes(self.octets) == 0
+    }
+
+    /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`).
+    ///
+    /// This property is defined by [IETF RFC 1122].
+    ///
+    /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
+    /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(since = "1.7.0", feature = "ip_17")]
+    #[must_use]
+    #[inline]
+    pub const fn is_loopback(&self) -> bool {
+        self.octets()[0] == 127
+    }
+
+    /// Returns [`true`] if this is a private address.
+    ///
+    /// The private address ranges are defined in [IETF RFC 1918] and include:
+    ///
+    ///  - `10.0.0.0/8`
+    ///  - `172.16.0.0/12`
+    ///  - `192.168.0.0/16`
+    ///
+    /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
+    /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
+    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
+    /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
+    /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
+    /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
+    /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(since = "1.7.0", feature = "ip_17")]
+    #[must_use]
+    #[inline]
+    pub const fn is_private(&self) -> bool {
+        match self.octets() {
+            [10, ..] => true,
+            [172, b, ..] if b >= 16 && b <= 31 => true,
+            [192, 168, ..] => true,
+            _ => false,
+        }
+    }
+
+    /// Returns [`true`] if the address is link-local (`169.254.0.0/16`).
+    ///
+    /// This property is defined by [IETF RFC 3927].
+    ///
+    /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
+    /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
+    /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(since = "1.7.0", feature = "ip_17")]
+    #[must_use]
+    #[inline]
+    pub const fn is_link_local(&self) -> bool {
+        matches!(self.octets(), [169, 254, ..])
+    }
+
+    /// Returns [`true`] if the address appears to be globally reachable
+    /// as specified by the [IANA IPv4 Special-Purpose Address Registry].
+    /// Whether or not an address is practically reachable will depend on your network configuration.
+    ///
+    /// Most IPv4 addresses are globally reachable;
+    /// unless they are specifically defined as *not* globally reachable.
+    ///
+    /// Non-exhaustive list of notable addresses that are not globally reachable:
+    ///
+    /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified))
+    /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private))
+    /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared))
+    /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback))
+    /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local))
+    /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation))
+    /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking))
+    /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved))
+    /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast))
+    ///
+    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry].
+    ///
+    /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+    /// [unspecified address]: Ipv4Addr::UNSPECIFIED
+    /// [broadcast address]: Ipv4Addr::BROADCAST
+
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv4Addr;
+    ///
+    /// // Most IPv4 addresses are globally reachable:
+    /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
+    ///
+    /// // However some addresses have been assigned a special meaning
+    /// // that makes them not globally reachable. Some examples are:
+    ///
+    /// // The unspecified address (`0.0.0.0`)
+    /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false);
+    ///
+    /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16)
+    /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
+    /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
+    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
+    ///
+    /// // Addresses in the shared address space (`100.64.0.0/10`)
+    /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
+    ///
+    /// // The loopback addresses (`127.0.0.0/8`)
+    /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false);
+    ///
+    /// // Link-local addresses (`169.254.0.0/16`)
+    /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
+    ///
+    /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`)
+    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
+    /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
+    /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
+    ///
+    /// // Addresses reserved for benchmarking (`198.18.0.0/15`)
+    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
+    ///
+    /// // Reserved addresses (`240.0.0.0/4`)
+    /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
+    ///
+    /// // The broadcast address (`255.255.255.255`)
+    /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false);
+    ///
+    /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_global(&self) -> bool {
+        !(self.octets()[0] == 0 // "This network"
+            || self.is_private()
+            || self.is_shared()
+            || self.is_loopback()
+            || self.is_link_local()
+            // addresses reserved for future protocols (`192.0.0.0/24`)
+            ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
+            || self.is_documentation()
+            || self.is_benchmarking()
+            || self.is_reserved()
+            || self.is_broadcast())
+    }
+
+    /// Returns [`true`] if this address is part of the Shared Address Space defined in
+    /// [IETF RFC 6598] (`100.64.0.0/10`).
+    ///
+    /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
+    /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
+    /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_shared(&self) -> bool {
+        self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
+    }
+
+    /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
+    /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
+    /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
+    ///
+    /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
+    /// [errata 423]: https://www.rfc-editor.org/errata/eid423
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
+    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
+    /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
+    /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_benchmarking(&self) -> bool {
+        self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
+    }
+
+    /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
+    /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
+    /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
+    /// it is obviously not reserved for future use.
+    ///
+    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
+    ///
+    /// # Warning
+    ///
+    /// As IANA assigns new addresses, this method will be
+    /// updated. This may result in non-reserved addresses being
+    /// treated as reserved in code that relies on an outdated version
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
+    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
+    ///
+    /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
+    /// // The broadcast address is not considered as reserved for future use by this implementation
+    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_reserved(&self) -> bool {
+        self.octets()[0] & 240 == 240 && !self.is_broadcast()
+    }
+
+    /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`).
+    ///
+    /// Multicast addresses have a most significant octet between `224` and `239`,
+    /// and is defined by [IETF RFC 5771].
+    ///
+    /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
+    /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
+    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(since = "1.7.0", feature = "ip_17")]
+    #[must_use]
+    #[inline]
+    pub const fn is_multicast(&self) -> bool {
+        self.octets()[0] >= 224 && self.octets()[0] <= 239
+    }
+
+    /// Returns [`true`] if this is a broadcast address (`255.255.255.255`).
+    ///
+    /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919].
+    ///
+    /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
+    /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(since = "1.7.0", feature = "ip_17")]
+    #[must_use]
+    #[inline]
+    pub const fn is_broadcast(&self) -> bool {
+        u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
+    }
+
+    /// Returns [`true`] if this address is in a range designated for documentation.
+    ///
+    /// This is defined in [IETF RFC 5737]:
+    ///
+    /// - `192.0.2.0/24` (TEST-NET-1)
+    /// - `198.51.100.0/24` (TEST-NET-2)
+    /// - `203.0.113.0/24` (TEST-NET-3)
+    ///
+    /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
+    /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
+    /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
+    /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(since = "1.7.0", feature = "ip_17")]
+    #[must_use]
+    #[inline]
+    pub const fn is_documentation(&self) -> bool {
+        matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
+    }
+
+    /// Converts this address to an [IPv4-compatible] [`IPv6` address].
+    ///
+    /// `a.b.c.d` becomes `::a.b.c.d`
+    ///
+    /// Note that IPv4-compatible addresses have been officially deprecated.
+    /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead.
+    ///
+    /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
+    /// [`IPv6` address]: Ipv6Addr
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(
+    ///     Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
+    ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff)
+    /// );
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use = "this returns the result of the operation, \
+                  without modifying the original"]
+    #[inline]
+    pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
+        let [a, b, c, d] = self.octets();
+        Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] }
+    }
+
+    /// Converts this address to an [IPv4-mapped] [`IPv6` address].
+    ///
+    /// `a.b.c.d` becomes `::ffff:a.b.c.d`
+    ///
+    /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
+    /// [`IPv6` address]: Ipv6Addr
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
+    ///            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff));
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use = "this returns the result of the operation, \
+                  without modifying the original"]
+    #[inline]
+    pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
+        let [a, b, c, d] = self.octets();
+        Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] }
+    }
+}
+
+#[stable(feature = "ip_addr", since = "1.7.0")]
+impl fmt::Display for IpAddr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            IpAddr::V4(ip) => ip.fmt(fmt),
+            IpAddr::V6(ip) => ip.fmt(fmt),
+        }
+    }
+}
+
+#[stable(feature = "ip_addr", since = "1.7.0")]
+impl fmt::Debug for IpAddr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
+#[stable(feature = "ip_from_ip", since = "1.16.0")]
+impl From<Ipv4Addr> for IpAddr {
+    /// Copies this address to a new `IpAddr::V4`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr};
+    ///
+    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
+    ///
+    /// assert_eq!(
+    ///     IpAddr::V4(addr),
+    ///     IpAddr::from(addr)
+    /// )
+    /// ```
+    #[inline]
+    fn from(ipv4: Ipv4Addr) -> IpAddr {
+        IpAddr::V4(ipv4)
+    }
+}
+
+#[stable(feature = "ip_from_ip", since = "1.16.0")]
+impl From<Ipv6Addr> for IpAddr {
+    /// Copies this address to a new `IpAddr::V6`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv6Addr};
+    ///
+    /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
+    ///
+    /// assert_eq!(
+    ///     IpAddr::V6(addr),
+    ///     IpAddr::from(addr)
+    /// );
+    /// ```
+    #[inline]
+    fn from(ipv6: Ipv6Addr) -> IpAddr {
+        IpAddr::V6(ipv6)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for Ipv4Addr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let octets = self.octets();
+
+        // If there are no alignment requirements, write the IP address directly to `f`.
+        // Otherwise, write it to a local buffer and then use `f.pad`.
+        if fmt.precision().is_none() && fmt.width().is_none() {
+            write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
+        } else {
+            const LONGEST_IPV4_ADDR: &str = "255.255.255.255";
+
+            let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
+            // Buffer is long enough for the longest possible IPv4 address, so this should never fail.
+            write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
+
+            fmt.pad(buf.as_str())
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Ipv4Addr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialEq<Ipv4Addr> for IpAddr {
+    #[inline]
+    fn eq(&self, other: &Ipv4Addr) -> bool {
+        match self {
+            IpAddr::V4(v4) => v4 == other,
+            IpAddr::V6(_) => false,
+        }
+    }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialEq<IpAddr> for Ipv4Addr {
+    #[inline]
+    fn eq(&self, other: &IpAddr) -> bool {
+        match other {
+            IpAddr::V4(v4) => self == v4,
+            IpAddr::V6(_) => false,
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for Ipv4Addr {
+    #[inline]
+    fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialOrd<Ipv4Addr> for IpAddr {
+    #[inline]
+    fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
+        match self {
+            IpAddr::V4(v4) => v4.partial_cmp(other),
+            IpAddr::V6(_) => Some(Ordering::Greater),
+        }
+    }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialOrd<IpAddr> for Ipv4Addr {
+    #[inline]
+    fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+        match other {
+            IpAddr::V4(v4) => self.partial_cmp(v4),
+            IpAddr::V6(_) => Some(Ordering::Less),
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Ord for Ipv4Addr {
+    #[inline]
+    fn cmp(&self, other: &Ipv4Addr) -> Ordering {
+        self.octets.cmp(&other.octets)
+    }
+}
+
+#[stable(feature = "ip_u32", since = "1.1.0")]
+impl From<Ipv4Addr> for u32 {
+    /// Converts an `Ipv4Addr` into a host byte order `u32`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
+    /// assert_eq!(0x12345678, u32::from(addr));
+    /// ```
+    #[inline]
+    fn from(ip: Ipv4Addr) -> u32 {
+        u32::from_be_bytes(ip.octets)
+    }
+}
+
+#[stable(feature = "ip_u32", since = "1.1.0")]
+impl From<u32> for Ipv4Addr {
+    /// Converts a host byte order `u32` into an `Ipv4Addr`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::from(0x12345678);
+    /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr);
+    /// ```
+    #[inline]
+    fn from(ip: u32) -> Ipv4Addr {
+        Ipv4Addr { octets: ip.to_be_bytes() }
+    }
+}
+
+#[stable(feature = "from_slice_v4", since = "1.9.0")]
+impl From<[u8; 4]> for Ipv4Addr {
+    /// Creates an `Ipv4Addr` from a four element byte array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
+    /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
+    /// ```
+    #[inline]
+    fn from(octets: [u8; 4]) -> Ipv4Addr {
+        Ipv4Addr { octets }
+    }
+}
+
+#[stable(feature = "ip_from_slice", since = "1.17.0")]
+impl From<[u8; 4]> for IpAddr {
+    /// Creates an `IpAddr::V4` from a four element byte array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr};
+    ///
+    /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
+    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
+    /// ```
+    #[inline]
+    fn from(octets: [u8; 4]) -> IpAddr {
+        IpAddr::V4(Ipv4Addr::from(octets))
+    }
+}
+
+impl Ipv6Addr {
+    /// Creates a new IPv6 address from eight 16-bit segments.
+    ///
+    /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
+    #[inline]
+    pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
+        let addr16 = [
+            a.to_be(),
+            b.to_be(),
+            c.to_be(),
+            d.to_be(),
+            e.to_be(),
+            f.to_be(),
+            g.to_be(),
+            h.to_be(),
+        ];
+        Ipv6Addr {
+            // All elements in `addr16` are big endian.
+            // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
+            octets: unsafe { transmute::<_, [u8; 16]>(addr16) },
+        }
+    }
+
+    /// An IPv6 address representing localhost: `::1`.
+    ///
+    /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other
+    /// languages.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// let addr = Ipv6Addr::LOCALHOST;
+    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+    /// ```
+    #[doc(alias = "IN6ADDR_LOOPBACK_INIT")]
+    #[doc(alias = "in6addr_loopback")]
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
+    pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+
+    /// An IPv6 address representing the unspecified address: `::`
+    ///
+    /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// let addr = Ipv6Addr::UNSPECIFIED;
+    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+    /// ```
+    #[doc(alias = "IN6ADDR_ANY_INIT")]
+    #[doc(alias = "in6addr_any")]
+    #[stable(feature = "ip_constructors", since = "1.30.0")]
+    pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
+
+    /// Returns the eight 16-bit segments that make up this address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
+    ///            [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
+    #[inline]
+    pub const fn segments(&self) -> [u16; 8] {
+        // All elements in `self.octets` must be big endian.
+        // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
+        let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) };
+        // We want native endian u16
+        [
+            u16::from_be(a),
+            u16::from_be(b),
+            u16::from_be(c),
+            u16::from_be(d),
+            u16::from_be(e),
+            u16::from_be(f),
+            u16::from_be(g),
+            u16::from_be(h),
+        ]
+    }
+
+    /// Returns [`true`] for the special 'unspecified' address (`::`).
+    ///
+    /// This property is defined in [IETF RFC 4291].
+    ///
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(since = "1.7.0", feature = "ip_17")]
+    #[must_use]
+    #[inline]
+    pub const fn is_unspecified(&self) -> bool {
+        u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
+    }
+
+    /// Returns [`true`] if this is the [loopback address] (`::1`),
+    /// as defined in [IETF RFC 4291 section 2.5.3].
+    ///
+    /// Contrary to IPv4, in IPv6 there is only one loopback address.
+    ///
+    /// [loopback address]: Ipv6Addr::LOCALHOST
+    /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(since = "1.7.0", feature = "ip_17")]
+    #[must_use]
+    #[inline]
+    pub const fn is_loopback(&self) -> bool {
+        u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
+    }
+
+    /// Returns [`true`] if the address appears to be globally reachable
+    /// as specified by the [IANA IPv6 Special-Purpose Address Registry].
+    /// Whether or not an address is practically reachable will depend on your network configuration.
+    ///
+    /// Most IPv6 addresses are globally reachable;
+    /// unless they are specifically defined as *not* globally reachable.
+    ///
+    /// Non-exhaustive list of notable addresses that are not globally reachable:
+    /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified))
+    /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback))
+    /// - IPv4-mapped addresses
+    /// - Addresses reserved for benchmarking
+    /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation))
+    /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local))
+    /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local))
+    ///
+    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry].
+    ///
+    /// Note that an address having global scope is not the same as being globally reachable,
+    /// and there is no direct relation between the two concepts: There exist addresses with global scope
+    /// that are not globally reachable (for example unique local addresses),
+    /// and addresses that are globally reachable without having global scope
+    /// (multicast addresses with non-global scope).
+    ///
+    /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
+    /// [unspecified address]: Ipv6Addr::UNSPECIFIED
+    /// [loopback address]: Ipv6Addr::LOCALHOST
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// // Most IPv6 addresses are globally reachable:
+    /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true);
+    ///
+    /// // However some addresses have been assigned a special meaning
+    /// // that makes them not globally reachable. Some examples are:
+    ///
+    /// // The unspecified address (`::`)
+    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false);
+    ///
+    /// // The loopback address (`::1`)
+    /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false);
+    ///
+    /// // IPv4-mapped addresses (`::ffff:0:0/96`)
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false);
+    ///
+    /// // Addresses reserved for benchmarking (`2001:2::/48`)
+    /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
+    ///
+    /// // Addresses reserved for documentation (`2001:db8::/32`)
+    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
+    ///
+    /// // Unique local addresses (`fc00::/7`)
+    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
+    ///
+    /// // Unicast addresses with link-local scope (`fe80::/10`)
+    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
+    ///
+    /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_global(&self) -> bool {
+        !(self.is_unspecified()
+            || self.is_loopback()
+            // IPv4-mapped Address (`::ffff:0:0/96`)
+            || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
+            // IPv4-IPv6 Translat. (`64:ff9b:1::/48`)
+            || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
+            // Discard-Only Address Block (`100::/64`)
+            || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _])
+            // IETF Protocol Assignments (`2001::/23`)
+            || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
+                && !(
+                    // Port Control Protocol Anycast (`2001:1::1`)
+                    u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
+                    // Traversal Using Relays around NAT Anycast (`2001:1::2`)
+                    || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
+                    // AMT (`2001:3::/32`)
+                    || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _])
+                    // AS112-v6 (`2001:4:112::/48`)
+                    || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
+                    // ORCHIDv2 (`2001:20::/28`)
+                    || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F)
+                ))
+            || self.is_documentation()
+            || self.is_unique_local()
+            || self.is_unicast_link_local())
+    }
+
+    /// Returns [`true`] if this is a unique local address (`fc00::/7`).
+    ///
+    /// This property is defined in [IETF RFC 4193].
+    ///
+    /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
+    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_unique_local(&self) -> bool {
+        (self.segments()[0] & 0xfe00) == 0xfc00
+    }
+
+    /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291].
+    /// Any address that is not a [multicast address] (`ff00::/8`) is unicast.
+    ///
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [multicast address]: Ipv6Addr::is_multicast
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// // The unspecified and loopback addresses are unicast.
+    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true);
+    /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true);
+    ///
+    /// // Any address that is not a multicast address (`ff00::/8`) is unicast.
+    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true);
+    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_unicast(&self) -> bool {
+        !self.is_multicast()
+    }
+
+    /// Returns `true` if the address is a unicast address with link-local scope,
+    /// as defined in [RFC 4291].
+    ///
+    /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4].
+    /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6],
+    /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format:
+    ///
+    /// ```text
+    /// | 10 bits  |         54 bits         |          64 bits           |
+    /// +----------+-------------------------+----------------------------+
+    /// |1111111010|           0             |       interface ID         |
+    /// +----------+-------------------------+----------------------------+
+    /// ```
+    /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`,
+    /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated,
+    /// and those addresses will have link-local scope.
+    ///
+    /// Also note that while [RFC 4291 section 2.5.3] mentions about the [loopback address] (`::1`) that "it is treated as having Link-Local scope",
+    /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it.
+    ///
+    /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
+    /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
+    /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
+    /// [loopback address]: Ipv6Addr::LOCALHOST
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// // The loopback address (`::1`) does not actually have link-local scope.
+    /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false);
+    ///
+    /// // Only addresses in `fe80::/10` have link-local scope.
+    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false);
+    /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
+    ///
+    /// // Addresses outside the stricter `fe80::/64` also have link-local scope.
+    /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true);
+    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_unicast_link_local(&self) -> bool {
+        (self.segments()[0] & 0xffc0) == 0xfe80
+    }
+
+    /// Returns [`true`] if this is an address reserved for documentation
+    /// (`2001:db8::/32`).
+    ///
+    /// This property is defined in [IETF RFC 3849].
+    ///
+    /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
+    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_documentation(&self) -> bool {
+        (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
+    }
+
+    /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`).
+    ///
+    /// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`.
+    /// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`.
+    ///
+    /// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180
+    /// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false);
+    /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true);
+    /// ```
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_benchmarking(&self) -> bool {
+        (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0)
+    }
+
+    /// Returns [`true`] if the address is a globally routable unicast address.
+    ///
+    /// The following return false:
+    ///
+    /// - the loopback address
+    /// - the link-local addresses
+    /// - unique local addresses
+    /// - the unspecified address
+    /// - the address range reserved for documentation
+    ///
+    /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
+    ///
+    /// ```no_rust
+    /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
+    /// be supported in new implementations (i.e., new implementations must treat this prefix as
+    /// Global Unicast).
+    /// ```
+    ///
+    /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn is_unicast_global(&self) -> bool {
+        self.is_unicast()
+            && !self.is_loopback()
+            && !self.is_unicast_link_local()
+            && !self.is_unique_local()
+            && !self.is_unspecified()
+            && !self.is_documentation()
+            && !self.is_benchmarking()
+    }
+
+    /// Returns the address's multicast scope if the address is multicast.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
+    ///
+    /// assert_eq!(
+    ///     Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
+    ///     Some(Ipv6MulticastScope::Global)
+    /// );
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use]
+    #[inline]
+    pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
+        if self.is_multicast() {
+            match self.segments()[0] & 0x000f {
+                1 => Some(Ipv6MulticastScope::InterfaceLocal),
+                2 => Some(Ipv6MulticastScope::LinkLocal),
+                3 => Some(Ipv6MulticastScope::RealmLocal),
+                4 => Some(Ipv6MulticastScope::AdminLocal),
+                5 => Some(Ipv6MulticastScope::SiteLocal),
+                8 => Some(Ipv6MulticastScope::OrganizationLocal),
+                14 => Some(Ipv6MulticastScope::Global),
+                _ => None,
+            }
+        } else {
+            None
+        }
+    }
+
+    /// Returns [`true`] if this is a multicast address (`ff00::/8`).
+    ///
+    /// This property is defined by [IETF RFC 4291].
+    ///
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(since = "1.7.0", feature = "ip_17")]
+    #[must_use]
+    #[inline]
+    pub const fn is_multicast(&self) -> bool {
+        (self.segments()[0] & 0xff00) == 0xff00
+    }
+
+    /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address,
+    /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
+    ///
+    /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
+    /// All addresses *not* starting with `::ffff` will return `None`.
+    ///
+    /// [`IPv4` address]: Ipv4Addr
+    /// [IPv4-mapped]: Ipv6Addr
+    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
+    ///            Some(Ipv4Addr::new(192, 10, 2, 255)));
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
+    #[must_use = "this returns the result of the operation, \
+                  without modifying the original"]
+    #[inline]
+    pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
+        match self.octets() {
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
+                Some(Ipv4Addr::new(a, b, c, d))
+            }
+            _ => None,
+        }
+    }
+
+    /// Converts this address to an [`IPv4` address] if it is either
+    /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1],
+    /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2],
+    /// otherwise returns [`None`].
+    ///
+    /// Note that this will return an [`IPv4` address] for the IPv6 loopback address `::1`. Use
+    /// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
+    ///
+    /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`. `::1` becomes `0.0.0.1`.
+    /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`.
+    ///
+    /// [`IPv4` address]: Ipv4Addr
+    /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
+    /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
+    /// [IETF RFC 4291 section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1
+    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{Ipv4Addr, Ipv6Addr};
+    ///
+    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
+    ///            Some(Ipv4Addr::new(192, 10, 2, 255)));
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
+    ///            Some(Ipv4Addr::new(0, 0, 0, 1)));
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use = "this returns the result of the operation, \
+                  without modifying the original"]
+    #[inline]
+    pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
+        if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
+            let [a, b] = ab.to_be_bytes();
+            let [c, d] = cd.to_be_bytes();
+            Some(Ipv4Addr::new(a, b, c, d))
+        } else {
+            None
+        }
+    }
+
+    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it
+    /// returns self wrapped in an `IpAddr::V6`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true);
+    /// ```
+    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
+    #[unstable(feature = "ip", issue = "27709")]
+    #[must_use = "this returns the result of the operation, \
+                  without modifying the original"]
+    #[inline]
+    pub const fn to_canonical(&self) -> IpAddr {
+        if let Some(mapped) = self.to_ipv4_mapped() {
+            return IpAddr::V4(mapped);
+        }
+        IpAddr::V6(*self)
+    }
+
+    /// Returns the sixteen eight-bit integers the IPv6 address consists of.
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
+    ///            [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
+    /// ```
+    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
+    #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
+    #[must_use]
+    #[inline]
+    pub const fn octets(&self) -> [u8; 16] {
+        self.octets
+    }
+}
+
+/// Write an Ipv6Addr, conforming to the canonical style described by
+/// [RFC 5952](https://tools.ietf.org/html/rfc5952).
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for Ipv6Addr {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // If there are no alignment requirements, write the IP address directly to `f`.
+        // Otherwise, write it to a local buffer and then use `f.pad`.
+        if f.precision().is_none() && f.width().is_none() {
+            let segments = self.segments();
+
+            // Special case for :: and ::1; otherwise they get written with the
+            // IPv4 formatter
+            if self.is_unspecified() {
+                f.write_str("::")
+            } else if self.is_loopback() {
+                f.write_str("::1")
+            } else if let Some(ipv4) = self.to_ipv4() {
+                match segments[5] {
+                    // IPv4 Compatible address
+                    0 => write!(f, "::{}", ipv4),
+                    // IPv4 Mapped address
+                    0xffff => write!(f, "::ffff:{}", ipv4),
+                    _ => unreachable!(),
+                }
+            } else {
+                #[derive(Copy, Clone, Default)]
+                struct Span {
+                    start: usize,
+                    len: usize,
+                }
+
+                // Find the inner 0 span
+                let zeroes = {
+                    let mut longest = Span::default();
+                    let mut current = Span::default();
+
+                    for (i, &segment) in segments.iter().enumerate() {
+                        if segment == 0 {
+                            if current.len == 0 {
+                                current.start = i;
+                            }
+
+                            current.len += 1;
+
+                            if current.len > longest.len {
+                                longest = current;
+                            }
+                        } else {
+                            current = Span::default();
+                        }
+                    }
+
+                    longest
+                };
+
+                /// Write a colon-separated part of the address
+                #[inline]
+                fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
+                    if let Some((first, tail)) = chunk.split_first() {
+                        write!(f, "{:x}", first)?;
+                        for segment in tail {
+                            f.write_char(':')?;
+                            write!(f, "{:x}", segment)?;
+                        }
+                    }
+                    Ok(())
+                }
+
+                if zeroes.len > 1 {
+                    fmt_subslice(f, &segments[..zeroes.start])?;
+                    f.write_str("::")?;
+                    fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
+                } else {
+                    fmt_subslice(f, &segments)
+                }
+            }
+        } else {
+            const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
+
+            let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
+            // Buffer is long enough for the longest possible IPv6 address, so this should never fail.
+            write!(buf, "{}", self).unwrap();
+
+            f.pad(buf.as_str())
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Ipv6Addr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialEq<IpAddr> for Ipv6Addr {
+    #[inline]
+    fn eq(&self, other: &IpAddr) -> bool {
+        match other {
+            IpAddr::V4(_) => false,
+            IpAddr::V6(v6) => self == v6,
+        }
+    }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialEq<Ipv6Addr> for IpAddr {
+    #[inline]
+    fn eq(&self, other: &Ipv6Addr) -> bool {
+        match self {
+            IpAddr::V4(_) => false,
+            IpAddr::V6(v6) => v6 == other,
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl PartialOrd for Ipv6Addr {
+    #[inline]
+    fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialOrd<Ipv6Addr> for IpAddr {
+    #[inline]
+    fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
+        match self {
+            IpAddr::V4(_) => Some(Ordering::Less),
+            IpAddr::V6(v6) => v6.partial_cmp(other),
+        }
+    }
+}
+
+#[stable(feature = "ip_cmp", since = "1.16.0")]
+impl PartialOrd<IpAddr> for Ipv6Addr {
+    #[inline]
+    fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
+        match other {
+            IpAddr::V4(_) => Some(Ordering::Greater),
+            IpAddr::V6(v6) => self.partial_cmp(v6),
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Ord for Ipv6Addr {
+    #[inline]
+    fn cmp(&self, other: &Ipv6Addr) -> Ordering {
+        self.segments().cmp(&other.segments())
+    }
+}
+
+#[stable(feature = "i128", since = "1.26.0")]
+impl From<Ipv6Addr> for u128 {
+    /// Convert an `Ipv6Addr` into a host byte order `u128`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// let addr = Ipv6Addr::new(
+    ///     0x1020, 0x3040, 0x5060, 0x7080,
+    ///     0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
+    /// );
+    /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
+    /// ```
+    #[inline]
+    fn from(ip: Ipv6Addr) -> u128 {
+        u128::from_be_bytes(ip.octets)
+    }
+}
+#[stable(feature = "i128", since = "1.26.0")]
+impl From<u128> for Ipv6Addr {
+    /// Convert a host byte order `u128` into an `Ipv6Addr`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
+    /// assert_eq!(
+    ///     Ipv6Addr::new(
+    ///         0x1020, 0x3040, 0x5060, 0x7080,
+    ///         0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
+    ///     ),
+    ///     addr);
+    /// ```
+    #[inline]
+    fn from(ip: u128) -> Ipv6Addr {
+        Ipv6Addr::from(ip.to_be_bytes())
+    }
+}
+
+#[stable(feature = "ipv6_from_octets", since = "1.9.0")]
+impl From<[u8; 16]> for Ipv6Addr {
+    /// Creates an `Ipv6Addr` from a sixteen element byte array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// let addr = Ipv6Addr::from([
+    ///     25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
+    ///     17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
+    /// ]);
+    /// assert_eq!(
+    ///     Ipv6Addr::new(
+    ///         0x1918, 0x1716,
+    ///         0x1514, 0x1312,
+    ///         0x1110, 0x0f0e,
+    ///         0x0d0c, 0x0b0a
+    ///     ),
+    ///     addr
+    /// );
+    /// ```
+    #[inline]
+    fn from(octets: [u8; 16]) -> Ipv6Addr {
+        Ipv6Addr { octets }
+    }
+}
+
+#[stable(feature = "ipv6_from_segments", since = "1.16.0")]
+impl From<[u16; 8]> for Ipv6Addr {
+    /// Creates an `Ipv6Addr` from an eight element 16-bit array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::Ipv6Addr;
+    ///
+    /// let addr = Ipv6Addr::from([
+    ///     525u16, 524u16, 523u16, 522u16,
+    ///     521u16, 520u16, 519u16, 518u16,
+    /// ]);
+    /// assert_eq!(
+    ///     Ipv6Addr::new(
+    ///         0x20d, 0x20c,
+    ///         0x20b, 0x20a,
+    ///         0x209, 0x208,
+    ///         0x207, 0x206
+    ///     ),
+    ///     addr
+    /// );
+    /// ```
+    #[inline]
+    fn from(segments: [u16; 8]) -> Ipv6Addr {
+        let [a, b, c, d, e, f, g, h] = segments;
+        Ipv6Addr::new(a, b, c, d, e, f, g, h)
+    }
+}
+
+#[stable(feature = "ip_from_slice", since = "1.17.0")]
+impl From<[u8; 16]> for IpAddr {
+    /// Creates an `IpAddr::V6` from a sixteen element byte array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv6Addr};
+    ///
+    /// let addr = IpAddr::from([
+    ///     25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
+    ///     17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
+    /// ]);
+    /// assert_eq!(
+    ///     IpAddr::V6(Ipv6Addr::new(
+    ///         0x1918, 0x1716,
+    ///         0x1514, 0x1312,
+    ///         0x1110, 0x0f0e,
+    ///         0x0d0c, 0x0b0a
+    ///     )),
+    ///     addr
+    /// );
+    /// ```
+    #[inline]
+    fn from(octets: [u8; 16]) -> IpAddr {
+        IpAddr::V6(Ipv6Addr::from(octets))
+    }
+}
+
+#[stable(feature = "ip_from_slice", since = "1.17.0")]
+impl From<[u16; 8]> for IpAddr {
+    /// Creates an `IpAddr::V6` from an eight element 16-bit array.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv6Addr};
+    ///
+    /// let addr = IpAddr::from([
+    ///     525u16, 524u16, 523u16, 522u16,
+    ///     521u16, 520u16, 519u16, 518u16,
+    /// ]);
+    /// assert_eq!(
+    ///     IpAddr::V6(Ipv6Addr::new(
+    ///         0x20d, 0x20c,
+    ///         0x20b, 0x20a,
+    ///         0x209, 0x208,
+    ///         0x207, 0x206
+    ///     )),
+    ///     addr
+    /// );
+    /// ```
+    #[inline]
+    fn from(segments: [u16; 8]) -> IpAddr {
+        IpAddr::V6(Ipv6Addr::from(segments))
+    }
+}
diff --git a/library/core/src/net/mod.rs b/library/core/src/net/mod.rs
new file mode 100644
index 00000000000..31f5f5d3c22
--- /dev/null
+++ b/library/core/src/net/mod.rs
@@ -0,0 +1,24 @@
+//! Networking primitives for IP communication.
+//!
+//! This module provides types for IP and socket addresses.
+//!
+//! # Organization
+//!
+//! * [`IpAddr`] represents IP addresses of either IPv4 or IPv6; [`Ipv4Addr`] and
+//!   [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses
+//! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`]
+//!   and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses
+
+#![unstable(feature = "ip_in_core", issue = "108443")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::parser::AddrParseError;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6};
+
+mod display_buffer;
+mod ip_addr;
+mod parser;
+mod socket_addr;
diff --git a/library/std/src/net/parser.rs b/library/core/src/net/parser.rs
index a38031c48c8..a08d2792d04 100644
--- a/library/std/src/net/parser.rs
+++ b/library/core/src/net/parser.rs
@@ -3,9 +3,7 @@
 //! This module is "publicly exported" through the `FromStr` implementations
 //! below.
 
-#[cfg(test)]
-mod tests;
-
+use crate::convert::TryInto;
 use crate::error::Error;
 use crate::fmt;
 use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs
new file mode 100644
index 00000000000..0d25ab1d5e1
--- /dev/null
+++ b/library/core/src/net/socket_addr.rs
@@ -0,0 +1,664 @@
+use crate::cmp::Ordering;
+use crate::fmt::{self, Write};
+use crate::hash;
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+
+use super::display_buffer::DisplayBuffer;
+
+/// An internet socket address, either IPv4 or IPv6.
+///
+/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
+/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
+/// [`SocketAddrV6`]'s respective documentation for more details.
+///
+/// The size of a `SocketAddr` instance may vary depending on the target operating
+/// system.
+///
+/// [IP address]: IpAddr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+///
+/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.port(), 8080);
+/// assert_eq!(socket.is_ipv4(), true);
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub enum SocketAddr {
+    /// An IPv4 socket address.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
+    /// An IPv6 socket address.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
+}
+
+/// An IPv4 socket address.
+///
+/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as
+/// stated in [IETF RFC 793].
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// The size of a `SocketAddrV4` struct may vary depending on the target operating
+/// system. Do not assume that this type has the same memory layout as the underlying
+/// system representation.
+///
+/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
+/// [`IPv4` address]: Ipv4Addr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv4Addr, SocketAddrV4};
+///
+/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SocketAddrV4 {
+    ip: Ipv4Addr,
+    port: u16,
+}
+
+/// An IPv6 socket address.
+///
+/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well
+/// as fields containing the traffic class, the flow label, and a scope identifier
+/// (see [IETF RFC 2553, Section 3.3] for more details).
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// The size of a `SocketAddrV6` struct may vary depending on the target operating
+/// system. Do not assume that this type has the same memory layout as the underlying
+/// system representation.
+///
+/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+/// [`IPv6` address]: Ipv6Addr
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv6Addr, SocketAddrV6};
+///
+/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+///
+/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SocketAddrV6 {
+    ip: Ipv6Addr,
+    port: u16,
+    flowinfo: u32,
+    scope_id: u32,
+}
+
+impl SocketAddr {
+    /// Creates a new socket address from an [IP address] and a port number.
+    ///
+    /// [IP address]: IpAddr
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
+    /// assert_eq!(socket.port(), 8080);
+    /// ```
+    #[stable(feature = "ip_addr", since = "1.7.0")]
+    #[must_use]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn new(ip: IpAddr, port: u16) -> SocketAddr {
+        match ip {
+            IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
+            IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)),
+        }
+    }
+
+    /// Returns the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
+    /// ```
+    #[must_use]
+    #[stable(feature = "ip_addr", since = "1.7.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn ip(&self) -> IpAddr {
+        match *self {
+            SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
+            SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
+        }
+    }
+
+    /// Changes the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
+    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
+    /// ```
+    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+    pub fn set_ip(&mut self, new_ip: IpAddr) {
+        // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away.
+        match (self, new_ip) {
+            (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip),
+            (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip),
+            (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()),
+        }
+    }
+
+    /// Returns the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// assert_eq!(socket.port(), 8080);
+    /// ```
+    #[must_use]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn port(&self) -> u16 {
+        match *self {
+            SocketAddr::V4(ref a) => a.port(),
+            SocketAddr::V6(ref a) => a.port(),
+        }
+    }
+
+    /// Changes the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// socket.set_port(1025);
+    /// assert_eq!(socket.port(), 1025);
+    /// ```
+    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+    pub fn set_port(&mut self, new_port: u16) {
+        match *self {
+            SocketAddr::V4(ref mut a) => a.set_port(new_port),
+            SocketAddr::V6(ref mut a) => a.set_port(new_port),
+        }
+    }
+
+    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+    /// [`IPv4` address], and [`false`] otherwise.
+    ///
+    /// [IP address]: IpAddr
+    /// [`IPv4` address]: IpAddr::V4
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+    ///
+    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+    /// assert_eq!(socket.is_ipv4(), true);
+    /// assert_eq!(socket.is_ipv6(), false);
+    /// ```
+    #[must_use]
+    #[stable(feature = "sockaddr_checker", since = "1.16.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn is_ipv4(&self) -> bool {
+        matches!(*self, SocketAddr::V4(_))
+    }
+
+    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+    /// [`IPv6` address], and [`false`] otherwise.
+    ///
+    /// [IP address]: IpAddr
+    /// [`IPv6` address]: IpAddr::V6
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{IpAddr, Ipv6Addr, SocketAddr};
+    ///
+    /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080);
+    /// assert_eq!(socket.is_ipv4(), false);
+    /// assert_eq!(socket.is_ipv6(), true);
+    /// ```
+    #[must_use]
+    #[stable(feature = "sockaddr_checker", since = "1.16.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn is_ipv6(&self) -> bool {
+        matches!(*self, SocketAddr::V6(_))
+    }
+}
+
+impl SocketAddrV4 {
+    /// Creates a new socket address from an [`IPv4` address] and a port number.
+    ///
+    /// [`IPv4` address]: Ipv4Addr
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
+        SocketAddrV4 { ip, port }
+    }
+
+    /// Returns the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+    /// ```
+    #[must_use]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn ip(&self) -> &Ipv4Addr {
+        &self.ip
+    }
+
+    /// Changes the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1));
+    /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1));
+    /// ```
+    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+    pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
+        self.ip = new_ip;
+    }
+
+    /// Returns the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// assert_eq!(socket.port(), 8080);
+    /// ```
+    #[must_use]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn port(&self) -> u16 {
+        self.port
+    }
+
+    /// Changes the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV4, Ipv4Addr};
+    ///
+    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+    /// socket.set_port(4242);
+    /// assert_eq!(socket.port(), 4242);
+    /// ```
+    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+    pub fn set_port(&mut self, new_port: u16) {
+        self.port = new_port;
+    }
+}
+
+impl SocketAddrV6 {
+    /// Creates a new socket address from an [`IPv6` address], a 16-bit port number,
+    /// and the `flowinfo` and `scope_id` fields.
+    ///
+    /// For more information on the meaning and layout of the `flowinfo` and `scope_id`
+    /// parameters, see [IETF RFC 2553, Section 3.3].
+    ///
+    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+    /// [`IPv6` address]: Ipv6Addr
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV6, Ipv6Addr};
+    ///
+    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[must_use]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
+        SocketAddrV6 { ip, port, flowinfo, scope_id }
+    }
+
+    /// Returns the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV6, Ipv6Addr};
+    ///
+    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+    /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+    /// ```
+    #[must_use]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn ip(&self) -> &Ipv6Addr {
+        &self.ip
+    }
+
+    /// Changes the IP address associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV6, Ipv6Addr};
+    ///
+    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+    /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
+    /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
+    /// ```
+    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+    pub fn set_ip(&mut self, new_ip: Ipv6Addr) {
+        self.ip = new_ip;
+    }
+
+    /// Returns the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV6, Ipv6Addr};
+    ///
+    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+    /// assert_eq!(socket.port(), 8080);
+    /// ```
+    #[must_use]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn port(&self) -> u16 {
+        self.port
+    }
+
+    /// Changes the port number associated with this socket address.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV6, Ipv6Addr};
+    ///
+    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+    /// socket.set_port(4242);
+    /// assert_eq!(socket.port(), 4242);
+    /// ```
+    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+    pub fn set_port(&mut self, new_port: u16) {
+        self.port = new_port;
+    }
+
+    /// Returns the flow information associated with this address.
+    ///
+    /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`,
+    /// as specified in [IETF RFC 2553, Section 3.3].
+    /// It combines information about the flow label and the traffic class as specified
+    /// in [IETF RFC 2460], respectively [Section 6] and [Section 7].
+    ///
+    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+    /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460
+    /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6
+    /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV6, Ipv6Addr};
+    ///
+    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
+    /// assert_eq!(socket.flowinfo(), 10);
+    /// ```
+    #[must_use]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn flowinfo(&self) -> u32 {
+        self.flowinfo
+    }
+
+    /// Changes the flow information associated with this socket address.
+    ///
+    /// See [`SocketAddrV6::flowinfo`]'s documentation for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV6, Ipv6Addr};
+    ///
+    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
+    /// socket.set_flowinfo(56);
+    /// assert_eq!(socket.flowinfo(), 56);
+    /// ```
+    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+    pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
+        self.flowinfo = new_flowinfo;
+    }
+
+    /// Returns the scope ID associated with this address.
+    ///
+    /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`,
+    /// as specified in [IETF RFC 2553, Section 3.3].
+    ///
+    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV6, Ipv6Addr};
+    ///
+    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
+    /// assert_eq!(socket.scope_id(), 78);
+    /// ```
+    #[must_use]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
+    pub const fn scope_id(&self) -> u32 {
+        self.scope_id
+    }
+
+    /// Changes the scope ID associated with this socket address.
+    ///
+    /// See [`SocketAddrV6::scope_id`]'s documentation for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::net::{SocketAddrV6, Ipv6Addr};
+    ///
+    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
+    /// socket.set_scope_id(42);
+    /// assert_eq!(socket.scope_id(), 42);
+    /// ```
+    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
+    pub fn set_scope_id(&mut self, new_scope_id: u32) {
+        self.scope_id = new_scope_id;
+    }
+}
+
+#[stable(feature = "ip_from_ip", since = "1.16.0")]
+impl From<SocketAddrV4> for SocketAddr {
+    /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
+    fn from(sock4: SocketAddrV4) -> SocketAddr {
+        SocketAddr::V4(sock4)
+    }
+}
+
+#[stable(feature = "ip_from_ip", since = "1.16.0")]
+impl From<SocketAddrV6> for SocketAddr {
+    /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
+    fn from(sock6: SocketAddrV6) -> SocketAddr {
+        SocketAddr::V6(sock6)
+    }
+}
+
+#[stable(feature = "addr_from_into_ip", since = "1.17.0")]
+impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
+    /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
+    ///
+    /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`]
+    /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`].
+    ///
+    /// `u16` is treated as port of the newly created [`SocketAddr`].
+    fn from(pieces: (I, u16)) -> SocketAddr {
+        SocketAddr::new(pieces.0.into(), pieces.1)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for SocketAddr {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            SocketAddr::V4(ref a) => a.fmt(f),
+            SocketAddr::V6(ref a) => a.fmt(f),
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for SocketAddrV4 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // If there are no alignment requirements, write the socket address directly to `f`.
+        // Otherwise, write it to a local buffer and then use `f.pad`.
+        if f.precision().is_none() && f.width().is_none() {
+            write!(f, "{}:{}", self.ip(), self.port())
+        } else {
+            const LONGEST_IPV4_SOCKET_ADDR: &str = "255.255.255.255:65536";
+
+            let mut buf = DisplayBuffer::<{ LONGEST_IPV4_SOCKET_ADDR.len() }>::new();
+            // Buffer is long enough for the longest possible IPv4 socket address, so this should never fail.
+            write!(buf, "{}:{}", self.ip(), self.port()).unwrap();
+
+            f.pad(buf.as_str())
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddrV4 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for SocketAddrV6 {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // If there are no alignment requirements, write the socket address directly to `f`.
+        // Otherwise, write it to a local buffer and then use `f.pad`.
+        if f.precision().is_none() && f.width().is_none() {
+            match self.scope_id() {
+                0 => write!(f, "[{}]:{}", self.ip(), self.port()),
+                scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
+            }
+        } else {
+            const LONGEST_IPV6_SOCKET_ADDR: &str =
+                "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%4294967296]:65536";
+
+            let mut buf = DisplayBuffer::<{ LONGEST_IPV6_SOCKET_ADDR.len() }>::new();
+            match self.scope_id() {
+                0 => write!(buf, "[{}]:{}", self.ip(), self.port()),
+                scope_id => write!(buf, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
+            }
+            // Buffer is long enough for the longest possible IPv6 socket address, so this should never fail.
+            .unwrap();
+
+            f.pad(buf.as_str())
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for SocketAddrV6 {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, fmt)
+    }
+}
+
+#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
+impl PartialOrd for SocketAddrV4 {
+    fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
+impl PartialOrd for SocketAddrV6 {
+    fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
+impl Ord for SocketAddrV4 {
+    fn cmp(&self, other: &SocketAddrV4) -> Ordering {
+        self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
+    }
+}
+
+#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
+impl Ord for SocketAddrV6 {
+    fn cmp(&self, other: &SocketAddrV6) -> Ordering {
+        self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl hash::Hash for SocketAddrV4 {
+    fn hash<H: hash::Hasher>(&self, s: &mut H) {
+        (self.port, self.ip).hash(s)
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl hash::Hash for SocketAddrV6 {
+    fn hash<H: hash::Hasher>(&self, s: &mut H) {
+        (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s)
+    }
+}
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 5d5e9559034..994c08d1fb5 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -553,6 +553,7 @@ use crate::pin::Pin;
 use crate::{
     cmp, convert, hint, mem,
     ops::{self, ControlFlow, Deref, DerefMut},
+    slice,
 };
 
 /// The `Option` type. See [the module level documentation](self) for more.
@@ -734,6 +735,124 @@ impl<T> Option<T> {
         }
     }
 
+    const fn get_some_offset() -> isize {
+        if mem::size_of::<Option<T>>() == mem::size_of::<T>() {
+            // niche optimization means the `T` is always stored at the same position as the Option.
+            0
+        } else {
+            assert!(mem::size_of::<Option<T>>() == mem::size_of::<Option<mem::MaybeUninit<T>>>());
+            let some_uninit = Some(mem::MaybeUninit::<T>::uninit());
+            // SAFETY: This gets the byte offset of the `Some(_)` value following the fact that
+            // niche optimization is not active, and thus Option<T> and Option<MaybeUninit<t>> share
+            // the same layout.
+            unsafe {
+                (some_uninit.as_ref().unwrap() as *const mem::MaybeUninit<T>)
+                    .byte_offset_from(&some_uninit as *const Option<mem::MaybeUninit<T>>)
+            }
+        }
+    }
+
+    /// Returns a slice of the contained value, if any. If this is `None`, an
+    /// empty slice is returned. This can be useful to have a single type of
+    /// iterator over an `Option` or slice.
+    ///
+    /// Note: Should you have an `Option<&T>` and wish to get a slice of `T`,
+    /// you can unpack it via `opt.map_or(&[], std::slice::from_ref)`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(option_as_slice)]
+    ///
+    /// assert_eq!(
+    ///     [Some(1234).as_slice(), None.as_slice()],
+    ///     [&[1234][..], &[][..]],
+    /// );
+    /// ```
+    ///
+    /// The inverse of this function is (discounting
+    /// borrowing) [`[_]::first`](slice::first):
+    ///
+    /// ```rust
+    /// #![feature(option_as_slice)]
+    ///
+    /// for i in [Some(1234_u16), None] {
+    ///     assert_eq!(i.as_ref(), i.as_slice().first());
+    /// }
+    /// ```
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "option_as_slice", issue = "108545")]
+    pub fn as_slice(&self) -> &[T] {
+        // SAFETY: This is sound as long as `get_some_offset` returns the
+        // correct offset. Though in the `None` case, the slice may be located
+        // at a pointer pointing into padding, the fact that the slice is
+        // empty, and the padding is at a properly aligned position for a
+        // value of that type makes it sound.
+        unsafe {
+            slice::from_raw_parts(
+                (self as *const Option<T>).wrapping_byte_offset(Self::get_some_offset())
+                    as *const T,
+                self.is_some() as usize,
+            )
+        }
+    }
+
+    /// Returns a mutable slice of the contained value, if any. If this is
+    /// `None`, an empty slice is returned. This can be useful to have a
+    /// single type of iterator over an `Option` or slice.
+    ///
+    /// Note: Should you have an `Option<&mut T>` instead of a
+    /// `&mut Option<T>`, which this method takes, you can obtain a mutable
+    /// slice via `opt.map_or(&mut [], std::slice::from_mut)`.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// #![feature(option_as_slice)]
+    ///
+    /// assert_eq!(
+    ///     [Some(1234).as_mut_slice(), None.as_mut_slice()],
+    ///     [&mut [1234][..], &mut [][..]],
+    /// );
+    /// ```
+    ///
+    /// The result is a mutable slice of zero or one items that points into
+    /// our original `Option`:
+    ///
+    /// ```rust
+    /// #![feature(option_as_slice)]
+    ///
+    /// let mut x = Some(1234);
+    /// x.as_mut_slice()[0] += 1;
+    /// assert_eq!(x, Some(1235));
+    /// ```
+    ///
+    /// The inverse of this method (discounting borrowing)
+    /// is [`[_]::first_mut`](slice::first_mut):
+    ///
+    /// ```rust
+    /// #![feature(option_as_slice)]
+    ///
+    /// assert_eq!(Some(123).as_mut_slice().first_mut(), Some(&mut 123))
+    /// ```
+    #[inline]
+    #[must_use]
+    #[unstable(feature = "option_as_slice", issue = "108545")]
+    pub fn as_mut_slice(&mut self) -> &mut [T] {
+        // SAFETY: This is sound as long as `get_some_offset` returns the
+        // correct offset. Though in the `None` case, the slice may be located
+        // at a pointer pointing into padding, the fact that the slice is
+        // empty, and the padding is at a properly aligned position for a
+        // value of that type makes it sound.
+        unsafe {
+            slice::from_raw_parts_mut(
+                (self as *mut Option<T>).wrapping_byte_offset(Self::get_some_offset()) as *mut T,
+                self.is_some() as usize,
+            )
+        }
+    }
+
     /////////////////////////////////////////////////////////////////////////
     // Getting to contained values
     /////////////////////////////////////////////////////////////////////////
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index d6e9da187e8..6f78811a186 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -587,8 +587,10 @@ mod prim_pointer {}
 /// There are two syntactic forms for creating an array:
 ///
 /// * A list with each element, i.e., `[x, y, z]`.
-/// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`.
-///   The type of `x` must be [`Copy`].
+/// * A repeat expression `[expr; N]` where `N` is how many times to repeat `expr` in the array. `expr` must either be:
+///
+///   * A value of a type implementing the [`Copy`] trait
+///   * A `const` value
 ///
 /// Note that `[expr; 0]` is allowed, and produces an empty array.
 /// This will still evaluate `expr`, however, and immediately drop the resulting value, so
diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs
index 2123147c7e4..efe6d4183e3 100644
--- a/library/core/src/ptr/alignment.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -41,7 +41,7 @@ impl Alignment {
     /// Returns the alignment for a type.
     ///
     /// This provides the same numerical value as [`mem::align_of`],
-    /// but in an `Alignment` instead of a `usize.
+    /// but in an `Alignment` instead of a `usize`.
     #[unstable(feature = "ptr_alignment_type", issue = "102070")]
     #[inline]
     pub const fn of<T>() -> Self {
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index 5e1b218e507..7601dd3c756 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -1,6 +1,6 @@
 //! Comparison traits for `[T]`.
 
-use crate::cmp::{self, Ordering};
+use crate::cmp::{self, BytewiseEq, Ordering};
 use crate::ffi;
 use crate::mem;
 
@@ -77,7 +77,7 @@ where
 // Use memcmp for bytewise equality when the types allow
 impl<A, B> SlicePartialEq<B> for [A]
 where
-    A: BytewiseEquality<B>,
+    A: BytewiseEq<B>,
 {
     fn equal(&self, other: &[B]) -> bool {
         if self.len() != other.len() {
@@ -203,29 +203,6 @@ impl SliceOrd for u8 {
     }
 }
 
-// Hack to allow specializing on `Eq` even though `Eq` has a method.
-#[rustc_unsafe_specialization_marker]
-trait MarkerEq<T>: PartialEq<T> {}
-
-impl<T: Eq> MarkerEq<T> for T {}
-
-#[doc(hidden)]
-/// Trait implemented for types that can be compared for equality using
-/// their bytewise representation
-#[rustc_specialization_trait]
-trait BytewiseEquality<T>: MarkerEq<T> + Copy {}
-
-macro_rules! impl_marker_for {
-    ($traitname:ident, $($ty:ty)*) => {
-        $(
-            impl $traitname<$ty> for $ty { }
-        )*
-    }
-}
-
-impl_marker_for!(BytewiseEquality,
-                 u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize char bool);
-
 pub(super) trait SliceContains: Sized {
     fn slice_contains(&self, x: &[Self]) -> bool;
 }
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index e8374784501..1cd86b445b0 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -2955,7 +2955,7 @@ impl<T> [T] {
         // This operation is still `O(n)`.
         //
         // Example: We start in this state, where `r` represents "next
-        // read" and `w` represents "next_write`.
+        // read" and `w` represents "next_write".
         //
         //           r
         //     +---+---+---+---+---+---+
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index 7b8062c431e..2333f60a888 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -317,7 +317,7 @@ where
     // 1. `block` - Number of elements in the block.
     // 2. `start` - Start pointer into the `offsets` array.
     // 3. `end` - End pointer into the `offsets` array.
-    // 4. `offsets - Indices of out-of-order elements within the block.
+    // 4. `offsets` - Indices of out-of-order elements within the block.
 
     // The current block on the left side (from `l` to `l.add(block_l)`).
     let mut l = v.as_mut_ptr();
@@ -327,7 +327,7 @@ where
     let mut offsets_l = [MaybeUninit::<u8>::uninit(); BLOCK];
 
     // The current block on the right side (from `r.sub(block_r)` to `r`).
-    // SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe`
+    // SAFETY: The documentation for .add() specifically mention that `vec.as_ptr().add(vec.len())` is always safe
     let mut r = unsafe { l.add(v.len()) };
     let mut block_r = BLOCK;
     let mut start_r = ptr::null_mut();
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index d3ed811b157..68f62ce8be5 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -28,10 +28,6 @@ impl PartialEq for str {
     fn eq(&self, other: &str) -> bool {
         self.as_bytes() == other.as_bytes()
     }
-    #[inline]
-    fn ne(&self, other: &str) -> bool {
-        !(*self).eq(other)
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 00bcaf3e18c..040a59184a6 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -305,6 +305,50 @@ impl AtomicBool {
         AtomicBool { v: UnsafeCell::new(v as u8) }
     }
 
+    /// Creates a new `AtomicBool` from a pointer.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(atomic_from_ptr, pointer_is_aligned)]
+    /// use std::sync::atomic::{self, AtomicBool};
+    /// use std::mem::align_of;
+    ///
+    /// // Get a pointer to an allocated value
+    /// let ptr: *mut bool = Box::into_raw(Box::new(false));
+    ///
+    /// assert!(ptr.is_aligned_to(align_of::<AtomicBool>()));
+    ///
+    /// {
+    ///     // Create an atomic view of the allocated value
+    ///     let atomic = unsafe { AtomicBool::from_ptr(ptr) };
+    ///
+    ///     // Use `atomic` for atomic operations, possibly share it with other threads
+    ///     atomic.store(true, atomic::Ordering::Relaxed);
+    /// }
+    ///
+    /// // It's ok to non-atomically access the value behind `ptr`,
+    /// // since the reference to the atomic ended its lifetime in the block above
+    /// assert_eq!(unsafe { *ptr }, true);
+    ///
+    /// // Deallocate the value
+    /// unsafe { drop(Box::from_raw(ptr)) }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
+    /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
+    /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
+    ///
+    /// [valid]: crate::ptr#safety
+    #[unstable(feature = "atomic_from_ptr", issue = "108652")]
+    #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
+    pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a AtomicBool {
+        // SAFETY: guaranteed by the caller
+        unsafe { &*ptr.cast() }
+    }
+
     /// Returns a mutable reference to the underlying [`bool`].
     ///
     /// This is safe because the mutable reference guarantees that no other threads are
@@ -1017,6 +1061,50 @@ impl<T> AtomicPtr<T> {
         AtomicPtr { p: UnsafeCell::new(p) }
     }
 
+    /// Creates a new `AtomicPtr` from a pointer.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(atomic_from_ptr, pointer_is_aligned)]
+    /// use std::sync::atomic::{self, AtomicPtr};
+    /// use std::mem::align_of;
+    ///
+    /// // Get a pointer to an allocated value
+    /// let ptr: *mut *mut u8 = Box::into_raw(Box::new(std::ptr::null_mut()));
+    ///
+    /// assert!(ptr.is_aligned_to(align_of::<AtomicPtr<u8>>()));
+    ///
+    /// {
+    ///     // Create an atomic view of the allocated value
+    ///     let atomic = unsafe { AtomicPtr::from_ptr(ptr) };
+    ///
+    ///     // Use `atomic` for atomic operations, possibly share it with other threads
+    ///     atomic.store(std::ptr::NonNull::dangling().as_ptr(), atomic::Ordering::Relaxed);
+    /// }
+    ///
+    /// // It's ok to non-atomically access the value behind `ptr`,
+    /// // since the reference to the atomic ended its lifetime in the block above
+    /// assert!(!unsafe { *ptr }.is_null());
+    ///
+    /// // Deallocate the value
+    /// unsafe { drop(Box::from_raw(ptr)) }
+    /// ```
+    ///
+    /// # Safety
+    ///
+    /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this can be bigger than `align_of::<*mut T>()`).
+    /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
+    /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
+    ///
+    /// [valid]: crate::ptr#safety
+    #[unstable(feature = "atomic_from_ptr", issue = "108652")]
+    #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
+    pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a AtomicPtr<T> {
+        // SAFETY: guaranteed by the caller
+        unsafe { &*ptr.cast() }
+    }
+
     /// Returns a mutable reference to the underlying pointer.
     ///
     /// This is safe because the mutable reference guarantees that no other threads are
@@ -1958,6 +2046,53 @@ macro_rules! atomic_int {
                 Self {v: UnsafeCell::new(v)}
             }
 
+            /// Creates a new reference to an atomic integer from a pointer.
+            ///
+            /// # Examples
+            ///
+            /// ```
+            /// #![feature(atomic_from_ptr, pointer_is_aligned)]
+            #[doc = concat!($extra_feature, "use std::sync::atomic::{self, ", stringify!($atomic_type), "};")]
+            /// use std::mem::align_of;
+            ///
+            /// // Get a pointer to an allocated value
+            #[doc = concat!("let ptr: *mut ", stringify!($int_type), " = Box::into_raw(Box::new(0));")]
+            ///
+            #[doc = concat!("assert!(ptr.is_aligned_to(align_of::<", stringify!($atomic_type), ">()));")]
+            ///
+            /// {
+            ///     // Create an atomic view of the allocated value
+            // SAFETY: this is a doc comment, tidy, it can't hurt you (also guaranteed by the construction of `ptr` and the assert above)
+            #[doc = concat!("    let atomic = unsafe {", stringify!($atomic_type), "::from_ptr(ptr) };")]
+            ///
+            ///     // Use `atomic` for atomic operations, possibly share it with other threads
+            ///     atomic.store(1, atomic::Ordering::Relaxed);
+            /// }
+            ///
+            /// // It's ok to non-atomically access the value behind `ptr`,
+            /// // since the reference to the atomic ended its lifetime in the block above
+            /// assert_eq!(unsafe { *ptr }, 1);
+            ///
+            /// // Deallocate the value
+            /// unsafe { drop(Box::from_raw(ptr)) }
+            /// ```
+            ///
+            /// # Safety
+            ///
+            /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can be bigger than `align_of::<bool>()`).
+            #[doc = concat!(" * `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this can be bigger than `align_of::<", stringify!($int_type), ">()`).")]
+            /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
+            /// * The value behind `ptr` must not be accessed through non-atomic operations for the whole lifetime `'a`.
+            ///
+            /// [valid]: crate::ptr#safety
+            #[unstable(feature = "atomic_from_ptr", issue = "108652")]
+            #[rustc_const_unstable(feature = "atomic_from_ptr", issue = "108652")]
+            pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a $atomic_type {
+                // SAFETY: guaranteed by the caller
+                unsafe { &*ptr.cast() }
+            }
+
+
             /// Returns a mutable reference to the underlying integer.
             ///
             /// This is safe because the mutable reference guarantees that no other threads are
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 25b61c0e666..af5bf441bb2 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -45,6 +45,7 @@ impl<T> Poll<T> {
     /// assert_eq!(poll_some_len, Poll::Ready(13));
     /// ```
     #[stable(feature = "futures_api", since = "1.36.0")]
+    #[inline]
     pub fn map<U, F>(self, f: F) -> Poll<U>
     where
         F: FnOnce(T) -> U,
@@ -144,6 +145,7 @@ impl<T, E> Poll<Result<T, E>> {
     /// assert_eq!(squared, Poll::Ready(Ok(144)));
     /// ```
     #[stable(feature = "futures_api", since = "1.36.0")]
+    #[inline]
     pub fn map_ok<U, F>(self, f: F) -> Poll<Result<U, E>>
     where
         F: FnOnce(T) -> U,
@@ -171,6 +173,7 @@ impl<T, E> Poll<Result<T, E>> {
     /// assert_eq!(res, Poll::Ready(Err(0)));
     /// ```
     #[stable(feature = "futures_api", since = "1.36.0")]
+    #[inline]
     pub fn map_err<U, F>(self, f: F) -> Poll<Result<T, U>>
     where
         F: FnOnce(E) -> U,
@@ -199,6 +202,7 @@ impl<T, E> Poll<Option<Result<T, E>>> {
     /// assert_eq!(squared, Poll::Ready(Some(Ok(144))));
     /// ```
     #[stable(feature = "poll_map", since = "1.51.0")]
+    #[inline]
     pub fn map_ok<U, F>(self, f: F) -> Poll<Option<Result<U, E>>>
     where
         F: FnOnce(T) -> U,
@@ -228,6 +232,7 @@ impl<T, E> Poll<Option<Result<T, E>>> {
     /// assert_eq!(res, Poll::Ready(Some(Err(0))));
     /// ```
     #[stable(feature = "poll_map", since = "1.51.0")]
+    #[inline]
     pub fn map_err<U, F>(self, f: F) -> Poll<Option<Result<T, U>>>
     where
         F: FnOnce(E) -> U,
diff --git a/library/core/tests/iter/adapters/mod.rs b/library/core/tests/iter/adapters/mod.rs
index ffd5f3857ae..ca3463aa7f7 100644
--- a/library/core/tests/iter/adapters/mod.rs
+++ b/library/core/tests/iter/adapters/mod.rs
@@ -24,7 +24,7 @@ mod zip;
 
 use core::cell::Cell;
 
-/// An iterator that panics whenever `next` or next_back` is called
+/// An iterator that panics whenever `next` or `next_back` is called
 /// after `None` has already been returned. This does not violate
 /// `Iterator`'s contract. Used to test that iterator adapters don't
 /// poll their inner iterators after exhausting them.
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 42a26ae1675..ccb7be68eb1 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -66,6 +66,8 @@
 #![feature(try_trait_v2)]
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
+#![feature(ip)]
+#![feature(ip_in_core)]
 #![feature(iter_advance_by)]
 #![feature(iter_array_chunks)]
 #![feature(iter_collect_into)]
@@ -77,6 +79,9 @@
 #![feature(iter_repeat_n)]
 #![feature(iterator_try_collect)]
 #![feature(iterator_try_reduce)]
+#![feature(const_ip)]
+#![feature(const_ipv4)]
+#![feature(const_ipv6)]
 #![feature(const_mut_refs)]
 #![feature(const_pin)]
 #![feature(const_waker)]
@@ -135,6 +140,7 @@ mod lazy;
 mod macros;
 mod manually_drop;
 mod mem;
+mod net;
 mod nonzero;
 mod num;
 mod ops;
diff --git a/library/core/tests/net/ip_addr.rs b/library/core/tests/net/ip_addr.rs
new file mode 100644
index 00000000000..5a6ac08c088
--- /dev/null
+++ b/library/core/tests/net/ip_addr.rs
@@ -0,0 +1,1035 @@
+use super::{sa4, sa6};
+use core::net::{
+    IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope, SocketAddr, SocketAddrV4, SocketAddrV6,
+};
+use core::str::FromStr;
+
+#[test]
+fn test_from_str_ipv4() {
+    assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
+    assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
+    assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
+
+    // out of range
+    let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
+    assert_eq!(None, none);
+    // too short
+    let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
+    assert_eq!(None, none);
+    // too long
+    let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
+    assert_eq!(None, none);
+    // no number between dots
+    let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
+    assert_eq!(None, none);
+    // octal
+    let none: Option<Ipv4Addr> = "255.0.0.01".parse().ok();
+    assert_eq!(None, none);
+    // octal zero
+    let none: Option<Ipv4Addr> = "255.0.0.00".parse().ok();
+    assert_eq!(None, none);
+    let none: Option<Ipv4Addr> = "255.0.00.0".parse().ok();
+    assert_eq!(None, none);
+}
+
+#[test]
+fn test_from_str_ipv6() {
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
+
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
+
+    assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)), "2a02:6b8::11:11".parse());
+
+    // too long group
+    let none: Option<Ipv6Addr> = "::00000".parse().ok();
+    assert_eq!(None, none);
+    // too short
+    let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
+    assert_eq!(None, none);
+    // too long
+    let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
+    assert_eq!(None, none);
+    // triple colon
+    let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
+    assert_eq!(None, none);
+    // two double colons
+    let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
+    assert_eq!(None, none);
+    // `::` indicating zero groups of zeros
+    let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
+    assert_eq!(None, none);
+}
+
+#[test]
+fn test_from_str_ipv4_in_ipv6() {
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse());
+    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)), "::FFFF:192.0.2.33".parse());
+    assert_eq!(
+        Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
+        "64:ff9b::192.0.2.33".parse()
+    );
+    assert_eq!(
+        Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
+        "2001:db8:122:c000:2:2100:192.0.2.33".parse()
+    );
+
+    // colon after v4
+    let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
+    assert_eq!(None, none);
+    // not enough groups
+    let none: Option<Ipv6Addr> = "1:2:3:4:5:127.0.0.1".parse().ok();
+    assert_eq!(None, none);
+    // too many groups
+    let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:127.0.0.1".parse().ok();
+    assert_eq!(None, none);
+}
+
+#[test]
+fn test_from_str_socket_addr() {
+    assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
+    assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
+    assert_eq!(
+        Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
+        "[2a02:6b8:0:1::1]:53".parse()
+    );
+    assert_eq!(
+        Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)),
+        "[2a02:6b8:0:1::1]:53".parse()
+    );
+    assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), "[::127.0.0.1]:22".parse());
+    assert_eq!(
+        Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)),
+        "[::127.0.0.1]:22".parse()
+    );
+
+    // without port
+    let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
+    assert_eq!(None, none);
+    // without port
+    let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
+    assert_eq!(None, none);
+    // wrong brackets around v4
+    let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
+    assert_eq!(None, none);
+    // port out of range
+    let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
+    assert_eq!(None, none);
+}
+
+#[test]
+fn ipv4_addr_to_string() {
+    assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1");
+    // Short address
+    assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
+    // Long address
+    assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127");
+
+    // Test padding
+    assert_eq!(format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1         ");
+    assert_eq!(format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), "         1.1.1.1");
+}
+
+#[test]
+fn ipv6_addr_to_string() {
+    // ipv4-mapped address
+    let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
+    assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
+
+    // ipv4-compatible address
+    let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
+    assert_eq!(a1.to_string(), "::192.0.2.128");
+
+    // v6 address with no zero segments
+    assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f");
+
+    // longest possible IPv6 length
+    assert_eq!(
+        Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888).to_string(),
+        "1111:2222:3333:4444:5555:6666:7777:8888"
+    );
+    // padding
+    assert_eq!(format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "1:2:3:4:5:6:7:8     ");
+    assert_eq!(format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "     1:2:3:4:5:6:7:8");
+
+    // reduce a single run of zeros
+    assert_eq!(
+        "ae::ffff:102:304",
+        Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()
+    );
+
+    // don't reduce just a single zero segment
+    assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
+
+    // 'any' address
+    assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
+
+    // loopback address
+    assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
+
+    // ends in zeros
+    assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
+
+    // two runs of zeros, second one is longer
+    assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
+
+    // two runs of zeros, equal length
+    assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
+
+    // don't prefix `0x` to each segment in `dbg!`.
+    assert_eq!("1::4:5:0:0:8", &format!("{:#?}", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8)));
+}
+
+#[test]
+fn ipv4_to_ipv6() {
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
+        Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()
+    );
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
+        Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()
+    );
+}
+
+#[test]
+fn ipv6_to_ipv4_mapped() {
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
+        Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+    );
+    assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
+}
+
+#[test]
+fn ipv6_to_ipv4() {
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
+        Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+    );
+    assert_eq!(
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
+        Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
+    );
+    assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None);
+}
+
+#[test]
+fn ip_properties() {
+    macro_rules! ip {
+        ($s:expr) => {
+            IpAddr::from_str($s).unwrap()
+        };
+    }
+
+    macro_rules! check {
+        ($s:expr) => {
+            check!($s, 0);
+        };
+
+        ($s:expr, $mask:expr) => {{
+            let unspec: u8 = 1 << 0;
+            let loopback: u8 = 1 << 1;
+            let global: u8 = 1 << 2;
+            let multicast: u8 = 1 << 3;
+            let doc: u8 = 1 << 4;
+            let benchmarking: u8 = 1 << 5;
+
+            if ($mask & unspec) == unspec {
+                assert!(ip!($s).is_unspecified());
+            } else {
+                assert!(!ip!($s).is_unspecified());
+            }
+
+            if ($mask & loopback) == loopback {
+                assert!(ip!($s).is_loopback());
+            } else {
+                assert!(!ip!($s).is_loopback());
+            }
+
+            if ($mask & global) == global {
+                assert!(ip!($s).is_global());
+            } else {
+                assert!(!ip!($s).is_global());
+            }
+
+            if ($mask & multicast) == multicast {
+                assert!(ip!($s).is_multicast());
+            } else {
+                assert!(!ip!($s).is_multicast());
+            }
+
+            if ($mask & doc) == doc {
+                assert!(ip!($s).is_documentation());
+            } else {
+                assert!(!ip!($s).is_documentation());
+            }
+
+            if ($mask & benchmarking) == benchmarking {
+                assert!(ip!($s).is_benchmarking());
+            } else {
+                assert!(!ip!($s).is_benchmarking());
+            }
+        }};
+    }
+
+    let unspec: u8 = 1 << 0;
+    let loopback: u8 = 1 << 1;
+    let global: u8 = 1 << 2;
+    let multicast: u8 = 1 << 3;
+    let doc: u8 = 1 << 4;
+    let benchmarking: u8 = 1 << 5;
+
+    check!("0.0.0.0", unspec);
+    check!("0.0.0.1");
+    check!("0.1.0.0");
+    check!("10.9.8.7");
+    check!("127.1.2.3", loopback);
+    check!("172.31.254.253");
+    check!("169.254.253.242");
+    check!("192.0.2.183", doc);
+    check!("192.1.2.183", global);
+    check!("192.168.254.253");
+    check!("198.51.100.0", doc);
+    check!("203.0.113.0", doc);
+    check!("203.2.113.0", global);
+    check!("224.0.0.0", global | multicast);
+    check!("239.255.255.255", global | multicast);
+    check!("255.255.255.255");
+    // make sure benchmarking addresses are not global
+    check!("198.18.0.0", benchmarking);
+    check!("198.18.54.2", benchmarking);
+    check!("198.19.255.255", benchmarking);
+    // make sure addresses reserved for protocol assignment are not global
+    check!("192.0.0.0");
+    check!("192.0.0.255");
+    check!("192.0.0.100");
+    // make sure reserved addresses are not global
+    check!("240.0.0.0");
+    check!("251.54.1.76");
+    check!("254.255.255.255");
+    // make sure shared addresses are not global
+    check!("100.64.0.0");
+    check!("100.127.255.255");
+    check!("100.100.100.0");
+
+    check!("::", unspec);
+    check!("::1", loopback);
+    check!("::0.0.0.2", global);
+    check!("1::", global);
+    check!("fc00::");
+    check!("fdff:ffff::");
+    check!("fe80:ffff::");
+    check!("febf:ffff::");
+    check!("fec0::", global);
+    check!("ff01::", global | multicast);
+    check!("ff02::", global | multicast);
+    check!("ff03::", global | multicast);
+    check!("ff04::", global | multicast);
+    check!("ff05::", global | multicast);
+    check!("ff08::", global | multicast);
+    check!("ff0e::", global | multicast);
+    check!("2001:db8:85a3::8a2e:370:7334", doc);
+    check!("2001:2::ac32:23ff:21", benchmarking);
+    check!("102:304:506:708:90a:b0c:d0e:f10", global);
+}
+
+#[test]
+fn ipv4_properties() {
+    macro_rules! ip {
+        ($s:expr) => {
+            Ipv4Addr::from_str($s).unwrap()
+        };
+    }
+
+    macro_rules! check {
+        ($s:expr) => {
+            check!($s, 0);
+        };
+
+        ($s:expr, $mask:expr) => {{
+            let unspec: u16 = 1 << 0;
+            let loopback: u16 = 1 << 1;
+            let private: u16 = 1 << 2;
+            let link_local: u16 = 1 << 3;
+            let global: u16 = 1 << 4;
+            let multicast: u16 = 1 << 5;
+            let broadcast: u16 = 1 << 6;
+            let documentation: u16 = 1 << 7;
+            let benchmarking: u16 = 1 << 8;
+            let reserved: u16 = 1 << 10;
+            let shared: u16 = 1 << 11;
+
+            if ($mask & unspec) == unspec {
+                assert!(ip!($s).is_unspecified());
+            } else {
+                assert!(!ip!($s).is_unspecified());
+            }
+
+            if ($mask & loopback) == loopback {
+                assert!(ip!($s).is_loopback());
+            } else {
+                assert!(!ip!($s).is_loopback());
+            }
+
+            if ($mask & private) == private {
+                assert!(ip!($s).is_private());
+            } else {
+                assert!(!ip!($s).is_private());
+            }
+
+            if ($mask & link_local) == link_local {
+                assert!(ip!($s).is_link_local());
+            } else {
+                assert!(!ip!($s).is_link_local());
+            }
+
+            if ($mask & global) == global {
+                assert!(ip!($s).is_global());
+            } else {
+                assert!(!ip!($s).is_global());
+            }
+
+            if ($mask & multicast) == multicast {
+                assert!(ip!($s).is_multicast());
+            } else {
+                assert!(!ip!($s).is_multicast());
+            }
+
+            if ($mask & broadcast) == broadcast {
+                assert!(ip!($s).is_broadcast());
+            } else {
+                assert!(!ip!($s).is_broadcast());
+            }
+
+            if ($mask & documentation) == documentation {
+                assert!(ip!($s).is_documentation());
+            } else {
+                assert!(!ip!($s).is_documentation());
+            }
+
+            if ($mask & benchmarking) == benchmarking {
+                assert!(ip!($s).is_benchmarking());
+            } else {
+                assert!(!ip!($s).is_benchmarking());
+            }
+
+            if ($mask & reserved) == reserved {
+                assert!(ip!($s).is_reserved());
+            } else {
+                assert!(!ip!($s).is_reserved());
+            }
+
+            if ($mask & shared) == shared {
+                assert!(ip!($s).is_shared());
+            } else {
+                assert!(!ip!($s).is_shared());
+            }
+        }};
+    }
+
+    let unspec: u16 = 1 << 0;
+    let loopback: u16 = 1 << 1;
+    let private: u16 = 1 << 2;
+    let link_local: u16 = 1 << 3;
+    let global: u16 = 1 << 4;
+    let multicast: u16 = 1 << 5;
+    let broadcast: u16 = 1 << 6;
+    let documentation: u16 = 1 << 7;
+    let benchmarking: u16 = 1 << 8;
+    let reserved: u16 = 1 << 10;
+    let shared: u16 = 1 << 11;
+
+    check!("0.0.0.0", unspec);
+    check!("0.0.0.1");
+    check!("0.1.0.0");
+    check!("10.9.8.7", private);
+    check!("127.1.2.3", loopback);
+    check!("172.31.254.253", private);
+    check!("169.254.253.242", link_local);
+    check!("192.0.2.183", documentation);
+    check!("192.1.2.183", global);
+    check!("192.168.254.253", private);
+    check!("198.51.100.0", documentation);
+    check!("203.0.113.0", documentation);
+    check!("203.2.113.0", global);
+    check!("224.0.0.0", global | multicast);
+    check!("239.255.255.255", global | multicast);
+    check!("255.255.255.255", broadcast);
+    check!("198.18.0.0", benchmarking);
+    check!("198.18.54.2", benchmarking);
+    check!("198.19.255.255", benchmarking);
+    check!("192.0.0.0");
+    check!("192.0.0.255");
+    check!("192.0.0.100");
+    check!("240.0.0.0", reserved);
+    check!("251.54.1.76", reserved);
+    check!("254.255.255.255", reserved);
+    check!("100.64.0.0", shared);
+    check!("100.127.255.255", shared);
+    check!("100.100.100.0", shared);
+}
+
+#[test]
+fn ipv6_properties() {
+    macro_rules! ip {
+        ($s:expr) => {
+            Ipv6Addr::from_str($s).unwrap()
+        };
+    }
+
+    macro_rules! check {
+        ($s:expr, &[$($octet:expr),*], $mask:expr) => {
+            assert_eq!($s, ip!($s).to_string());
+            let octets = &[$($octet),*];
+            assert_eq!(&ip!($s).octets(), octets);
+            assert_eq!(Ipv6Addr::from(*octets), ip!($s));
+
+            let unspecified: u32 = 1 << 0;
+            let loopback: u32 = 1 << 1;
+            let unique_local: u32 = 1 << 2;
+            let global: u32 = 1 << 3;
+            let unicast_link_local: u32 = 1 << 4;
+            let unicast_global: u32 = 1 << 7;
+            let documentation: u32 = 1 << 8;
+            let benchmarking: u32 = 1 << 16;
+            let multicast_interface_local: u32 = 1 << 9;
+            let multicast_link_local: u32 = 1 << 10;
+            let multicast_realm_local: u32 = 1 << 11;
+            let multicast_admin_local: u32 = 1 << 12;
+            let multicast_site_local: u32 = 1 << 13;
+            let multicast_organization_local: u32 = 1 << 14;
+            let multicast_global: u32 = 1 << 15;
+            let multicast: u32 = multicast_interface_local
+                | multicast_admin_local
+                | multicast_global
+                | multicast_link_local
+                | multicast_realm_local
+                | multicast_site_local
+                | multicast_organization_local;
+
+            if ($mask & unspecified) == unspecified {
+                assert!(ip!($s).is_unspecified());
+            } else {
+                assert!(!ip!($s).is_unspecified());
+            }
+            if ($mask & loopback) == loopback {
+                assert!(ip!($s).is_loopback());
+            } else {
+                assert!(!ip!($s).is_loopback());
+            }
+            if ($mask & unique_local) == unique_local {
+                assert!(ip!($s).is_unique_local());
+            } else {
+                assert!(!ip!($s).is_unique_local());
+            }
+            if ($mask & global) == global {
+                assert!(ip!($s).is_global());
+            } else {
+                assert!(!ip!($s).is_global());
+            }
+            if ($mask & unicast_link_local) == unicast_link_local {
+                assert!(ip!($s).is_unicast_link_local());
+            } else {
+                assert!(!ip!($s).is_unicast_link_local());
+            }
+            if ($mask & unicast_global) == unicast_global {
+                assert!(ip!($s).is_unicast_global());
+            } else {
+                assert!(!ip!($s).is_unicast_global());
+            }
+            if ($mask & documentation) == documentation {
+                assert!(ip!($s).is_documentation());
+            } else {
+                assert!(!ip!($s).is_documentation());
+            }
+            if ($mask & benchmarking) == benchmarking {
+                assert!(ip!($s).is_benchmarking());
+            } else {
+                assert!(!ip!($s).is_benchmarking());
+            }
+            if ($mask & multicast) != 0 {
+                assert!(ip!($s).multicast_scope().is_some());
+                assert!(ip!($s).is_multicast());
+            } else {
+                assert!(ip!($s).multicast_scope().is_none());
+                assert!(!ip!($s).is_multicast());
+            }
+            if ($mask & multicast_interface_local) == multicast_interface_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::InterfaceLocal);
+            }
+            if ($mask & multicast_link_local) == multicast_link_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::LinkLocal);
+            }
+            if ($mask & multicast_realm_local) == multicast_realm_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::RealmLocal);
+            }
+            if ($mask & multicast_admin_local) == multicast_admin_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::AdminLocal);
+            }
+            if ($mask & multicast_site_local) == multicast_site_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::SiteLocal);
+            }
+            if ($mask & multicast_organization_local) == multicast_organization_local {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::OrganizationLocal);
+            }
+            if ($mask & multicast_global) == multicast_global {
+                assert_eq!(ip!($s).multicast_scope().unwrap(),
+                           Ipv6MulticastScope::Global);
+            }
+        }
+    }
+
+    let unspecified: u32 = 1 << 0;
+    let loopback: u32 = 1 << 1;
+    let unique_local: u32 = 1 << 2;
+    let global: u32 = 1 << 3;
+    let unicast_link_local: u32 = 1 << 4;
+    let unicast_global: u32 = 1 << 7;
+    let documentation: u32 = 1 << 8;
+    let benchmarking: u32 = 1 << 16;
+    let multicast_interface_local: u32 = 1 << 9;
+    let multicast_link_local: u32 = 1 << 10;
+    let multicast_realm_local: u32 = 1 << 11;
+    let multicast_admin_local: u32 = 1 << 12;
+    let multicast_site_local: u32 = 1 << 13;
+    let multicast_organization_local: u32 = 1 << 14;
+    let multicast_global: u32 = 1 << 15;
+
+    check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified);
+
+    check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback);
+
+    check!("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global);
+
+    check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
+
+    check!(
+        "::ffff:127.0.0.1",
+        &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1],
+        unicast_global
+    );
+
+    check!(
+        "64:ff9b:1::",
+        &[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_global
+    );
+
+    check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+    check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+    check!(
+        "2001:1::1",
+        &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:1::2",
+        &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:3::",
+        &[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:4:112::",
+        &[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:20::",
+        &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+    check!(
+        "2001:200::",
+        &[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
+
+    check!(
+        "fdff:ffff::",
+        &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unique_local
+    );
+
+    check!(
+        "fe80:ffff::",
+        &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_link_local
+    );
+
+    check!("fe80::", &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local);
+
+    check!(
+        "febf:ffff::",
+        &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_link_local
+    );
+
+    check!("febf::", &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local);
+
+    check!(
+        "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+        &[
+            0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff
+        ],
+        unicast_link_local
+    );
+
+    check!(
+        "fe80::ffff:ffff:ffff:ffff",
+        &[
+            0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+            0xff, 0xff
+        ],
+        unicast_link_local
+    );
+
+    check!(
+        "fe80:0:0:1::",
+        &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_link_local
+    );
+
+    check!(
+        "fec0::",
+        &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_global | global
+    );
+
+    check!(
+        "ff01::",
+        &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_interface_local | global
+    );
+
+    check!(
+        "ff02::",
+        &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_link_local | global
+    );
+
+    check!(
+        "ff03::",
+        &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_realm_local | global
+    );
+
+    check!(
+        "ff04::",
+        &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_admin_local | global
+    );
+
+    check!(
+        "ff05::",
+        &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_site_local | global
+    );
+
+    check!(
+        "ff08::",
+        &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_organization_local | global
+    );
+
+    check!(
+        "ff0e::",
+        &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_global | global
+    );
+
+    check!(
+        "2001:db8:85a3::8a2e:370:7334",
+        &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
+        documentation
+    );
+
+    check!(
+        "2001:2::ac32:23ff:21",
+        &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
+        benchmarking
+    );
+
+    check!(
+        "102:304:506:708:90a:b0c:d0e:f10",
+        &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
+        global | unicast_global
+    );
+}
+
+#[test]
+fn test_ipv4_to_int() {
+    let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
+    assert_eq!(u32::from(a), 0x11223344);
+}
+
+#[test]
+fn test_int_to_ipv4() {
+    let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
+    assert_eq!(Ipv4Addr::from(0x11223344), a);
+}
+
+#[test]
+fn test_ipv6_to_int() {
+    let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
+    assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
+}
+
+#[test]
+fn test_int_to_ipv6() {
+    let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
+    assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
+}
+
+#[test]
+fn ipv4_from_constructors() {
+    assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
+    assert!(Ipv4Addr::LOCALHOST.is_loopback());
+    assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
+    assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
+    assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
+    assert!(Ipv4Addr::BROADCAST.is_broadcast());
+}
+
+#[test]
+fn ipv6_from_constructors() {
+    assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+    assert!(Ipv6Addr::LOCALHOST.is_loopback());
+    assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+    assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
+}
+
+#[test]
+fn ipv4_from_octets() {
+    assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
+}
+
+#[test]
+fn ipv6_from_segments() {
+    let from_u16s =
+        Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
+    let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
+    assert_eq!(new, from_u16s);
+}
+
+#[test]
+fn ipv6_from_octets() {
+    let from_u16s =
+        Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
+    let from_u8s = Ipv6Addr::from([
+        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
+        0xff,
+    ]);
+    assert_eq!(from_u16s, from_u8s);
+}
+
+#[test]
+fn cmp() {
+    let v41 = Ipv4Addr::new(100, 64, 3, 3);
+    let v42 = Ipv4Addr::new(192, 0, 2, 2);
+    let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
+    let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
+    assert!(v41 < v42);
+    assert!(v61 < v62);
+
+    assert_eq!(v41, IpAddr::V4(v41));
+    assert_eq!(v61, IpAddr::V6(v61));
+    assert!(v41 != IpAddr::V4(v42));
+    assert!(v61 != IpAddr::V6(v62));
+
+    assert!(v41 < IpAddr::V4(v42));
+    assert!(v61 < IpAddr::V6(v62));
+    assert!(IpAddr::V4(v41) < v42);
+    assert!(IpAddr::V6(v61) < v62);
+
+    assert!(v41 < IpAddr::V6(v61));
+    assert!(IpAddr::V4(v41) < v61);
+}
+
+#[test]
+fn is_v4() {
+    let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
+    assert!(ip.is_ipv4());
+    assert!(!ip.is_ipv6());
+}
+
+#[test]
+fn is_v6() {
+    let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
+    assert!(!ip.is_ipv4());
+    assert!(ip.is_ipv6());
+}
+
+#[test]
+fn ipv4_const() {
+    // test that the methods of `Ipv4Addr` are usable in a const context
+
+    const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
+    assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST);
+
+    const OCTETS: [u8; 4] = IP_ADDRESS.octets();
+    assert_eq!(OCTETS, [127, 0, 0, 1]);
+
+    const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
+    assert!(!IS_UNSPECIFIED);
+
+    const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
+    assert!(IS_LOOPBACK);
+
+    const IS_PRIVATE: bool = IP_ADDRESS.is_private();
+    assert!(!IS_PRIVATE);
+
+    const IS_LINK_LOCAL: bool = IP_ADDRESS.is_link_local();
+    assert!(!IS_LINK_LOCAL);
+
+    const IS_GLOBAL: bool = IP_ADDRESS.is_global();
+    assert!(!IS_GLOBAL);
+
+    const IS_SHARED: bool = IP_ADDRESS.is_shared();
+    assert!(!IS_SHARED);
+
+    const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking();
+    assert!(!IS_BENCHMARKING);
+
+    const IS_RESERVED: bool = IP_ADDRESS.is_reserved();
+    assert!(!IS_RESERVED);
+
+    const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
+    assert!(!IS_MULTICAST);
+
+    const IS_BROADCAST: bool = IP_ADDRESS.is_broadcast();
+    assert!(!IS_BROADCAST);
+
+    const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
+    assert!(!IS_DOCUMENTATION);
+
+    const IP_V6_COMPATIBLE: Ipv6Addr = IP_ADDRESS.to_ipv6_compatible();
+    assert_eq!(
+        IP_V6_COMPATIBLE,
+        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1])
+    );
+
+    const IP_V6_MAPPED: Ipv6Addr = IP_ADDRESS.to_ipv6_mapped();
+    assert_eq!(
+        IP_V6_MAPPED,
+        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1])
+    );
+}
+
+#[test]
+fn ipv6_const() {
+    // test that the methods of `Ipv6Addr` are usable in a const context
+
+    const IP_ADDRESS: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+    assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);
+
+    const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
+    assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]);
+
+    const OCTETS: [u8; 16] = IP_ADDRESS.octets();
+    assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
+
+    const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
+    assert!(!IS_UNSPECIFIED);
+
+    const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
+    assert!(IS_LOOPBACK);
+
+    const IS_GLOBAL: bool = IP_ADDRESS.is_global();
+    assert!(!IS_GLOBAL);
+
+    const IS_UNIQUE_LOCAL: bool = IP_ADDRESS.is_unique_local();
+    assert!(!IS_UNIQUE_LOCAL);
+
+    const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local();
+    assert!(!IS_UNICAST_LINK_LOCAL);
+
+    const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
+    assert!(!IS_DOCUMENTATION);
+
+    const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking();
+    assert!(!IS_BENCHMARKING);
+
+    const IS_UNICAST_GLOBAL: bool = IP_ADDRESS.is_unicast_global();
+    assert!(!IS_UNICAST_GLOBAL);
+
+    const MULTICAST_SCOPE: Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
+    assert_eq!(MULTICAST_SCOPE, None);
+
+    const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
+    assert!(!IS_MULTICAST);
+
+    const IP_V4: Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
+    assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
+}
+
+#[test]
+fn ip_const() {
+    // test that the methods of `IpAddr` are usable in a const context
+
+    const IP_ADDRESS: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
+
+    const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
+    assert!(!IS_UNSPECIFIED);
+
+    const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
+    assert!(IS_LOOPBACK);
+
+    const IS_GLOBAL: bool = IP_ADDRESS.is_global();
+    assert!(!IS_GLOBAL);
+
+    const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
+    assert!(!IS_MULTICAST);
+
+    const IS_IP_V4: bool = IP_ADDRESS.is_ipv4();
+    assert!(IS_IP_V4);
+
+    const IS_IP_V6: bool = IP_ADDRESS.is_ipv6();
+    assert!(!IS_IP_V6);
+}
+
+#[test]
+fn structural_match() {
+    // test that all IP types can be structurally matched upon
+
+    const IPV4: Ipv4Addr = Ipv4Addr::LOCALHOST;
+    match IPV4 {
+        Ipv4Addr::LOCALHOST => {}
+        _ => unreachable!(),
+    }
+
+    const IPV6: Ipv6Addr = Ipv6Addr::LOCALHOST;
+    match IPV6 {
+        Ipv6Addr::LOCALHOST => {}
+        _ => unreachable!(),
+    }
+
+    const IP: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
+    match IP {
+        IpAddr::V4(Ipv4Addr::LOCALHOST) => {}
+        _ => unreachable!(),
+    }
+}
diff --git a/library/core/tests/net/mod.rs b/library/core/tests/net/mod.rs
new file mode 100644
index 00000000000..8f17bbe5548
--- /dev/null
+++ b/library/core/tests/net/mod.rs
@@ -0,0 +1,13 @@
+use core::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+
+mod ip_addr;
+mod parser;
+mod socket_addr;
+
+pub fn sa4(a: Ipv4Addr, p: u16) -> SocketAddr {
+    SocketAddr::V4(SocketAddrV4::new(a, p))
+}
+
+pub fn sa6(a: Ipv6Addr, p: u16) -> SocketAddr {
+    SocketAddr::V6(SocketAddrV6::new(a, p, 0, 0))
+}
diff --git a/library/std/src/net/parser/tests.rs b/library/core/tests/net/parser.rs
index 6d2d48ecad0..36b87d7c1f5 100644
--- a/library/std/src/net/parser/tests.rs
+++ b/library/core/tests/net/parser.rs
@@ -1,6 +1,6 @@
 // FIXME: These tests are all excellent candidates for AFL fuzz testing
-use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
-use crate::str::FromStr;
+use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+use core::str::FromStr;
 
 const PORT: u16 = 8080;
 const SCOPE_ID: u32 = 1337;
diff --git a/library/core/tests/net/socket_addr.rs b/library/core/tests/net/socket_addr.rs
new file mode 100644
index 00000000000..68c7cd94d32
--- /dev/null
+++ b/library/core/tests/net/socket_addr.rs
@@ -0,0 +1,233 @@
+use core::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+
+#[test]
+fn ipv4_socket_addr_to_string() {
+    // Shortest possible IPv4 length.
+    assert_eq!(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0).to_string(), "0.0.0.0:0");
+
+    // Longest possible IPv4 length.
+    assert_eq!(
+        SocketAddrV4::new(Ipv4Addr::new(255, 255, 255, 255), u16::MAX).to_string(),
+        "255.255.255.255:65535"
+    );
+
+    // Test padding.
+    assert_eq!(
+        &format!("{:16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
+        "1.1.1.1:53      "
+    );
+    assert_eq!(
+        &format!("{:>16}", SocketAddrV4::new(Ipv4Addr::new(1, 1, 1, 1), 53)),
+        "      1.1.1.1:53"
+    );
+}
+
+#[test]
+fn ipv6_socket_addr_to_string() {
+    // IPv4-mapped address.
+    assert_eq!(
+        SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280), 8080, 0, 0)
+            .to_string(),
+        "[::ffff:192.0.2.128]:8080"
+    );
+
+    // IPv4-compatible address.
+    assert_eq!(
+        SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280), 8080, 0, 0).to_string(),
+        "[::192.0.2.128]:8080"
+    );
+
+    // IPv6 address with no zero segments.
+    assert_eq!(
+        SocketAddrV6::new(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15), 80, 0, 0).to_string(),
+        "[8:9:a:b:c:d:e:f]:80"
+    );
+
+    // Shortest possible IPv6 length.
+    assert_eq!(SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 0, 0, 0).to_string(), "[::]:0");
+
+    // Longest possible IPv6 length.
+    assert_eq!(
+        SocketAddrV6::new(
+            Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888),
+            u16::MAX,
+            u32::MAX,
+            u32::MAX,
+        )
+        .to_string(),
+        "[1111:2222:3333:4444:5555:6666:7777:8888%4294967295]:65535"
+    );
+
+    // Test padding.
+    assert_eq!(
+        &format!("{:22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
+        "[1:2:3:4:5:6:7:8]:9   "
+    );
+    assert_eq!(
+        &format!("{:>22}", SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 9, 0, 0)),
+        "   [1:2:3:4:5:6:7:8]:9"
+    );
+}
+
+#[test]
+fn set_ip() {
+    fn ip4(low: u8) -> Ipv4Addr {
+        Ipv4Addr::new(77, 88, 21, low)
+    }
+    fn ip6(low: u16) -> Ipv6Addr {
+        Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, low)
+    }
+
+    let mut v4 = SocketAddrV4::new(ip4(11), 80);
+    assert_eq!(v4.ip(), &ip4(11));
+    v4.set_ip(ip4(12));
+    assert_eq!(v4.ip(), &ip4(12));
+
+    let mut addr = SocketAddr::V4(v4);
+    assert_eq!(addr.ip(), IpAddr::V4(ip4(12)));
+    addr.set_ip(IpAddr::V4(ip4(13)));
+    assert_eq!(addr.ip(), IpAddr::V4(ip4(13)));
+    addr.set_ip(IpAddr::V6(ip6(14)));
+    assert_eq!(addr.ip(), IpAddr::V6(ip6(14)));
+
+    let mut v6 = SocketAddrV6::new(ip6(1), 80, 0, 0);
+    assert_eq!(v6.ip(), &ip6(1));
+    v6.set_ip(ip6(2));
+    assert_eq!(v6.ip(), &ip6(2));
+
+    let mut addr = SocketAddr::V6(v6);
+    assert_eq!(addr.ip(), IpAddr::V6(ip6(2)));
+    addr.set_ip(IpAddr::V6(ip6(3)));
+    assert_eq!(addr.ip(), IpAddr::V6(ip6(3)));
+    addr.set_ip(IpAddr::V4(ip4(4)));
+    assert_eq!(addr.ip(), IpAddr::V4(ip4(4)));
+}
+
+#[test]
+fn set_port() {
+    let mut v4 = SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80);
+    assert_eq!(v4.port(), 80);
+    v4.set_port(443);
+    assert_eq!(v4.port(), 443);
+
+    let mut addr = SocketAddr::V4(v4);
+    assert_eq!(addr.port(), 443);
+    addr.set_port(8080);
+    assert_eq!(addr.port(), 8080);
+
+    let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 0);
+    assert_eq!(v6.port(), 80);
+    v6.set_port(443);
+    assert_eq!(v6.port(), 443);
+
+    let mut addr = SocketAddr::V6(v6);
+    assert_eq!(addr.port(), 443);
+    addr.set_port(8080);
+    assert_eq!(addr.port(), 8080);
+}
+
+#[test]
+fn set_flowinfo() {
+    let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 10, 0);
+    assert_eq!(v6.flowinfo(), 10);
+    v6.set_flowinfo(20);
+    assert_eq!(v6.flowinfo(), 20);
+}
+
+#[test]
+fn set_scope_id() {
+    let mut v6 = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 80, 0, 10);
+    assert_eq!(v6.scope_id(), 10);
+    v6.set_scope_id(20);
+    assert_eq!(v6.scope_id(), 20);
+}
+
+#[test]
+fn is_v4() {
+    let v4 = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80));
+    assert!(v4.is_ipv4());
+    assert!(!v4.is_ipv6());
+}
+
+#[test]
+fn is_v6() {
+    let v6 = SocketAddr::V6(SocketAddrV6::new(
+        Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1),
+        80,
+        10,
+        0,
+    ));
+    assert!(!v6.is_ipv4());
+    assert!(v6.is_ipv6());
+}
+
+#[test]
+fn socket_v4_to_str() {
+    let socket = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 8080);
+
+    assert_eq!(format!("{socket}"), "192.168.0.1:8080");
+    assert_eq!(format!("{socket:<20}"), "192.168.0.1:8080    ");
+    assert_eq!(format!("{socket:>20}"), "    192.168.0.1:8080");
+    assert_eq!(format!("{socket:^20}"), "  192.168.0.1:8080  ");
+    assert_eq!(format!("{socket:.10}"), "192.168.0.");
+}
+
+#[test]
+fn socket_v6_to_str() {
+    let mut socket = SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0);
+
+    assert_eq!(format!("{socket}"), "[2a02:6b8:0:1::1]:53");
+    assert_eq!(format!("{socket:<24}"), "[2a02:6b8:0:1::1]:53    ");
+    assert_eq!(format!("{socket:>24}"), "    [2a02:6b8:0:1::1]:53");
+    assert_eq!(format!("{socket:^24}"), "  [2a02:6b8:0:1::1]:53  ");
+    assert_eq!(format!("{socket:.15}"), "[2a02:6b8:0:1::");
+
+    socket.set_scope_id(5);
+
+    assert_eq!(format!("{socket}"), "[2a02:6b8:0:1::1%5]:53");
+    assert_eq!(format!("{socket:<24}"), "[2a02:6b8:0:1::1%5]:53  ");
+    assert_eq!(format!("{socket:>24}"), "  [2a02:6b8:0:1::1%5]:53");
+    assert_eq!(format!("{socket:^24}"), " [2a02:6b8:0:1::1%5]:53 ");
+    assert_eq!(format!("{socket:.18}"), "[2a02:6b8:0:1::1%5");
+}
+
+#[test]
+fn compare() {
+    let v4_1 = "224.120.45.1:23456".parse::<SocketAddrV4>().unwrap();
+    let v4_2 = "224.210.103.5:12345".parse::<SocketAddrV4>().unwrap();
+    let v4_3 = "224.210.103.5:23456".parse::<SocketAddrV4>().unwrap();
+    let v6_1 = "[2001:db8:f00::1002]:23456".parse::<SocketAddrV6>().unwrap();
+    let v6_2 = "[2001:db8:f00::2001]:12345".parse::<SocketAddrV6>().unwrap();
+    let v6_3 = "[2001:db8:f00::2001]:23456".parse::<SocketAddrV6>().unwrap();
+
+    // equality
+    assert_eq!(v4_1, v4_1);
+    assert_eq!(v6_1, v6_1);
+    assert_eq!(SocketAddr::V4(v4_1), SocketAddr::V4(v4_1));
+    assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1));
+    assert!(v4_1 != v4_2);
+    assert!(v6_1 != v6_2);
+
+    // compare different addresses
+    assert!(v4_1 < v4_2);
+    assert!(v6_1 < v6_2);
+    assert!(v4_2 > v4_1);
+    assert!(v6_2 > v6_1);
+
+    // compare the same address with different ports
+    assert!(v4_2 < v4_3);
+    assert!(v6_2 < v6_3);
+    assert!(v4_3 > v4_2);
+    assert!(v6_3 > v6_2);
+
+    // compare different addresses with the same port
+    assert!(v4_1 < v4_3);
+    assert!(v6_1 < v6_3);
+    assert!(v4_3 > v4_1);
+    assert!(v6_3 > v6_1);
+
+    // compare with an inferred right-hand side
+    assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap());
+    assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap());
+    assert_eq!(SocketAddr::V4(v4_1), "224.120.45.1:23456".parse().unwrap());
+}
diff --git a/library/portable-simd/crates/core_simd/src/vector.rs b/library/portable-simd/crates/core_simd/src/vector.rs
index 78f56402eba..d52d1ac4d3a 100644
--- a/library/portable-simd/crates/core_simd/src/vector.rs
+++ b/library/portable-simd/crates/core_simd/src/vector.rs
@@ -28,7 +28,7 @@ use crate::simd::{
 /// let zm_add = a0.zip(a1).map(|(lhs, rhs)| lhs + rhs);
 /// let zm_mul = a0.zip(a1).map(|(lhs, rhs)| lhs * rhs);
 ///
-/// // `Simd<T, N>` implements `From<[T; N]>
+/// // `Simd<T, N>` implements `From<[T; N]>`
 /// let (v0, v1) = (Simd::from(a0), Simd::from(a1));
 /// // Which means arrays implement `Into<Simd<T, N>>`.
 /// assert_eq!(v0 + v1, zm_add.into());
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 311b2e21c17..598a4bf9282 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core" }
-libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.139", default-features = false, features = ['rustc-dep-of-std'] }
 compiler_builtins = { version = "0.1.87" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
diff --git a/library/std/build.rs b/library/std/build.rs
index 8b1a06ee750..ea879667558 100644
--- a/library/std/build.rs
+++ b/library/std/build.rs
@@ -31,6 +31,7 @@ fn main() {
         || target.contains("espidf")
         || target.contains("solid")
         || target.contains("nintendo-3ds")
+        || target.contains("nto")
     {
         // These platforms don't have any special requirements.
     } else {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 363a2667174..b62f3ad29d3 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -232,6 +232,7 @@
     all(target_vendor = "fortanix", target_env = "sgx"),
     feature(slice_index_methods, coerce_unsized, sgx_platform)
 )]
+#![cfg_attr(windows, feature(round_char_boundary))]
 //
 // Language features:
 #![feature(alloc_error_handler)]
@@ -287,6 +288,8 @@
 #![feature(float_next_up_down)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
+#![feature(ip)]
+#![feature(ip_in_core)]
 #![feature(is_some_and)]
 #![feature(maybe_uninit_slice)]
 #![feature(maybe_uninit_write_slice)]
diff --git a/library/std/src/net/ip_addr.rs b/library/std/src/net/ip_addr.rs
index 07f08c1b586..e167fbd1b9c 100644
--- a/library/std/src/net/ip_addr.rs
+++ b/library/std/src/net/ip_addr.rs
@@ -2,2101 +2,40 @@
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
-use crate::cmp::Ordering;
-use crate::fmt::{self, Write};
-use crate::mem::transmute;
 use crate::sys::net::netc as c;
 use crate::sys_common::{FromInner, IntoInner};
 
-use super::display_buffer::DisplayBuffer;
-
-/// An IP address, either IPv4 or IPv6.
-///
-/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
-/// respective documentation for more details.
-///
-/// # Examples
-///
-/// ```
-/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-///
-/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
-/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
-///
-/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
-/// assert_eq!("::1".parse(), Ok(localhost_v6));
-///
-/// assert_eq!(localhost_v4.is_ipv6(), false);
-/// assert_eq!(localhost_v4.is_ipv4(), true);
-/// ```
-#[cfg_attr(not(test), rustc_diagnostic_item = "IpAddr")]
 #[stable(feature = "ip_addr", since = "1.7.0")]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
-pub enum IpAddr {
-    /// An IPv4 address.
-    #[stable(feature = "ip_addr", since = "1.7.0")]
-    V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
-    /// An IPv6 address.
-    #[stable(feature = "ip_addr", since = "1.7.0")]
-    V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
-}
+pub use core::net::IpAddr;
 
-/// An IPv4 address.
-///
-/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
-/// They are usually represented as four octets.
-///
-/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
-///
-/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
-///
-/// # Textual representation
-///
-/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
-/// notation, divided by `.` (this is called "dot-decimal notation").
-/// Notably, octal numbers (which are indicated with a leading `0`) and hexadecimal numbers (which
-/// are indicated with a leading `0x`) are not allowed per [IETF RFC 6943].
-///
-/// [IETF RFC 6943]: https://tools.ietf.org/html/rfc6943#section-3.1.1
-/// [`FromStr`]: crate::str::FromStr
-///
-/// # Examples
-///
-/// ```
-/// use std::net::Ipv4Addr;
-///
-/// let localhost = Ipv4Addr::new(127, 0, 0, 1);
-/// assert_eq!("127.0.0.1".parse(), Ok(localhost));
-/// assert_eq!(localhost.is_loopback(), true);
-/// assert!("012.004.002.000".parse::<Ipv4Addr>().is_err()); // all octets are in octal
-/// assert!("0000000.0.0.0".parse::<Ipv4Addr>().is_err()); // first octet is a zero in octal
-/// assert!("0xcb.0x0.0x71.0x00".parse::<Ipv4Addr>().is_err()); // all octets are in hex
-/// ```
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Ipv4Addr {
-    octets: [u8; 4],
-}
+pub use core::net::{Ipv4Addr, Ipv6Addr};
 
-/// An IPv6 address.
-///
-/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
-/// They are usually represented as eight 16-bit segments.
-///
-/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
-///
-/// # Embedding IPv4 Addresses
-///
-/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
-///
-/// To assist in the transition from IPv4 to IPv6 two types of IPv6 addresses that embed an IPv4 address were defined:
-/// IPv4-compatible and IPv4-mapped addresses. Of these IPv4-compatible addresses have been officially deprecated.
-///
-/// Both types of addresses are not assigned any special meaning by this implementation,
-/// other than what the relevant standards prescribe. This means that an address like `::ffff:127.0.0.1`,
-/// while representing an IPv4 loopback address, is not itself an IPv6 loopback address; only `::1` is.
-/// To handle these so called "IPv4-in-IPv6" addresses, they have to first be converted to their canonical IPv4 address.
-///
-/// ### IPv4-Compatible IPv6 Addresses
-///
-/// IPv4-compatible IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.1], and have been officially deprecated.
-/// The RFC describes the format of an "IPv4-Compatible IPv6 address" as follows:
-///
-/// ```text
-/// |                80 bits               | 16 |      32 bits        |
-/// +--------------------------------------+--------------------------+
-/// |0000..............................0000|0000|    IPv4 address     |
-/// +--------------------------------------+----+---------------------+
-/// ```
-/// So `::a.b.c.d` would be an IPv4-compatible IPv6 address representing the IPv4 address `a.b.c.d`.
-///
-/// To convert from an IPv4 address to an IPv4-compatible IPv6 address, use [`Ipv4Addr::to_ipv6_compatible`].
-/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-compatible IPv6 address to the canonical IPv4 address.
-///
-/// [IETF RFC 4291 Section 2.5.5.1]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1
-///
-/// ### IPv4-Mapped IPv6 Addresses
-///
-/// IPv4-mapped IPv6 addresses are defined in [IETF RFC 4291 Section 2.5.5.2].
-/// The RFC describes the format of an "IPv4-Mapped IPv6 address" as follows:
-///
-/// ```text
-/// |                80 bits               | 16 |      32 bits        |
-/// +--------------------------------------+--------------------------+
-/// |0000..............................0000|FFFF|    IPv4 address     |
-/// +--------------------------------------+----+---------------------+
-/// ```
-/// So `::ffff:a.b.c.d` would be an IPv4-mapped IPv6 address representing the IPv4 address `a.b.c.d`.
-///
-/// To convert from an IPv4 address to an IPv4-mapped IPv6 address, use [`Ipv4Addr::to_ipv6_mapped`].
-/// Use [`Ipv6Addr::to_ipv4`] to convert an IPv4-mapped IPv6 address to the canonical IPv4 address.
-/// Note that this will also convert the IPv6 loopback address `::1` to `0.0.0.1`. Use
-/// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
-///
-/// [IETF RFC 4291 Section 2.5.5.2]: https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2
-///
-/// # Textual representation
-///
-/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
-/// an IPv6 address in text, but in general, each segments is written in hexadecimal
-/// notation, and segments are separated by `:`. For more information, see
-/// [IETF RFC 5952].
-///
-/// [`FromStr`]: crate::str::FromStr
-/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
-///
-/// # Examples
-///
-/// ```
-/// use std::net::Ipv6Addr;
-///
-/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
-/// assert_eq!("::1".parse(), Ok(localhost));
-/// assert_eq!(localhost.is_loopback(), true);
-/// ```
-#[derive(Copy, Clone, PartialEq, Eq, Hash)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Ipv6Addr {
-    octets: [u8; 16],
-}
-
-/// Scope of an [IPv6 multicast address] as defined in [IETF RFC 7346 section 2].
-///
-/// # Stability Guarantees
-///
-/// Not all possible values for a multicast scope have been assigned.
-/// Future RFCs may introduce new scopes, which will be added as variants to this enum;
-/// because of this the enum is marked as `#[non_exhaustive]`.
-///
-/// # Examples
-/// ```
-/// #![feature(ip)]
-///
-/// use std::net::Ipv6Addr;
-/// use std::net::Ipv6MulticastScope::*;
-///
-/// // An IPv6 multicast address with global scope (`ff0e::`).
-/// let address = Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0);
-///
-/// // Will print "Global scope".
-/// match address.multicast_scope() {
-///     Some(InterfaceLocal) => println!("Interface-Local scope"),
-///     Some(LinkLocal) => println!("Link-Local scope"),
-///     Some(RealmLocal) => println!("Realm-Local scope"),
-///     Some(AdminLocal) => println!("Admin-Local scope"),
-///     Some(SiteLocal) => println!("Site-Local scope"),
-///     Some(OrganizationLocal) => println!("Organization-Local scope"),
-///     Some(Global) => println!("Global scope"),
-///     Some(_) => println!("Unknown scope"),
-///     None => println!("Not a multicast address!")
-/// }
-///
-/// ```
-///
-/// [IPv6 multicast address]: Ipv6Addr
-/// [IETF RFC 7346 section 2]: https://tools.ietf.org/html/rfc7346#section-2
-#[derive(Copy, PartialEq, Eq, Clone, Hash, Debug)]
 #[unstable(feature = "ip", issue = "27709")]
-#[non_exhaustive]
-pub enum Ipv6MulticastScope {
-    /// Interface-Local scope.
-    InterfaceLocal,
-    /// Link-Local scope.
-    LinkLocal,
-    /// Realm-Local scope.
-    RealmLocal,
-    /// Admin-Local scope.
-    AdminLocal,
-    /// Site-Local scope.
-    SiteLocal,
-    /// Organization-Local scope.
-    OrganizationLocal,
-    /// Global scope.
-    Global,
-}
-
-impl IpAddr {
-    /// Returns [`true`] for the special 'unspecified' address.
-    ///
-    /// See the documentation for [`Ipv4Addr::is_unspecified()`] and
-    /// [`Ipv6Addr::is_unspecified()`] for more details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)).is_unspecified(), true);
-    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)).is_unspecified(), true);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "ip_shared", since = "1.12.0")]
-    #[must_use]
-    #[inline]
-    pub const fn is_unspecified(&self) -> bool {
-        match self {
-            IpAddr::V4(ip) => ip.is_unspecified(),
-            IpAddr::V6(ip) => ip.is_unspecified(),
-        }
-    }
-
-    /// Returns [`true`] if this is a loopback address.
-    ///
-    /// See the documentation for [`Ipv4Addr::is_loopback()`] and
-    /// [`Ipv6Addr::is_loopback()`] for more details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).is_loopback(), true);
-    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1)).is_loopback(), true);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "ip_shared", since = "1.12.0")]
-    #[must_use]
-    #[inline]
-    pub const fn is_loopback(&self) -> bool {
-        match self {
-            IpAddr::V4(ip) => ip.is_loopback(),
-            IpAddr::V6(ip) => ip.is_loopback(),
-        }
-    }
-
-    /// Returns [`true`] if the address appears to be globally routable.
-    ///
-    /// See the documentation for [`Ipv4Addr::is_global()`] and
-    /// [`Ipv6Addr::is_global()`] for more details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(80, 9, 12, 3)).is_global(), true);
-    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1)).is_global(), true);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_global(&self) -> bool {
-        match self {
-            IpAddr::V4(ip) => ip.is_global(),
-            IpAddr::V6(ip) => ip.is_global(),
-        }
-    }
-
-    /// Returns [`true`] if this is a multicast address.
-    ///
-    /// See the documentation for [`Ipv4Addr::is_multicast()`] and
-    /// [`Ipv6Addr::is_multicast()`] for more details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(224, 254, 0, 0)).is_multicast(), true);
-    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0)).is_multicast(), true);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "ip_shared", since = "1.12.0")]
-    #[must_use]
-    #[inline]
-    pub const fn is_multicast(&self) -> bool {
-        match self {
-            IpAddr::V4(ip) => ip.is_multicast(),
-            IpAddr::V6(ip) => ip.is_multicast(),
-        }
-    }
-
-    /// Returns [`true`] if this address is in a range designated for documentation.
-    ///
-    /// See the documentation for [`Ipv4Addr::is_documentation()`] and
-    /// [`Ipv6Addr::is_documentation()`] for more details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_documentation(), true);
-    /// assert_eq!(
-    ///     IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_documentation(),
-    ///     true
-    /// );
-    /// ```
-    #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_documentation(&self) -> bool {
-        match self {
-            IpAddr::V4(ip) => ip.is_documentation(),
-            IpAddr::V6(ip) => ip.is_documentation(),
-        }
-    }
-
-    /// Returns [`true`] if this address is in a range designated for benchmarking.
-    ///
-    /// See the documentation for [`Ipv4Addr::is_benchmarking()`] and
-    /// [`Ipv6Addr::is_benchmarking()`] for more details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true);
-    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true);
-    /// ```
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_benchmarking(&self) -> bool {
-        match self {
-            IpAddr::V4(ip) => ip.is_benchmarking(),
-            IpAddr::V6(ip) => ip.is_benchmarking(),
-        }
-    }
-
-    /// Returns [`true`] if this address is an [`IPv4` address], and [`false`]
-    /// otherwise.
-    ///
-    /// [`IPv4` address]: IpAddr::V4
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
-    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "ipaddr_checker", since = "1.16.0")]
-    #[must_use]
-    #[inline]
-    pub const fn is_ipv4(&self) -> bool {
-        matches!(self, IpAddr::V4(_))
-    }
-
-    /// Returns [`true`] if this address is an [`IPv6` address], and [`false`]
-    /// otherwise.
-    ///
-    /// [`IPv6` address]: IpAddr::V6
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
-    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "ipaddr_checker", since = "1.16.0")]
-    #[must_use]
-    #[inline]
-    pub const fn is_ipv6(&self) -> bool {
-        matches!(self, IpAddr::V6(_))
-    }
-
-    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped IPv6 addresses, otherwise it
-    /// return `self` as-is.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    /// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)).to_canonical().is_loopback(), true);
-    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).is_loopback(), false);
-    /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1)).to_canonical().is_loopback(), true);
-    /// ```
-    #[inline]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    #[rustc_const_unstable(feature = "const_ip", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    pub const fn to_canonical(&self) -> IpAddr {
-        match self {
-            &v4 @ IpAddr::V4(_) => v4,
-            IpAddr::V6(v6) => v6.to_canonical(),
-        }
-    }
-}
-
-impl Ipv4Addr {
-    /// Creates a new IPv4 address from four eight-bit octets.
-    ///
-    /// The result will represent the IP address `a`.`b`.`c`.`d`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[must_use]
-    #[inline]
-    pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
-        Ipv4Addr { octets: [a, b, c, d] }
-    }
-
-    /// An IPv4 address with the address pointing to localhost: `127.0.0.1`
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// let addr = Ipv4Addr::LOCALHOST;
-    /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
-    /// ```
-    #[stable(feature = "ip_constructors", since = "1.30.0")]
-    pub const LOCALHOST: Self = Ipv4Addr::new(127, 0, 0, 1);
-
-    /// An IPv4 address representing an unspecified address: `0.0.0.0`
-    ///
-    /// This corresponds to the constant `INADDR_ANY` in other languages.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// let addr = Ipv4Addr::UNSPECIFIED;
-    /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
-    /// ```
-    #[doc(alias = "INADDR_ANY")]
-    #[stable(feature = "ip_constructors", since = "1.30.0")]
-    pub const UNSPECIFIED: Self = Ipv4Addr::new(0, 0, 0, 0);
-
-    /// An IPv4 address representing the broadcast address: `255.255.255.255`
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// let addr = Ipv4Addr::BROADCAST;
-    /// assert_eq!(addr, Ipv4Addr::new(255, 255, 255, 255));
-    /// ```
-    #[stable(feature = "ip_constructors", since = "1.30.0")]
-    pub const BROADCAST: Self = Ipv4Addr::new(255, 255, 255, 255);
-
-    /// Returns the four eight-bit integers that make up this address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
-    /// assert_eq!(addr.octets(), [127, 0, 0, 1]);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[must_use]
-    #[inline]
-    pub const fn octets(&self) -> [u8; 4] {
-        self.octets
-    }
-
-    /// Returns [`true`] for the special 'unspecified' address (`0.0.0.0`).
-    ///
-    /// This property is defined in _UNIX Network Programming, Second Edition_,
-    /// W. Richard Stevens, p. 891; see also [ip7].
-    ///
-    /// [ip7]: https://man7.org/linux/man-pages/man7/ip.7.html
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_unspecified(), true);
-    /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
-    #[stable(feature = "ip_shared", since = "1.12.0")]
-    #[must_use]
-    #[inline]
-    pub const fn is_unspecified(&self) -> bool {
-        u32::from_be_bytes(self.octets) == 0
-    }
-
-    /// Returns [`true`] if this is a loopback address (`127.0.0.0/8`).
-    ///
-    /// This property is defined by [IETF RFC 1122].
-    ///
-    /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_loopback(), true);
-    /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_loopback(), false);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(since = "1.7.0", feature = "ip_17")]
-    #[must_use]
-    #[inline]
-    pub const fn is_loopback(&self) -> bool {
-        self.octets()[0] == 127
-    }
-
-    /// Returns [`true`] if this is a private address.
-    ///
-    /// The private address ranges are defined in [IETF RFC 1918] and include:
-    ///
-    ///  - `10.0.0.0/8`
-    ///  - `172.16.0.0/12`
-    ///  - `192.168.0.0/16`
-    ///
-    /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(10, 0, 0, 1).is_private(), true);
-    /// assert_eq!(Ipv4Addr::new(10, 10, 10, 10).is_private(), true);
-    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 10).is_private(), true);
-    /// assert_eq!(Ipv4Addr::new(172, 29, 45, 14).is_private(), true);
-    /// assert_eq!(Ipv4Addr::new(172, 32, 0, 2).is_private(), false);
-    /// assert_eq!(Ipv4Addr::new(192, 168, 0, 2).is_private(), true);
-    /// assert_eq!(Ipv4Addr::new(192, 169, 0, 2).is_private(), false);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(since = "1.7.0", feature = "ip_17")]
-    #[must_use]
-    #[inline]
-    pub const fn is_private(&self) -> bool {
-        match self.octets() {
-            [10, ..] => true,
-            [172, b, ..] if b >= 16 && b <= 31 => true,
-            [192, 168, ..] => true,
-            _ => false,
-        }
-    }
-
-    /// Returns [`true`] if the address is link-local (`169.254.0.0/16`).
-    ///
-    /// This property is defined by [IETF RFC 3927].
-    ///
-    /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(169, 254, 0, 0).is_link_local(), true);
-    /// assert_eq!(Ipv4Addr::new(169, 254, 10, 65).is_link_local(), true);
-    /// assert_eq!(Ipv4Addr::new(16, 89, 10, 65).is_link_local(), false);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(since = "1.7.0", feature = "ip_17")]
-    #[must_use]
-    #[inline]
-    pub const fn is_link_local(&self) -> bool {
-        matches!(self.octets(), [169, 254, ..])
-    }
-
-    /// Returns [`true`] if the address appears to be globally reachable
-    /// as specified by the [IANA IPv4 Special-Purpose Address Registry].
-    /// Whether or not an address is practically reachable will depend on your network configuration.
-    ///
-    /// Most IPv4 addresses are globally reachable;
-    /// unless they are specifically defined as *not* globally reachable.
-    ///
-    /// Non-exhaustive list of notable addresses that are not globally reachable:
-    ///
-    /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified))
-    /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private))
-    /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared))
-    /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback))
-    /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local))
-    /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation))
-    /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking))
-    /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved))
-    /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast))
-    ///
-    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry].
-    ///
-    /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
-    /// [unspecified address]: Ipv4Addr::UNSPECIFIED
-    /// [broadcast address]: Ipv4Addr::BROADCAST
-
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::Ipv4Addr;
-    ///
-    /// // Most IPv4 addresses are globally reachable:
-    /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
-    ///
-    /// // However some addresses have been assigned a special meaning
-    /// // that makes them not globally reachable. Some examples are:
-    ///
-    /// // The unspecified address (`0.0.0.0`)
-    /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false);
-    ///
-    /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16)
-    /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
-    /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
-    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
-    ///
-    /// // Addresses in the shared address space (`100.64.0.0/10`)
-    /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
-    ///
-    /// // The loopback addresses (`127.0.0.0/8`)
-    /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false);
-    ///
-    /// // Link-local addresses (`169.254.0.0/16`)
-    /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
-    ///
-    /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`)
-    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
-    /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
-    /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
-    ///
-    /// // Addresses reserved for benchmarking (`198.18.0.0/15`)
-    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
-    ///
-    /// // Reserved addresses (`240.0.0.0/4`)
-    /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
-    ///
-    /// // The broadcast address (`255.255.255.255`)
-    /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false);
-    ///
-    /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_global(&self) -> bool {
-        !(self.octets()[0] == 0 // "This network"
-            || self.is_private()
-            || self.is_shared()
-            || self.is_loopback()
-            || self.is_link_local()
-            // addresses reserved for future protocols (`192.0.0.0/24`)
-            ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
-            || self.is_documentation()
-            || self.is_benchmarking()
-            || self.is_reserved()
-            || self.is_broadcast())
-    }
-
-    /// Returns [`true`] if this address is part of the Shared Address Space defined in
-    /// [IETF RFC 6598] (`100.64.0.0/10`).
-    ///
-    /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
-    /// assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
-    /// assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_shared(&self) -> bool {
-        self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
-    }
-
-    /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
-    /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
-    /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
-    ///
-    /// [IETF RFC 2544]: https://tools.ietf.org/html/rfc2544
-    /// [errata 423]: https://www.rfc-editor.org/errata/eid423
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
-    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
-    /// assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
-    /// assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_benchmarking(&self) -> bool {
-        self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
-    }
-
-    /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
-    /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
-    /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since
-    /// it is obviously not reserved for future use.
-    ///
-    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
-    ///
-    /// # Warning
-    ///
-    /// As IANA assigns new addresses, this method will be
-    /// updated. This may result in non-reserved addresses being
-    /// treated as reserved in code that relies on an outdated version
-    /// of this method.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
-    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
-    ///
-    /// assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
-    /// // The broadcast address is not considered as reserved for future use by this implementation
-    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_reserved(&self) -> bool {
-        self.octets()[0] & 240 == 240 && !self.is_broadcast()
-    }
-
-    /// Returns [`true`] if this is a multicast address (`224.0.0.0/4`).
-    ///
-    /// Multicast addresses have a most significant octet between `224` and `239`,
-    /// and is defined by [IETF RFC 5771].
-    ///
-    /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(224, 254, 0, 0).is_multicast(), true);
-    /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_multicast(), true);
-    /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_multicast(), false);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(since = "1.7.0", feature = "ip_17")]
-    #[must_use]
-    #[inline]
-    pub const fn is_multicast(&self) -> bool {
-        self.octets()[0] >= 224 && self.octets()[0] <= 239
-    }
-
-    /// Returns [`true`] if this is a broadcast address (`255.255.255.255`).
-    ///
-    /// A broadcast address has all octets set to `255` as defined in [IETF RFC 919].
-    ///
-    /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_broadcast(), true);
-    /// assert_eq!(Ipv4Addr::new(236, 168, 10, 65).is_broadcast(), false);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(since = "1.7.0", feature = "ip_17")]
-    #[must_use]
-    #[inline]
-    pub const fn is_broadcast(&self) -> bool {
-        u32::from_be_bytes(self.octets()) == u32::from_be_bytes(Self::BROADCAST.octets())
-    }
-
-    /// Returns [`true`] if this address is in a range designated for documentation.
-    ///
-    /// This is defined in [IETF RFC 5737]:
-    ///
-    /// - `192.0.2.0/24` (TEST-NET-1)
-    /// - `198.51.100.0/24` (TEST-NET-2)
-    /// - `203.0.113.0/24` (TEST-NET-3)
-    ///
-    /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_documentation(), true);
-    /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_documentation(), true);
-    /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_documentation(), true);
-    /// assert_eq!(Ipv4Addr::new(193, 34, 17, 19).is_documentation(), false);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(since = "1.7.0", feature = "ip_17")]
-    #[must_use]
-    #[inline]
-    pub const fn is_documentation(&self) -> bool {
-        matches!(self.octets(), [192, 0, 2, _] | [198, 51, 100, _] | [203, 0, 113, _])
-    }
-
-    /// Converts this address to an [IPv4-compatible] [`IPv6` address].
-    ///
-    /// `a.b.c.d` becomes `::a.b.c.d`
-    ///
-    /// Note that IPv4-compatible addresses have been officially deprecated.
-    /// If you don't explicitly need an IPv4-compatible address for legacy reasons, consider using `to_ipv6_mapped` instead.
-    ///
-    /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
-    /// [`IPv6` address]: Ipv6Addr
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(
-    ///     Ipv4Addr::new(192, 0, 2, 255).to_ipv6_compatible(),
-    ///     Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x2ff)
-    /// );
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    #[inline]
-    pub const fn to_ipv6_compatible(&self) -> Ipv6Addr {
-        let [a, b, c, d] = self.octets();
-        Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d] }
-    }
-
-    /// Converts this address to an [IPv4-mapped] [`IPv6` address].
-    ///
-    /// `a.b.c.d` becomes `::ffff:a.b.c.d`
-    ///
-    /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
-    /// [`IPv6` address]: Ipv6Addr
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).to_ipv6_mapped(),
-    ///            Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x2ff));
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    #[inline]
-    pub const fn to_ipv6_mapped(&self) -> Ipv6Addr {
-        let [a, b, c, d] = self.octets();
-        Ipv6Addr { octets: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d] }
-    }
-}
-
-#[stable(feature = "ip_addr", since = "1.7.0")]
-impl fmt::Display for IpAddr {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            IpAddr::V4(ip) => ip.fmt(fmt),
-            IpAddr::V6(ip) => ip.fmt(fmt),
-        }
-    }
-}
-
-#[stable(feature = "ip_addr", since = "1.7.0")]
-impl fmt::Debug for IpAddr {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self, fmt)
-    }
-}
-
-#[stable(feature = "ip_from_ip", since = "1.16.0")]
-impl From<Ipv4Addr> for IpAddr {
-    /// Copies this address to a new `IpAddr::V4`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr};
-    ///
-    /// let addr = Ipv4Addr::new(127, 0, 0, 1);
-    ///
-    /// assert_eq!(
-    ///     IpAddr::V4(addr),
-    ///     IpAddr::from(addr)
-    /// )
-    /// ```
-    #[inline]
-    fn from(ipv4: Ipv4Addr) -> IpAddr {
-        IpAddr::V4(ipv4)
-    }
-}
-
-#[stable(feature = "ip_from_ip", since = "1.16.0")]
-impl From<Ipv6Addr> for IpAddr {
-    /// Copies this address to a new `IpAddr::V6`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv6Addr};
-    ///
-    /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
-    ///
-    /// assert_eq!(
-    ///     IpAddr::V6(addr),
-    ///     IpAddr::from(addr)
-    /// );
-    /// ```
-    #[inline]
-    fn from(ipv6: Ipv6Addr) -> IpAddr {
-        IpAddr::V6(ipv6)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for Ipv4Addr {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let octets = self.octets();
-
-        // If there are no alignment requirements, write the IP address directly to `f`.
-        // Otherwise, write it to a local buffer and then use `f.pad`.
-        if fmt.precision().is_none() && fmt.width().is_none() {
-            write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
-        } else {
-            const LONGEST_IPV4_ADDR: &str = "255.255.255.255";
-
-            let mut buf = DisplayBuffer::<{ LONGEST_IPV4_ADDR.len() }>::new();
-            // Buffer is long enough for the longest possible IPv4 address, so this should never fail.
-            write!(buf, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3]).unwrap();
-
-            fmt.pad(buf.as_str())
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Ipv4Addr {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self, fmt)
-    }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialEq<Ipv4Addr> for IpAddr {
-    #[inline]
-    fn eq(&self, other: &Ipv4Addr) -> bool {
-        match self {
-            IpAddr::V4(v4) => v4 == other,
-            IpAddr::V6(_) => false,
-        }
-    }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialEq<IpAddr> for Ipv4Addr {
-    #[inline]
-    fn eq(&self, other: &IpAddr) -> bool {
-        match other {
-            IpAddr::V4(v4) => self == v4,
-            IpAddr::V6(_) => false,
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialOrd for Ipv4Addr {
-    #[inline]
-    fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialOrd<Ipv4Addr> for IpAddr {
-    #[inline]
-    fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
-        match self {
-            IpAddr::V4(v4) => v4.partial_cmp(other),
-            IpAddr::V6(_) => Some(Ordering::Greater),
-        }
-    }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialOrd<IpAddr> for Ipv4Addr {
-    #[inline]
-    fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
-        match other {
-            IpAddr::V4(v4) => self.partial_cmp(v4),
-            IpAddr::V6(_) => Some(Ordering::Less),
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Ord for Ipv4Addr {
-    #[inline]
-    fn cmp(&self, other: &Ipv4Addr) -> Ordering {
-        self.octets.cmp(&other.octets)
-    }
-}
+pub use core::net::Ipv6MulticastScope;
 
 impl IntoInner<c::in_addr> for Ipv4Addr {
     #[inline]
     fn into_inner(self) -> c::in_addr {
         // `s_addr` is stored as BE on all machines and the array is in BE order.
         // So the native endian conversion method is used so that it's never swapped.
-        c::in_addr { s_addr: u32::from_ne_bytes(self.octets) }
+        c::in_addr { s_addr: u32::from_ne_bytes(self.octets()) }
     }
 }
 impl FromInner<c::in_addr> for Ipv4Addr {
     fn from_inner(addr: c::in_addr) -> Ipv4Addr {
-        Ipv4Addr { octets: addr.s_addr.to_ne_bytes() }
-    }
-}
-
-#[stable(feature = "ip_u32", since = "1.1.0")]
-impl From<Ipv4Addr> for u32 {
-    /// Converts an `Ipv4Addr` into a host byte order `u32`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
-    /// assert_eq!(0x12345678, u32::from(addr));
-    /// ```
-    #[inline]
-    fn from(ip: Ipv4Addr) -> u32 {
-        u32::from_be_bytes(ip.octets)
-    }
-}
-
-#[stable(feature = "ip_u32", since = "1.1.0")]
-impl From<u32> for Ipv4Addr {
-    /// Converts a host byte order `u32` into an `Ipv4Addr`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// let addr = Ipv4Addr::from(0x12345678);
-    /// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr);
-    /// ```
-    #[inline]
-    fn from(ip: u32) -> Ipv4Addr {
-        Ipv4Addr { octets: ip.to_be_bytes() }
-    }
-}
-
-#[stable(feature = "from_slice_v4", since = "1.9.0")]
-impl From<[u8; 4]> for Ipv4Addr {
-    /// Creates an `Ipv4Addr` from a four element byte array.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv4Addr;
-    ///
-    /// let addr = Ipv4Addr::from([13u8, 12u8, 11u8, 10u8]);
-    /// assert_eq!(Ipv4Addr::new(13, 12, 11, 10), addr);
-    /// ```
-    #[inline]
-    fn from(octets: [u8; 4]) -> Ipv4Addr {
-        Ipv4Addr { octets }
-    }
-}
-
-#[stable(feature = "ip_from_slice", since = "1.17.0")]
-impl From<[u8; 4]> for IpAddr {
-    /// Creates an `IpAddr::V4` from a four element byte array.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr};
-    ///
-    /// let addr = IpAddr::from([13u8, 12u8, 11u8, 10u8]);
-    /// assert_eq!(IpAddr::V4(Ipv4Addr::new(13, 12, 11, 10)), addr);
-    /// ```
-    #[inline]
-    fn from(octets: [u8; 4]) -> IpAddr {
-        IpAddr::V4(Ipv4Addr::from(octets))
-    }
-}
-
-impl Ipv6Addr {
-    /// Creates a new IPv6 address from eight 16-bit segments.
-    ///
-    /// The result will represent the IP address `a:b:c:d:e:f:g:h`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[must_use]
-    #[inline]
-    pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
-        let addr16 = [
-            a.to_be(),
-            b.to_be(),
-            c.to_be(),
-            d.to_be(),
-            e.to_be(),
-            f.to_be(),
-            g.to_be(),
-            h.to_be(),
-        ];
-        Ipv6Addr {
-            // All elements in `addr16` are big endian.
-            // SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
-            octets: unsafe { transmute::<_, [u8; 16]>(addr16) },
-        }
-    }
-
-    /// An IPv6 address representing localhost: `::1`.
-    ///
-    /// This corresponds to constant `IN6ADDR_LOOPBACK_INIT` or `in6addr_loopback` in other
-    /// languages.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// let addr = Ipv6Addr::LOCALHOST;
-    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
-    /// ```
-    #[doc(alias = "IN6ADDR_LOOPBACK_INIT")]
-    #[doc(alias = "in6addr_loopback")]
-    #[stable(feature = "ip_constructors", since = "1.30.0")]
-    pub const LOCALHOST: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
-
-    /// An IPv6 address representing the unspecified address: `::`
-    ///
-    /// This corresponds to constant `IN6ADDR_ANY_INIT` or `in6addr_any` in other languages.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// let addr = Ipv6Addr::UNSPECIFIED;
-    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
-    /// ```
-    #[doc(alias = "IN6ADDR_ANY_INIT")]
-    #[doc(alias = "in6addr_any")]
-    #[stable(feature = "ip_constructors", since = "1.30.0")]
-    pub const UNSPECIFIED: Self = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
-
-    /// Returns the eight 16-bit segments that make up this address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).segments(),
-    ///            [0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff]);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[must_use]
-    #[inline]
-    pub const fn segments(&self) -> [u16; 8] {
-        // All elements in `self.octets` must be big endian.
-        // SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
-        let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.octets) };
-        // We want native endian u16
-        [
-            u16::from_be(a),
-            u16::from_be(b),
-            u16::from_be(c),
-            u16::from_be(d),
-            u16::from_be(e),
-            u16::from_be(f),
-            u16::from_be(g),
-            u16::from_be(h),
-        ]
-    }
-
-    /// Returns [`true`] for the special 'unspecified' address (`::`).
-    ///
-    /// This property is defined in [IETF RFC 4291].
-    ///
-    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unspecified(), false);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).is_unspecified(), true);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(since = "1.7.0", feature = "ip_17")]
-    #[must_use]
-    #[inline]
-    pub const fn is_unspecified(&self) -> bool {
-        u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::UNSPECIFIED.octets())
-    }
-
-    /// Returns [`true`] if this is the [loopback address] (`::1`),
-    /// as defined in [IETF RFC 4291 section 2.5.3].
-    ///
-    /// Contrary to IPv4, in IPv6 there is only one loopback address.
-    ///
-    /// [loopback address]: Ipv6Addr::LOCALHOST
-    /// [IETF RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_loopback(), false);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_loopback(), true);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(since = "1.7.0", feature = "ip_17")]
-    #[must_use]
-    #[inline]
-    pub const fn is_loopback(&self) -> bool {
-        u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
-    }
-
-    /// Returns [`true`] if the address appears to be globally reachable
-    /// as specified by the [IANA IPv6 Special-Purpose Address Registry].
-    /// Whether or not an address is practically reachable will depend on your network configuration.
-    ///
-    /// Most IPv6 addresses are globally reachable;
-    /// unless they are specifically defined as *not* globally reachable.
-    ///
-    /// Non-exhaustive list of notable addresses that are not globally reachable:
-    /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified))
-    /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback))
-    /// - IPv4-mapped addresses
-    /// - Addresses reserved for benchmarking
-    /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation))
-    /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local))
-    /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local))
-    ///
-    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry].
-    ///
-    /// Note that an address having global scope is not the same as being globally reachable,
-    /// and there is no direct relation between the two concepts: There exist addresses with global scope
-    /// that are not globally reachable (for example unique local addresses),
-    /// and addresses that are globally reachable without having global scope
-    /// (multicast addresses with non-global scope).
-    ///
-    /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
-    /// [unspecified address]: Ipv6Addr::UNSPECIFIED
-    /// [loopback address]: Ipv6Addr::LOCALHOST
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::Ipv6Addr;
-    ///
-    /// // Most IPv6 addresses are globally reachable:
-    /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true);
-    ///
-    /// // However some addresses have been assigned a special meaning
-    /// // that makes them not globally reachable. Some examples are:
-    ///
-    /// // The unspecified address (`::`)
-    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false);
-    ///
-    /// // The loopback address (`::1`)
-    /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false);
-    ///
-    /// // IPv4-mapped addresses (`::ffff:0:0/96`)
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false);
-    ///
-    /// // Addresses reserved for benchmarking (`2001:2::/48`)
-    /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
-    ///
-    /// // Addresses reserved for documentation (`2001:db8::/32`)
-    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
-    ///
-    /// // Unique local addresses (`fc00::/7`)
-    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
-    ///
-    /// // Unicast addresses with link-local scope (`fe80::/10`)
-    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
-    ///
-    /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_global(&self) -> bool {
-        !(self.is_unspecified()
-            || self.is_loopback()
-            // IPv4-mapped Address (`::ffff:0:0/96`)
-            || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
-            // IPv4-IPv6 Translat. (`64:ff9b:1::/48`)
-            || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
-            // Discard-Only Address Block (`100::/64`)
-            || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _])
-            // IETF Protocol Assignments (`2001::/23`)
-            || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
-                && !(
-                    // Port Control Protocol Anycast (`2001:1::1`)
-                    u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
-                    // Traversal Using Relays around NAT Anycast (`2001:1::2`)
-                    || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
-                    // AMT (`2001:3::/32`)
-                    || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _])
-                    // AS112-v6 (`2001:4:112::/48`)
-                    || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
-                    // ORCHIDv2 (`2001:20::/28`)
-                    || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F)
-                ))
-            || self.is_documentation()
-            || self.is_unique_local()
-            || self.is_unicast_link_local())
-    }
-
-    /// Returns [`true`] if this is a unique local address (`fc00::/7`).
-    ///
-    /// This property is defined in [IETF RFC 4193].
-    ///
-    /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unique_local(), false);
-    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 0).is_unique_local(), true);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_unique_local(&self) -> bool {
-        (self.segments()[0] & 0xfe00) == 0xfc00
-    }
-
-    /// Returns [`true`] if this is a unicast address, as defined by [IETF RFC 4291].
-    /// Any address that is not a [multicast address] (`ff00::/8`) is unicast.
-    ///
-    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
-    /// [multicast address]: Ipv6Addr::is_multicast
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::Ipv6Addr;
-    ///
-    /// // The unspecified and loopback addresses are unicast.
-    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_unicast(), true);
-    /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast(), true);
-    ///
-    /// // Any address that is not a multicast address (`ff00::/8`) is unicast.
-    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast(), true);
-    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_unicast(), false);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_unicast(&self) -> bool {
-        !self.is_multicast()
-    }
-
-    /// Returns `true` if the address is a unicast address with link-local scope,
-    /// as defined in [RFC 4291].
-    ///
-    /// A unicast address has link-local scope if it has the prefix `fe80::/10`, as per [RFC 4291 section 2.4].
-    /// Note that this encompasses more addresses than those defined in [RFC 4291 section 2.5.6],
-    /// which describes "Link-Local IPv6 Unicast Addresses" as having the following stricter format:
-    ///
-    /// ```text
-    /// | 10 bits  |         54 bits         |          64 bits           |
-    /// +----------+-------------------------+----------------------------+
-    /// |1111111010|           0             |       interface ID         |
-    /// +----------+-------------------------+----------------------------+
-    /// ```
-    /// So while currently the only addresses with link-local scope an application will encounter are all in `fe80::/64`,
-    /// this might change in the future with the publication of new standards. More addresses in `fe80::/10` could be allocated,
-    /// and those addresses will have link-local scope.
-    ///
-    /// Also note that while [RFC 4291 section 2.5.3] mentions about the [loopback address] (`::1`) that "it is treated as having Link-Local scope",
-    /// this does not mean that the loopback address actually has link-local scope and this method will return `false` on it.
-    ///
-    /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
-    /// [RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
-    /// [RFC 4291 section 2.5.3]: https://tools.ietf.org/html/rfc4291#section-2.5.3
-    /// [RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
-    /// [loopback address]: Ipv6Addr::LOCALHOST
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::Ipv6Addr;
-    ///
-    /// // The loopback address (`::1`) does not actually have link-local scope.
-    /// assert_eq!(Ipv6Addr::LOCALHOST.is_unicast_link_local(), false);
-    ///
-    /// // Only addresses in `fe80::/10` have link-local scope.
-    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), false);
-    /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
-    ///
-    /// // Addresses outside the stricter `fe80::/64` also have link-local scope.
-    /// assert_eq!(Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0).is_unicast_link_local(), true);
-    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_unicast_link_local(&self) -> bool {
-        (self.segments()[0] & 0xffc0) == 0xfe80
-    }
-
-    /// Returns [`true`] if this is an address reserved for documentation
-    /// (`2001:db8::/32`).
-    ///
-    /// This property is defined in [IETF RFC 3849].
-    ///
-    /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false);
-    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_documentation(&self) -> bool {
-        (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
-    }
-
-    /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`).
-    ///
-    /// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`.
-    /// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`.
-    ///
-    /// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180
-    /// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false);
-    /// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true);
-    /// ```
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_benchmarking(&self) -> bool {
-        (self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0)
-    }
-
-    /// Returns [`true`] if the address is a globally routable unicast address.
-    ///
-    /// The following return false:
-    ///
-    /// - the loopback address
-    /// - the link-local addresses
-    /// - unique local addresses
-    /// - the unspecified address
-    /// - the address range reserved for documentation
-    ///
-    /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
-    ///
-    /// ```no_rust
-    /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
-    /// be supported in new implementations (i.e., new implementations must treat this prefix as
-    /// Global Unicast).
-    /// ```
-    ///
-    /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_unicast_global(), false);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_global(), true);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn is_unicast_global(&self) -> bool {
-        self.is_unicast()
-            && !self.is_loopback()
-            && !self.is_unicast_link_local()
-            && !self.is_unique_local()
-            && !self.is_unspecified()
-            && !self.is_documentation()
-            && !self.is_benchmarking()
-    }
-
-    /// Returns the address's multicast scope if the address is multicast.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    ///
-    /// use std::net::{Ipv6Addr, Ipv6MulticastScope};
-    ///
-    /// assert_eq!(
-    ///     Ipv6Addr::new(0xff0e, 0, 0, 0, 0, 0, 0, 0).multicast_scope(),
-    ///     Some(Ipv6MulticastScope::Global)
-    /// );
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).multicast_scope(), None);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use]
-    #[inline]
-    pub const fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
-        if self.is_multicast() {
-            match self.segments()[0] & 0x000f {
-                1 => Some(Ipv6MulticastScope::InterfaceLocal),
-                2 => Some(Ipv6MulticastScope::LinkLocal),
-                3 => Some(Ipv6MulticastScope::RealmLocal),
-                4 => Some(Ipv6MulticastScope::AdminLocal),
-                5 => Some(Ipv6MulticastScope::SiteLocal),
-                8 => Some(Ipv6MulticastScope::OrganizationLocal),
-                14 => Some(Ipv6MulticastScope::Global),
-                _ => None,
-            }
-        } else {
-            None
-        }
-    }
-
-    /// Returns [`true`] if this is a multicast address (`ff00::/8`).
-    ///
-    /// This property is defined by [IETF RFC 4291].
-    ///
-    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).is_multicast(), true);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_multicast(), false);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(since = "1.7.0", feature = "ip_17")]
-    #[must_use]
-    #[inline]
-    pub const fn is_multicast(&self) -> bool {
-        (self.segments()[0] & 0xff00) == 0xff00
-    }
-
-    /// Converts this address to an [`IPv4` address] if it's an [IPv4-mapped] address,
-    /// as defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
-    ///
-    /// `::ffff:a.b.c.d` becomes `a.b.c.d`.
-    /// All addresses *not* starting with `::ffff` will return `None`.
-    ///
-    /// [`IPv4` address]: Ipv4Addr
-    /// [IPv4-mapped]: Ipv6Addr
-    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
-    ///            Some(Ipv4Addr::new(192, 10, 2, 255)));
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[stable(feature = "ipv6_to_ipv4_mapped", since = "1.63.0")]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    #[inline]
-    pub const fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
-        match self.octets() {
-            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
-                Some(Ipv4Addr::new(a, b, c, d))
-            }
-            _ => None,
-        }
-    }
-
-    /// Converts this address to an [`IPv4` address] if it is either
-    /// an [IPv4-compatible] address as defined in [IETF RFC 4291 section 2.5.5.1],
-    /// or an [IPv4-mapped] address as defined in [IETF RFC 4291 section 2.5.5.2],
-    /// otherwise returns [`None`].
-    ///
-    /// Note that this will return an [`IPv4` address] for the IPv6 loopback address `::1`. Use
-    /// [`Ipv6Addr::to_ipv4_mapped`] to avoid this.
-    ///
-    /// `::a.b.c.d` and `::ffff:a.b.c.d` become `a.b.c.d`. `::1` becomes `0.0.0.1`.
-    /// All addresses *not* starting with either all zeroes or `::ffff` will return `None`.
-    ///
-    /// [`IPv4` address]: Ipv4Addr
-    /// [IPv4-compatible]: Ipv6Addr#ipv4-compatible-ipv6-addresses
-    /// [IPv4-mapped]: Ipv6Addr#ipv4-mapped-ipv6-addresses
-    /// [IETF RFC 4291 section 2.5.5.1]: https://tools.ietf.org/html/rfc4291#section-2.5.5.1
-    /// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{Ipv4Addr, Ipv6Addr};
-    ///
-    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4(), None);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4(),
-    ///            Some(Ipv4Addr::new(192, 10, 2, 255)));
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4(),
-    ///            Some(Ipv4Addr::new(0, 0, 0, 1)));
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_50", since = "1.50.0")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    #[inline]
-    pub const fn to_ipv4(&self) -> Option<Ipv4Addr> {
-        if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
-            let [a, b] = ab.to_be_bytes();
-            let [c, d] = cd.to_be_bytes();
-            Some(Ipv4Addr::new(a, b, c, d))
-        } else {
-            None
-        }
-    }
-
-    /// Converts this address to an `IpAddr::V4` if it is an IPv4-mapped addresses, otherwise it
-    /// returns self wrapped in an `IpAddr::V6`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(ip)]
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).to_canonical().is_loopback(), true);
-    /// ```
-    #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
-    #[unstable(feature = "ip", issue = "27709")]
-    #[must_use = "this returns the result of the operation, \
-                  without modifying the original"]
-    #[inline]
-    pub const fn to_canonical(&self) -> IpAddr {
-        if let Some(mapped) = self.to_ipv4_mapped() {
-            return IpAddr::V4(mapped);
-        }
-        IpAddr::V6(*self)
-    }
-
-    /// Returns the sixteen eight-bit integers the IPv6 address consists of.
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).octets(),
-    ///            [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
-    /// ```
-    #[rustc_const_stable(feature = "const_ip_32", since = "1.32.0")]
-    #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
-    #[must_use]
-    #[inline]
-    pub const fn octets(&self) -> [u8; 16] {
-        self.octets
-    }
-}
-
-/// Write an Ipv6Addr, conforming to the canonical style described by
-/// [RFC 5952](https://tools.ietf.org/html/rfc5952).
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for Ipv6Addr {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // If there are no alignment requirements, write the IP address directly to `f`.
-        // Otherwise, write it to a local buffer and then use `f.pad`.
-        if f.precision().is_none() && f.width().is_none() {
-            let segments = self.segments();
-
-            // Special case for :: and ::1; otherwise they get written with the
-            // IPv4 formatter
-            if self.is_unspecified() {
-                f.write_str("::")
-            } else if self.is_loopback() {
-                f.write_str("::1")
-            } else if let Some(ipv4) = self.to_ipv4() {
-                match segments[5] {
-                    // IPv4 Compatible address
-                    0 => write!(f, "::{}", ipv4),
-                    // IPv4 Mapped address
-                    0xffff => write!(f, "::ffff:{}", ipv4),
-                    _ => unreachable!(),
-                }
-            } else {
-                #[derive(Copy, Clone, Default)]
-                struct Span {
-                    start: usize,
-                    len: usize,
-                }
-
-                // Find the inner 0 span
-                let zeroes = {
-                    let mut longest = Span::default();
-                    let mut current = Span::default();
-
-                    for (i, &segment) in segments.iter().enumerate() {
-                        if segment == 0 {
-                            if current.len == 0 {
-                                current.start = i;
-                            }
-
-                            current.len += 1;
-
-                            if current.len > longest.len {
-                                longest = current;
-                            }
-                        } else {
-                            current = Span::default();
-                        }
-                    }
-
-                    longest
-                };
-
-                /// Write a colon-separated part of the address
-                #[inline]
-                fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
-                    if let Some((first, tail)) = chunk.split_first() {
-                        write!(f, "{:x}", first)?;
-                        for segment in tail {
-                            f.write_char(':')?;
-                            write!(f, "{:x}", segment)?;
-                        }
-                    }
-                    Ok(())
-                }
-
-                if zeroes.len > 1 {
-                    fmt_subslice(f, &segments[..zeroes.start])?;
-                    f.write_str("::")?;
-                    fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
-                } else {
-                    fmt_subslice(f, &segments)
-                }
-            }
-        } else {
-            const LONGEST_IPV6_ADDR: &str = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
-
-            let mut buf = DisplayBuffer::<{ LONGEST_IPV6_ADDR.len() }>::new();
-            // Buffer is long enough for the longest possible IPv6 address, so this should never fail.
-            write!(buf, "{}", self).unwrap();
-
-            f.pad(buf.as_str())
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Ipv6Addr {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self, fmt)
-    }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialEq<IpAddr> for Ipv6Addr {
-    #[inline]
-    fn eq(&self, other: &IpAddr) -> bool {
-        match other {
-            IpAddr::V4(_) => false,
-            IpAddr::V6(v6) => self == v6,
-        }
-    }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialEq<Ipv6Addr> for IpAddr {
-    #[inline]
-    fn eq(&self, other: &Ipv6Addr) -> bool {
-        match self {
-            IpAddr::V4(_) => false,
-            IpAddr::V6(v6) => v6 == other,
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialOrd for Ipv6Addr {
-    #[inline]
-    fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialOrd<Ipv6Addr> for IpAddr {
-    #[inline]
-    fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
-        match self {
-            IpAddr::V4(_) => Some(Ordering::Less),
-            IpAddr::V6(v6) => v6.partial_cmp(other),
-        }
-    }
-}
-
-#[stable(feature = "ip_cmp", since = "1.16.0")]
-impl PartialOrd<IpAddr> for Ipv6Addr {
-    #[inline]
-    fn partial_cmp(&self, other: &IpAddr) -> Option<Ordering> {
-        match other {
-            IpAddr::V4(_) => Some(Ordering::Greater),
-            IpAddr::V6(v6) => self.partial_cmp(v6),
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Ord for Ipv6Addr {
-    #[inline]
-    fn cmp(&self, other: &Ipv6Addr) -> Ordering {
-        self.segments().cmp(&other.segments())
+        Ipv4Addr::from(addr.s_addr.to_ne_bytes())
     }
 }
 
 impl IntoInner<c::in6_addr> for Ipv6Addr {
     fn into_inner(self) -> c::in6_addr {
-        c::in6_addr { s6_addr: self.octets }
+        c::in6_addr { s6_addr: self.octets() }
     }
 }
 impl FromInner<c::in6_addr> for Ipv6Addr {
     #[inline]
     fn from_inner(addr: c::in6_addr) -> Ipv6Addr {
-        Ipv6Addr { octets: addr.s6_addr }
-    }
-}
-
-#[stable(feature = "i128", since = "1.26.0")]
-impl From<Ipv6Addr> for u128 {
-    /// Convert an `Ipv6Addr` into a host byte order `u128`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// let addr = Ipv6Addr::new(
-    ///     0x1020, 0x3040, 0x5060, 0x7080,
-    ///     0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
-    /// );
-    /// assert_eq!(0x102030405060708090A0B0C0D0E0F00D_u128, u128::from(addr));
-    /// ```
-    #[inline]
-    fn from(ip: Ipv6Addr) -> u128 {
-        u128::from_be_bytes(ip.octets)
-    }
-}
-#[stable(feature = "i128", since = "1.26.0")]
-impl From<u128> for Ipv6Addr {
-    /// Convert a host byte order `u128` into an `Ipv6Addr`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// let addr = Ipv6Addr::from(0x102030405060708090A0B0C0D0E0F00D_u128);
-    /// assert_eq!(
-    ///     Ipv6Addr::new(
-    ///         0x1020, 0x3040, 0x5060, 0x7080,
-    ///         0x90A0, 0xB0C0, 0xD0E0, 0xF00D,
-    ///     ),
-    ///     addr);
-    /// ```
-    #[inline]
-    fn from(ip: u128) -> Ipv6Addr {
-        Ipv6Addr::from(ip.to_be_bytes())
-    }
-}
-
-#[stable(feature = "ipv6_from_octets", since = "1.9.0")]
-impl From<[u8; 16]> for Ipv6Addr {
-    /// Creates an `Ipv6Addr` from a sixteen element byte array.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// let addr = Ipv6Addr::from([
-    ///     25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
-    ///     17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
-    /// ]);
-    /// assert_eq!(
-    ///     Ipv6Addr::new(
-    ///         0x1918, 0x1716,
-    ///         0x1514, 0x1312,
-    ///         0x1110, 0x0f0e,
-    ///         0x0d0c, 0x0b0a
-    ///     ),
-    ///     addr
-    /// );
-    /// ```
-    #[inline]
-    fn from(octets: [u8; 16]) -> Ipv6Addr {
-        Ipv6Addr { octets }
-    }
-}
-
-#[stable(feature = "ipv6_from_segments", since = "1.16.0")]
-impl From<[u16; 8]> for Ipv6Addr {
-    /// Creates an `Ipv6Addr` from an eight element 16-bit array.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::Ipv6Addr;
-    ///
-    /// let addr = Ipv6Addr::from([
-    ///     525u16, 524u16, 523u16, 522u16,
-    ///     521u16, 520u16, 519u16, 518u16,
-    /// ]);
-    /// assert_eq!(
-    ///     Ipv6Addr::new(
-    ///         0x20d, 0x20c,
-    ///         0x20b, 0x20a,
-    ///         0x209, 0x208,
-    ///         0x207, 0x206
-    ///     ),
-    ///     addr
-    /// );
-    /// ```
-    #[inline]
-    fn from(segments: [u16; 8]) -> Ipv6Addr {
-        let [a, b, c, d, e, f, g, h] = segments;
-        Ipv6Addr::new(a, b, c, d, e, f, g, h)
-    }
-}
-
-#[stable(feature = "ip_from_slice", since = "1.17.0")]
-impl From<[u8; 16]> for IpAddr {
-    /// Creates an `IpAddr::V6` from a sixteen element byte array.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv6Addr};
-    ///
-    /// let addr = IpAddr::from([
-    ///     25u8, 24u8, 23u8, 22u8, 21u8, 20u8, 19u8, 18u8,
-    ///     17u8, 16u8, 15u8, 14u8, 13u8, 12u8, 11u8, 10u8,
-    /// ]);
-    /// assert_eq!(
-    ///     IpAddr::V6(Ipv6Addr::new(
-    ///         0x1918, 0x1716,
-    ///         0x1514, 0x1312,
-    ///         0x1110, 0x0f0e,
-    ///         0x0d0c, 0x0b0a
-    ///     )),
-    ///     addr
-    /// );
-    /// ```
-    #[inline]
-    fn from(octets: [u8; 16]) -> IpAddr {
-        IpAddr::V6(Ipv6Addr::from(octets))
-    }
-}
-
-#[stable(feature = "ip_from_slice", since = "1.17.0")]
-impl From<[u16; 8]> for IpAddr {
-    /// Creates an `IpAddr::V6` from an eight element 16-bit array.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv6Addr};
-    ///
-    /// let addr = IpAddr::from([
-    ///     525u16, 524u16, 523u16, 522u16,
-    ///     521u16, 520u16, 519u16, 518u16,
-    /// ]);
-    /// assert_eq!(
-    ///     IpAddr::V6(Ipv6Addr::new(
-    ///         0x20d, 0x20c,
-    ///         0x20b, 0x20a,
-    ///         0x209, 0x208,
-    ///         0x207, 0x206
-    ///     )),
-    ///     addr
-    /// );
-    /// ```
-    #[inline]
-    fn from(segments: [u16; 8]) -> IpAddr {
-        IpAddr::V6(Ipv6Addr::from(segments))
+        Ipv6Addr::from(addr.s6_addr)
     }
 }
diff --git a/library/std/src/net/ip_addr/tests.rs b/library/std/src/net/ip_addr/tests.rs
index 0eb59d45de7..ab99c0c2fcc 100644
--- a/library/std/src/net/ip_addr/tests.rs
+++ b/library/std/src/net/ip_addr/tests.rs
@@ -1,1039 +1,8 @@
-use crate::net::test::{sa4, sa6, tsa};
-use crate::net::*;
-use crate::str::FromStr;
-
-#[test]
-fn test_from_str_ipv4() {
-    assert_eq!(Ok(Ipv4Addr::new(127, 0, 0, 1)), "127.0.0.1".parse());
-    assert_eq!(Ok(Ipv4Addr::new(255, 255, 255, 255)), "255.255.255.255".parse());
-    assert_eq!(Ok(Ipv4Addr::new(0, 0, 0, 0)), "0.0.0.0".parse());
-
-    // out of range
-    let none: Option<Ipv4Addr> = "256.0.0.1".parse().ok();
-    assert_eq!(None, none);
-    // too short
-    let none: Option<Ipv4Addr> = "255.0.0".parse().ok();
-    assert_eq!(None, none);
-    // too long
-    let none: Option<Ipv4Addr> = "255.0.0.1.2".parse().ok();
-    assert_eq!(None, none);
-    // no number between dots
-    let none: Option<Ipv4Addr> = "255.0..1".parse().ok();
-    assert_eq!(None, none);
-    // octal
-    let none: Option<Ipv4Addr> = "255.0.0.01".parse().ok();
-    assert_eq!(None, none);
-    // octal zero
-    let none: Option<Ipv4Addr> = "255.0.0.00".parse().ok();
-    assert_eq!(None, none);
-    let none: Option<Ipv4Addr> = "255.0.00.0".parse().ok();
-    assert_eq!(None, none);
-}
-
-#[test]
-fn test_from_str_ipv6() {
-    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "0:0:0:0:0:0:0:0".parse());
-    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "0:0:0:0:0:0:0:1".parse());
-
-    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), "::1".parse());
-    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), "::".parse());
-
-    assert_eq!(Ok(Ipv6Addr::new(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)), "2a02:6b8::11:11".parse());
-
-    // too long group
-    let none: Option<Ipv6Addr> = "::00000".parse().ok();
-    assert_eq!(None, none);
-    // too short
-    let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7".parse().ok();
-    assert_eq!(None, none);
-    // too long
-    let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:8:9".parse().ok();
-    assert_eq!(None, none);
-    // triple colon
-    let none: Option<Ipv6Addr> = "1:2:::6:7:8".parse().ok();
-    assert_eq!(None, none);
-    // two double colons
-    let none: Option<Ipv6Addr> = "1:2::6::8".parse().ok();
-    assert_eq!(None, none);
-    // `::` indicating zero groups of zeros
-    let none: Option<Ipv6Addr> = "1:2:3:4::5:6:7:8".parse().ok();
-    assert_eq!(None, none);
-}
-
-#[test]
-fn test_from_str_ipv4_in_ipv6() {
-    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 49152, 545)), "::192.0.2.33".parse());
-    assert_eq!(Ok(Ipv6Addr::new(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)), "::FFFF:192.0.2.33".parse());
-    assert_eq!(
-        Ok(Ipv6Addr::new(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
-        "64:ff9b::192.0.2.33".parse()
-    );
-    assert_eq!(
-        Ok(Ipv6Addr::new(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
-        "2001:db8:122:c000:2:2100:192.0.2.33".parse()
-    );
-
-    // colon after v4
-    let none: Option<Ipv4Addr> = "::127.0.0.1:".parse().ok();
-    assert_eq!(None, none);
-    // not enough groups
-    let none: Option<Ipv6Addr> = "1:2:3:4:5:127.0.0.1".parse().ok();
-    assert_eq!(None, none);
-    // too many groups
-    let none: Option<Ipv6Addr> = "1:2:3:4:5:6:7:127.0.0.1".parse().ok();
-    assert_eq!(None, none);
-}
-
-#[test]
-fn test_from_str_socket_addr() {
-    assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
-    assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)), "77.88.21.11:80".parse());
-    assert_eq!(
-        Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
-        "[2a02:6b8:0:1::1]:53".parse()
-    );
-    assert_eq!(
-        Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53, 0, 0)),
-        "[2a02:6b8:0:1::1]:53".parse()
-    );
-    assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)), "[::127.0.0.1]:22".parse());
-    assert_eq!(
-        Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22, 0, 0)),
-        "[::127.0.0.1]:22".parse()
-    );
-
-    // without port
-    let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
-    assert_eq!(None, none);
-    // without port
-    let none: Option<SocketAddr> = "127.0.0.1:".parse().ok();
-    assert_eq!(None, none);
-    // wrong brackets around v4
-    let none: Option<SocketAddr> = "[127.0.0.1]:22".parse().ok();
-    assert_eq!(None, none);
-    // port out of range
-    let none: Option<SocketAddr> = "127.0.0.1:123456".parse().ok();
-    assert_eq!(None, none);
-}
-
-#[test]
-fn ipv4_addr_to_string() {
-    assert_eq!(Ipv4Addr::new(127, 0, 0, 1).to_string(), "127.0.0.1");
-    // Short address
-    assert_eq!(Ipv4Addr::new(1, 1, 1, 1).to_string(), "1.1.1.1");
-    // Long address
-    assert_eq!(Ipv4Addr::new(127, 127, 127, 127).to_string(), "127.127.127.127");
-
-    // Test padding
-    assert_eq!(format!("{:16}", Ipv4Addr::new(1, 1, 1, 1)), "1.1.1.1         ");
-    assert_eq!(format!("{:>16}", Ipv4Addr::new(1, 1, 1, 1)), "         1.1.1.1");
-}
-
-#[test]
-fn ipv6_addr_to_string() {
-    // ipv4-mapped address
-    let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
-    assert_eq!(a1.to_string(), "::ffff:192.0.2.128");
-
-    // ipv4-compatible address
-    let a1 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0xc000, 0x280);
-    assert_eq!(a1.to_string(), "::192.0.2.128");
-
-    // v6 address with no zero segments
-    assert_eq!(Ipv6Addr::new(8, 9, 10, 11, 12, 13, 14, 15).to_string(), "8:9:a:b:c:d:e:f");
-
-    // longest possible IPv6 length
-    assert_eq!(
-        Ipv6Addr::new(0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888).to_string(),
-        "1111:2222:3333:4444:5555:6666:7777:8888"
-    );
-    // padding
-    assert_eq!(format!("{:20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "1:2:3:4:5:6:7:8     ");
-    assert_eq!(format!("{:>20}", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8)), "     1:2:3:4:5:6:7:8");
-
-    // reduce a single run of zeros
-    assert_eq!(
-        "ae::ffff:102:304",
-        Ipv6Addr::new(0xae, 0, 0, 0, 0, 0xffff, 0x0102, 0x0304).to_string()
-    );
-
-    // don't reduce just a single zero segment
-    assert_eq!("1:2:3:4:5:6:0:8", Ipv6Addr::new(1, 2, 3, 4, 5, 6, 0, 8).to_string());
-
-    // 'any' address
-    assert_eq!("::", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0).to_string());
-
-    // loopback address
-    assert_eq!("::1", Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_string());
-
-    // ends in zeros
-    assert_eq!("1::", Ipv6Addr::new(1, 0, 0, 0, 0, 0, 0, 0).to_string());
-
-    // two runs of zeros, second one is longer
-    assert_eq!("1:0:0:4::8", Ipv6Addr::new(1, 0, 0, 4, 0, 0, 0, 8).to_string());
-
-    // two runs of zeros, equal length
-    assert_eq!("1::4:5:0:0:8", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8).to_string());
-
-    // don't prefix `0x` to each segment in `dbg!`.
-    assert_eq!("1::4:5:0:0:8", &format!("{:#?}", Ipv6Addr::new(1, 0, 0, 4, 5, 0, 0, 8)));
-}
-
-#[test]
-fn ipv4_to_ipv6() {
-    assert_eq!(
-        Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678),
-        Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_mapped()
-    );
-    assert_eq!(
-        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678),
-        Ipv4Addr::new(0x12, 0x34, 0x56, 0x78).to_ipv6_compatible()
-    );
-}
-
-#[test]
-fn ipv6_to_ipv4_mapped() {
-    assert_eq!(
-        Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
-        Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
-    );
-    assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
-}
-
-#[test]
-fn ipv6_to_ipv4() {
-    assert_eq!(
-        Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4(),
-        Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
-    );
-    assert_eq!(
-        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4(),
-        Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
-    );
-    assert_eq!(Ipv6Addr::new(0, 0, 1, 0, 0, 0, 0x1234, 0x5678).to_ipv4(), None);
-}
-
-#[test]
-fn ip_properties() {
-    macro_rules! ip {
-        ($s:expr) => {
-            IpAddr::from_str($s).unwrap()
-        };
-    }
-
-    macro_rules! check {
-        ($s:expr) => {
-            check!($s, 0);
-        };
-
-        ($s:expr, $mask:expr) => {{
-            let unspec: u8 = 1 << 0;
-            let loopback: u8 = 1 << 1;
-            let global: u8 = 1 << 2;
-            let multicast: u8 = 1 << 3;
-            let doc: u8 = 1 << 4;
-            let benchmarking: u8 = 1 << 5;
-
-            if ($mask & unspec) == unspec {
-                assert!(ip!($s).is_unspecified());
-            } else {
-                assert!(!ip!($s).is_unspecified());
-            }
-
-            if ($mask & loopback) == loopback {
-                assert!(ip!($s).is_loopback());
-            } else {
-                assert!(!ip!($s).is_loopback());
-            }
-
-            if ($mask & global) == global {
-                assert!(ip!($s).is_global());
-            } else {
-                assert!(!ip!($s).is_global());
-            }
-
-            if ($mask & multicast) == multicast {
-                assert!(ip!($s).is_multicast());
-            } else {
-                assert!(!ip!($s).is_multicast());
-            }
-
-            if ($mask & doc) == doc {
-                assert!(ip!($s).is_documentation());
-            } else {
-                assert!(!ip!($s).is_documentation());
-            }
-
-            if ($mask & benchmarking) == benchmarking {
-                assert!(ip!($s).is_benchmarking());
-            } else {
-                assert!(!ip!($s).is_benchmarking());
-            }
-        }};
-    }
-
-    let unspec: u8 = 1 << 0;
-    let loopback: u8 = 1 << 1;
-    let global: u8 = 1 << 2;
-    let multicast: u8 = 1 << 3;
-    let doc: u8 = 1 << 4;
-    let benchmarking: u8 = 1 << 5;
-
-    check!("0.0.0.0", unspec);
-    check!("0.0.0.1");
-    check!("0.1.0.0");
-    check!("10.9.8.7");
-    check!("127.1.2.3", loopback);
-    check!("172.31.254.253");
-    check!("169.254.253.242");
-    check!("192.0.2.183", doc);
-    check!("192.1.2.183", global);
-    check!("192.168.254.253");
-    check!("198.51.100.0", doc);
-    check!("203.0.113.0", doc);
-    check!("203.2.113.0", global);
-    check!("224.0.0.0", global | multicast);
-    check!("239.255.255.255", global | multicast);
-    check!("255.255.255.255");
-    // make sure benchmarking addresses are not global
-    check!("198.18.0.0", benchmarking);
-    check!("198.18.54.2", benchmarking);
-    check!("198.19.255.255", benchmarking);
-    // make sure addresses reserved for protocol assignment are not global
-    check!("192.0.0.0");
-    check!("192.0.0.255");
-    check!("192.0.0.100");
-    // make sure reserved addresses are not global
-    check!("240.0.0.0");
-    check!("251.54.1.76");
-    check!("254.255.255.255");
-    // make sure shared addresses are not global
-    check!("100.64.0.0");
-    check!("100.127.255.255");
-    check!("100.100.100.0");
-
-    check!("::", unspec);
-    check!("::1", loopback);
-    check!("::0.0.0.2", global);
-    check!("1::", global);
-    check!("fc00::");
-    check!("fdff:ffff::");
-    check!("fe80:ffff::");
-    check!("febf:ffff::");
-    check!("fec0::", global);
-    check!("ff01::", global | multicast);
-    check!("ff02::", global | multicast);
-    check!("ff03::", global | multicast);
-    check!("ff04::", global | multicast);
-    check!("ff05::", global | multicast);
-    check!("ff08::", global | multicast);
-    check!("ff0e::", global | multicast);
-    check!("2001:db8:85a3::8a2e:370:7334", doc);
-    check!("2001:2::ac32:23ff:21", benchmarking);
-    check!("102:304:506:708:90a:b0c:d0e:f10", global);
-}
-
-#[test]
-fn ipv4_properties() {
-    macro_rules! ip {
-        ($s:expr) => {
-            Ipv4Addr::from_str($s).unwrap()
-        };
-    }
-
-    macro_rules! check {
-        ($s:expr) => {
-            check!($s, 0);
-        };
-
-        ($s:expr, $mask:expr) => {{
-            let unspec: u16 = 1 << 0;
-            let loopback: u16 = 1 << 1;
-            let private: u16 = 1 << 2;
-            let link_local: u16 = 1 << 3;
-            let global: u16 = 1 << 4;
-            let multicast: u16 = 1 << 5;
-            let broadcast: u16 = 1 << 6;
-            let documentation: u16 = 1 << 7;
-            let benchmarking: u16 = 1 << 8;
-            let reserved: u16 = 1 << 10;
-            let shared: u16 = 1 << 11;
-
-            if ($mask & unspec) == unspec {
-                assert!(ip!($s).is_unspecified());
-            } else {
-                assert!(!ip!($s).is_unspecified());
-            }
-
-            if ($mask & loopback) == loopback {
-                assert!(ip!($s).is_loopback());
-            } else {
-                assert!(!ip!($s).is_loopback());
-            }
-
-            if ($mask & private) == private {
-                assert!(ip!($s).is_private());
-            } else {
-                assert!(!ip!($s).is_private());
-            }
-
-            if ($mask & link_local) == link_local {
-                assert!(ip!($s).is_link_local());
-            } else {
-                assert!(!ip!($s).is_link_local());
-            }
-
-            if ($mask & global) == global {
-                assert!(ip!($s).is_global());
-            } else {
-                assert!(!ip!($s).is_global());
-            }
-
-            if ($mask & multicast) == multicast {
-                assert!(ip!($s).is_multicast());
-            } else {
-                assert!(!ip!($s).is_multicast());
-            }
-
-            if ($mask & broadcast) == broadcast {
-                assert!(ip!($s).is_broadcast());
-            } else {
-                assert!(!ip!($s).is_broadcast());
-            }
-
-            if ($mask & documentation) == documentation {
-                assert!(ip!($s).is_documentation());
-            } else {
-                assert!(!ip!($s).is_documentation());
-            }
-
-            if ($mask & benchmarking) == benchmarking {
-                assert!(ip!($s).is_benchmarking());
-            } else {
-                assert!(!ip!($s).is_benchmarking());
-            }
-
-            if ($mask & reserved) == reserved {
-                assert!(ip!($s).is_reserved());
-            } else {
-                assert!(!ip!($s).is_reserved());
-            }
-
-            if ($mask & shared) == shared {
-                assert!(ip!($s).is_shared());
-            } else {
-                assert!(!ip!($s).is_shared());
-            }
-        }};
-    }
-
-    let unspec: u16 = 1 << 0;
-    let loopback: u16 = 1 << 1;
-    let private: u16 = 1 << 2;
-    let link_local: u16 = 1 << 3;
-    let global: u16 = 1 << 4;
-    let multicast: u16 = 1 << 5;
-    let broadcast: u16 = 1 << 6;
-    let documentation: u16 = 1 << 7;
-    let benchmarking: u16 = 1 << 8;
-    let reserved: u16 = 1 << 10;
-    let shared: u16 = 1 << 11;
-
-    check!("0.0.0.0", unspec);
-    check!("0.0.0.1");
-    check!("0.1.0.0");
-    check!("10.9.8.7", private);
-    check!("127.1.2.3", loopback);
-    check!("172.31.254.253", private);
-    check!("169.254.253.242", link_local);
-    check!("192.0.2.183", documentation);
-    check!("192.1.2.183", global);
-    check!("192.168.254.253", private);
-    check!("198.51.100.0", documentation);
-    check!("203.0.113.0", documentation);
-    check!("203.2.113.0", global);
-    check!("224.0.0.0", global | multicast);
-    check!("239.255.255.255", global | multicast);
-    check!("255.255.255.255", broadcast);
-    check!("198.18.0.0", benchmarking);
-    check!("198.18.54.2", benchmarking);
-    check!("198.19.255.255", benchmarking);
-    check!("192.0.0.0");
-    check!("192.0.0.255");
-    check!("192.0.0.100");
-    check!("240.0.0.0", reserved);
-    check!("251.54.1.76", reserved);
-    check!("254.255.255.255", reserved);
-    check!("100.64.0.0", shared);
-    check!("100.127.255.255", shared);
-    check!("100.100.100.0", shared);
-}
-
-#[test]
-fn ipv6_properties() {
-    macro_rules! ip {
-        ($s:expr) => {
-            Ipv6Addr::from_str($s).unwrap()
-        };
-    }
-
-    macro_rules! check {
-        ($s:expr, &[$($octet:expr),*], $mask:expr) => {
-            assert_eq!($s, ip!($s).to_string());
-            let octets = &[$($octet),*];
-            assert_eq!(&ip!($s).octets(), octets);
-            assert_eq!(Ipv6Addr::from(*octets), ip!($s));
-
-            let unspecified: u32 = 1 << 0;
-            let loopback: u32 = 1 << 1;
-            let unique_local: u32 = 1 << 2;
-            let global: u32 = 1 << 3;
-            let unicast_link_local: u32 = 1 << 4;
-            let unicast_global: u32 = 1 << 7;
-            let documentation: u32 = 1 << 8;
-            let benchmarking: u32 = 1 << 16;
-            let multicast_interface_local: u32 = 1 << 9;
-            let multicast_link_local: u32 = 1 << 10;
-            let multicast_realm_local: u32 = 1 << 11;
-            let multicast_admin_local: u32 = 1 << 12;
-            let multicast_site_local: u32 = 1 << 13;
-            let multicast_organization_local: u32 = 1 << 14;
-            let multicast_global: u32 = 1 << 15;
-            let multicast: u32 = multicast_interface_local
-                | multicast_admin_local
-                | multicast_global
-                | multicast_link_local
-                | multicast_realm_local
-                | multicast_site_local
-                | multicast_organization_local;
-
-            if ($mask & unspecified) == unspecified {
-                assert!(ip!($s).is_unspecified());
-            } else {
-                assert!(!ip!($s).is_unspecified());
-            }
-            if ($mask & loopback) == loopback {
-                assert!(ip!($s).is_loopback());
-            } else {
-                assert!(!ip!($s).is_loopback());
-            }
-            if ($mask & unique_local) == unique_local {
-                assert!(ip!($s).is_unique_local());
-            } else {
-                assert!(!ip!($s).is_unique_local());
-            }
-            if ($mask & global) == global {
-                assert!(ip!($s).is_global());
-            } else {
-                assert!(!ip!($s).is_global());
-            }
-            if ($mask & unicast_link_local) == unicast_link_local {
-                assert!(ip!($s).is_unicast_link_local());
-            } else {
-                assert!(!ip!($s).is_unicast_link_local());
-            }
-            if ($mask & unicast_global) == unicast_global {
-                assert!(ip!($s).is_unicast_global());
-            } else {
-                assert!(!ip!($s).is_unicast_global());
-            }
-            if ($mask & documentation) == documentation {
-                assert!(ip!($s).is_documentation());
-            } else {
-                assert!(!ip!($s).is_documentation());
-            }
-            if ($mask & benchmarking) == benchmarking {
-                assert!(ip!($s).is_benchmarking());
-            } else {
-                assert!(!ip!($s).is_benchmarking());
-            }
-            if ($mask & multicast) != 0 {
-                assert!(ip!($s).multicast_scope().is_some());
-                assert!(ip!($s).is_multicast());
-            } else {
-                assert!(ip!($s).multicast_scope().is_none());
-                assert!(!ip!($s).is_multicast());
-            }
-            if ($mask & multicast_interface_local) == multicast_interface_local {
-                assert_eq!(ip!($s).multicast_scope().unwrap(),
-                           Ipv6MulticastScope::InterfaceLocal);
-            }
-            if ($mask & multicast_link_local) == multicast_link_local {
-                assert_eq!(ip!($s).multicast_scope().unwrap(),
-                           Ipv6MulticastScope::LinkLocal);
-            }
-            if ($mask & multicast_realm_local) == multicast_realm_local {
-                assert_eq!(ip!($s).multicast_scope().unwrap(),
-                           Ipv6MulticastScope::RealmLocal);
-            }
-            if ($mask & multicast_admin_local) == multicast_admin_local {
-                assert_eq!(ip!($s).multicast_scope().unwrap(),
-                           Ipv6MulticastScope::AdminLocal);
-            }
-            if ($mask & multicast_site_local) == multicast_site_local {
-                assert_eq!(ip!($s).multicast_scope().unwrap(),
-                           Ipv6MulticastScope::SiteLocal);
-            }
-            if ($mask & multicast_organization_local) == multicast_organization_local {
-                assert_eq!(ip!($s).multicast_scope().unwrap(),
-                           Ipv6MulticastScope::OrganizationLocal);
-            }
-            if ($mask & multicast_global) == multicast_global {
-                assert_eq!(ip!($s).multicast_scope().unwrap(),
-                           Ipv6MulticastScope::Global);
-            }
-        }
-    }
-
-    let unspecified: u32 = 1 << 0;
-    let loopback: u32 = 1 << 1;
-    let unique_local: u32 = 1 << 2;
-    let global: u32 = 1 << 3;
-    let unicast_link_local: u32 = 1 << 4;
-    let unicast_global: u32 = 1 << 7;
-    let documentation: u32 = 1 << 8;
-    let benchmarking: u32 = 1 << 16;
-    let multicast_interface_local: u32 = 1 << 9;
-    let multicast_link_local: u32 = 1 << 10;
-    let multicast_realm_local: u32 = 1 << 11;
-    let multicast_admin_local: u32 = 1 << 12;
-    let multicast_site_local: u32 = 1 << 13;
-    let multicast_organization_local: u32 = 1 << 14;
-    let multicast_global: u32 = 1 << 15;
-
-    check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified);
-
-    check!("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], loopback);
-
-    check!("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2], global | unicast_global);
-
-    check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
-
-    check!(
-        "::ffff:127.0.0.1",
-        &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1],
-        unicast_global
-    );
-
-    check!(
-        "64:ff9b:1::",
-        &[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        unicast_global
-    );
-
-    check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
-
-    check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
-
-    check!(
-        "2001:1::1",
-        &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
-        global | unicast_global
-    );
-
-    check!(
-        "2001:1::2",
-        &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
-        global | unicast_global
-    );
-
-    check!(
-        "2001:3::",
-        &[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        global | unicast_global
-    );
-
-    check!(
-        "2001:4:112::",
-        &[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        global | unicast_global
-    );
-
-    check!(
-        "2001:20::",
-        &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        global | unicast_global
-    );
-
-    check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
-
-    check!(
-        "2001:200::",
-        &[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        global | unicast_global
-    );
-
-    check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
-
-    check!(
-        "fdff:ffff::",
-        &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        unique_local
-    );
-
-    check!(
-        "fe80:ffff::",
-        &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        unicast_link_local
-    );
-
-    check!("fe80::", &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local);
-
-    check!(
-        "febf:ffff::",
-        &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        unicast_link_local
-    );
-
-    check!("febf::", &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_link_local);
-
-    check!(
-        "febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
-        &[
-            0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-            0xff, 0xff
-        ],
-        unicast_link_local
-    );
-
-    check!(
-        "fe80::ffff:ffff:ffff:ffff",
-        &[
-            0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-            0xff, 0xff
-        ],
-        unicast_link_local
-    );
-
-    check!(
-        "fe80:0:0:1::",
-        &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
-        unicast_link_local
-    );
-
-    check!(
-        "fec0::",
-        &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        unicast_global | global
-    );
-
-    check!(
-        "ff01::",
-        &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_interface_local | global
-    );
-
-    check!(
-        "ff02::",
-        &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_link_local | global
-    );
-
-    check!(
-        "ff03::",
-        &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_realm_local | global
-    );
-
-    check!(
-        "ff04::",
-        &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_admin_local | global
-    );
-
-    check!(
-        "ff05::",
-        &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_site_local | global
-    );
-
-    check!(
-        "ff08::",
-        &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_organization_local | global
-    );
-
-    check!(
-        "ff0e::",
-        &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_global | global
-    );
-
-    check!(
-        "2001:db8:85a3::8a2e:370:7334",
-        &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
-        documentation
-    );
-
-    check!(
-        "2001:2::ac32:23ff:21",
-        &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
-        benchmarking
-    );
-
-    check!(
-        "102:304:506:708:90a:b0c:d0e:f10",
-        &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
-        global | unicast_global
-    );
-}
+use crate::net::test::{sa4, tsa};
+use crate::net::Ipv4Addr;
 
 #[test]
 fn to_socket_addr_socketaddr() {
     let a = sa4(Ipv4Addr::new(77, 88, 21, 11), 12345);
     assert_eq!(Ok(vec![a]), tsa(a));
 }
-
-#[test]
-fn test_ipv4_to_int() {
-    let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
-    assert_eq!(u32::from(a), 0x11223344);
-}
-
-#[test]
-fn test_int_to_ipv4() {
-    let a = Ipv4Addr::new(0x11, 0x22, 0x33, 0x44);
-    assert_eq!(Ipv4Addr::from(0x11223344), a);
-}
-
-#[test]
-fn test_ipv6_to_int() {
-    let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
-    assert_eq!(u128::from(a), 0x112233445566778899aabbccddeeff11u128);
-}
-
-#[test]
-fn test_int_to_ipv6() {
-    let a = Ipv6Addr::new(0x1122, 0x3344, 0x5566, 0x7788, 0x99aa, 0xbbcc, 0xddee, 0xff11);
-    assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
-}
-
-#[test]
-fn ipv4_from_constructors() {
-    assert_eq!(Ipv4Addr::LOCALHOST, Ipv4Addr::new(127, 0, 0, 1));
-    assert!(Ipv4Addr::LOCALHOST.is_loopback());
-    assert_eq!(Ipv4Addr::UNSPECIFIED, Ipv4Addr::new(0, 0, 0, 0));
-    assert!(Ipv4Addr::UNSPECIFIED.is_unspecified());
-    assert_eq!(Ipv4Addr::BROADCAST, Ipv4Addr::new(255, 255, 255, 255));
-    assert!(Ipv4Addr::BROADCAST.is_broadcast());
-}
-
-#[test]
-fn ipv6_from_constructors() {
-    assert_eq!(Ipv6Addr::LOCALHOST, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
-    assert!(Ipv6Addr::LOCALHOST.is_loopback());
-    assert_eq!(Ipv6Addr::UNSPECIFIED, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
-    assert!(Ipv6Addr::UNSPECIFIED.is_unspecified());
-}
-
-#[test]
-fn ipv4_from_octets() {
-    assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
-}
-
-#[test]
-fn ipv6_from_segments() {
-    let from_u16s =
-        Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
-    let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff);
-    assert_eq!(new, from_u16s);
-}
-
-#[test]
-fn ipv6_from_octets() {
-    let from_u16s =
-        Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677, 0x8899, 0xaabb, 0xccdd, 0xeeff]);
-    let from_u8s = Ipv6Addr::from([
-        0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff,
-    ]);
-    assert_eq!(from_u16s, from_u8s);
-}
-
-#[test]
-fn cmp() {
-    let v41 = Ipv4Addr::new(100, 64, 3, 3);
-    let v42 = Ipv4Addr::new(192, 0, 2, 2);
-    let v61 = "2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap();
-    let v62 = "2001:db8:f00::2001".parse::<Ipv6Addr>().unwrap();
-    assert!(v41 < v42);
-    assert!(v61 < v62);
-
-    assert_eq!(v41, IpAddr::V4(v41));
-    assert_eq!(v61, IpAddr::V6(v61));
-    assert!(v41 != IpAddr::V4(v42));
-    assert!(v61 != IpAddr::V6(v62));
-
-    assert!(v41 < IpAddr::V4(v42));
-    assert!(v61 < IpAddr::V6(v62));
-    assert!(IpAddr::V4(v41) < v42);
-    assert!(IpAddr::V6(v61) < v62);
-
-    assert!(v41 < IpAddr::V6(v61));
-    assert!(IpAddr::V4(v41) < v61);
-}
-
-#[test]
-fn is_v4() {
-    let ip = IpAddr::V4(Ipv4Addr::new(100, 64, 3, 3));
-    assert!(ip.is_ipv4());
-    assert!(!ip.is_ipv6());
-}
-
-#[test]
-fn is_v6() {
-    let ip = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678));
-    assert!(!ip.is_ipv4());
-    assert!(ip.is_ipv6());
-}
-
-#[test]
-fn ipv4_const() {
-    // test that the methods of `Ipv4Addr` are usable in a const context
-
-    const IP_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);
-    assert_eq!(IP_ADDRESS, Ipv4Addr::LOCALHOST);
-
-    const OCTETS: [u8; 4] = IP_ADDRESS.octets();
-    assert_eq!(OCTETS, [127, 0, 0, 1]);
-
-    const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
-    assert!(!IS_UNSPECIFIED);
-
-    const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
-    assert!(IS_LOOPBACK);
-
-    const IS_PRIVATE: bool = IP_ADDRESS.is_private();
-    assert!(!IS_PRIVATE);
-
-    const IS_LINK_LOCAL: bool = IP_ADDRESS.is_link_local();
-    assert!(!IS_LINK_LOCAL);
-
-    const IS_GLOBAL: bool = IP_ADDRESS.is_global();
-    assert!(!IS_GLOBAL);
-
-    const IS_SHARED: bool = IP_ADDRESS.is_shared();
-    assert!(!IS_SHARED);
-
-    const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking();
-    assert!(!IS_BENCHMARKING);
-
-    const IS_RESERVED: bool = IP_ADDRESS.is_reserved();
-    assert!(!IS_RESERVED);
-
-    const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
-    assert!(!IS_MULTICAST);
-
-    const IS_BROADCAST: bool = IP_ADDRESS.is_broadcast();
-    assert!(!IS_BROADCAST);
-
-    const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
-    assert!(!IS_DOCUMENTATION);
-
-    const IP_V6_COMPATIBLE: Ipv6Addr = IP_ADDRESS.to_ipv6_compatible();
-    assert_eq!(
-        IP_V6_COMPATIBLE,
-        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 1])
-    );
-
-    const IP_V6_MAPPED: Ipv6Addr = IP_ADDRESS.to_ipv6_mapped();
-    assert_eq!(
-        IP_V6_MAPPED,
-        Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1])
-    );
-}
-
-#[test]
-fn ipv6_const() {
-    // test that the methods of `Ipv6Addr` are usable in a const context
-
-    const IP_ADDRESS: Ipv6Addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
-    assert_eq!(IP_ADDRESS, Ipv6Addr::LOCALHOST);
-
-    const SEGMENTS: [u16; 8] = IP_ADDRESS.segments();
-    assert_eq!(SEGMENTS, [0, 0, 0, 0, 0, 0, 0, 1]);
-
-    const OCTETS: [u8; 16] = IP_ADDRESS.octets();
-    assert_eq!(OCTETS, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
-
-    const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
-    assert!(!IS_UNSPECIFIED);
-
-    const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
-    assert!(IS_LOOPBACK);
-
-    const IS_GLOBAL: bool = IP_ADDRESS.is_global();
-    assert!(!IS_GLOBAL);
-
-    const IS_UNIQUE_LOCAL: bool = IP_ADDRESS.is_unique_local();
-    assert!(!IS_UNIQUE_LOCAL);
-
-    const IS_UNICAST_LINK_LOCAL: bool = IP_ADDRESS.is_unicast_link_local();
-    assert!(!IS_UNICAST_LINK_LOCAL);
-
-    const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
-    assert!(!IS_DOCUMENTATION);
-
-    const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking();
-    assert!(!IS_BENCHMARKING);
-
-    const IS_UNICAST_GLOBAL: bool = IP_ADDRESS.is_unicast_global();
-    assert!(!IS_UNICAST_GLOBAL);
-
-    const MULTICAST_SCOPE: Option<Ipv6MulticastScope> = IP_ADDRESS.multicast_scope();
-    assert_eq!(MULTICAST_SCOPE, None);
-
-    const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
-    assert!(!IS_MULTICAST);
-
-    const IP_V4: Option<Ipv4Addr> = IP_ADDRESS.to_ipv4();
-    assert_eq!(IP_V4.unwrap(), Ipv4Addr::new(0, 0, 0, 1));
-}
-
-#[test]
-fn ip_const() {
-    // test that the methods of `IpAddr` are usable in a const context
-
-    const IP_ADDRESS: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
-
-    const IS_UNSPECIFIED: bool = IP_ADDRESS.is_unspecified();
-    assert!(!IS_UNSPECIFIED);
-
-    const IS_LOOPBACK: bool = IP_ADDRESS.is_loopback();
-    assert!(IS_LOOPBACK);
-
-    const IS_GLOBAL: bool = IP_ADDRESS.is_global();
-    assert!(!IS_GLOBAL);
-
-    const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
-    assert!(!IS_MULTICAST);
-
-    const IS_IP_V4: bool = IP_ADDRESS.is_ipv4();
-    assert!(IS_IP_V4);
-
-    const IS_IP_V6: bool = IP_ADDRESS.is_ipv6();
-    assert!(!IS_IP_V6);
-}
-
-#[test]
-fn structural_match() {
-    // test that all IP types can be structurally matched upon
-
-    const IPV4: Ipv4Addr = Ipv4Addr::LOCALHOST;
-    match IPV4 {
-        Ipv4Addr::LOCALHOST => {}
-        _ => unreachable!(),
-    }
-
-    const IPV6: Ipv6Addr = Ipv6Addr::LOCALHOST;
-    match IPV6 {
-        Ipv6Addr::LOCALHOST => {}
-        _ => unreachable!(),
-    }
-
-    const IP: IpAddr = IpAddr::V4(Ipv4Addr::LOCALHOST);
-    match IP {
-        IpAddr::V4(Ipv4Addr::LOCALHOST) => {}
-        _ => unreachable!(),
-    }
-}
diff --git a/library/std/src/net/mod.rs b/library/std/src/net/mod.rs
index 19d90e7ec38..bcab15db35b 100644
--- a/library/std/src/net/mod.rs
+++ b/library/std/src/net/mod.rs
@@ -26,8 +26,6 @@ use crate::io::{self, ErrorKind};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::ip_addr::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::parser::AddrParseError;
-#[stable(feature = "rust1", since = "1.0.0")]
 pub use self::socket_addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
 #[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
 pub use self::tcp::IntoIncoming;
@@ -35,10 +33,10 @@ pub use self::tcp::IntoIncoming;
 pub use self::tcp::{Incoming, TcpListener, TcpStream};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::udp::UdpSocket;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::net::AddrParseError;
 
-mod display_buffer;
 mod ip_addr;
-mod parser;
 mod socket_addr;
 mod tcp;
 #[cfg(test)]
diff --git a/library/std/src/net/socket_addr.rs b/library/std/src/net/socket_addr.rs
index 1264bae809b..421fed9077c 100644
--- a/library/std/src/net/socket_addr.rs
+++ b/library/std/src/net/socket_addr.rs
@@ -1,9 +1,7 @@
+// Tests for this module
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
-use crate::cmp::Ordering;
-use crate::fmt::{self, Write};
-use crate::hash;
 use crate::io;
 use crate::iter;
 use crate::mem;
@@ -15,533 +13,23 @@ use crate::sys_common::net::LookupHost;
 use crate::sys_common::{FromInner, IntoInner};
 use crate::vec;
 
-use super::display_buffer::DisplayBuffer;
-
-/// An internet socket address, either IPv4 or IPv6.
-///
-/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
-/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
-/// [`SocketAddrV6`]'s respective documentation for more details.
-///
-/// The size of a `SocketAddr` instance may vary depending on the target operating
-/// system.
-///
-/// [IP address]: IpAddr
-///
-/// # Examples
-///
-/// ```
-/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-///
-/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-///
-/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
-/// assert_eq!(socket.port(), 8080);
-/// assert_eq!(socket.is_ipv4(), true);
-/// ```
-#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub enum SocketAddr {
-    /// An IPv4 socket address.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
-    /// An IPv6 socket address.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
-}
-
-/// An IPv4 socket address.
-///
-/// IPv4 socket addresses consist of an [`IPv4` address] and a 16-bit port number, as
-/// stated in [IETF RFC 793].
-///
-/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
-///
-/// The size of a `SocketAddrV4` struct may vary depending on the target operating
-/// system. Do not assume that this type has the same memory layout as the underlying
-/// system representation.
-///
-/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
-/// [`IPv4` address]: Ipv4Addr
-///
-/// # Examples
-///
-/// ```
-/// use std::net::{Ipv4Addr, SocketAddrV4};
-///
-/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
-///
-/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
-/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
-/// assert_eq!(socket.port(), 8080);
-/// ```
-#[derive(Copy, Clone, Eq, PartialEq)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct SocketAddrV4 {
-    ip: Ipv4Addr,
-    port: u16,
-}
-
-/// An IPv6 socket address.
-///
-/// IPv6 socket addresses consist of an [`IPv6` address], a 16-bit port number, as well
-/// as fields containing the traffic class, the flow label, and a scope identifier
-/// (see [IETF RFC 2553, Section 3.3] for more details).
-///
-/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
-///
-/// The size of a `SocketAddrV6` struct may vary depending on the target operating
-/// system. Do not assume that this type has the same memory layout as the underlying
-/// system representation.
-///
-/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
-/// [`IPv6` address]: Ipv6Addr
-///
-/// # Examples
-///
-/// ```
-/// use std::net::{Ipv6Addr, SocketAddrV6};
-///
-/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
-///
-/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket));
-/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
-/// assert_eq!(socket.port(), 8080);
-/// ```
-#[derive(Copy, Clone, Eq, PartialEq)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct SocketAddrV6 {
-    ip: Ipv6Addr,
-    port: u16,
-    flowinfo: u32,
-    scope_id: u32,
-}
-
-impl SocketAddr {
-    /// Creates a new socket address from an [IP address] and a port number.
-    ///
-    /// [IP address]: IpAddr
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-    ///
-    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
-    /// assert_eq!(socket.port(), 8080);
-    /// ```
-    #[stable(feature = "ip_addr", since = "1.7.0")]
-    #[must_use]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn new(ip: IpAddr, port: u16) -> SocketAddr {
-        match ip {
-            IpAddr::V4(a) => SocketAddr::V4(SocketAddrV4::new(a, port)),
-            IpAddr::V6(a) => SocketAddr::V6(SocketAddrV6::new(a, port, 0, 0)),
-        }
-    }
-
-    /// Returns the IP address associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-    ///
-    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
-    /// ```
-    #[must_use]
-    #[stable(feature = "ip_addr", since = "1.7.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn ip(&self) -> IpAddr {
-        match *self {
-            SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
-            SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
-        }
-    }
-
-    /// Changes the IP address associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-    ///
-    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-    /// socket.set_ip(IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
-    /// assert_eq!(socket.ip(), IpAddr::V4(Ipv4Addr::new(10, 10, 0, 1)));
-    /// ```
-    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    pub fn set_ip(&mut self, new_ip: IpAddr) {
-        // `match (*self, new_ip)` would have us mutate a copy of self only to throw it away.
-        match (self, new_ip) {
-            (&mut SocketAddr::V4(ref mut a), IpAddr::V4(new_ip)) => a.set_ip(new_ip),
-            (&mut SocketAddr::V6(ref mut a), IpAddr::V6(new_ip)) => a.set_ip(new_ip),
-            (self_, new_ip) => *self_ = Self::new(new_ip, self_.port()),
-        }
-    }
-
-    /// Returns the port number associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-    ///
-    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-    /// assert_eq!(socket.port(), 8080);
-    /// ```
-    #[must_use]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn port(&self) -> u16 {
-        match *self {
-            SocketAddr::V4(ref a) => a.port(),
-            SocketAddr::V6(ref a) => a.port(),
-        }
-    }
-
-    /// Changes the port number associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-    ///
-    /// let mut socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-    /// socket.set_port(1025);
-    /// assert_eq!(socket.port(), 1025);
-    /// ```
-    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    pub fn set_port(&mut self, new_port: u16) {
-        match *self {
-            SocketAddr::V4(ref mut a) => a.set_port(new_port),
-            SocketAddr::V6(ref mut a) => a.set_port(new_port),
-        }
-    }
-
-    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
-    /// [`IPv4` address], and [`false`] otherwise.
-    ///
-    /// [IP address]: IpAddr
-    /// [`IPv4` address]: IpAddr::V4
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
-    ///
-    /// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
-    /// assert_eq!(socket.is_ipv4(), true);
-    /// assert_eq!(socket.is_ipv6(), false);
-    /// ```
-    #[must_use]
-    #[stable(feature = "sockaddr_checker", since = "1.16.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn is_ipv4(&self) -> bool {
-        matches!(*self, SocketAddr::V4(_))
-    }
-
-    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
-    /// [`IPv6` address], and [`false`] otherwise.
-    ///
-    /// [IP address]: IpAddr
-    /// [`IPv6` address]: IpAddr::V6
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{IpAddr, Ipv6Addr, SocketAddr};
-    ///
-    /// let socket = SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 65535, 0, 1)), 8080);
-    /// assert_eq!(socket.is_ipv4(), false);
-    /// assert_eq!(socket.is_ipv6(), true);
-    /// ```
-    #[must_use]
-    #[stable(feature = "sockaddr_checker", since = "1.16.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn is_ipv6(&self) -> bool {
-        matches!(*self, SocketAddr::V6(_))
-    }
-}
-
-impl SocketAddrV4 {
-    /// Creates a new socket address from an [`IPv4` address] and a port number.
-    ///
-    /// [`IPv4` address]: Ipv4Addr
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV4, Ipv4Addr};
-    ///
-    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[must_use]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
-        SocketAddrV4 { ip, port }
-    }
-
-    /// Returns the IP address associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV4, Ipv4Addr};
-    ///
-    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
-    /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
-    /// ```
-    #[must_use]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn ip(&self) -> &Ipv4Addr {
-        &self.ip
-    }
-
-    /// Changes the IP address associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV4, Ipv4Addr};
-    ///
-    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
-    /// socket.set_ip(Ipv4Addr::new(192, 168, 0, 1));
-    /// assert_eq!(socket.ip(), &Ipv4Addr::new(192, 168, 0, 1));
-    /// ```
-    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    pub fn set_ip(&mut self, new_ip: Ipv4Addr) {
-        self.ip = new_ip;
-    }
-
-    /// Returns the port number associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV4, Ipv4Addr};
-    ///
-    /// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
-    /// assert_eq!(socket.port(), 8080);
-    /// ```
-    #[must_use]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn port(&self) -> u16 {
-        self.port
-    }
-
-    /// Changes the port number associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV4, Ipv4Addr};
-    ///
-    /// let mut socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
-    /// socket.set_port(4242);
-    /// assert_eq!(socket.port(), 4242);
-    /// ```
-    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    pub fn set_port(&mut self, new_port: u16) {
-        self.port = new_port;
-    }
-}
-
-impl SocketAddrV6 {
-    /// Creates a new socket address from an [`IPv6` address], a 16-bit port number,
-    /// and the `flowinfo` and `scope_id` fields.
-    ///
-    /// For more information on the meaning and layout of the `flowinfo` and `scope_id`
-    /// parameters, see [IETF RFC 2553, Section 3.3].
-    ///
-    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
-    /// [`IPv6` address]: Ipv6Addr
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV6, Ipv6Addr};
-    ///
-    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[must_use]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32) -> SocketAddrV6 {
-        SocketAddrV6 { ip, port, flowinfo, scope_id }
-    }
-
-    /// Returns the IP address associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV6, Ipv6Addr};
-    ///
-    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
-    /// assert_eq!(socket.ip(), &Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
-    /// ```
-    #[must_use]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn ip(&self) -> &Ipv6Addr {
-        &self.ip
-    }
-
-    /// Changes the IP address associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV6, Ipv6Addr};
-    ///
-    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
-    /// socket.set_ip(Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
-    /// assert_eq!(socket.ip(), &Ipv6Addr::new(76, 45, 0, 0, 0, 0, 0, 0));
-    /// ```
-    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    pub fn set_ip(&mut self, new_ip: Ipv6Addr) {
-        self.ip = new_ip;
-    }
-
-    /// Returns the port number associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV6, Ipv6Addr};
-    ///
-    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
-    /// assert_eq!(socket.port(), 8080);
-    /// ```
-    #[must_use]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn port(&self) -> u16 {
-        self.port
-    }
-
-    /// Changes the port number associated with this socket address.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV6, Ipv6Addr};
-    ///
-    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
-    /// socket.set_port(4242);
-    /// assert_eq!(socket.port(), 4242);
-    /// ```
-    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    pub fn set_port(&mut self, new_port: u16) {
-        self.port = new_port;
-    }
-
-    /// Returns the flow information associated with this address.
-    ///
-    /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`,
-    /// as specified in [IETF RFC 2553, Section 3.3].
-    /// It combines information about the flow label and the traffic class as specified
-    /// in [IETF RFC 2460], respectively [Section 6] and [Section 7].
-    ///
-    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
-    /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460
-    /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6
-    /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV6, Ipv6Addr};
-    ///
-    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
-    /// assert_eq!(socket.flowinfo(), 10);
-    /// ```
-    #[must_use]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn flowinfo(&self) -> u32 {
-        self.flowinfo
-    }
-
-    /// Changes the flow information associated with this socket address.
-    ///
-    /// See [`SocketAddrV6::flowinfo`]'s documentation for more details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV6, Ipv6Addr};
-    ///
-    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 10, 0);
-    /// socket.set_flowinfo(56);
-    /// assert_eq!(socket.flowinfo(), 56);
-    /// ```
-    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
-        self.flowinfo = new_flowinfo;
-    }
-
-    /// Returns the scope ID associated with this address.
-    ///
-    /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`,
-    /// as specified in [IETF RFC 2553, Section 3.3].
-    ///
-    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV6, Ipv6Addr};
-    ///
-    /// let socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
-    /// assert_eq!(socket.scope_id(), 78);
-    /// ```
-    #[must_use]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_socketaddr", since = "CURRENT_RUSTC_VERSION")]
-    pub const fn scope_id(&self) -> u32 {
-        self.scope_id
-    }
-
-    /// Changes the scope ID associated with this socket address.
-    ///
-    /// See [`SocketAddrV6::scope_id`]'s documentation for more details.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::net::{SocketAddrV6, Ipv6Addr};
-    ///
-    /// let mut socket = SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 8080, 0, 78);
-    /// socket.set_scope_id(42);
-    /// assert_eq!(socket.scope_id(), 42);
-    /// ```
-    #[stable(feature = "sockaddr_setters", since = "1.9.0")]
-    pub fn set_scope_id(&mut self, new_scope_id: u32) {
-        self.scope_id = new_scope_id;
-    }
-}
+pub use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
 
 impl FromInner<c::sockaddr_in> for SocketAddrV4 {
     fn from_inner(addr: c::sockaddr_in) -> SocketAddrV4 {
-        SocketAddrV4 { ip: Ipv4Addr::from_inner(addr.sin_addr), port: u16::from_be(addr.sin_port) }
+        SocketAddrV4::new(Ipv4Addr::from_inner(addr.sin_addr), u16::from_be(addr.sin_port))
     }
 }
 
 impl FromInner<c::sockaddr_in6> for SocketAddrV6 {
     fn from_inner(addr: c::sockaddr_in6) -> SocketAddrV6 {
-        SocketAddrV6 {
-            ip: Ipv6Addr::from_inner(addr.sin6_addr),
-            port: u16::from_be(addr.sin6_port),
-            flowinfo: addr.sin6_flowinfo,
-            scope_id: addr.sin6_scope_id,
-        }
+        SocketAddrV6::new(
+            Ipv6Addr::from_inner(addr.sin6_addr),
+            u16::from_be(addr.sin6_port),
+            addr.sin6_flowinfo,
+            addr.sin6_scope_id,
+        )
     }
 }
 
@@ -549,8 +37,8 @@ impl IntoInner<c::sockaddr_in> for SocketAddrV4 {
     fn into_inner(self) -> c::sockaddr_in {
         c::sockaddr_in {
             sin_family: c::AF_INET as c::sa_family_t,
-            sin_port: self.port.to_be(),
-            sin_addr: self.ip.into_inner(),
+            sin_port: self.port().to_be(),
+            sin_addr: self.ip().into_inner(),
             ..unsafe { mem::zeroed() }
         }
     }
@@ -560,162 +48,15 @@ impl IntoInner<c::sockaddr_in6> for SocketAddrV6 {
     fn into_inner(self) -> c::sockaddr_in6 {
         c::sockaddr_in6 {
             sin6_family: c::AF_INET6 as c::sa_family_t,
-            sin6_port: self.port.to_be(),
-            sin6_addr: self.ip.into_inner(),
-            sin6_flowinfo: self.flowinfo,
-            sin6_scope_id: self.scope_id,
+            sin6_port: self.port().to_be(),
+            sin6_addr: self.ip().into_inner(),
+            sin6_flowinfo: self.flowinfo(),
+            sin6_scope_id: self.scope_id(),
             ..unsafe { mem::zeroed() }
         }
     }
 }
 
-#[stable(feature = "ip_from_ip", since = "1.16.0")]
-impl From<SocketAddrV4> for SocketAddr {
-    /// Converts a [`SocketAddrV4`] into a [`SocketAddr::V4`].
-    fn from(sock4: SocketAddrV4) -> SocketAddr {
-        SocketAddr::V4(sock4)
-    }
-}
-
-#[stable(feature = "ip_from_ip", since = "1.16.0")]
-impl From<SocketAddrV6> for SocketAddr {
-    /// Converts a [`SocketAddrV6`] into a [`SocketAddr::V6`].
-    fn from(sock6: SocketAddrV6) -> SocketAddr {
-        SocketAddr::V6(sock6)
-    }
-}
-
-#[stable(feature = "addr_from_into_ip", since = "1.17.0")]
-impl<I: Into<IpAddr>> From<(I, u16)> for SocketAddr {
-    /// Converts a tuple struct (Into<[`IpAddr`]>, `u16`) into a [`SocketAddr`].
-    ///
-    /// This conversion creates a [`SocketAddr::V4`] for an [`IpAddr::V4`]
-    /// and creates a [`SocketAddr::V6`] for an [`IpAddr::V6`].
-    ///
-    /// `u16` is treated as port of the newly created [`SocketAddr`].
-    fn from(pieces: (I, u16)) -> SocketAddr {
-        SocketAddr::new(pieces.0.into(), pieces.1)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for SocketAddr {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            SocketAddr::V4(ref a) => a.fmt(f),
-            SocketAddr::V6(ref a) => a.fmt(f),
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for SocketAddr {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self, fmt)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for SocketAddrV4 {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // If there are no alignment requirements, write the socket address directly to `f`.
-        // Otherwise, write it to a local buffer and then use `f.pad`.
-        if f.precision().is_none() && f.width().is_none() {
-            write!(f, "{}:{}", self.ip(), self.port())
-        } else {
-            const LONGEST_IPV4_SOCKET_ADDR: &str = "255.255.255.255:65536";
-
-            let mut buf = DisplayBuffer::<{ LONGEST_IPV4_SOCKET_ADDR.len() }>::new();
-            // Buffer is long enough for the longest possible IPv4 socket address, so this should never fail.
-            write!(buf, "{}:{}", self.ip(), self.port()).unwrap();
-
-            f.pad(buf.as_str())
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for SocketAddrV4 {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self, fmt)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for SocketAddrV6 {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // If there are no alignment requirements, write the socket address directly to `f`.
-        // Otherwise, write it to a local buffer and then use `f.pad`.
-        if f.precision().is_none() && f.width().is_none() {
-            match self.scope_id() {
-                0 => write!(f, "[{}]:{}", self.ip(), self.port()),
-                scope_id => write!(f, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
-            }
-        } else {
-            const LONGEST_IPV6_SOCKET_ADDR: &str =
-                "[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%4294967296]:65536";
-
-            let mut buf = DisplayBuffer::<{ LONGEST_IPV6_SOCKET_ADDR.len() }>::new();
-            match self.scope_id() {
-                0 => write!(buf, "[{}]:{}", self.ip(), self.port()),
-                scope_id => write!(buf, "[{}%{}]:{}", self.ip(), scope_id, self.port()),
-            }
-            // Buffer is long enough for the longest possible IPv6 socket address, so this should never fail.
-            .unwrap();
-
-            f.pad(buf.as_str())
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for SocketAddrV6 {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self, fmt)
-    }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialOrd for SocketAddrV4 {
-    fn partial_cmp(&self, other: &SocketAddrV4) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialOrd for SocketAddrV6 {
-    fn partial_cmp(&self, other: &SocketAddrV6) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl Ord for SocketAddrV4 {
-    fn cmp(&self, other: &SocketAddrV4) -> Ordering {
-        self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
-    }
-}
-
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl Ord for SocketAddrV6 {
-    fn cmp(&self, other: &SocketAddrV6) -> Ordering {
-        self.ip().cmp(other.ip()).then(self.port().cmp(&other.port()))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl hash::Hash for SocketAddrV4 {
-    fn hash<H: hash::Hasher>(&self, s: &mut H) {
-        (self.port, self.ip).hash(s)
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl hash::Hash for SocketAddrV6 {
-    fn hash<H: hash::Hasher>(&self, s: &mut H) {
-        (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s)
-    }
-}
-
 /// A trait for objects which can be converted or resolved to one or more
 /// [`SocketAddr`] values.
 ///
diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
index 8c0adcfb0eb..e019bc0b67a 100644
--- a/library/std/src/net/tcp/tests.rs
+++ b/library/std/src/net/tcp/tests.rs
@@ -670,7 +670,10 @@ fn debug() {
 // FIXME: re-enabled openbsd tests once their socket timeout code
 //        no longer has rounding errors.
 // VxWorks ignores SO_SNDTIMEO.
-#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"),
+    ignore
+)]
 #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
 #[test]
 fn timeouts() {
diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs
index f82904ffbbf..892fe2ba8ba 100644
--- a/library/std/src/net/udp/tests.rs
+++ b/library/std/src/net/udp/tests.rs
@@ -180,7 +180,10 @@ fn debug() {
 // FIXME: re-enabled openbsd/netbsd tests once their socket timeout code
 //        no longer has rounding errors.
 // VxWorks ignores SO_SNDTIMEO.
-#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
+#[cfg_attr(
+    any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"),
+    ignore
+)]
 #[test]
 fn timeouts() {
     let addr = next_test_ip4();
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index af137c9bd85..b148d8a0091 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -127,6 +127,8 @@ pub mod l4re;
 pub mod macos;
 #[cfg(target_os = "netbsd")]
 pub mod netbsd;
+#[cfg(target_os = "nto")]
+pub mod nto;
 #[cfg(target_os = "openbsd")]
 pub mod openbsd;
 #[cfg(target_os = "redox")]
diff --git a/library/std/src/os/nto/fs.rs b/library/std/src/os/nto/fs.rs
new file mode 100644
index 00000000000..8f915b08c9e
--- /dev/null
+++ b/library/std/src/os/nto/fs.rs
@@ -0,0 +1,92 @@
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_dev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ino(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mode(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_nlink(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_uid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_gid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_rdev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_size(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blksize(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blocks(&self) -> u64;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+    fn st_dev(&self) -> u64 {
+        self.as_inner().as_inner().st_dev as u64
+    }
+    fn st_ino(&self) -> u64 {
+        self.as_inner().as_inner().st_ino as u64
+    }
+    fn st_mode(&self) -> u32 {
+        self.as_inner().as_inner().st_mode as u32
+    }
+    fn st_nlink(&self) -> u64 {
+        self.as_inner().as_inner().st_nlink as u64
+    }
+    fn st_uid(&self) -> u32 {
+        self.as_inner().as_inner().st_uid as u32
+    }
+    fn st_gid(&self) -> u32 {
+        self.as_inner().as_inner().st_gid as u32
+    }
+    fn st_rdev(&self) -> u64 {
+        self.as_inner().as_inner().st_rdev as u64
+    }
+    fn st_size(&self) -> u64 {
+        self.as_inner().as_inner().st_size as u64
+    }
+    fn st_atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atim.tv_sec as i64
+    }
+    fn st_atime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_atim.tv_nsec as i64
+    }
+    fn st_mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtim.tv_sec as i64
+    }
+    fn st_mtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_mtim.tv_nsec as i64
+    }
+    fn st_ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctim.tv_sec as i64
+    }
+    fn st_ctime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_ctim.tv_nsec as i64
+    }
+    fn st_blksize(&self) -> u64 {
+        self.as_inner().as_inner().st_blksize as u64
+    }
+    fn st_blocks(&self) -> u64 {
+        self.as_inner().as_inner().st_blocks as u64
+    }
+}
diff --git a/library/std/src/os/nto/mod.rs b/library/std/src/os/nto/mod.rs
new file mode 100644
index 00000000000..3e591dace92
--- /dev/null
+++ b/library/std/src/os/nto/mod.rs
@@ -0,0 +1,4 @@
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod fs;
+pub(super) mod raw;
diff --git a/library/std/src/os/nto/raw.rs b/library/std/src/os/nto/raw.rs
new file mode 100644
index 00000000000..90e9ad54643
--- /dev/null
+++ b/library/std/src/os/nto/raw.rs
@@ -0,0 +1,40 @@
+#![stable(feature = "raw_ext", since = "1.1.0")]
+#![deprecated(
+    since = "1.8.0",
+    note = "these type aliases are no longer supported by \
+            the standard library, the `libc` crate on \
+            crates.io should be used instead for the correct \
+            definitions"
+)]
+#![allow(deprecated)]
+
+use crate::os::raw::c_int;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type dev_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type mode_t = u32;
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = c_int;
+
+#[doc(inline)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, time_t};
+
+mod arch {
+    use crate::os::raw::c_long;
+
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type blkcnt_t = i64;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type blksize_t = i32;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type ino_t = u64;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type nlink_t = u32;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type off_t = i64;
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub type time_t = c_long;
+}
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index 3fc6cc44ce4..a0e664acd13 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -17,6 +17,10 @@ use crate::sealed::Sealed;
 #[allow(unused_imports)]
 use io::{Read, Write};
 
+// Tests for this module
+#[cfg(test)]
+mod tests;
+
 /// Unix-specific extensions to [`fs::File`].
 #[stable(feature = "file_offset", since = "1.15.0")]
 pub trait FileExt {
@@ -54,6 +58,16 @@ pub trait FileExt {
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
 
+    /// Like `read_at`, except that it reads into a slice of buffers.
+    ///
+    /// Data is copied to fill each buffer in order, with the final buffer
+    /// written to possibly being only partially filled. This method must behave
+    /// equivalently to a single call to read with concatenated buffers.
+    #[unstable(feature = "unix_file_vectored_at", issue = "89517")]
+    fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        io::default_read_vectored(|b| self.read_at(b, offset), bufs)
+    }
+
     /// Reads the exact number of byte required to fill `buf` from the given offset.
     ///
     /// The offset is relative to the start of the file and thus independent
@@ -155,6 +169,16 @@ pub trait FileExt {
     #[stable(feature = "file_offset", since = "1.15.0")]
     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
 
+    /// Like `write_at`, except that it writes from a slice of buffers.
+    ///
+    /// Data is copied from each buffer in order, with the final buffer read
+    /// from possibly being only partially consumed. This method must behave as
+    /// a call to `write_at` with the buffers concatenated would.
+    #[unstable(feature = "unix_file_vectored_at", issue = "89517")]
+    fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        io::default_write_vectored(|b| self.write_at(b, offset), bufs)
+    }
+
     /// Attempts to write an entire buffer starting from a given offset.
     ///
     /// The offset is relative to the start of the file and thus independent
@@ -218,9 +242,15 @@ impl FileExt for fs::File {
     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         self.as_inner().read_at(buf, offset)
     }
+    fn read_vectored_at(&self, bufs: &mut [io::IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        self.as_inner().read_vectored_at(bufs, offset)
+    }
     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         self.as_inner().write_at(buf, offset)
     }
+    fn write_vectored_at(&self, bufs: &[io::IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        self.as_inner().write_vectored_at(bufs, offset)
+    }
 }
 
 /// Unix-specific extensions to [`fs::Permissions`].
diff --git a/library/std/src/os/unix/fs/tests.rs b/library/std/src/os/unix/fs/tests.rs
new file mode 100644
index 00000000000..67f607bd468
--- /dev/null
+++ b/library/std/src/os/unix/fs/tests.rs
@@ -0,0 +1,57 @@
+use super::*;
+
+#[test]
+fn read_vectored_at() {
+    let msg = b"preadv is working!";
+    let dir = crate::sys_common::io::test::tmpdir();
+
+    let filename = dir.join("preadv.txt");
+    {
+        let mut file = fs::File::create(&filename).unwrap();
+        file.write_all(msg).unwrap();
+    }
+    {
+        let file = fs::File::open(&filename).unwrap();
+        let mut buf0 = [0; 4];
+        let mut buf1 = [0; 3];
+
+        let mut iovec = [io::IoSliceMut::new(&mut buf0), io::IoSliceMut::new(&mut buf1)];
+
+        let n = file.read_vectored_at(&mut iovec, 4).unwrap();
+
+        assert!(n == 4 || n == 7);
+        assert_eq!(&buf0, b"dv i");
+
+        if n == 7 {
+            assert_eq!(&buf1, b"s w");
+        }
+    }
+}
+
+#[test]
+fn write_vectored_at() {
+    let msg = b"pwritev is not working!";
+    let dir = crate::sys_common::io::test::tmpdir();
+
+    let filename = dir.join("preadv.txt");
+    {
+        let mut file = fs::File::create(&filename).unwrap();
+        file.write_all(msg).unwrap();
+    }
+    let expected = {
+        let file = fs::File::options().write(true).open(&filename).unwrap();
+        let buf0 = b"    ";
+        let buf1 = b"great  ";
+
+        let iovec = [io::IoSlice::new(buf0), io::IoSlice::new(buf1)];
+
+        let n = file.write_vectored_at(&iovec, 11).unwrap();
+
+        assert!(n == 4 || n == 11);
+
+        if n == 4 { b"pwritev is     working!" } else { b"pwritev is     great  !" }
+    };
+
+    let content = fs::read(&filename).unwrap();
+    assert_eq!(&content, expected);
+}
diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs
index f97fa0fb06f..eb2d7ce1174 100644
--- a/library/std/src/os/unix/mod.rs
+++ b/library/std/src/os/unix/mod.rs
@@ -65,6 +65,8 @@ mod platform {
     pub use crate::os::macos::*;
     #[cfg(target_os = "netbsd")]
     pub use crate::os::netbsd::*;
+    #[cfg(target_os = "nto")]
+    pub use crate::os::nto::*;
     #[cfg(target_os = "openbsd")]
     pub use crate::os::openbsd::*;
     #[cfg(target_os = "redox")]
@@ -95,7 +97,8 @@ pub mod thread;
     target_os = "watchos",
     target_os = "macos",
     target_os = "netbsd",
-    target_os = "openbsd"
+    target_os = "openbsd",
+    target_os = "nto",
 ))]
 pub mod ucred;
 
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index f758f88d0a3..272b4f5dcd5 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -19,7 +19,8 @@ use crate::{fmt, io};
     target_os = "freebsd",
     target_os = "openbsd",
     target_os = "netbsd",
-    target_os = "haiku"
+    target_os = "haiku",
+    target_os = "nto",
 ))]
 use libc::MSG_NOSIGNAL;
 #[cfg(not(any(
@@ -29,7 +30,8 @@ use libc::MSG_NOSIGNAL;
     target_os = "freebsd",
     target_os = "openbsd",
     target_os = "netbsd",
-    target_os = "haiku"
+    target_os = "haiku",
+    target_os = "nto",
 )))]
 const MSG_NOSIGNAL: libc::c_int = 0x0;
 
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index 37fcfa8446b..f8c29a6d3a1 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -167,6 +167,7 @@ fn long_path() {
 }
 
 #[test]
+#[cfg(not(target_os = "nto"))]
 fn timeouts() {
     let dir = tmpdir();
     let socket_path = dir.path().join("sock");
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 09b2bfe39f0..729c63d184f 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -12,15 +12,23 @@ use crate::sealed::Sealed;
 use crate::sys;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
-#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
-type UserId = u32;
-#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
-type GroupId = u32;
-
-#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))]
-type UserId = u16;
-#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))]
-type GroupId = u16;
+use cfg_if::cfg_if;
+
+cfg_if! {
+    if #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] {
+        type UserId = u16;
+        type GroupId = u16;
+    } else if #[cfg(target_os = "nto")] {
+        // Both IDs are signed, see `sys/target_nto.h` of the QNX Neutrino SDP.
+        // Only positive values should be used, see e.g.
+        // https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/s/setuid.html
+        type UserId = i32;
+        type GroupId = i32;
+    } else {
+        type UserId = u32;
+        type GroupId = u32;
+    }
+}
 
 /// Unix-specific extensions to the [`process::Command`] builder.
 ///
diff --git a/library/std/src/os/unix/ucred.rs b/library/std/src/os/unix/ucred.rs
index ae4faf27b4d..95967eac295 100644
--- a/library/std/src/os/unix/ucred.rs
+++ b/library/std/src/os/unix/ucred.rs
@@ -79,7 +79,8 @@ pub mod impl_linux {
     target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "openbsd",
-    target_os = "netbsd"
+    target_os = "netbsd",
+    target_os = "nto",
 ))]
 pub mod impl_bsd {
     use super::UCred;
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index d6e9da187e8..6f78811a186 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -587,8 +587,10 @@ mod prim_pointer {}
 /// There are two syntactic forms for creating an array:
 ///
 /// * A list with each element, i.e., `[x, y, z]`.
-/// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`.
-///   The type of `x` must be [`Copy`].
+/// * A repeat expression `[expr; N]` where `N` is how many times to repeat `expr` in the array. `expr` must either be:
+///
+///   * A value of a type implementing the [`Copy`] trait
+///   * A `const` value
 ///
 /// Note that `[expr; 0]` is allowed, and produces an empty array.
 /// This will still evaluate `expr`, however, and immediately drop the resulting value, so
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 62ce2cb33dc..1952e19e607 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1416,7 +1416,7 @@ impl From<fs::File> for Stdio {
     /// use std::fs::File;
     /// use std::process::Command;
     ///
-    /// // With the `foo.txt` file containing `Hello, world!"
+    /// // With the `foo.txt` file containing "Hello, world!"
     /// let file = File::open("foo.txt").unwrap();
     ///
     /// let reverse = Command::new("rev")
diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs
index 19350b83fab..ae0f718535b 100644
--- a/library/std/src/sys/itron/thread.rs
+++ b/library/std/src/sys/itron/thread.rs
@@ -247,7 +247,7 @@ impl Thread {
                 // [FINISHED → JOINED]
                 // To synchronize with the child task's memory accesses to
                 // `inner` up to the point of the assignment of `FINISHED`,
-                // `Ordering::Acquire` must be used for the above `swap` call`.
+                // `Ordering::Acquire` must be used for the above `swap` call.
             }
             _ => unsafe { hint::unreachable_unchecked() },
         }
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index a5ce6d5120d..3d79058b320 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -69,7 +69,8 @@ impl DoubleEndedIterator for Args {
     target_os = "fuchsia",
     target_os = "redox",
     target_os = "vxworks",
-    target_os = "horizon"
+    target_os = "horizon",
+    target_os = "nto",
 ))]
 mod imp {
     use super::Args;
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index c9ba661c829..1a9276f1110 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -185,6 +185,17 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "";
 }
 
+#[cfg(target_os = "nto")]
+pub mod os {
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "nto";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
+}
+
 #[cfg(target_os = "redox")]
 pub mod os {
     pub const FAMILY: &str = "unix";
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index 66c33d58d6c..9874af4d3e2 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -53,7 +53,12 @@ const fn max_iov() -> usize {
     libc::IOV_MAX as usize
 }
 
-#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
+#[cfg(any(
+    target_os = "android",
+    target_os = "emscripten",
+    target_os = "linux",
+    target_os = "nto",
+))]
 const fn max_iov() -> usize {
     libc::UIO_MAXIOV as usize
 }
@@ -67,6 +72,7 @@ const fn max_iov() -> usize {
     target_os = "linux",
     target_os = "macos",
     target_os = "netbsd",
+    target_os = "nto",
     target_os = "openbsd",
     target_os = "horizon",
     target_os = "watchos",
@@ -92,7 +98,7 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::readv(
                 self.as_raw_fd(),
-                bufs.as_ptr() as *const libc::iovec,
+                bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
                 cmp::min(bufs.len(), max_iov()) as libc::c_int,
             )
         })?;
@@ -101,7 +107,7 @@ impl FileDesc {
 
     #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        return crate::io::default_read_vectored(|b| self.read(b), bufs);
+        io::default_read_vectored(|b| self.read(b), bufs)
     }
 
     #[inline]
@@ -147,6 +153,95 @@ impl FileDesc {
         Ok(())
     }
 
+    #[cfg(any(
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "illumos",
+        target_os = "linux",
+        target_os = "netbsd",
+    ))]
+    pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::preadv(
+                self.as_raw_fd(),
+                bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
+                cmp::min(bufs.len(), max_iov()) as libc::c_int,
+                offset as _,
+            )
+        })?;
+        Ok(ret as usize)
+    }
+
+    #[cfg(not(any(
+        target_os = "android",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "illumos",
+        target_os = "ios",
+        target_os = "linux",
+        target_os = "macos",
+        target_os = "netbsd",
+    )))]
+    pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        io::default_read_vectored(|b| self.read_at(b, offset), bufs)
+    }
+
+    // We support some old Android versions that do not have `preadv` in libc,
+    // so we use weak linkage and fallback to a direct syscall if not available.
+    //
+    // On 32-bit targets, we don't want to deal with weird ABI issues around
+    // passing 64-bits parameters to syscalls, so we fallback to the default
+    // implementation if `preadv` is not available.
+    #[cfg(all(target_os = "android", target_pointer_width = "64"))]
+    pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        super::weak::syscall! {
+            fn preadv(
+                fd: libc::c_int,
+                iovec: *const libc::iovec,
+                n_iovec: libc::c_int,
+                offset: off64_t
+            ) -> isize
+        }
+
+        let ret = cvt(unsafe {
+            preadv(
+                self.as_raw_fd(),
+                bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
+                cmp::min(bufs.len(), max_iov()) as libc::c_int,
+                offset as _,
+            )
+        })?;
+        Ok(ret as usize)
+    }
+
+    // We support old MacOS and iOS versions that do not have `preadv`. There is
+    // no `syscall` possible in these platform.
+    #[cfg(any(
+        all(target_os = "android", target_pointer_width = "32"),
+        target_os = "ios",
+        target_os = "macos",
+    ))]
+    pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+
+        match preadv64.get() {
+            Some(preadv) => {
+                let ret = cvt(unsafe {
+                    preadv(
+                        self.as_raw_fd(),
+                        bufs.as_mut_ptr() as *mut libc::iovec as *const libc::iovec,
+                        cmp::min(bufs.len(), max_iov()) as libc::c_int,
+                        offset as _,
+                    )
+                })?;
+                Ok(ret as usize)
+            }
+            None => io::default_read_vectored(|b| self.read_at(b, offset), bufs),
+        }
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::write(
@@ -172,7 +267,7 @@ impl FileDesc {
 
     #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        return crate::io::default_write_vectored(|b| self.write(b), bufs);
+        io::default_write_vectored(|b| self.write(b), bufs)
     }
 
     #[inline]
@@ -197,6 +292,95 @@ impl FileDesc {
         }
     }
 
+    #[cfg(any(
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "illumos",
+        target_os = "linux",
+        target_os = "netbsd",
+    ))]
+    pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        let ret = cvt(unsafe {
+            libc::pwritev(
+                self.as_raw_fd(),
+                bufs.as_ptr() as *const libc::iovec,
+                cmp::min(bufs.len(), max_iov()) as libc::c_int,
+                offset as _,
+            )
+        })?;
+        Ok(ret as usize)
+    }
+
+    #[cfg(not(any(
+        target_os = "android",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "fuchsia",
+        target_os = "illumos",
+        target_os = "ios",
+        target_os = "linux",
+        target_os = "macos",
+        target_os = "netbsd",
+    )))]
+    pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        io::default_write_vectored(|b| self.write_at(b, offset), bufs)
+    }
+
+    // We support some old Android versions that do not have `pwritev` in libc,
+    // so we use weak linkage and fallback to a direct syscall if not available.
+    //
+    // On 32-bit targets, we don't want to deal with weird ABI issues around
+    // passing 64-bits parameters to syscalls, so we fallback to the default
+    // implementation if `pwritev` is not available.
+    #[cfg(all(target_os = "android", target_pointer_width = "64"))]
+    pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        super::weak::syscall! {
+            fn pwritev(
+                fd: libc::c_int,
+                iovec: *const libc::iovec,
+                n_iovec: libc::c_int,
+                offset: off64_t
+            ) -> isize
+        }
+
+        let ret = cvt(unsafe {
+            pwritev(
+                self.as_raw_fd(),
+                bufs.as_ptr() as *const libc::iovec,
+                cmp::min(bufs.len(), max_iov()) as libc::c_int,
+                offset as _,
+            )
+        })?;
+        Ok(ret as usize)
+    }
+
+    // We support old MacOS and iOS versions that do not have `pwritev`. There is
+    // no `syscall` possible in these platform.
+    #[cfg(any(
+        all(target_os = "android", target_pointer_width = "32"),
+        target_os = "ios",
+        target_os = "macos",
+    ))]
+    pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
+
+        match pwritev64.get() {
+            Some(pwritev) => {
+                let ret = cvt(unsafe {
+                    pwritev(
+                        self.as_raw_fd(),
+                        bufs.as_ptr() as *const libc::iovec,
+                        cmp::min(bufs.len(), max_iov()) as libc::c_int,
+                        offset as _,
+                    )
+                })?;
+                Ok(ret as usize)
+            }
+            None => io::default_write_vectored(|b| self.write_at(b, offset), bufs),
+        }
+    }
+
     #[cfg(not(any(
         target_env = "newlib",
         target_os = "solaris",
@@ -207,7 +391,8 @@ impl FileDesc {
         target_os = "linux",
         target_os = "haiku",
         target_os = "redox",
-        target_os = "vxworks"
+        target_os = "vxworks",
+        target_os = "nto",
     )))]
     pub fn set_cloexec(&self) -> io::Result<()> {
         unsafe {
@@ -225,7 +410,8 @@ impl FileDesc {
         target_os = "linux",
         target_os = "haiku",
         target_os = "redox",
-        target_os = "vxworks"
+        target_os = "vxworks",
+        target_os = "nto",
     ))]
     pub fn set_cloexec(&self) -> io::Result<()> {
         unsafe {
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 8e1f35d6cc9..7566fafda24 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -13,7 +13,8 @@ use crate::mem;
     target_os = "solaris",
     target_os = "fuchsia",
     target_os = "redox",
-    target_os = "illumos"
+    target_os = "illumos",
+    target_os = "nto",
 ))]
 use crate::mem::MaybeUninit;
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
@@ -54,7 +55,8 @@ use libc::fstatat64;
     target_os = "solaris",
     target_os = "fuchsia",
     target_os = "redox",
-    target_os = "illumos"
+    target_os = "illumos",
+    target_os = "nto",
 ))]
 use libc::readdir as readdir64;
 #[cfg(target_os = "linux")]
@@ -69,7 +71,8 @@ use libc::readdir64_r;
     target_os = "illumos",
     target_os = "l4re",
     target_os = "fuchsia",
-    target_os = "redox"
+    target_os = "redox",
+    target_os = "nto",
 )))]
 use libc::readdir_r as readdir64_r;
 #[cfg(target_os = "android")]
@@ -277,7 +280,8 @@ unsafe impl Sync for Dir {}
     target_os = "solaris",
     target_os = "illumos",
     target_os = "fuchsia",
-    target_os = "redox"
+    target_os = "redox",
+    target_os = "nto",
 ))]
 pub struct DirEntry {
     dir: Arc<InnerReadDir>,
@@ -297,11 +301,12 @@ pub struct DirEntry {
     target_os = "solaris",
     target_os = "illumos",
     target_os = "fuchsia",
-    target_os = "redox"
+    target_os = "redox",
+    target_os = "nto",
 ))]
 struct dirent64_min {
     d_ino: u64,
-    #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
+    #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "nto")))]
     d_type: u8,
 }
 
@@ -311,7 +316,8 @@ struct dirent64_min {
     target_os = "solaris",
     target_os = "illumos",
     target_os = "fuchsia",
-    target_os = "redox"
+    target_os = "redox",
+    target_os = "nto",
 )))]
 pub struct DirEntry {
     dir: Arc<InnerReadDir>,
@@ -438,7 +444,7 @@ impl FileAttr {
     }
 }
 
-#[cfg(not(target_os = "netbsd"))]
+#[cfg(not(any(target_os = "netbsd", target_os = "nto")))]
 impl FileAttr {
     #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
     pub fn modified(&self) -> io::Result<SystemTime> {
@@ -524,6 +530,21 @@ impl FileAttr {
     }
 }
 
+#[cfg(target_os = "nto")]
+impl FileAttr {
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::new(self.stat.st_mtim.tv_sec, self.stat.st_mtim.tv_nsec))
+    }
+
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::new(self.stat.st_atim.tv_sec, self.stat.st_atim.tv_nsec))
+    }
+
+    pub fn created(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::new(self.stat.st_ctim.tv_sec, self.stat.st_ctim.tv_nsec))
+    }
+}
+
 impl AsInner<stat64> for FileAttr {
     fn as_inner(&self) -> &stat64 {
         &self.stat
@@ -603,7 +624,8 @@ impl Iterator for ReadDir {
         target_os = "solaris",
         target_os = "fuchsia",
         target_os = "redox",
-        target_os = "illumos"
+        target_os = "illumos",
+        target_os = "nto",
     ))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         if self.end_of_stream {
@@ -686,7 +708,11 @@ impl Iterator for ReadDir {
 
                 let entry = dirent64_min {
                     d_ino: *offset_ptr!(entry_ptr, d_ino) as u64,
-                    #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
+                    #[cfg(not(any(
+                        target_os = "solaris",
+                        target_os = "illumos",
+                        target_os = "nto",
+                    )))]
                     d_type: *offset_ptr!(entry_ptr, d_type) as u8,
                 };
 
@@ -705,7 +731,8 @@ impl Iterator for ReadDir {
         target_os = "solaris",
         target_os = "fuchsia",
         target_os = "redox",
-        target_os = "illumos"
+        target_os = "illumos",
+        target_os = "nto",
     )))]
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
         if self.end_of_stream {
@@ -794,7 +821,8 @@ impl DirEntry {
         target_os = "solaris",
         target_os = "illumos",
         target_os = "haiku",
-        target_os = "vxworks"
+        target_os = "vxworks",
+        target_os = "nto",
     ))]
     pub fn file_type(&self) -> io::Result<FileType> {
         self.metadata().map(|m| m.file_type())
@@ -804,7 +832,8 @@ impl DirEntry {
         target_os = "solaris",
         target_os = "illumos",
         target_os = "haiku",
-        target_os = "vxworks"
+        target_os = "vxworks",
+        target_os = "nto",
     )))]
     pub fn file_type(&self) -> io::Result<FileType> {
         match self.entry.d_type {
@@ -834,7 +863,8 @@ impl DirEntry {
         target_os = "redox",
         target_os = "vxworks",
         target_os = "espidf",
-        target_os = "horizon"
+        target_os = "horizon",
+        target_os = "nto",
     ))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
@@ -887,7 +917,8 @@ impl DirEntry {
         target_os = "solaris",
         target_os = "illumos",
         target_os = "fuchsia",
-        target_os = "redox"
+        target_os = "redox",
+        target_os = "nto",
     )))]
     fn name_cstr(&self) -> &CStr {
         unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
@@ -898,7 +929,8 @@ impl DirEntry {
         target_os = "solaris",
         target_os = "illumos",
         target_os = "fuchsia",
-        target_os = "redox"
+        target_os = "redox",
+        target_os = "nto",
     ))]
     fn name_cstr(&self) -> &CStr {
         &self.name
@@ -1051,7 +1083,8 @@ impl File {
             target_os = "linux",
             target_os = "android",
             target_os = "netbsd",
-            target_os = "openbsd"
+            target_os = "openbsd",
+            target_os = "nto",
         ))]
         unsafe fn os_datasync(fd: c_int) -> c_int {
             libc::fdatasync(fd)
@@ -1065,6 +1098,7 @@ impl File {
             target_os = "netbsd",
             target_os = "openbsd",
             target_os = "watchos",
+            target_os = "nto",
         )))]
         unsafe fn os_datasync(fd: c_int) -> c_int {
             libc::fsync(fd)
@@ -1098,6 +1132,10 @@ impl File {
         self.0.read_buf(cursor)
     }
 
+    pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+        self.0.read_vectored_at(bufs, offset)
+    }
+
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
     }
@@ -1115,6 +1153,10 @@ impl File {
         self.0.write_at(buf, offset)
     }
 
+    pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
+        self.0.write_vectored_at(bufs, offset)
+    }
+
     pub fn flush(&self) -> io::Result<()> {
         Ok(())
     }
@@ -1750,13 +1792,25 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
 pub use remove_dir_impl::remove_dir_all;
 
 // Fallback for REDOX, ESP-ID, Horizon, and Miri
-#[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri))]
+#[cfg(any(
+    target_os = "redox",
+    target_os = "espidf",
+    target_os = "horizon",
+    target_os = "nto",
+    miri
+))]
 mod remove_dir_impl {
     pub use crate::sys_common::fs::remove_dir_all;
 }
 
 // Modern implementation using openat(), unlinkat() and fdopendir()
-#[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri)))]
+#[cfg(not(any(
+    target_os = "redox",
+    target_os = "espidf",
+    target_os = "horizon",
+    target_os = "nto",
+    miri
+)))]
 mod remove_dir_impl {
     use super::{lstat, Dir, DirEntry, InnerReadDir, ReadDir};
     use crate::ffi::CStr;
diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs
index 6be1abc2b08..192fa216dfa 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -2,7 +2,10 @@ use crate::cell::UnsafeCell;
 use crate::ptr;
 use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
 use crate::sys::locks::{pthread_mutex, Mutex};
+#[cfg(not(target_os = "nto"))]
 use crate::sys::time::TIMESPEC_MAX;
+#[cfg(target_os = "nto")]
+use crate::sys::time::TIMESPEC_MAX_CAPPED;
 use crate::sys_common::lazy_box::{LazyBox, LazyInit};
 use crate::time::Duration;
 
@@ -132,10 +135,18 @@ impl Condvar {
         let mutex = pthread_mutex::raw(mutex);
         self.verify(mutex);
 
+        #[cfg(not(target_os = "nto"))]
         let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
             .checked_add_duration(&dur)
             .and_then(|t| t.to_timespec())
             .unwrap_or(TIMESPEC_MAX);
+
+        #[cfg(target_os = "nto")]
+        let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
+            .checked_add_duration(&dur)
+            .and_then(|t| t.to_timespec_capped())
+            .unwrap_or(TIMESPEC_MAX_CAPPED);
+
         let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
         assert!(r == libc::ETIMEDOUT || r == 0);
         r == 0
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 30a96be1430..68c9520cc9e 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -329,7 +329,7 @@ pub fn cvt_nz(error: libc::c_int) -> crate::io::Result<()> {
 // do so.  In 1003.1-2004 this was fixed.
 //
 // glibc's implementation did the flush, unsafely, before glibc commit
-// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]' by Florian
+// 91e7cf982d01 `abort: Do not flush stdio streams [BZ #15436]` by Florian
 // Weimer.  According to glibc's NEWS:
 //
 //    The abort function terminates the process immediately, without flushing
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index c86f80972a6..8e05b618daa 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -78,6 +78,7 @@ impl Socket {
                     target_os = "linux",
                     target_os = "netbsd",
                     target_os = "openbsd",
+                    target_os = "nto",
                 ))] {
                     // On platforms that support it we pass the SOCK_CLOEXEC
                     // flag to atomically create the socket and set it as
@@ -115,6 +116,7 @@ impl Socket {
                     target_os = "linux",
                     target_os = "netbsd",
                     target_os = "openbsd",
+                    target_os = "nto",
                 ))] {
                     // Like above, set cloexec atomically
                     cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?;
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 2f2663db607..21b035fb373 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -62,6 +62,7 @@ extern "C" {
         link_name = "__errno"
     )]
     #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
+    #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
     #[cfg_attr(
         any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"),
         link_name = "__error"
@@ -361,6 +362,17 @@ pub fn current_exe() -> io::Result<PathBuf> {
     }
 }
 
+#[cfg(target_os = "nto")]
+pub fn current_exe() -> io::Result<PathBuf> {
+    let mut e = crate::fs::read("/proc/self/exefile")?;
+    // Current versions of QNX Neutrino provide a null-terminated path.
+    // Ensure the trailing null byte is not returned here.
+    if let Some(0) = e.last() {
+        e.pop();
+    }
+    Ok(PathBuf::from(OsString::from_vec(e)))
+}
+
 #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 3bc17b7754d..ceaff596684 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -18,6 +18,7 @@ use crate::sys::weak::raw_syscall;
     target_os = "freebsd",
     all(target_os = "linux", target_env = "gnu"),
     all(target_os = "linux", target_env = "musl"),
+    target_os = "nto",
 ))]
 use crate::sys::weak::weak;
 
@@ -30,6 +31,15 @@ use libc::{c_int, pid_t};
 #[cfg(not(any(target_os = "vxworks", target_os = "l4re")))]
 use libc::{gid_t, uid_t};
 
+cfg_if::cfg_if! {
+    if #[cfg(all(target_os = "nto", target_env = "nto71"))] {
+        use crate::thread;
+        use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t};
+        // arbitrary number of tries:
+        const MAX_FORKSPAWN_TRIES: u32 = 4;
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Command
 ////////////////////////////////////////////////////////////////////////////////
@@ -140,11 +150,31 @@ impl Command {
 
     // Attempts to fork the process. If successful, returns Ok((0, -1))
     // in the child, and Ok((child_pid, -1)) in the parent.
-    #[cfg(not(target_os = "linux"))]
+    #[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))]
     unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
         cvt(libc::fork()).map(|res| (res, -1))
     }
 
+    // On QNX Neutrino, fork can fail with EBADF in case "another thread might have opened
+    // or closed a file descriptor while the fork() was occurring".
+    // Documentation says "... or try calling fork() again". This is what we do here.
+    // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html
+    #[cfg(all(target_os = "nto", target_env = "nto71"))]
+    unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
+        use crate::sys::os::errno;
+
+        let mut tries_left = MAX_FORKSPAWN_TRIES;
+        loop {
+            let r = libc::fork();
+            if r == -1 as libc::pid_t && tries_left > 0 && errno() as libc::c_int == libc::EBADF {
+                thread::yield_now();
+                tries_left -= 1;
+            } else {
+                return cvt(r).map(|res| (res, -1));
+            }
+        }
+    }
+
     // Attempts to fork the process. If successful, returns Ok((0, -1))
     // in the child, and Ok((child_pid, child_pidfd)) in the parent.
     #[cfg(target_os = "linux")]
@@ -389,6 +419,7 @@ impl Command {
         target_os = "freebsd",
         all(target_os = "linux", target_env = "gnu"),
         all(target_os = "linux", target_env = "musl"),
+        target_os = "nto",
     )))]
     fn posix_spawn(
         &mut self,
@@ -405,6 +436,7 @@ impl Command {
         target_os = "freebsd",
         all(target_os = "linux", target_env = "gnu"),
         all(target_os = "linux", target_env = "musl"),
+        target_os = "nto",
     ))]
     fn posix_spawn(
         &mut self,
@@ -436,6 +468,34 @@ impl Command {
             }
         }
 
+        // On QNX Neutrino, posix_spawnp can fail with EBADF in case "another thread might have opened
+        // or closed a file descriptor while the posix_spawn() was occurring".
+        // Documentation says "... or try calling posix_spawn() again". This is what we do here.
+        // See also http://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html
+        #[cfg(all(target_os = "nto", target_env = "nto71"))]
+        unsafe fn retrying_libc_posix_spawnp(
+            pid: *mut pid_t,
+            file: *const c_char,
+            file_actions: *const posix_spawn_file_actions_t,
+            attrp: *const posix_spawnattr_t,
+            argv: *const *mut c_char,
+            envp: *const *mut c_char,
+        ) -> i32 {
+            let mut tries_left = MAX_FORKSPAWN_TRIES;
+            loop {
+                match libc::posix_spawnp(pid, file, file_actions, attrp, argv, envp) {
+                    libc::EBADF if tries_left > 0 => {
+                        thread::yield_now();
+                        tries_left -= 1;
+                        continue;
+                    }
+                    r => {
+                        return r;
+                    }
+                }
+            }
+        }
+
         // Solaris, glibc 2.29+, and musl 1.24+ can set a new working directory,
         // and maybe others will gain this non-POSIX function too. We'll check
         // for this weak symbol as soon as it's needed, so we can return early
@@ -555,7 +615,12 @@ impl Command {
             // Make sure we synchronize access to the global `environ` resource
             let _env_lock = sys::os::env_read_lock();
             let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _);
-            cvt_nz(libc::posix_spawnp(
+
+            #[cfg(not(target_os = "nto"))]
+            let spawn_fn = libc::posix_spawnp;
+            #[cfg(target_os = "nto")]
+            let spawn_fn = retrying_libc_posix_spawnp;
+            cvt_nz(spawn_fn(
                 &mut p.pid,
                 self.get_program_cstr().as_ptr(),
                 file_actions.0.as_ptr(),
@@ -760,7 +825,7 @@ fn signal_string(signal: i32) -> &'static str {
             )
         ))]
         libc::SIGSTKFLT => " (SIGSTKFLT)",
-        #[cfg(target_os = "linux")]
+        #[cfg(any(target_os = "linux", target_os = "nto"))]
         libc::SIGPWR => " (SIGPWR)",
         #[cfg(any(
             target_os = "macos",
@@ -769,7 +834,8 @@ fn signal_string(signal: i32) -> &'static str {
             target_os = "freebsd",
             target_os = "netbsd",
             target_os = "openbsd",
-            target_os = "dragonfly"
+            target_os = "dragonfly",
+            target_os = "nto",
         ))]
         libc::SIGEMT => " (SIGEMT)",
         #[cfg(any(
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index cc0e5929569..15070b1f6a7 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -9,7 +9,7 @@ use crate::time::Duration;
 
 #[cfg(all(target_os = "linux", target_env = "gnu"))]
 use crate::sys::weak::dlsym;
-#[cfg(any(target_os = "solaris", target_os = "illumos"))]
+#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
 use crate::sys::weak::weak;
 #[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))]
 pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
@@ -173,7 +173,7 @@ impl Thread {
         }
     }
 
-    #[cfg(any(target_os = "solaris", target_os = "illumos"))]
+    #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
     pub fn set_name(name: &CStr) {
         weak! {
             fn pthread_setname_np(
@@ -381,6 +381,17 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
             }
 
             Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
+        } else if #[cfg(target_os = "nto")] {
+            unsafe {
+                use libc::_syspage_ptr;
+                if _syspage_ptr.is_null() {
+                    Err(io::const_io_error!(io::ErrorKind::NotFound, "No syspage available"))
+                } else {
+                    let cpus = (*_syspage_ptr).num_cpu;
+                    NonZeroUsize::new(cpus as usize)
+                        .ok_or(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"))
+                }
+            }
         } else if #[cfg(target_os = "haiku")] {
             // system_info cpu_count field gets the static data set at boot time with `smp_set_num_cpus`
             // `get_system_info` calls then `smp_get_num_cpus`
diff --git a/library/std/src/sys/unix/thread_parking/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs
index 082d25e68f5..43046ed07b8 100644
--- a/library/std/src/sys/unix/thread_parking/pthread.rs
+++ b/library/std/src/sys/unix/thread_parking/pthread.rs
@@ -6,7 +6,10 @@ use crate::pin::Pin;
 use crate::ptr::addr_of_mut;
 use crate::sync::atomic::AtomicUsize;
 use crate::sync::atomic::Ordering::SeqCst;
+#[cfg(not(target_os = "nto"))]
 use crate::sys::time::TIMESPEC_MAX;
+#[cfg(target_os = "nto")]
+use crate::sys::time::TIMESPEC_MAX_CAPPED;
 use crate::time::Duration;
 
 const EMPTY: usize = 0;
@@ -80,8 +83,14 @@ unsafe fn wait_timeout(
         (Timespec::now(libc::CLOCK_MONOTONIC), dur)
     };
 
+    #[cfg(not(target_os = "nto"))]
     let timeout =
         now.checked_add_duration(&dur).and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX);
+    #[cfg(target_os = "nto")]
+    let timeout = now
+        .checked_add_duration(&dur)
+        .and_then(|t| t.to_timespec_capped())
+        .unwrap_or(TIMESPEC_MAX_CAPPED);
     let r = libc::pthread_cond_timedwait(cond, lock, &timeout);
     debug_assert!(r == libc::ETIMEDOUT || r == 0);
 }
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index 2daad981b73..0f11de8f5b8 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -9,6 +9,14 @@ pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
 pub const TIMESPEC_MAX: libc::timespec =
     libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
 
+// This additional constant is only used when calling
+// `libc::pthread_cond_timedwait`.
+#[cfg(target_os = "nto")]
+pub(super) const TIMESPEC_MAX_CAPPED: libc::timespec = libc::timespec {
+    tv_sec: (u64::MAX / NSEC_PER_SEC) as i64,
+    tv_nsec: (u64::MAX % NSEC_PER_SEC) as i64,
+};
+
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(0)]
@@ -144,6 +152,20 @@ impl Timespec {
             tv_nsec: self.tv_nsec.0.try_into().ok()?,
         })
     }
+
+    // On QNX Neutrino, the maximum timespec for e.g. pthread_cond_timedwait
+    // is 2^64 nanoseconds
+    #[cfg(target_os = "nto")]
+    pub(super) fn to_timespec_capped(&self) -> Option<libc::timespec> {
+        // Check if timeout in nanoseconds would fit into an u64
+        if (self.tv_nsec.0 as u64)
+            .checked_add((self.tv_sec as u64).checked_mul(NSEC_PER_SEC)?)
+            .is_none()
+        {
+            return None;
+        }
+        self.to_timespec()
+    }
 }
 
 impl From<libc::timespec> for Timespec {
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 1d0ab772739..5d150eca00e 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -6,13 +6,15 @@
 
 use crate::ffi::CStr;
 use crate::mem;
-use crate::os::raw::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ushort};
+use crate::os::raw::{c_char, c_long, c_longlong, c_uint, c_ulong, c_ushort};
 use crate::os::windows::io::{BorrowedHandle, HandleOrInvalid, HandleOrNull};
 use crate::ptr;
 use core::ffi::NonZero_c_ulong;
 
 use libc::{c_void, size_t, wchar_t};
 
+pub use crate::os::raw::c_int;
+
 #[path = "c/errors.rs"] // c.rs is included from two places so we need to specify this
 mod errors;
 pub use errors::*;
@@ -47,16 +49,19 @@ pub type ACCESS_MASK = DWORD;
 
 pub type LPBOOL = *mut BOOL;
 pub type LPBYTE = *mut BYTE;
+pub type LPCCH = *const CHAR;
 pub type LPCSTR = *const CHAR;
+pub type LPCWCH = *const WCHAR;
 pub type LPCWSTR = *const WCHAR;
+pub type LPCVOID = *const c_void;
 pub type LPDWORD = *mut DWORD;
 pub type LPHANDLE = *mut HANDLE;
 pub type LPOVERLAPPED = *mut OVERLAPPED;
 pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
 pub type LPSECURITY_ATTRIBUTES = *mut SECURITY_ATTRIBUTES;
 pub type LPSTARTUPINFO = *mut STARTUPINFO;
+pub type LPSTR = *mut CHAR;
 pub type LPVOID = *mut c_void;
-pub type LPCVOID = *const c_void;
 pub type LPWCH = *mut WCHAR;
 pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
 pub type LPWSADATA = *mut WSADATA;
@@ -132,6 +137,10 @@ pub const MAX_PATH: usize = 260;
 
 pub const FILE_TYPE_PIPE: u32 = 3;
 
+pub const CP_UTF8: DWORD = 65001;
+pub const MB_ERR_INVALID_CHARS: DWORD = 0x08;
+pub const WC_ERR_INVALID_CHARS: DWORD = 0x80;
+
 #[repr(C)]
 #[derive(Copy)]
 pub struct WIN32_FIND_DATAW {
@@ -1147,6 +1156,25 @@ extern "system" {
         lpFilePart: *mut LPWSTR,
     ) -> DWORD;
     pub fn GetFileAttributesW(lpFileName: LPCWSTR) -> DWORD;
+
+    pub fn MultiByteToWideChar(
+        CodePage: UINT,
+        dwFlags: DWORD,
+        lpMultiByteStr: LPCCH,
+        cbMultiByte: c_int,
+        lpWideCharStr: LPWSTR,
+        cchWideChar: c_int,
+    ) -> c_int;
+    pub fn WideCharToMultiByte(
+        CodePage: UINT,
+        dwFlags: DWORD,
+        lpWideCharStr: LPCWCH,
+        cchWideChar: c_int,
+        lpMultiByteStr: LPSTR,
+        cbMultiByte: c_int,
+        lpDefaultChar: LPCCH,
+        lpUsedDefaultChar: LPBOOL,
+    ) -> c_int;
 }
 
 #[link(name = "ws2_32")]
diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs
index c2cd48470bd..32c6ccffb7a 100644
--- a/library/std/src/sys/windows/stdio.rs
+++ b/library/std/src/sys/windows/stdio.rs
@@ -169,14 +169,27 @@ fn write(
 }
 
 fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usize> {
+    debug_assert!(!utf8.is_empty());
+
     let mut utf16 = [MaybeUninit::<u16>::uninit(); MAX_BUFFER_SIZE / 2];
-    let mut len_utf16 = 0;
-    for (chr, dest) in utf8.encode_utf16().zip(utf16.iter_mut()) {
-        *dest = MaybeUninit::new(chr);
-        len_utf16 += 1;
-    }
-    // Safety: We've initialized `len_utf16` values.
-    let utf16: &[u16] = unsafe { MaybeUninit::slice_assume_init_ref(&utf16[..len_utf16]) };
+    let utf8 = &utf8[..utf8.floor_char_boundary(utf16.len())];
+
+    let utf16: &[u16] = unsafe {
+        // Note that this theoretically checks validity twice in the (most common) case
+        // where the underlying byte sequence is valid utf-8 (given the check in `write()`).
+        let result = c::MultiByteToWideChar(
+            c::CP_UTF8,                      // CodePage
+            c::MB_ERR_INVALID_CHARS,         // dwFlags
+            utf8.as_ptr() as c::LPCCH,       // lpMultiByteStr
+            utf8.len() as c::c_int,          // cbMultiByte
+            utf16.as_mut_ptr() as c::LPWSTR, // lpWideCharStr
+            utf16.len() as c::c_int,         // cchWideChar
+        );
+        assert!(result != 0, "Unexpected error in MultiByteToWideChar");
+
+        // Safety: MultiByteToWideChar initializes `result` values.
+        MaybeUninit::slice_assume_init_ref(&utf16[..result as usize])
+    };
 
     let mut written = write_u16s(handle, &utf16)?;
 
@@ -189,8 +202,8 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz
         // a missing surrogate can be produced (and also because of the UTF-8 validation above),
         // write the missing surrogate out now.
         // Buffering it would mean we have to lie about the number of bytes written.
-        let first_char_remaining = utf16[written];
-        if first_char_remaining >= 0xDCEE && first_char_remaining <= 0xDFFF {
+        let first_code_unit_remaining = utf16[written];
+        if first_code_unit_remaining >= 0xDCEE && first_code_unit_remaining <= 0xDFFF {
             // low surrogate
             // We just hope this works, and give up otherwise
             let _ = write_u16s(handle, &utf16[written..written + 1]);
@@ -212,6 +225,7 @@ fn write_valid_utf8_to_console(handle: c::HANDLE, utf8: &str) -> io::Result<usiz
 }
 
 fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result<usize> {
+    debug_assert!(data.len() < u32::MAX as usize);
     let mut written = 0;
     cvt(unsafe {
         c::WriteConsoleW(
@@ -365,26 +379,32 @@ fn read_u16s(handle: c::HANDLE, buf: &mut [MaybeUninit<u16>]) -> io::Result<usiz
     Ok(amount as usize)
 }
 
-#[allow(unused)]
 fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
-    let mut written = 0;
-    for chr in char::decode_utf16(utf16.iter().cloned()) {
-        match chr {
-            Ok(chr) => {
-                chr.encode_utf8(&mut utf8[written..]);
-                written += chr.len_utf8();
-            }
-            Err(_) => {
-                // We can't really do any better than forget all data and return an error.
-                return Err(io::const_io_error!(
-                    io::ErrorKind::InvalidData,
-                    "Windows stdin in console mode does not support non-UTF-16 input; \
-                     encountered unpaired surrogate",
-                ));
-            }
-        }
+    debug_assert!(utf16.len() <= c::c_int::MAX as usize);
+    debug_assert!(utf8.len() <= c::c_int::MAX as usize);
+
+    let result = unsafe {
+        c::WideCharToMultiByte(
+            c::CP_UTF8,                    // CodePage
+            c::WC_ERR_INVALID_CHARS,       // dwFlags
+            utf16.as_ptr(),                // lpWideCharStr
+            utf16.len() as c::c_int,       // cchWideChar
+            utf8.as_mut_ptr() as c::LPSTR, // lpMultiByteStr
+            utf8.len() as c::c_int,        // cbMultiByte
+            ptr::null(),                   // lpDefaultChar
+            ptr::null_mut(),               // lpUsedDefaultChar
+        )
+    };
+    if result == 0 {
+        // We can't really do any better than forget all data and return an error.
+        Err(io::const_io_error!(
+            io::ErrorKind::InvalidData,
+            "Windows stdin in console mode does not support non-UTF-16 input; \
+            encountered unpaired surrogate",
+        ))
+    } else {
+        Ok(result as usize)
     }
-    Ok(written)
 }
 
 impl IncompleteUtf8 {
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs
index f1d804ef40c..8752f46ff81 100644
--- a/library/std/src/sys_common/backtrace.rs
+++ b/library/std/src/sys_common/backtrace.rs
@@ -91,6 +91,19 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
         if stop {
             return false;
         }
+        #[cfg(target_os = "nto")]
+        if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
+            if !hit && start {
+                use crate::backtrace_rs::SymbolName;
+                res = bt_fmt.frame().print_raw(
+                    frame.ip(),
+                    Some(SymbolName::new("__my_thread_exit".as_bytes())),
+                    None,
+                    None,
+                );
+            }
+            return false;
+        }
         if !hit && start {
             res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
         }
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 2c38dfecf97..85ecc1def3a 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -21,7 +21,7 @@ cfg_if::cfg_if! {
         target_os = "dragonfly", target_os = "freebsd",
         target_os = "ios", target_os = "macos", target_os = "watchos",
         target_os = "openbsd", target_os = "netbsd", target_os = "illumos",
-        target_os = "solaris", target_os = "haiku", target_os = "l4re"))] {
+        target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] {
         use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
         use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
     } else {
@@ -35,7 +35,7 @@ cfg_if::cfg_if! {
         target_os = "linux", target_os = "android",
         target_os = "dragonfly", target_os = "freebsd",
         target_os = "openbsd", target_os = "netbsd",
-        target_os = "haiku"))] {
+        target_os = "haiku", target_os = "nto"))] {
         use libc::MSG_NOSIGNAL;
     } else {
         const MSG_NOSIGNAL: c_int = 0x0;
@@ -46,7 +46,8 @@ cfg_if::cfg_if! {
     if #[cfg(any(
         target_os = "dragonfly", target_os = "freebsd",
         target_os = "openbsd", target_os = "netbsd",
-        target_os = "solaris", target_os = "illumos"))] {
+        target_os = "solaris", target_os = "illumos",
+        target_os = "nto"))] {
         use crate::ffi::c_uchar;
         type IpV4MultiCastType = c_uchar;
     } else {
diff --git a/library/std/src/sys_common/net/tests.rs b/library/std/src/sys_common/net/tests.rs
index ac75d9ebfc8..fc236b8027b 100644
--- a/library/std/src/sys_common/net/tests.rs
+++ b/library/std/src/sys_common/net/tests.rs
@@ -6,7 +6,7 @@ fn no_lookup_host_duplicates() {
     let mut addrs = HashMap::new();
     let lh = match LookupHost::try_from(("localhost", 0)) {
         Ok(lh) => lh,
-        Err(e) => panic!("couldn't resolve `localhost': {e}"),
+        Err(e) => panic!("couldn't resolve `localhost`: {e}"),
     };
     for sa in lh {
         *addrs.entry(sa).or_insert(0) += 1;
diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs
index 2672a2a75b0..89360e45601 100644
--- a/library/std/src/sys_common/thread_local_key.rs
+++ b/library/std/src/sys_common/thread_local_key.rs
@@ -117,9 +117,15 @@ pub struct Key {
 /// This value specifies no destructor by default.
 pub const INIT: StaticKey = StaticKey::new(None);
 
-// Define a sentinel value that is unlikely to be returned
-// as a TLS key (but it may be returned).
+// Define a sentinel value that is likely not to be returned
+// as a TLS key.
+#[cfg(not(target_os = "nto"))]
 const KEY_SENTVAL: usize = 0;
+// On QNX Neutrino, 0 is always returned when currently not in use.
+// Using 0 would mean to always create two keys and remote the first
+// one (with value of 0) immediately afterwards.
+#[cfg(target_os = "nto")]
+const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1;
 
 impl StaticKey {
     #[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index e202d17e1c2..bc588bdbb3c 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -594,7 +594,7 @@ impl Wtf8 {
     }
 
     /// Returns the code point at `position` if it is in the ASCII range,
-    /// or `b'\xFF' otherwise.
+    /// or `b'\xFF'` otherwise.
     ///
     /// # Panics
     ///
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 69fb529d7f5..88d8e5fe97a 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -204,7 +204,7 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn {
 }
 
 /// Invoked when unit tests terminate. Returns `Result::Err` if the test is
-/// considered a failure. By default, invokes `report() and checks for a `0`
+/// considered a failure. By default, invokes `report()` and checks for a `0`
 /// result.
 pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
     let code = result.report().to_i32();
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index 3753071d5f0..edc10aa39af 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -127,3 +127,7 @@ extern "C" {}
 #[cfg(target_os = "haiku")]
 #[link(name = "gcc_s")]
 extern "C" {}
+
+#[cfg(target_os = "nto")]
+#[link(name = "gcc_s")]
+extern "C" {}
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index 036a35869a5..eeeed3afcd3 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -89,7 +89,7 @@ pub type _Unwind_Exception_Cleanup_Fn =
 
 // FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in
 // the block are reexported in dylib build of std. This is needed when build rustc with
-// feature `llvm-libunwind', as no other cdylib will provided those _Unwind_* symbols.
+// feature `llvm-libunwind`, as no other cdylib will provided those _Unwind_* symbols.
 // However the `link` attribute is duplicated multiple times and does not just export symbol,
 // a better way to manually export symbol would be another attribute like `#[export]`.
 // See the logic in function rustc_codegen_ssa::src::back::exported_symbols, module
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 4a0ba592577..e861d520c53 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -50,6 +50,7 @@ dependencies = [
  "opener",
  "pretty_assertions",
  "serde",
+ "serde_derive",
  "serde_json",
  "sha2",
  "sysinfo",
@@ -564,9 +565,6 @@ name = "serde"
 version = "1.0.137"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
-dependencies = [
- "serde_derive",
-]
 
 [[package]]
 name = "serde_derive"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 22ceeca941e..663987f113c 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -39,7 +39,10 @@ cc = "1.0.69"
 libc = "0.2"
 hex = "0.4"
 object = { version = "0.29.0", default-features = false, features = ["archive", "coff", "read_core", "unaligned"] }
-serde = { version = "1.0.8", features = ["derive"] }
+serde = "1.0.137"
+# Directly use serde_derive rather than through the derive feature of serde to allow building both
+# in parallel and to allow serde_json and toml to start building as soon as serde has been built.
+serde_derive = "1.0.137"
 serde_json = "1.0.2"
 sha2 = "0.10"
 tar = "0.4"
diff --git a/src/bootstrap/bolt.rs b/src/bootstrap/bolt.rs
index ea37cd47049..973dc4f602b 100644
--- a/src/bootstrap/bolt.rs
+++ b/src/bootstrap/bolt.rs
@@ -1,46 +1,40 @@
 use std::path::Path;
 use std::process::Command;
 
-/// Uses the `llvm-bolt` binary to instrument the binary/library at the given `path` with BOLT.
+/// Uses the `llvm-bolt` binary to instrument the artifact at the given `path` with BOLT.
 /// When the instrumented artifact is executed, it will generate BOLT profiles into
 /// `/tmp/prof.fdata.<pid>.fdata`.
-pub fn instrument_with_bolt_inplace(path: &Path) {
-    let dir = std::env::temp_dir();
-    let instrumented_path = dir.join("instrumented.so");
-
+/// Creates the instrumented artifact at `output_path`.
+pub fn instrument_with_bolt(path: &Path, output_path: &Path) {
     let status = Command::new("llvm-bolt")
         .arg("-instrument")
         .arg(&path)
         // Make sure that each process will write its profiles into a separate file
         .arg("--instrumentation-file-append-pid")
         .arg("-o")
-        .arg(&instrumented_path)
+        .arg(output_path)
         .status()
         .expect("Could not instrument artifact using BOLT");
 
     if !status.success() {
         panic!("Could not instrument {} with BOLT, exit code {:?}", path.display(), status.code());
     }
-
-    std::fs::copy(&instrumented_path, path).expect("Cannot copy instrumented artifact");
-    std::fs::remove_file(instrumented_path).expect("Cannot delete instrumented artifact");
 }
 
-/// Uses the `llvm-bolt` binary to optimize the binary/library at the given `path` with BOLT,
+/// Uses the `llvm-bolt` binary to optimize the artifact at the given `path` with BOLT,
 /// using merged profiles from `profile_path`.
 ///
 /// The recorded profiles have to be merged using the `merge-fdata` tool from LLVM and the merged
 /// profile path should be then passed to this function.
-pub fn optimize_library_with_bolt_inplace(path: &Path, profile_path: &Path) {
-    let dir = std::env::temp_dir();
-    let optimized_path = dir.join("optimized.so");
-
+///
+/// Creates the optimized artifact at `output_path`.
+pub fn optimize_with_bolt(path: &Path, profile_path: &Path, output_path: &Path) {
     let status = Command::new("llvm-bolt")
         .arg(&path)
         .arg("-data")
         .arg(&profile_path)
         .arg("-o")
-        .arg(&optimized_path)
+        .arg(output_path)
         // Reorder basic blocks within functions
         .arg("-reorder-blocks=ext-tsp")
         // Reorder functions within the binary
@@ -65,7 +59,4 @@ pub fn optimize_library_with_bolt_inplace(path: &Path, profile_path: &Path) {
     if !status.success() {
         panic!("Could not optimize {} with BOLT, exit code {:?}", path.display(), status.code());
     }
-
-    std::fs::copy(&optimized_path, path).expect("Cannot copy optimized artifact");
-    std::fs::remove_file(optimized_path).expect("Cannot delete optimized artifact");
 }
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index b33fc02f49c..3d48db8660a 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -910,14 +910,16 @@ impl<'a> Builder<'a> {
     /// new artifacts, it can't be used to rely on the presence of a particular
     /// sysroot.
     ///
-    /// See `force_use_stage1` for documentation on what each argument is.
+    /// See `force_use_stage1` and `force_use_stage2` for documentation on what each argument is.
     pub fn compiler_for(
         &self,
         stage: u32,
         host: TargetSelection,
         target: TargetSelection,
     ) -> Compiler {
-        if self.build.force_use_stage1(Compiler { stage, host }, target) {
+        if self.build.force_use_stage2() {
+            self.compiler(2, self.config.build)
+        } else if self.build.force_use_stage1(Compiler { stage, host }, target) {
             self.compiler(1, self.config.build)
         } else {
             self.compiler(stage, host)
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index ff7821fb9ff..cd19667139a 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -105,10 +105,15 @@ impl Step for Std {
             cargo.arg("--lib");
         }
 
-        builder.info(&format!(
-            "Checking stage{} library artifacts ({} -> {})",
-            builder.top_stage, &compiler.host, target
-        ));
+        let msg = if compiler.host == target {
+            format!("Checking stage{} library artifacts ({target})", builder.top_stage)
+        } else {
+            format!(
+                "Checking stage{} library artifacts ({} -> {})",
+                builder.top_stage, &compiler.host, target
+            )
+        };
+        builder.info(&msg);
         run_cargo(
             builder,
             cargo,
@@ -162,10 +167,18 @@ impl Step for Std {
             cargo.arg("-p").arg(krate.name);
         }
 
-        builder.info(&format!(
-            "Checking stage{} library test/bench/example targets ({} -> {})",
-            builder.top_stage, &compiler.host, target
-        ));
+        let msg = if compiler.host == target {
+            format!(
+                "Checking stage{} library test/bench/example targets ({target})",
+                builder.top_stage
+            )
+        } else {
+            format!(
+                "Checking stage{} library test/bench/example targets ({} -> {})",
+                builder.top_stage, &compiler.host, target
+            )
+        };
+        builder.info(&msg);
         run_cargo(
             builder,
             cargo,
@@ -239,10 +252,15 @@ impl Step for Rustc {
             cargo.arg("-p").arg(krate.name);
         }
 
-        builder.info(&format!(
-            "Checking stage{} compiler artifacts ({} -> {})",
-            builder.top_stage, &compiler.host, target
-        ));
+        let msg = if compiler.host == target {
+            format!("Checking stage{} compiler artifacts ({target})", builder.top_stage)
+        } else {
+            format!(
+                "Checking stage{} compiler artifacts ({} -> {})",
+                builder.top_stage, &compiler.host, target
+            )
+        };
+        builder.info(&msg);
         run_cargo(
             builder,
             cargo,
@@ -299,10 +317,15 @@ impl Step for CodegenBackend {
             .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
         rustc_cargo_env(builder, &mut cargo, target);
 
-        builder.info(&format!(
-            "Checking stage{} {} artifacts ({} -> {})",
-            builder.top_stage, backend, &compiler.host.triple, target.triple
-        ));
+        let msg = if compiler.host == target {
+            format!("Checking stage{} {} artifacts ({target})", builder.top_stage, backend)
+        } else {
+            format!(
+                "Checking stage{} {} library ({} -> {})",
+                builder.top_stage, backend, &compiler.host.triple, target.triple
+            )
+        };
+        builder.info(&msg);
 
         run_cargo(
             builder,
@@ -362,10 +385,15 @@ impl Step for RustAnalyzer {
             cargo.arg("--benches");
         }
 
-        builder.info(&format!(
-            "Checking stage{} {} artifacts ({} -> {})",
-            compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple
-        ));
+        let msg = if compiler.host == target {
+            format!("Checking stage{} {} artifacts ({target})", compiler.stage, "rust-analyzer")
+        } else {
+            format!(
+                "Checking stage{} {} artifacts ({} -> {})",
+                compiler.stage, "rust-analyzer", &compiler.host.triple, target.triple
+            )
+        };
+        builder.info(&msg);
         run_cargo(
             builder,
             cargo,
@@ -432,14 +460,18 @@ macro_rules! tool_check_step {
                 // NOTE: this doesn't enable lints for any other tools unless they explicitly add `#![warn(rustc::internal)]`
                 // See https://github.com/rust-lang/rust/pull/80573#issuecomment-754010776
                 cargo.rustflag("-Zunstable-options");
-
-                builder.info(&format!(
-                    "Checking stage{} {} artifacts ({} -> {})",
-                    builder.top_stage,
-                    stringify!($name).to_lowercase(),
-                    &compiler.host.triple,
-                    target.triple
-                ));
+                let msg = if compiler.host == target {
+                    format!("Checking stage{} {} artifacts ({target})", builder.top_stage, stringify!($name).to_lowercase())
+                } else {
+                    format!(
+                        "Checking stage{} {} artifacts ({} -> {})",
+                        builder.top_stage,
+                        stringify!($name).to_lowercase(),
+                        &compiler.host.triple,
+                        target.triple
+                    )
+                };
+                builder.info(&msg);
                 run_cargo(
                     builder,
                     cargo,
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index 468efc1114c..7ebd0a8f270 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -62,6 +62,7 @@ macro_rules! clean_crate_tree {
                 let target = compiler.host;
                 let mut cargo = builder.bare_cargo(compiler, $mode, target, "clean");
                 for krate in &*self.crates {
+                    cargo.arg("-p");
                     cargo.arg(krate);
                 }
 
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 348d22a9ce6..8b80dfc0f9b 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -16,7 +16,7 @@ use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
 use std::str;
 
-use serde::Deserialize;
+use serde_derive::Deserialize;
 
 use crate::builder::crate_description;
 use crate::builder::Cargo;
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 4a563bc396d..05e74254949 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -25,6 +25,7 @@ use crate::flags::{Color, Flags};
 use crate::util::{exe, output, t};
 use once_cell::sync::OnceCell;
 use serde::{Deserialize, Deserializer};
+use serde_derive::Deserialize;
 
 macro_rules! check_ci_llvm {
     ($name:expr) => {
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index 681ecbfeb5b..5a105007f21 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -11,6 +11,11 @@ fn parse(config: &str) -> Config {
 
 #[test]
 fn download_ci_llvm() {
+    if crate::native::is_ci_llvm_modified(&parse("")) {
+        eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change");
+        return;
+    }
+
     let parse_llvm = |s| parse(s).llvm_from_ci;
     let if_available = parse_llvm("llvm.download-ci-llvm = \"if-available\"");
 
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 04e798e3949..c0d382d8a50 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -442,6 +442,8 @@ def to_toml(value):
             return value
         else:
             return "'" + value + "'"
+    elif isinstance(value, dict):
+        return "{" + ", ".join(map(lambda a: "{} = {}".format(to_toml(a[0]), to_toml(a[1])), value.items())) + "}"
     else:
         raise RuntimeError('no toml')
 
@@ -486,6 +488,22 @@ for section_key, section_config in config.items():
     else:
         configure_section(sections[section_key], section_config)
 
+def write_uncommented(target, f):
+    block = []
+    is_comment = True
+
+    for line in target:
+        block.append(line)
+        if len(line) == 0:
+            if not is_comment:
+                for l in block:
+                    f.write(l + "\n")
+            block = []
+            is_comment = True
+            continue
+        is_comment = is_comment and line.startswith('#')
+    return f
+
 # Now that we've built up our `config.toml`, write it all out in the same
 # order that we read it in.
 p("")
@@ -494,11 +512,9 @@ with bootstrap.output('config.toml') as f:
     for section in section_order:
         if section == 'target':
             for target in targets:
-                for line in targets[target]:
-                    f.write(line + "\n")
+                f = write_uncommented(targets[target], f)
         else:
-            for line in sections[section]:
-                f.write(line + "\n")
+            f = write_uncommented(sections[section], f)
 
 with bootstrap.output('Makefile') as f:
     contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in')
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 9b2b549612d..d7008df4179 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -18,7 +18,9 @@ use std::process::Command;
 
 use object::read::archive::ArchiveFile;
 use object::BinaryFormat;
+use sha2::Digest;
 
+use crate::bolt::{instrument_with_bolt, optimize_with_bolt};
 use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::cache::{Interned, INTERNER};
 use crate::channel;
@@ -1904,6 +1906,26 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
     }
 }
 
+fn install_llvm_file(builder: &Builder<'_>, source: &Path, destination: &Path) {
+    if builder.config.dry_run() {
+        return;
+    }
+
+    // After LLVM is built, we modify (instrument or optimize) the libLLVM.so library file.
+    // This is not done in-place so that the built LLVM files are not "tainted" with BOLT.
+    // We perform the instrumentation/optimization here, on the fly, just before they are being
+    // packaged into some destination directory.
+    let postprocessed = if builder.config.llvm_bolt_profile_generate {
+        builder.ensure(BoltInstrument::new(source.to_path_buf()))
+    } else if let Some(path) = &builder.config.llvm_bolt_profile_use {
+        builder.ensure(BoltOptimize::new(source.to_path_buf(), path.into()))
+    } else {
+        source.to_path_buf()
+    };
+
+    builder.install(&postprocessed, destination, 0o644);
+}
+
 /// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
 ///
 /// Returns whether the files were actually copied.
@@ -1955,7 +1977,7 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
             } else {
                 PathBuf::from(file)
             };
-            builder.install(&file, dst_libdir, 0o644);
+            install_llvm_file(builder, &file, dst_libdir);
         }
         !builder.config.dry_run()
     } else {
@@ -1986,6 +2008,117 @@ pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection
     }
 }
 
+/// Creates an output path to a BOLT-manipulated artifact for the given `file`.
+/// The hash of the file is used to make sure that we don't mix BOLT artifacts amongst different
+/// files with the same name.
+///
+/// We need to keep the file-name the same though, to make sure that copying the manipulated file
+/// to a directory will not change the final file path.
+fn create_bolt_output_path(builder: &Builder<'_>, file: &Path, hash: &str) -> PathBuf {
+    let directory = builder.out.join("bolt").join(hash);
+    t!(fs::create_dir_all(&directory));
+    directory.join(file.file_name().unwrap())
+}
+
+/// Instrument the provided file with BOLT.
+/// Returns a path to the instrumented artifact.
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct BoltInstrument {
+    file: PathBuf,
+    hash: String,
+}
+
+impl BoltInstrument {
+    fn new(file: PathBuf) -> Self {
+        let mut hasher = sha2::Sha256::new();
+        hasher.update(t!(fs::read(&file)));
+        let hash = hex::encode(hasher.finalize().as_slice());
+
+        Self { file, hash }
+    }
+}
+
+impl Step for BoltInstrument {
+    type Output = PathBuf;
+
+    const ONLY_HOSTS: bool = false;
+    const DEFAULT: bool = false;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.never()
+    }
+
+    fn run(self, builder: &Builder<'_>) -> PathBuf {
+        if builder.build.config.dry_run() {
+            return self.file.clone();
+        }
+
+        if builder.build.config.llvm_from_ci {
+            println!("warning: trying to use BOLT with LLVM from CI, this will probably not work");
+        }
+
+        println!("Instrumenting {} with BOLT", self.file.display());
+
+        let output_path = create_bolt_output_path(builder, &self.file, &self.hash);
+        if !output_path.is_file() {
+            instrument_with_bolt(&self.file, &output_path);
+        }
+        output_path
+    }
+}
+
+/// Optimize the provided file with BOLT.
+/// Returns a path to the optimized artifact.
+///
+/// The hash is stored in the step to make sure that we don't optimize the same file
+/// twice (even under  different file paths).
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct BoltOptimize {
+    file: PathBuf,
+    profile: PathBuf,
+    hash: String,
+}
+
+impl BoltOptimize {
+    fn new(file: PathBuf, profile: PathBuf) -> Self {
+        let mut hasher = sha2::Sha256::new();
+        hasher.update(t!(fs::read(&file)));
+        hasher.update(t!(fs::read(&profile)));
+        let hash = hex::encode(hasher.finalize().as_slice());
+
+        Self { file, profile, hash }
+    }
+}
+
+impl Step for BoltOptimize {
+    type Output = PathBuf;
+
+    const ONLY_HOSTS: bool = false;
+    const DEFAULT: bool = false;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.never()
+    }
+
+    fn run(self, builder: &Builder<'_>) -> PathBuf {
+        if builder.build.config.dry_run() {
+            return self.file.clone();
+        }
+
+        if builder.build.config.llvm_from_ci {
+            println!("warning: trying to use BOLT with LLVM from CI, this will probably not work");
+        }
+
+        println!("Optimizing {} with BOLT", self.file.display());
+
+        let output_path = create_bolt_output_path(builder, &self.file, &self.hash);
+        if !output_path.is_file() {
+            optimize_with_bolt(&self.file, &self.profile, &output_path);
+        }
+        output_path
+    }
+}
+
 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
 pub struct LlvmTools {
     pub target: TargetSelection,
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 7f8aa2573dd..cc80763ef44 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -62,6 +62,7 @@ macro_rules! book {
                     target: self.target,
                     name: INTERNER.intern_str($book_name),
                     src: INTERNER.intern_path(builder.src.join($path)),
+                    parent: Some(self),
                 })
             }
         }
@@ -119,18 +120,20 @@ impl Step for UnstableBook {
             target: self.target,
             name: INTERNER.intern_str("unstable-book"),
             src: INTERNER.intern_path(builder.md_doc_out(self.target).join("unstable-book")),
+            parent: Some(self),
         })
     }
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
-struct RustbookSrc {
+struct RustbookSrc<P: Step> {
     target: TargetSelection,
     name: Interned<String>,
     src: Interned<PathBuf>,
+    parent: Option<P>,
 }
 
-impl Step for RustbookSrc {
+impl<P: Step> Step for RustbookSrc<P> {
     type Output = ();
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -152,13 +155,18 @@ impl Step for RustbookSrc {
         let index = out.join("index.html");
         let rustbook = builder.tool_exe(Tool::Rustbook);
         let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
-        if builder.config.dry_run() || up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
-            return;
+
+        if !builder.config.dry_run() && !(up_to_date(&src, &index) || up_to_date(&rustbook, &index))
+        {
+            builder.info(&format!("Rustbook ({}) - {}", target, name));
+            let _ = fs::remove_dir_all(&out);
+
+            builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(out));
         }
-        builder.info(&format!("Rustbook ({}) - {}", target, name));
-        let _ = fs::remove_dir_all(&out);
 
-        builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(out));
+        if self.parent.is_some() {
+            builder.maybe_open_in_browser::<P>(index)
+        }
     }
 }
 
@@ -205,6 +213,7 @@ impl Step for TheBook {
             target,
             name: INTERNER.intern_str("book"),
             src: INTERNER.intern_path(builder.src.join(&relative_path)),
+            parent: Some(self),
         });
 
         // building older edition redirects
@@ -213,6 +222,9 @@ impl Step for TheBook {
                 target,
                 name: INTERNER.intern_string(format!("book/{}", edition)),
                 src: INTERNER.intern_path(builder.src.join(&relative_path).join(edition)),
+                // There should only be one book that is marked as the parent for each target, so
+                // treat the other editions as not having a parent.
+                parent: Option::<Self>::None,
             });
         }
 
@@ -228,10 +240,6 @@ impl Step for TheBook {
 
             invoke_rustdoc(builder, compiler, &shared_assets, target, path);
         }
-
-        let out = builder.doc_out(target);
-        let index = out.join("book").join("index.html");
-        builder.maybe_open_in_browser::<Self>(index);
     }
 }
 
@@ -1032,10 +1040,7 @@ impl Step for RustcBook {
             target: self.target,
             name: INTERNER.intern_str("rustc"),
             src: INTERNER.intern_path(out_base),
+            parent: Some(self),
         });
-
-        let out = builder.doc_out(self.target);
-        let index = out.join("rustc").join("index.html");
-        builder.maybe_open_in_browser::<Self>(index);
     }
 }
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index ae72a42973c..6d5753e8a6d 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -87,7 +87,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result<Option<Vec<String>>, Str
     get_git_modified_files(Some(&build.config.src), &vec!["rs"])
 }
 
-#[derive(serde::Deserialize)]
+#[derive(serde_derive::Deserialize)]
 struct RustfmtConfig {
     ignore: Vec<String>,
 }
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index f4abdf1cc57..ebd42bcf678 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1209,6 +1209,15 @@ impl Build {
             && (self.hosts.iter().any(|h| *h == target) || target == self.build)
     }
 
+    /// Checks whether the `compiler` compiling for `target` should be forced to
+    /// use a stage2 compiler instead.
+    ///
+    /// When we download the pre-compiled version of rustc it should be forced to
+    /// use a stage2 compiler.
+    fn force_use_stage2(&self) -> bool {
+        self.config.download_rustc()
+    }
+
     /// Given `num` in the form "a.b.c" return a "release string" which
     /// describes the release version number.
     ///
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index e193e70a0c4..bba4d65e8c3 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -1,7 +1,7 @@
 use std::path::PathBuf;
 use std::process::Command;
 
-use serde::Deserialize;
+use serde_derive::Deserialize;
 
 use crate::cache::INTERNER;
 use crate::util::output;
diff --git a/src/bootstrap/metrics.rs b/src/bootstrap/metrics.rs
index c823dc79684..2e62c950709 100644
--- a/src/bootstrap/metrics.rs
+++ b/src/bootstrap/metrics.rs
@@ -7,7 +7,7 @@
 use crate::builder::Step;
 use crate::util::t;
 use crate::Build;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::cell::RefCell;
 use std::fs::File;
 use std::io::BufWriter;
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 21157b02a78..8c2bece1e62 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -16,7 +16,6 @@ use std::io;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
-use crate::bolt::{instrument_with_bolt_inplace, optimize_library_with_bolt_inplace};
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::channel;
 use crate::config::{Config, TargetSelection};
@@ -216,21 +215,24 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
         }
     }
 
-    if CiEnv::is_ci() {
+    if is_ci_llvm_modified(config) {
+        eprintln!("Detected LLVM as non-available: running in CI and modified LLVM in this change");
+        return false;
+    }
+
+    true
+}
+
+/// Returns true if we're running in CI with modified LLVM (and thus can't download it)
+pub(crate) fn is_ci_llvm_modified(config: &Config) -> bool {
+    CiEnv::is_ci() && {
         // We assume we have access to git, so it's okay to unconditionally pass
         // `true` here.
         let llvm_sha = detect_llvm_sha(config, true);
         let head_sha = output(config.git().arg("rev-parse").arg("HEAD"));
         let head_sha = head_sha.trim();
-        if llvm_sha == head_sha {
-            eprintln!(
-                "Detected LLVM as non-available: running in CI and modified LLVM in this change"
-            );
-            return false;
-        }
+        llvm_sha == head_sha
     }
-
-    true
 }
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@@ -520,34 +522,12 @@ impl Step for Llvm {
             }
         }
 
-        // After LLVM is built, we modify (instrument or optimize) the libLLVM.so library file
-        // in place. This is fine, because currently we do not support incrementally rebuilding
-        // LLVM after a configuration change, so to rebuild it the build files have to be removed,
-        // which will also remove these modified files.
-        if builder.config.llvm_bolt_profile_generate {
-            instrument_with_bolt_inplace(&get_built_llvm_lib_path(&res.llvm_config));
-        }
-        if let Some(path) = &builder.config.llvm_bolt_profile_use {
-            optimize_library_with_bolt_inplace(
-                &get_built_llvm_lib_path(&res.llvm_config),
-                &Path::new(path),
-            );
-        }
-
         t!(stamp.write());
 
         res
     }
 }
 
-/// Returns path to a built LLVM library (libLLVM.so).
-/// Assumes that we have built LLVM into a single library file.
-fn get_built_llvm_lib_path(llvm_config_path: &Path) -> PathBuf {
-    let mut cmd = Command::new(llvm_config_path);
-    cmd.arg("--libfiles");
-    PathBuf::from(output(&mut cmd).trim())
-}
-
 fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
     if !builder.config.llvm_version_check {
         return;
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index 1969e0b6f87..7aab88a1a73 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -1,6 +1,6 @@
 use crate::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::util::t;
-use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
 use std::collections::HashMap;
 use std::env;
 use std::fmt;
diff --git a/src/ci/docker/scripts/fuchsia-test-runner.py b/src/ci/docker/scripts/fuchsia-test-runner.py
index c3d532c4b27..e7d1d9781d5 100755
--- a/src/ci/docker/scripts/fuchsia-test-runner.py
+++ b/src/ci/docker/scripts/fuchsia-test-runner.py
@@ -9,6 +9,7 @@ https://doc.rust-lang.org/stable/rustc/platform-support/fuchsia.html#aarch64-unk
 
 import argparse
 from dataclasses import dataclass
+import fcntl
 import glob
 import hashlib
 import json
@@ -146,6 +147,9 @@ class TestEnvironment:
     def zxdb_script_path(self):
         return os.path.join(self.tmp_dir(), "zxdb_script")
 
+    def pm_lockfile_path(self):
+        return os.path.join(self.tmp_dir(), "pm.lock")
+
     def log_info(self, msg):
         print(msg)
 
@@ -460,6 +464,9 @@ class TestEnvironment:
             stderr=self.subprocess_output(),
         )
 
+        # Create lockfiles
+        open(self.pm_lockfile_path(), 'a').close()
+
         # Write to file
         self.write_to_file()
 
@@ -676,19 +683,25 @@ class TestEnvironment:
             log("Publishing package to repo...")
 
             # Publish package to repo
-            subprocess.check_call(
-                [
-                    self.tool_path("pm"),
-                    "publish",
-                    "-a",
-                    "-repo",
-                    self.repo_dir(),
-                    "-f",
-                    far_path,
-                ],
-                stdout=log_file,
-                stderr=log_file,
-            )
+            with open(self.pm_lockfile_path(), 'w') as pm_lockfile:
+                fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_EX)
+                subprocess.check_call(
+                    [
+                        self.tool_path("pm"),
+                        "publish",
+                        "-a",
+                        "-repo",
+                        self.repo_dir(),
+                        "-f",
+                        far_path,
+                    ],
+                    stdout=log_file,
+                    stderr=log_file,
+                )
+                # This lock should be released automatically when the pm
+                # lockfile is closed, but we'll be polite and unlock it now
+                # since the spec leaves some wiggle room.
+                fcntl.lockf(pm_lockfile.fileno(), fcntl.LOCK_UN)
 
             log("Running ffx test...")
 
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index ad9c308ad85..11f1532bef5 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -78,7 +78,7 @@ x--expand-yaml-anchors--remove:
     <<: *base-job
 
   - &job-macos-xl
-    os: macos-latest  # We don't have an XL builder for this
+    os: macos-12-xl
     <<: *base-job
 
   - &job-windows-xl
diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh
deleted file mode 100755
index cbe32920a74..00000000000
--- a/src/ci/pgo.sh
+++ /dev/null
@@ -1,230 +0,0 @@
-#!/bin/bash
-# ignore-tidy-linelength
-
-set -euxo pipefail
-
-ci_dir=`cd $(dirname $0) && pwd`
-source "$ci_dir/shared.sh"
-
-# The root checkout, where the source is located
-CHECKOUT=/checkout
-
-DOWNLOADED_LLVM=/rustroot
-
-# The main directory where the build occurs, which can be different between linux and windows
-BUILD_ROOT=$CHECKOUT/obj
-
-if isWindows; then
-    CHECKOUT=$(pwd)
-    DOWNLOADED_LLVM=$CHECKOUT/citools/clang-rust
-    BUILD_ROOT=$CHECKOUT
-fi
-
-# The various build artifacts used in other commands: to launch rustc builds, build the perf
-# collector, and run benchmarks to gather profiling data
-BUILD_ARTIFACTS=$BUILD_ROOT/build/$PGO_HOST
-RUSTC_STAGE_0=$BUILD_ARTIFACTS/stage0/bin/rustc
-CARGO_STAGE_0=$BUILD_ARTIFACTS/stage0/bin/cargo
-RUSTC_STAGE_2=$BUILD_ARTIFACTS/stage2/bin/rustc
-
-# Windows needs these to have the .exe extension
-if isWindows; then
-    RUSTC_STAGE_0="${RUSTC_STAGE_0}.exe"
-    CARGO_STAGE_0="${CARGO_STAGE_0}.exe"
-    RUSTC_STAGE_2="${RUSTC_STAGE_2}.exe"
-fi
-
-# Make sure we have a temporary PGO work folder
-PGO_TMP=/tmp/tmp-pgo
-mkdir -p $PGO_TMP
-rm -rf $PGO_TMP/*
-
-RUSTC_PERF=$PGO_TMP/rustc-perf
-
-# Compile several crates to gather execution PGO profiles.
-# Arg0 => profiles (Debug, Opt)
-# Arg1 => scenarios (Full, IncrFull, All)
-# Arg2 => crates (syn, cargo, ...)
-gather_profiles () {
-  cd $BUILD_ROOT
-
-  # Compile libcore, both in opt-level=0 and opt-level=3
-  RUSTC_BOOTSTRAP=1 $RUSTC_STAGE_2 \
-      --edition=2021 --crate-type=lib $CHECKOUT/library/core/src/lib.rs \
-      --out-dir $PGO_TMP
-  RUSTC_BOOTSTRAP=1 $RUSTC_STAGE_2 \
-      --edition=2021 --crate-type=lib -Copt-level=3 $CHECKOUT/library/core/src/lib.rs \
-      --out-dir $PGO_TMP
-
-  cd $RUSTC_PERF
-
-  # Run rustc-perf benchmarks
-  # Benchmark using profile_local with eprintln, which essentially just means
-  # don't actually benchmark -- just make sure we run rustc a bunch of times.
-  RUST_LOG=collector=debug \
-  RUSTC=$RUSTC_STAGE_0 \
-  RUSTC_BOOTSTRAP=1 \
-  $CARGO_STAGE_0 run -p collector --bin collector -- \
-      profile_local \
-      eprintln \
-      $RUSTC_STAGE_2 \
-      --id Test \
-      --profiles $1 \
-      --cargo $CARGO_STAGE_0 \
-      --scenarios $2 \
-      --include $3
-
-  cd $BUILD_ROOT
-}
-
-# This path has to be absolute
-LLVM_PROFILE_DIRECTORY_ROOT=$PGO_TMP/llvm-pgo
-
-# We collect LLVM profiling information and rustc profiling information in
-# separate phases. This increases build time -- though not by a huge amount --
-# but prevents any problems from arising due to different profiling runtimes
-# being simultaneously linked in.
-# LLVM IR PGO does not respect LLVM_PROFILE_FILE, so we have to set the profiling file
-# path through our custom environment variable. We include the PID in the directory path
-# to avoid updates to profile files being lost because of race conditions.
-LLVM_PROFILE_DIR=${LLVM_PROFILE_DIRECTORY_ROOT}/prof-%p python3 $CHECKOUT/x.py build \
-    --target=$PGO_HOST \
-    --host=$PGO_HOST \
-    --stage 2 library/std \
-    --llvm-profile-generate
-
-# Compile rustc-perf:
-# - get the expected commit source code: on linux, the Dockerfile downloads a source archive before
-# running this script. On Windows, we do that here.
-if isLinux; then
-    cp -r /tmp/rustc-perf $RUSTC_PERF
-    chown -R $(whoami): $RUSTC_PERF
-else
-    # rustc-perf version from 2022-07-22
-    PERF_COMMIT=3c253134664fdcba862c539d37f0de18557a9a4c
-    retry curl -LS -o $PGO_TMP/perf.zip \
-        https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \
-        cd $PGO_TMP && unzip -q perf.zip && \
-        mv rustc-perf-$PERF_COMMIT $RUSTC_PERF && \
-        rm perf.zip
-fi
-
-# - build rustc-perf's collector ahead of time, which is needed to make sure the rustc-fake binary
-# used by the collector is present.
-cd $RUSTC_PERF
-
-RUSTC=$RUSTC_STAGE_0 \
-RUSTC_BOOTSTRAP=1 \
-$CARGO_STAGE_0 build -p collector
-
-# Here we're profiling LLVM, so we only care about `Debug` and `Opt`, because we want to stress
-# codegen. We also profile some of the most prolific crates.
-gather_profiles "Debug,Opt" "Full" \
-    "syn-1.0.89,cargo-0.60.0,serde-1.0.136,ripgrep-13.0.0,regex-1.5.5,clap-3.1.6,hyper-0.14.18"
-
-LLVM_PROFILE_MERGED_FILE=$PGO_TMP/llvm-pgo.profdata
-
-# Merge the profile data we gathered for LLVM
-# Note that this uses the profdata from the clang we used to build LLVM,
-# which likely has a different version than our in-tree clang.
-$DOWNLOADED_LLVM/bin/llvm-profdata merge -o ${LLVM_PROFILE_MERGED_FILE} ${LLVM_PROFILE_DIRECTORY_ROOT}
-
-echo "LLVM PGO statistics"
-du -sh ${LLVM_PROFILE_MERGED_FILE}
-du -sh ${LLVM_PROFILE_DIRECTORY_ROOT}
-echo "Profile file count"
-find ${LLVM_PROFILE_DIRECTORY_ROOT} -type f | wc -l
-
-# We don't need the individual .profraw files now that they have been merged into a final .profdata
-rm -r $LLVM_PROFILE_DIRECTORY_ROOT
-
-# Rustbuild currently doesn't support rebuilding LLVM when PGO options
-# change (or any other llvm-related options); so just clear out the relevant
-# directories ourselves.
-rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld
-
-# Okay, LLVM profiling is done, switch to rustc PGO.
-
-# The path has to be absolute
-RUSTC_PROFILE_DIRECTORY_ROOT=$PGO_TMP/rustc-pgo
-
-python3 $CHECKOUT/x.py build --target=$PGO_HOST --host=$PGO_HOST \
-    --stage 2 library/std \
-    --rust-profile-generate=${RUSTC_PROFILE_DIRECTORY_ROOT}
-
-# Here we're profiling the `rustc` frontend, so we also include `Check`.
-# The benchmark set includes various stress tests that put the frontend under pressure.
-if isLinux; then
-    # The profile data is written into a single filepath that is being repeatedly merged when each
-    # rustc invocation ends. Empirically, this can result in some profiling data being lost. That's
-    # why we override the profile path to include the PID. This will produce many more profiling
-    # files, but the resulting profile will produce a slightly faster rustc binary.
-    LLVM_PROFILE_FILE=${RUSTC_PROFILE_DIRECTORY_ROOT}/default_%m_%p.profraw gather_profiles \
-        "Check,Debug,Opt" "All" \
-        "externs,ctfe-stress-5,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress,diesel-1.4.8,bitmaps-3.1.0"
-else
-    # On windows, we don't do that yet (because it generates a lot of data, hitting disk space
-    # limits on the builder), and use the default profraw merging behavior.
-    gather_profiles \
-        "Check,Debug,Opt" "All" \
-        "externs,ctfe-stress-5,cargo-0.60.0,token-stream-stress,match-stress,tuple-stress,diesel-1.4.8,bitmaps-3.1.0"
-fi
-
-RUSTC_PROFILE_MERGED_FILE=$PGO_TMP/rustc-pgo.profdata
-
-# Merge the profile data we gathered
-$BUILD_ARTIFACTS/llvm/bin/llvm-profdata \
-    merge -o ${RUSTC_PROFILE_MERGED_FILE} ${RUSTC_PROFILE_DIRECTORY_ROOT}
-
-echo "Rustc PGO statistics"
-du -sh ${RUSTC_PROFILE_MERGED_FILE}
-du -sh ${RUSTC_PROFILE_DIRECTORY_ROOT}
-echo "Profile file count"
-find ${RUSTC_PROFILE_DIRECTORY_ROOT} -type f | wc -l
-
-# We don't need the individual .profraw files now that they have been merged into a final .profdata
-rm -r $RUSTC_PROFILE_DIRECTORY_ROOT
-
-# Rustbuild currently doesn't support rebuilding LLVM when PGO options
-# change (or any other llvm-related options); so just clear out the relevant
-# directories ourselves.
-rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld
-
-if isLinux; then
-  # Gather BOLT profile (BOLT is currently only available on Linux)
-  python3 ../x.py build --target=$PGO_HOST --host=$PGO_HOST \
-      --stage 2 library/std \
-      --llvm-profile-use=${LLVM_PROFILE_MERGED_FILE} \
-      --llvm-bolt-profile-generate
-
-  BOLT_PROFILE_MERGED_FILE=/tmp/bolt.profdata
-
-  # Here we're profiling Bolt.
-  gather_profiles "Check,Debug,Opt" "Full" \
-  "syn-1.0.89,serde-1.0.136,ripgrep-13.0.0,regex-1.5.5,clap-3.1.6,hyper-0.14.18"
-
-  merge-fdata /tmp/prof.fdata* > ${BOLT_PROFILE_MERGED_FILE}
-
-  echo "BOLT statistics"
-  du -sh /tmp/prof.fdata*
-  du -sh ${BOLT_PROFILE_MERGED_FILE}
-  echo "Profile file count"
-  find /tmp/prof.fdata* -type f | wc -l
-
-  rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld
-
-  # This produces the actual final set of artifacts, using both the LLVM and rustc
-  # collected profiling data.
-  $@ \
-      --rust-profile-use=${RUSTC_PROFILE_MERGED_FILE} \
-      --llvm-profile-use=${LLVM_PROFILE_MERGED_FILE} \
-      --llvm-bolt-profile-use=${BOLT_PROFILE_MERGED_FILE}
-else
-  $@ \
-      --rust-profile-use=${RUSTC_PROFILE_MERGED_FILE} \
-      --llvm-profile-use=${LLVM_PROFILE_MERGED_FILE}
-fi
-
-echo "Rustc binary size"
-ls -la ./build/$PGO_HOST/stage2/bin
-ls -la ./build/$PGO_HOST/stage2/lib
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
index bd8fd524a26..fe3083dc31e 100644
--- a/src/ci/stage-build.py
+++ b/src/ci/stage-build.py
@@ -798,14 +798,16 @@ def execute_build_pipeline(timer: Timer, pipeline: Pipeline, final_build_args: L
                     "--llvm-profile-use",
                     pipeline.llvm_profile_merged_file(),
                     "--llvm-bolt-profile-generate",
+                    "--rust-profile-use",
+                    pipeline.rustc_profile_merged_file()
                 ])
                 record_metrics(pipeline, rustc_build)
 
             with stage3.section("Gather profiles"):
                 gather_llvm_bolt_profiles(pipeline)
 
+        # LLVM is not being cleared here, we want to reuse the previous build
         print_free_disk_space(pipeline)
-        clear_llvm_files(pipeline)
         final_build_args += [
             "--llvm-bolt-profile-use",
             pipeline.llvm_bolt_profile_merged_file()
diff --git a/src/doc/book b/src/doc/book
-Subproject d94e03a18a2590ed3f1c67b859cb11528d2a2d5
+Subproject 21a2ed14f4480dab62438dcc1130291bebc6537
diff --git a/src/doc/reference b/src/doc/reference
-Subproject e5adb99c04817b7fbe08f4ffce5b36702667345
+Subproject a9afb04b47a84a6753e4dc657348c324c876102
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject efe23c4fe12e06351b8dc8c3d18312c76145510
+Subproject af0998b7473839ca75563ba3d3e7fd0160bef23
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 41a96ab971cb45e2a184df20619ad1829765c99
+Subproject b06dab84083390e0ee1e998f466545a8a1a76a9
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 16057048259..9eafa27e2b7 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -13,6 +13,8 @@ for targets at each tier, see the [Target Tier Policy](target-tier-policy.md).
 Targets are identified by their "target triple" which is the string to inform
 the compiler what kind of output should be produced.
 
+Component availability is tracked [here](https://rust-lang.github.io/rustup-components-history/).
+
 ## Tier 1 with Host Tools
 
 Tier 1 targets can be thought of as "guaranteed to work". The Rust project
@@ -216,7 +218,7 @@ target | std | host | notes
 [`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ |  | ARM64 SOLID with TOPPERS/ASP3
 [`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * |  | ARM64 Nintendo Switch, Horizon
 [`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
-[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ? |  | ARM64 QNX Neutrino 7.1 RTOS |
+[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ |  | ARM64 QNX Neutrino 7.1 RTOS |
 `aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
 `aarch64-unknown-hermit` | ✓ |  | ARM64 HermitCore
 `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
@@ -308,7 +310,7 @@ target | std | host | notes
 `x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
 `x86_64-apple-tvos` | * | | x86 64-bit tvOS
 [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
-[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ? |  | x86 64-bit QNX Neutrino 7.1 RTOS |
+[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ |  | x86 64-bit QNX Neutrino 7.1 RTOS |
 [`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
 `x86_64-pc-windows-msvc` | * |  | 64-bit Windows XP support
 `x86_64-sun-solaris` | ? |  | Deprecated target for 64-bit Solaris 10/11, illumos
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index 63dde2aaedd..4d97b8c6cb9 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -12,7 +12,6 @@ The [Fuchsia team]:
 - Tyler Mandry ([@tmandry](https://github.com/tmandry))
 - Dan Johnson ([@computerdruid](https://github.com/computerdruid))
 - David Koloski ([@djkoloski](https://github.com/djkoloski))
-- Andrew Pollack ([@andrewpollack](https://github.com/andrewpollack))
 - Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3))
 
 As the team evolves over time, the specific members listed here may differ from
@@ -717,7 +716,7 @@ run the full `tests/ui` test suite:
     --stage=2                                                                 \
     test tests/ui                                                             \
     --target x86_64-unknown-fuchsia                                           \
-    --run=always --jobs 1                                                     \
+    --run=always                                                              \
     --test-args --target-rustcflags                                           \
     --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib             \
     --test-args --target-rustcflags                                           \
@@ -729,9 +728,6 @@ run the full `tests/ui` test suite:
 )
 ```
 
-*Note: The test suite cannot be run in parallel at the moment, so `x.py`
-must be run with `--jobs 1` to ensure only one test runs at a time.*
-
 By default, `x.py` compiles test binaries with `panic=unwind`. If you built your
 Rust toolchain with `-Cpanic=abort`, you need to tell `x.py` to compile test
 binaries with `panic=abort` as well:
@@ -908,7 +904,7 @@ through our `x.py` invocation. The full invocation is:
     --stage=2                                                                 \
     test tests/${TEST}                                                        \
     --target x86_64-unknown-fuchsia                                           \
-    --run=always --jobs 1                                                     \
+    --run=always                                                              \
     --test-args --target-rustcflags                                           \
     --test-args -Lnative=${SDK_PATH}/arch/{x64|arm64}/sysroot/lib             \
     --test-args --target-rustcflags                                           \
diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md
index 37d0c31976c..38198fe6c3a 100644
--- a/src/doc/rustc/src/platform-support/nto-qnx.md
+++ b/src/doc/rustc/src/platform-support/nto-qnx.md
@@ -2,9 +2,9 @@
 
 **Tier: 3**
 
-[BlackBerry® QNX®][BlackBerry] Neutrino (nto) Real-time operating system.
+[QNX®][BlackBerry] Neutrino (nto) Real-time operating system.
 The support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit]
-and [BlackBerry][BlackBerry].
+and [Blackberry QNX][BlackBerry].
 
 [BlackBerry]: https://blackberry.qnx.com
 [Elektrobit]: https://www.elektrobit.com
@@ -19,19 +19,24 @@ and [BlackBerry][BlackBerry].
 Currently, only cross-compilation for QNX Neutrino on AArch64 and x86_64 are supported (little endian).
 Adding other architectures that are supported by QNX Neutrino is possible.
 
-The standard library does not yet support QNX Neutrino. Therefore, only `no_std` code can
-be compiled.
+The standard library, including `core` and `alloc` (with default allocator) are supported.
 
-`core` and `alloc` (with default allocator) are supported.
+For building or using the Rust toolchain for QNX Neutrino, the
+[QNX Software Development Platform (SDP)](https://blackberry.qnx.com/en/products/foundation-software/qnx-software-development-platform)
+must be installed and initialized.
+Initialization is usually done by sourcing `qnxsdp-env.sh` (this will be installed as part of the SDP, see also installation instruction provided with the SDP).
+Afterwards [`qcc`](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.utilities/topic/q/qcc.html) (QNX C/C++ compiler)
+should be available (in the `$PATH` variable).
+`qcc` will be called e.g. for linking executables.
 
-Applications must link against `libc.so` (see example). This is required because applications
-always link against the `crt` library and `crt` depends on `libc.so`.
-
-The correct version of `qcc` must be available by setting the `$PATH` variable (e.g. by sourcing `qnxsdp-env.sh` of the
-QNX Neutrino toolchain).
+When linking `no_std` applications, they must link against `libc.so` (see example). This is
+required because applications always link against the `crt` library and `crt` depends on `libc.so`.
+This is done automatically when using the standard library.
 
 ### Small example application
 
+Small `no_std` example is shown below. Applications using the standard library work as well.
+
 ```rust,ignore (platform-specific)
 #![no_std]
 #![no_main]
@@ -89,30 +94,150 @@ changelog-seen = 2
 
 2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets)
 
-Run the following:
+Compiling the Rust toolchain requires the same environment variables used for compiling C binaries.
+Refer to the [QNX developer manual](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.prog/topic/devel_OS_version.html).
+
+To compile for QNX Neutrino (aarch64 and x86_64) and Linux (x86_64):
 
 ```bash
-env \
-    CC_aarch64-unknown-nto-qnx710="qcc" \
-    CFLAGS_aarch64-unknown-nto-qnx710="-Vgcc_ntoaarch64le_cxx" \
-    CXX_aarch64-unknown-nto-qnx710="qcc" \
-    AR_aarch64_unknown_nto_qnx710="ntoaarch64-ar" \
-    CC_x86_64-pc-nto-qnx710="qcc" \
-    CFLAGS_x86_64-pc-nto-qnx710="-Vgcc_ntox86_64_cxx" \
-    CXX_x86_64-pc-nto-qnx710="qcc" \
-    AR_x86_64_pc_nto_qnx710="ntox86_64-ar" \
-        ./x.py build --target aarch64-unknown-nto-qnx710 --target x86_64-pc-nto-qnx710 --target x86_64-unknown-linux-gnu rustc library/core library/alloc/
+export build_env='
+    CC_aarch64-unknown-nto-qnx710=qcc
+    CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx
+    CXX_aarch64-unknown-nto-qnx710=qcc
+    AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar
+    CC_x86_64-pc-nto-qnx710=qcc
+    CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx
+    CXX_x86_64-pc-nto-qnx710=qcc
+    AR_x86_64_pc_nto_qnx710=ntox86_64-ar'
+
+env $build_env \
+    ./x.py build \
+        --target aarch64-unknown-nto-qnx710 \
+        --target x86_64-pc-nto-qnx710 \
+        --target x86_64-unknown-linux-gnu \
+        rustc library/core library/alloc
 ```
 
+## Running the Rust test suite
+
+The test suites of the Rust compiler and standard library can be executed much like other Rust targets.
+The environment for testing should match the one used during compiler compilation (refer to `build_env` and `qcc`/`PATH` above) with the
+addition of the TEST_DEVICE_ADDR environment variable.
+The TEST_DEVICE_ADDR variable controls the remote runner and should point to the target, despite localhost being shown in the following example.
+Note that some tests are failing which is why they are currently excluded by the target maintainers which can be seen in the following example.
+
+To run all tests on a x86_64 QNX Neutrino target:
+
+```bash
+export TEST_DEVICE_ADDR="localhost:12345" # must address the test target, can be a SSH tunnel
+export build_env='
+    CC_aarch64-unknown-nto-qnx710=qcc
+    CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx
+    CXX_aarch64-unknown-nto-qnx710=qcc
+    AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar
+    CC_x86_64-pc-nto-qnx710=qcc
+    CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx
+    CXX_x86_64-pc-nto-qnx710=qcc
+    AR_x86_64_pc_nto_qnx710=ntox86_64-ar'
+
+# Disable tests that only work on the host or don't make sense for this target.
+# See also:
+# - src/ci/docker/host-x86_64/i686-gnu/Dockerfile
+# - https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Running.20tests.20on.20remote.20target
+# - .github/workflows/ci.yml
+export exclude_tests='
+    --exclude src/bootstrap
+    --exclude src/tools/error_index_generator
+    --exclude src/tools/linkchecker
+    --exclude tests/ui-fulldeps
+    --exclude rustc
+    --exclude rustdoc
+    --exclude tests/run-make-fulldeps'
+
+env $build_env \
+    ./x.py test -j 1 \
+        $exclude_tests \
+        --stage 1 \
+        --target x86_64-pc-nto-qnx710
+```
+
+Currently, only one thread can be used when testing due to limitations in `libc::fork` and `libc::posix_spawnp`.
+See [fork documentation](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html)
+(error section) for more information.
+This can be achieved by using the `-j 1` parameter in the `x.py` call.
+This issue is being researched and we will try to allow parallelism in the future.
+
 ## Building Rust programs
 
-Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you must either build Rust with the target enabled (see "Building the target" above), or build your own copy of  `core` by using
-`build-std` or similar.
+Rust does not yet ship pre-compiled artifacts for this target.
+To compile for this target, you must either build Rust with the target enabled (see "Building the target" above),
+or build your own copy of `core` by using `build-std` or similar.
 
 ## Testing
 
-Compiled executables can directly be run on QNX Neutrino.
+Compiled executables can run directly on QNX Neutrino.
+
+### Rust std library test suite
+
+The target needs sufficient resources to execute all tests. The commands below assume that a QEMU image
+is used.
+
+* Ensure that the temporary directory used by `remote-test-server` has enough free space and inodes.
+  5GB of free space and 40000 inodes are known to be sufficient (the test will create more than 32k files).
+  To create a QEMU image in an empty directory, run this command inside the directory:
+
+  ```bash
+  mkqnximage --type=qemu --ssh-ident=$HOME/.ssh/id_ed25519.pub --data-size=5000 --data-inodes=40000
+  ```
+
+  `/data` should have enough free resources.
+  Set the `TMPDIR` environment variable accordingly when running `remote-test-server`, e.g.:
+  ```bash
+  TMPDIR=/data/tmp/rust remote-test-server --bind 0.0.0.0:12345
+  ```
+
+* Ensure the TCP stack can handle enough parallel connections (default is 200, should be 300 or higher).
+  After creating an image (see above), edit the file `output/build/startup.sh`:
+  1. Search for `io-pkt-v6-hc`
+  2. Add the parameter `-ptcpip threads_max=300`, e.g.:
+     ```text
+     io-pkt-v6-hc -U 33:33 -d e1000 -ptcpip threads_max=300
+     ```
+  3. Update the image by running `mkqnximage` again with the same parameters as above for creating it.
+
+* Running and stopping the virtual machine
+
+  To start the virtual machine, run inside the directory of the VM:
+
+  ```bash
+  mkqnximage --run=-h
+  ```
+
+  To stop the virtual machine, run inside the directory of the VM:
+
+  ```bash
+  mkqnximage --stop
+  ```
+
+* Ensure local networking
+
+  Ensure that 'localhost' is getting resolved to 127.0.0.1. If you can't ping the localhost, some tests may fail.
+  Ensure it's appended to /etc/hosts (if first `ping` command fails).
+  Commands have to be executed inside the virtual machine!
+
+  ```bash
+  $ ping localhost
+  ping: Cannot resolve "localhost" (Host name lookup failure)
+
+  $ echo "127.0.0.1 localhost" >> /etc/hosts
+
+  $ ping localhost
+  PING localhost (127.0.0.1): 56 data bytes
+  64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=1 ms
+  ```
 
 ## Cross-compilation toolchains and C code
 
-Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above), to ensure `qcc` is used with proper arguments. To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout.
+Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above),
+to ensure `qcc` is used with proper arguments.
+To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout.
diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md
index d666d54b315..28a004a9253 100644
--- a/src/doc/rustdoc/src/how-to-read-rustdoc.md
+++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md
@@ -84,6 +84,9 @@ When typing in the search bar, you can prefix your search term with a type
 followed by a colon (such as `mod:`) to restrict the results to just that
 kind of item. (The available items are listed in the help popup.)
 
+Searching for `println!` will search for a macro named `println`, just like
+searching for `macro:println` does.
+
 ### Changing displayed theme
 
 You can change the displayed theme by opening the settings menu (the gear
diff --git a/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md b/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md
new file mode 100644
index 00000000000..c7f10afaccc
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/export-executable-symbols.md
@@ -0,0 +1,43 @@
+# `export-executable-symbols`
+
+The tracking issue for this feature is: [#84161](https://github.com/rust-lang/rust/issues/84161).
+
+------------------------
+
+The `-Zexport-executable-symbols` compiler flag makes `rustc` export symbols from executables. The resulting binary is runnable, but can also be used as a dynamic library. This is useful for interoperating with programs written in other languages, in particular languages with a runtime like Java or Lua.
+
+For example on windows:
+```rust
+#[no_mangle]
+fn my_function() -> usize {
+    return 42;
+}
+
+fn main() {
+    println!("Hello, world!");
+}
+```
+
+A standard `cargo build` will produce a `.exe` without an export directory. When the `export-executable-symbols` flag is added
+
+```Bash
+export RUSTFLAGS="-Zexport-executable-symbols"
+cargo build
+```
+
+the binary has an export directory with the functions:
+
+```plain
+The Export Tables (interpreted .edata section contents)
+
+...
+
+[Ordinal/Name Pointer] Table
+    [   0] my_function
+    [   1] main
+```
+(the output of `objdump -x` on the binary)
+
+Please note that the `#[no_mangle]` attribute is required. Without it, the symbol is not exported.
+
+The equivalent of this flag in C and C++ compilers is the `__declspec(dllexport)` annotation or the `-rdynamic` linker flag.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0e8f0cfc518..bbd9f18973a 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -25,7 +25,7 @@ use rustc_middle::middle::resolve_bound_vars as rbv;
 use rustc_middle::ty::fold::TypeFolder;
 use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::TypeVisitableExt;
-use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
+use rustc_middle::ty::{self, AdtKind, EarlyBinder, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{AstPass, MacroKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index fc1396e86f6..6d8380c5fcc 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -22,7 +22,7 @@ use rustc_hir::{BodyId, Mutability};
 use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
 use rustc_index::vec::IndexVec;
 use rustc_middle::ty::fast_reject::SimplifiedType;
-use rustc_middle::ty::{self, DefIdTree, TyCtxt, Visibility};
+use rustc_middle::ty::{self, TyCtxt, Visibility};
 use rustc_resolve::rustdoc::{add_doc_fragment, attrs_to_doc_fragments, inner_docs, DocFragment};
 use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
@@ -1017,12 +1017,12 @@ pub(crate) fn collapse_doc_fragments(doc_strings: &[DocFragment]) -> String {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub(crate) struct ItemLink {
     /// The original link written in the markdown
-    pub(crate) link: String,
+    pub(crate) link: Box<str>,
     /// The link text displayed in the HTML.
     ///
     /// This may not be the same as `link` if there was a disambiguator
     /// in an intra-doc link (e.g. \[`fn@f`\])
-    pub(crate) link_text: String,
+    pub(crate) link_text: Box<str>,
     /// The `DefId` of the Item whose **HTML Page** contains the item being
     /// linked to. This will be different to `item_id` on item's that don't
     /// have their own page, such as struct fields and enum variants.
@@ -1035,9 +1035,9 @@ pub struct RenderedLink {
     /// The text the link was original written as.
     ///
     /// This could potentially include disambiguators and backticks.
-    pub(crate) original_text: String,
+    pub(crate) original_text: Box<str>,
     /// The text to display in the HTML
-    pub(crate) new_text: String,
+    pub(crate) new_text: Box<str>,
     /// The URL to put in the `href`
     pub(crate) href: String,
     /// The tooltip.
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index c9c1c2c458a..cafb00df51e 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -17,7 +17,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::ConstValue;
 use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
-use rustc_middle::ty::{self, DefIdTree, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::symbol::{kw, sym, Symbol};
 use std::fmt::Write as _;
 use std::mem;
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 8a73d25d3f0..9cf84acc79f 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -769,8 +769,8 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
                 match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) {
                     Ok(p) => p,
                     Err(_) => {
-                        debug!("Cannot build a parser to check mod attr so skipping...");
-                        return true;
+                        // If there is an unclosed delimiter, an error will be returned by the tokentrees.
+                        return false;
                     }
                 };
             // If a parsing error happened, it's very likely that the attribute is incomplete.
@@ -778,15 +778,7 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool {
                 e.cancel();
                 return false;
             }
-            // We now check if there is an unclosed delimiter for the attribute. To do so, we look at
-            // the `unclosed_delims` and see if the opening square bracket was closed.
-            parser
-                .unclosed_delims()
-                .get(0)
-                .map(|unclosed| {
-                    unclosed.unclosed_span.map(|s| s.lo()).unwrap_or(BytePos(0)) != BytePos(2)
-                })
-                .unwrap_or(true)
+            true
         })
     })
     .unwrap_or(false)
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 6bdd9db9bfa..f9ea829e388 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -19,7 +19,6 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_metadata::creader::{CStore, LoadedMacro};
 use rustc_middle::ty;
-use rustc_middle::ty::DefIdTree;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::kw;
 use rustc_span::{sym, Symbol};
@@ -772,14 +771,21 @@ pub(crate) fn link_tooltip(did: DefId, fragment: &Option<UrlFragment>, cx: &Cont
     let Some((fqp, shortty)) = cache.paths.get(&did)
         .or_else(|| cache.external_paths.get(&did))
         else { return String::new() };
-    let fqp = fqp.iter().map(|sym| sym.as_str()).join("::");
+    let mut buf = Buffer::new();
     if let &Some(UrlFragment::Item(id)) = fragment {
-        let name = cx.tcx().item_name(id);
-        let descr = cx.tcx().def_descr(id);
-        format!("{descr} {fqp}::{name}")
-    } else {
-        format!("{shortty} {fqp}")
+        write!(buf, "{} ", cx.tcx().def_descr(id));
+        for component in fqp {
+            write!(buf, "{component}::");
+        }
+        write!(buf, "{}", cx.tcx().item_name(id));
+    } else if !fqp.is_empty() {
+        let mut fqp_it = fqp.into_iter();
+        write!(buf, "{shortty} {}", fqp_it.next().unwrap());
+        for component in fqp_it {
+            write!(buf, "::{component}");
+        }
     }
+    buf.into_inner()
 }
 
 /// Used to render a [`clean::Path`].
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 89f1ad71134..fe446ae3c16 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -978,7 +978,7 @@ impl Markdown<'_> {
         let mut replacer = |broken_link: BrokenLink<'_>| {
             links
                 .iter()
-                .find(|link| link.original_text.as_str() == &*broken_link.reference)
+                .find(|link| &*link.original_text == &*broken_link.reference)
                 .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
         };
 
@@ -1061,7 +1061,7 @@ impl MarkdownSummaryLine<'_> {
         let mut replacer = |broken_link: BrokenLink<'_>| {
             links
                 .iter()
-                .find(|link| link.original_text.as_str() == &*broken_link.reference)
+                .find(|link| &*link.original_text == &*broken_link.reference)
                 .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
         };
 
@@ -1108,7 +1108,7 @@ fn markdown_summary_with_limit(
     let mut replacer = |broken_link: BrokenLink<'_>| {
         link_names
             .iter()
-            .find(|link| link.original_text.as_str() == &*broken_link.reference)
+            .find(|link| &*link.original_text == &*broken_link.reference)
             .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
     };
 
@@ -1189,7 +1189,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
     let mut replacer = |broken_link: BrokenLink<'_>| {
         link_names
             .iter()
-            .find(|link| link.original_text.as_str() == &*broken_link.reference)
+            .find(|link| &*link.original_text == &*broken_link.reference)
             .map(|link| (link.href.as_str().into(), link.tooltip.as_str().into()))
     };
 
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 2869a39613f..08796f10d92 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1839,6 +1839,12 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
         } else {
             let size = layout.size.bytes() - tag_size;
             write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" },);
+            if layout.abi.is_uninhabited() {
+                write!(
+                    w,
+                    " (<a href=\"https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\">uninhabited</a>)"
+                );
+            }
         }
     }
 
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 090ea2cb157..e22ac6ec19b 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -7,9 +7,7 @@ use rustc_span::symbol::Symbol;
 use serde::ser::{Serialize, SerializeStruct, Serializer};
 
 use crate::clean;
-use crate::clean::types::{
-    FnRetTy, Function, GenericBound, Generics, ItemId, Type, WherePredicate,
-};
+use crate::clean::types::{FnRetTy, Function, Generics, ItemId, Type, WherePredicate};
 use crate::formats::cache::{Cache, OrphanImplItem};
 use crate::formats::item_type::ItemType;
 use crate::html::format::join_with_double_colon;
@@ -482,29 +480,23 @@ fn add_generics_and_bounds_as_types<'tcx, 'a>(
     if let Type::Generic(arg_s) = *arg {
         // First we check if the bounds are in a `where` predicate...
         if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g {
-            WherePredicate::BoundPredicate { ty, .. } => ty.def_id(cache) == arg.def_id(cache),
+            WherePredicate::BoundPredicate { ty: Type::Generic(ty_s), .. } => *ty_s == arg_s,
             _ => false,
         }) {
             let mut ty_generics = Vec::new();
             let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]);
             for bound in bounds.iter() {
-                if let GenericBound::TraitBound(poly_trait, _) = bound {
-                    for param_def in poly_trait.generic_params.iter() {
-                        match &param_def.kind {
-                            clean::GenericParamDefKind::Type { default: Some(ty), .. } => {
-                                add_generics_and_bounds_as_types(
-                                    self_,
-                                    generics,
-                                    ty,
-                                    tcx,
-                                    recurse + 1,
-                                    &mut ty_generics,
-                                    cache,
-                                )
-                            }
-                            _ => {}
-                        }
-                    }
+                if let Some(path) = bound.get_trait_path() {
+                    let ty = Type::Path { path };
+                    add_generics_and_bounds_as_types(
+                        self_,
+                        generics,
+                        &ty,
+                        tcx,
+                        recurse + 1,
+                        &mut ty_generics,
+                        cache,
+                    );
                 }
             }
             insert_ty(res, arg.clone(), ty_generics);
diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js
index fcd925bb358..1a34530c2d1 100644
--- a/src/librustdoc/html/static/.eslintrc.js
+++ b/src/librustdoc/html/static/.eslintrc.js
@@ -90,7 +90,6 @@ module.exports = {
         "no-return-assign": "error",
         "no-script-url": "error",
         "no-sequences": "error",
-        "no-throw-literal": "error",
         "no-div-regex": "error",
     }
 };
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index d18b56eb19c..95528e70e35 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1260,6 +1260,11 @@ a.tooltip:hover::after {
 	color: var(--search-tab-title-count-color);
 }
 
+#search .error code {
+	border-radius: 3px;
+	background-color: var(--search-error-code-background-color);
+}
+
 #src-sidebar-toggle {
 	position: sticky;
 	top: 0;
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 472a725f053..90cf689ad33 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -43,6 +43,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--search-result-link-focus-background-color: #3c3c3c;
 	--search-result-border-color: #aaa3;
 	--search-color: #fff;
+	--search-error-code-background-color: #4f4c4c;
 	--search-results-alias-color: #c5c5c5;
 	--search-results-grey-color: #999;
 	--search-tab-title-count-color: #888;
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 5612bde96a8..e8cd0693139 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -38,6 +38,7 @@
 	--search-result-link-focus-background-color: #616161;
 	--search-result-border-color: #aaa3;
 	--search-color: #111;
+	--search-error-code-background-color: #484848;
 	--search-results-alias-color: #fff;
 	--search-results-grey-color: #ccc;
 	--search-tab-title-count-color: #888;
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 34b35c405a8..5e3f14e483f 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -38,6 +38,7 @@
 	--search-result-link-focus-background-color: #ccc;
 	--search-result-border-color: #aaa3;
 	--search-color: #000;
+	--search-error-code-background-color: #d0cccc;
 	--search-results-alias-color: #000;
 	--search-results-grey-color: #999;
 	--search-tab-title-count-color: #888;
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 1e6c94d29ba..b98bced4126 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -144,7 +144,7 @@ function initSearch(rawSearchIndex) {
     function itemTypeFromName(typename) {
         const index = itemTypes.findIndex(i => i === typename);
         if (index < 0) {
-            throw new Error("Unknown type filter `" + typename + "`");
+            throw ["Unknown type filter ", typename];
         }
         return index;
     }
@@ -164,21 +164,21 @@ function initSearch(rawSearchIndex) {
      */
     function getStringElem(query, parserState, isInGenerics) {
         if (isInGenerics) {
-            throw new Error("`\"` cannot be used in generics");
+            throw ["Unexpected ", "\"", " in generics"];
         } else if (query.literalSearch) {
-            throw new Error("Cannot have more than one literal search element");
+            throw ["Cannot have more than one literal search element"];
         } else if (parserState.totalElems - parserState.genericsElems > 0) {
-            throw new Error("Cannot use literal search when there is more than one element");
+            throw ["Cannot use literal search when there is more than one element"];
         }
         parserState.pos += 1;
         const start = parserState.pos;
         const end = getIdentEndPosition(parserState);
         if (parserState.pos >= parserState.length) {
-            throw new Error("Unclosed `\"`");
+            throw ["Unclosed ", "\""];
         } else if (parserState.userQuery[end] !== "\"") {
-            throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`);
+            throw ["Unexpected ", parserState.userQuery[end], " in a string element"];
         } else if (start === end) {
-            throw new Error("Cannot have empty string element");
+            throw ["Cannot have empty string element"];
         }
         // To skip the quote at the end.
         parserState.pos += 1;
@@ -257,7 +257,7 @@ function initSearch(rawSearchIndex) {
             return;
         }
         if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) {
-            throw new Error("You cannot have more than one element if you use quotes");
+            throw ["You cannot have more than one element if you use quotes"];
         }
         const pathSegments = name.split("::");
         if (pathSegments.length > 1) {
@@ -266,17 +266,17 @@ function initSearch(rawSearchIndex) {
 
                 if (pathSegment.length === 0) {
                     if (i === 0) {
-                        throw new Error("Paths cannot start with `::`");
+                        throw ["Paths cannot start with ", "::"];
                     } else if (i + 1 === len) {
-                        throw new Error("Paths cannot end with `::`");
+                        throw ["Paths cannot end with ", "::"];
                     }
-                    throw new Error("Unexpected `::::`");
+                    throw ["Unexpected ", "::::"];
                 }
             }
         }
         // In case we only have something like `<p>`, there is no name.
         if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) {
-            throw new Error("Found generics without a path");
+            throw ["Found generics without a path"];
         }
         parserState.totalElems += 1;
         if (isInGenerics) {
@@ -300,22 +300,23 @@ function initSearch(rawSearchIndex) {
      * @return {integer}
      */
     function getIdentEndPosition(parserState) {
+        const start = parserState.pos;
         let end = parserState.pos;
-        let foundExclamation = false;
+        let foundExclamation = -1;
         while (parserState.pos < parserState.length) {
             const c = parserState.userQuery[parserState.pos];
             if (!isIdentCharacter(c)) {
                 if (c === "!") {
-                    if (foundExclamation) {
-                        throw new Error("Cannot have more than one `!` in an ident");
+                    if (foundExclamation !== -1) {
+                        throw ["Cannot have more than one ", "!", " in an ident"];
                     } else if (parserState.pos + 1 < parserState.length &&
                         isIdentCharacter(parserState.userQuery[parserState.pos + 1])
                     ) {
-                        throw new Error("`!` can only be at the end of an ident");
+                        throw ["Unexpected ", "!", ": it can only be at the end of an ident"];
                     }
-                    foundExclamation = true;
+                    foundExclamation = parserState.pos;
                 } else if (isErrorCharacter(c)) {
-                    throw new Error(`Unexpected \`${c}\``);
+                    throw ["Unexpected ", c];
                 } else if (
                     isStopCharacter(c) ||
                     isSpecialStartCharacter(c) ||
@@ -326,16 +327,40 @@ function initSearch(rawSearchIndex) {
                     if (!isPathStart(parserState)) {
                         break;
                     }
+                    if (foundExclamation !== -1) {
+                        if (start <= (end - 2)) {
+                            throw ["Cannot have associated items in macros"];
+                        } else {
+                            // if start == end - 1, we got the never type
+                            // while the never type has no associated macros, we still
+                            // can parse a path like that
+                            foundExclamation = -1;
+                        }
+                    }
                     // Skip current ":".
                     parserState.pos += 1;
-                    foundExclamation = false;
                 } else {
-                    throw new Error(`Unexpected \`${c}\``);
+                    throw ["Unexpected ", c];
                 }
             }
             parserState.pos += 1;
             end = parserState.pos;
         }
+        // if start == end - 1, we got the never type
+        if (foundExclamation !== -1 && start <= (end - 2)) {
+            if (parserState.typeFilter === null) {
+                parserState.typeFilter = "macro";
+            } else if (parserState.typeFilter !== "macro") {
+                throw [
+                    "Invalid search type: macro ",
+                    "!",
+                    " and ",
+                    parserState.typeFilter,
+                    " both specified",
+                ];
+            }
+            end = foundExclamation;
+        }
         return end;
     }
 
@@ -362,9 +387,9 @@ function initSearch(rawSearchIndex) {
             parserState.userQuery[parserState.pos] === "<"
         ) {
             if (isInGenerics) {
-                throw new Error("Unexpected `<` after `<`");
+                throw ["Unexpected ", "<", " after ", "<"];
             } else if (start >= end) {
-                throw new Error("Found generics without a path");
+                throw ["Found generics without a path"];
             }
             parserState.pos += 1;
             getItemsBefore(query, parserState, generics, ">");
@@ -408,24 +433,51 @@ function initSearch(rawSearchIndex) {
                 foundStopChar = true;
                 continue;
             } else if (c === ":" && isPathStart(parserState)) {
-                throw new Error("Unexpected `::`: paths cannot start with `::`");
+                throw ["Unexpected ", "::", ": paths cannot start with ", "::"];
             } else if (c === ":" || isEndCharacter(c)) {
                 let extra = "";
                 if (endChar === ">") {
-                    extra = "`<`";
+                    extra = "<";
                 } else if (endChar === "") {
-                    extra = "`->`";
+                    extra = "->";
+                } else {
+                    extra = endChar;
                 }
-                throw new Error("Unexpected `" + c + "` after " + extra);
+                throw ["Unexpected ", c, " after ", extra];
             }
             if (!foundStopChar) {
                 if (endChar !== "") {
-                    throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``);
+                    throw [
+                        "Expected ",
+                        ",", // comma
+                        ", ",
+                        "&nbsp;", // whitespace
+                        " or ",
+                        endChar,
+                        ", found ",
+                        c,
+                    ];
                 }
-                throw new Error(`Expected \`,\` or \` \`, found \`${c}\``);
+                throw [
+                    "Expected ",
+                    ",", // comma
+                    " or ",
+                    "&nbsp;", // whitespace
+                    ", found ",
+                    c,
+                ];
             }
             const posBefore = parserState.pos;
             getNextElem(query, parserState, elems, endChar === ">");
+            if (endChar !== "") {
+                if (parserState.pos >= parserState.length) {
+                    throw ["Unclosed ", "<"];
+                }
+                const c2 = parserState.userQuery[parserState.pos];
+                if (!isSeparatorCharacter(c2) && c2 !== endChar) {
+                    throw ["Expected ", endChar, ", found ", c2];
+                }
+            }
             // This case can be encountered if `getNextElem` encountered a "stop character" right
             // from the start. For example if you have `,,` or `<>`. In this case, we simply move up
             // the current position to continue the parsing.
@@ -434,7 +486,10 @@ function initSearch(rawSearchIndex) {
             }
             foundStopChar = false;
         }
-        // We are either at the end of the string or on the `endChar`` character, let's move forward
+        if (parserState.pos >= parserState.length && endChar !== "") {
+            throw ["Unclosed ", "<"];
+        }
+        // We are either at the end of the string or on the `endChar` character, let's move forward
         // in any case.
         parserState.pos += 1;
     }
@@ -450,7 +505,7 @@ function initSearch(rawSearchIndex) {
 
         for (let pos = 0; pos < parserState.pos; ++pos) {
             if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) {
-                throw new Error(`Unexpected \`${query[pos]}\` in type filter`);
+                throw ["Unexpected ", query[pos], " in type filter"];
             }
         }
     }
@@ -463,11 +518,10 @@ function initSearch(rawSearchIndex) {
      * @param {ParserState} parserState
      */
     function parseInput(query, parserState) {
-        let c, before;
         let foundStopChar = true;
 
         while (parserState.pos < parserState.length) {
-            c = parserState.userQuery[parserState.pos];
+            const c = parserState.userQuery[parserState.pos];
             if (isStopCharacter(c)) {
                 foundStopChar = true;
                 if (isSeparatorCharacter(c)) {
@@ -477,19 +531,19 @@ function initSearch(rawSearchIndex) {
                     if (isReturnArrow(parserState)) {
                         break;
                     }
-                    throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`);
+                    throw ["Unexpected ", c, " (did you mean ", "->", "?)"];
                 }
-                throw new Error(`Unexpected \`${c}\``);
+                throw ["Unexpected ", c];
             } else if (c === ":" && !isPathStart(parserState)) {
                 if (parserState.typeFilter !== null) {
-                    throw new Error("Unexpected `:`");
+                    throw ["Unexpected ", ":"];
                 }
                 if (query.elems.length === 0) {
-                    throw new Error("Expected type filter before `:`");
+                    throw ["Expected type filter before ", ":"];
                 } else if (query.elems.length !== 1 || parserState.totalElems !== 1) {
-                    throw new Error("Unexpected `:`");
+                    throw ["Unexpected ", ":"];
                 } else if (query.literalSearch) {
-                    throw new Error("You cannot use quotes on type filter");
+                    throw ["You cannot use quotes on type filter"];
                 }
                 checkExtraTypeFilterCharacters(parserState);
                 // The type filter doesn't count as an element since it's a modifier.
@@ -502,11 +556,31 @@ function initSearch(rawSearchIndex) {
             }
             if (!foundStopChar) {
                 if (parserState.typeFilter !== null) {
-                    throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``);
+                    throw [
+                        "Expected ",
+                        ",", // comma
+                        ", ",
+                        "&nbsp;", // whitespace
+                        " or ",
+                        "->", // arrow
+                        ", found ",
+                        c,
+                    ];
                 }
-                throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``);
-            }
-            before = query.elems.length;
+                throw [
+                    "Expected ",
+                    ",", // comma
+                    ", ",
+                    "&nbsp;", // whitespace
+                    ", ",
+                    ":", // colon
+                    " or ",
+                    "->", // arrow
+                    ", found ",
+                    c,
+                ];
+            }
+            const before = query.elems.length;
             getNextElem(query, parserState, query.elems, false);
             if (query.elems.length === before) {
                 // Nothing was added, weird... Let's increase the position to not remain stuck.
@@ -515,14 +589,13 @@ function initSearch(rawSearchIndex) {
             foundStopChar = false;
         }
         while (parserState.pos < parserState.length) {
-            c = parserState.userQuery[parserState.pos];
             if (isReturnArrow(parserState)) {
                 parserState.pos += 2;
                 // Get returned elements.
                 getItemsBefore(query, parserState, query.returned, "");
                 // Nothing can come afterward!
                 if (query.returned.length === 0) {
-                    throw new Error("Expected at least one item after `->`");
+                    throw ["Expected at least one item after ", "->"];
                 }
                 break;
             } else {
@@ -591,8 +664,8 @@ function initSearch(rawSearchIndex) {
      *
      * The supported syntax by this parser is as follow:
      *
-     * ident = *(ALPHA / DIGIT / "_") [!]
-     * path = ident *(DOUBLE-COLON ident)
+     * ident = *(ALPHA / DIGIT / "_")
+     * path = ident *(DOUBLE-COLON ident) [!]
      * arg = path [generics]
      * arg-without-generic = path
      * type-sep = COMMA/WS *(COMMA/WS)
@@ -676,7 +749,7 @@ function initSearch(rawSearchIndex) {
             }
         } catch (err) {
             query = newParsedQuery(userQuery);
-            query.error = err.message;
+            query.error = err;
             query.typeFilter = -1;
             return query;
         }
@@ -1742,7 +1815,16 @@ function initSearch(rawSearchIndex) {
 
         let output = `<h1 class="search-results-title">Results${crates}</h1>`;
         if (results.query.error !== null) {
-            output += `<h3>Query parser error: "${results.query.error}".</h3>`;
+            const error = results.query.error;
+            error.forEach((value, index) => {
+                value = value.split("<").join("&lt;").split(">").join("&gt;");
+                if (index % 2 !== 0) {
+                    error[index] = `<code>${value}</code>`;
+                } else {
+                    error[index] = value;
+                }
+            });
+            output += `<h3 class="error">Query parser error: "${error.join("")}".</h3>`;
             output += "<div id=\"search-tabs\">" +
                 makeTabHeader(0, "In Names", ret_others[1]) +
                 "</div>";
@@ -1940,7 +2022,6 @@ function initSearch(rawSearchIndex) {
          */
         const searchWords = [];
         const charA = "A".charCodeAt(0);
-        let i, word;
         let currentIndex = 0;
         let id = 0;
 
@@ -2035,7 +2116,7 @@ function initSearch(rawSearchIndex) {
             // convert `rawPaths` entries into object form
             // generate normalizedPaths for function search mode
             let len = paths.length;
-            for (i = 0; i < len; ++i) {
+            for (let i = 0; i < len; ++i) {
                 lowercasePaths.push({ty: paths[i][0], name: paths[i][1].toLowerCase()});
                 paths[i] = {ty: paths[i][0], name: paths[i][1]};
             }
@@ -2049,16 +2130,14 @@ function initSearch(rawSearchIndex) {
             // faster analysis operations
             len = itemTypes.length;
             let lastPath = "";
-            for (i = 0; i < len; ++i) {
+            for (let i = 0; i < len; ++i) {
+                let word = "";
                 // This object should have exactly the same set of fields as the "crateRow"
                 // object defined above.
                 if (typeof itemNames[i] === "string") {
                     word = itemNames[i].toLowerCase();
-                    searchWords.push(word);
-                } else {
-                    word = "";
-                    searchWords.push("");
                 }
+                searchWords.push(word);
                 const row = {
                     crate: crate,
                     ty: itemTypes.charCodeAt(i) - charA,
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 0e1c864e62d..6c0f03b5bb0 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -117,8 +117,7 @@ function createSourceSidebar() {
     sidebar.appendChild(title);
     Object.keys(sourcesIndex).forEach(key => {
         sourcesIndex[key][NAME_OFFSET] = key;
-        hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "",
-            hasFoundFile);
+        hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", hasFoundFile);
     });
 
     container.appendChild(sidebar);
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index d5e9010eb4e..18c45fd6991 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -38,7 +38,7 @@ impl JsonRenderer<'_> {
                     Some(UrlFragment::UserWritten(_)) | None => *page_id,
                 };
 
-                (link.clone(), id_from_item_default(id.into(), self.tcx))
+                (String::from(&**link), id_from_item_default(id.into(), self.tcx))
             })
             .collect();
         let docs = item.attrs.collapsed_doc_value();
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 0b22f943dab..be5286b24d7 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -8,7 +8,6 @@ use crate::visit::DocVisitor;
 use rustc_hir as hir;
 use rustc_lint::builtin::MISSING_DOCS;
 use rustc_middle::lint::LintLevelSource;
-use rustc_middle::ty::DefIdTree;
 use rustc_session::lint;
 use rustc_span::FileName;
 use serde::Serialize;
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index a39d57d42b7..6b13e6c9581 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -14,7 +14,6 @@ use crate::visit::DocVisitor;
 use crate::visit_ast::inherits_doc_hidden;
 use rustc_hir as hir;
 use rustc_middle::lint::LintLevelSource;
-use rustc_middle::ty::DefIdTree;
 use rustc_session::lint;
 
 pub(crate) const CHECK_DOC_TEST_VISIBILITY: Pass = Pass {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 920a3b22f25..bcb69d1a4ca 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -13,7 +13,7 @@ use rustc_hir::def::Namespace::*;
 use rustc_hir::def::{DefKind, Namespace, PerNS};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_hir::Mutability;
-use rustc_middle::ty::{DefIdTree, Ty, TyCtxt};
+use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_middle::{bug, ty};
 use rustc_resolve::rustdoc::MalformedGenerics;
 use rustc_resolve::rustdoc::{prepare_to_doc_link_resolution, strip_generics_from_path};
@@ -228,7 +228,7 @@ struct ResolutionInfo {
     item_id: ItemId,
     module_id: DefId,
     dis: Option<Disambiguator>,
-    path_str: String,
+    path_str: Box<str>,
     extra_fragment: Option<String>,
 }
 
@@ -849,10 +849,10 @@ impl PreprocessingError {
 
 #[derive(Clone)]
 struct PreprocessingInfo {
-    path_str: String,
+    path_str: Box<str>,
     disambiguator: Option<Disambiguator>,
     extra_fragment: Option<String>,
-    link_text: String,
+    link_text: Box<str>,
 }
 
 // Not a typedef to avoid leaking several private structures from this module.
@@ -937,7 +937,7 @@ fn preprocess_link(
         path_str,
         disambiguator,
         extra_fragment: extra_fragment.map(|frag| frag.to_owned()),
-        link_text: link_text.to_owned(),
+        link_text: Box::<str>::from(link_text),
     }))
 }
 
@@ -993,7 +993,7 @@ impl LinkCollector<'_, '_> {
                 item_id: item.item_id,
                 module_id,
                 dis: disambiguator,
-                path_str: path_str.to_owned(),
+                path_str: path_str.clone(),
                 extra_fragment: extra_fragment.clone(),
             },
             diag_info.clone(), // this struct should really be Copy, but Range is not :(
@@ -1067,7 +1067,7 @@ impl LinkCollector<'_, '_> {
                 }
 
                 res.def_id(self.cx.tcx).map(|page_id| ItemLink {
-                    link: ori_link.link.clone(),
+                    link: Box::<str>::from(&*ori_link.link),
                     link_text: link_text.clone(),
                     page_id,
                     fragment,
@@ -1091,7 +1091,7 @@ impl LinkCollector<'_, '_> {
 
                 let page_id = clean::register_res(self.cx, rustc_hir::def::Res::Def(kind, id));
                 Some(ItemLink {
-                    link: ori_link.link.clone(),
+                    link: Box::<str>::from(&*ori_link.link),
                     link_text: link_text.clone(),
                     page_id,
                     fragment,
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 01ed4a60b3b..d32e8185d3f 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -9,7 +9,7 @@ use crate::visit::DocVisitor;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE};
-use rustc_middle::ty::{self, DefIdTree};
+use rustc_middle::ty;
 use rustc_span::symbol::sym;
 
 pub(crate) const COLLECT_TRAIT_IMPLS: Pass = Pass {
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index eac362b37b2..4f72df5a5cd 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -113,7 +113,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
             if let Some(link) =
                 link_names.iter().find(|link| *link.original_text == *broken_link.reference)
             {
-                Some((link.href.as_str().into(), link.new_text.as_str().into()))
+                Some((link.href.as_str().into(), link.new_text.to_string().into()))
             } else if matches!(
                 &broken_link.link_type,
                 LinkType::Reference | LinkType::ReferenceUnknown
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index a4bc486900b..f35643af637 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -9,7 +9,6 @@ use crate::fold::DocFolder;
 use crate::passes::Pass;
 
 use rustc_hir::def_id::LocalDefId;
-use rustc_middle::ty::DefIdTree;
 
 pub(crate) const PROPAGATE_DOC_CFG: Pass = Pass {
     name: "propagate-doc-cfg",
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 277201e4de9..5bbbff175cf 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -8,7 +8,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet};
 use rustc_hir::intravisit::{walk_item, Visitor};
 use rustc_hir::{Node, CRATE_HIR_ID};
 use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{DefIdTree, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 477e7285b12f876ad105188cfcfc8adda7dc29a
+Subproject fd949f3034f8a422ecfffa889c2823485dde4bd
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 9d5b32f503fc099c4064298465add14d4bce11e
+Subproject 9880b408a3af50c08fab3dbf4aa2a972df71e95
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index 659e8aebcd5..765826ed867 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -4430,6 +4430,7 @@ Released 2018-09-13
 [`if_same_then_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_same_then_else
 [`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
 [`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
+[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
 [`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
 [`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
 [`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
@@ -4494,6 +4495,7 @@ Released 2018-09-13
 [`let_underscore_future`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_future
 [`let_underscore_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_lock
 [`let_underscore_must_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_must_use
+[`let_underscore_untyped`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_underscore_untyped
 [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value
 [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
 [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
@@ -4620,6 +4622,7 @@ Released 2018-09-13
 [`no_effect`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect
 [`no_effect_replace`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_replace
 [`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding
+[`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
 [`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
 [`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
 [`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
@@ -4675,6 +4678,7 @@ Released 2018-09-13
 [`pub_enum_variant_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_enum_variant_names
 [`pub_use`]: https://rust-lang.github.io/rust-clippy/master/index.html#pub_use
 [`question_mark`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark
+[`question_mark_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#question_mark_used
 [`range_minus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_minus_one
 [`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
 [`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero
@@ -4734,6 +4738,7 @@ Released 2018-09-13
 [`should_assert_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_assert_eq
 [`should_implement_trait`]: https://rust-lang.github.io/rust-clippy/master/index.html#should_implement_trait
 [`significant_drop_in_scrutinee`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_in_scrutinee
+[`significant_drop_tightening`]: https://rust-lang.github.io/rust-clippy/master/index.html#significant_drop_tightening
 [`similar_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#similar_names
 [`single_char_add_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_add_str
 [`single_char_lifetime_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_char_lifetime_names
@@ -4764,6 +4769,7 @@ Released 2018-09-13
 [`suboptimal_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#suboptimal_flops
 [`suspicious_arithmetic_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_arithmetic_impl
 [`suspicious_assignment_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_assignment_formatting
+[`suspicious_command_arg_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_command_arg_space
 [`suspicious_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
@@ -4790,6 +4796,7 @@ Released 2018-09-13
 [`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool
 [`transmute_int_to_char`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_char
 [`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float
+[`transmute_int_to_non_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_non_zero
 [`transmute_null_to_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_null_to_fn
 [`transmute_num_to_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_num_to_bytes
 [`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index 95f6d2cc45c..3e7379ace7e 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -19,21 +19,35 @@ You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the
 | `clippy::complexity`  | code that does something simple but in a complex way                                | **warn**      |
 | `clippy::perf`        | code that can be written to run faster                                              | **warn**      |
 | `clippy::pedantic`    | lints which are rather strict or have occasional false positives                    | allow         |
+| `clippy::restriction` | lints which prevent the use of language and library features[^restrict]             | allow         |
 | `clippy::nursery`     | new lints that are still under development                                          | allow         |
 | `clippy::cargo`       | lints for the cargo manifest                                                        | allow         |
 
 More to come, please [file an issue](https://github.com/rust-lang/rust-clippy/issues) if you have ideas!
 
-The [lint list](https://rust-lang.github.io/rust-clippy/master/index.html) also contains "restriction lints", which are
-for things which are usually not considered "bad", but may be useful to turn on in specific cases. These should be used
-very selectively, if at all.
+The `restriction` category should, *emphatically*, not be enabled as a whole. The contained
+lints may lint against perfectly reasonable code, may not have an alternative suggestion,
+and may contradict any other lints (including other categories). Lints should be considered
+on a case-by-case basis before enabling.
+
+[^restrict]: Some use cases for `restriction` lints include:
+    - Strict coding styles (e.g. [`clippy::else_if_without_else`]).
+    - Additional restrictions on CI (e.g. [`clippy::todo`]).
+    - Preventing panicking in certain functions (e.g. [`clippy::unwrap_used`]).
+    - Running a lint only on a subset of code (e.g. `#[forbid(clippy::float_arithmetic)]` on a module).
+
+[`clippy::else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
+[`clippy::todo`]: https://rust-lang.github.io/rust-clippy/master/index.html#todo
+[`clippy::unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#unwrap_used
+
+---
 
 Table of contents:
 
-*   [Usage instructions](#usage)
-*   [Configuration](#configuration)
-*   [Contributing](#contributing)
-*   [License](#license)
+* [Usage instructions](#usage)
+* [Configuration](#configuration)
+* [Contributing](#contributing)
+* [License](#license)
 
 ## Usage
 
@@ -64,6 +78,7 @@ Once you have rustup and the latest stable release (at least Rust 1.29) installe
 ```terminal
 rustup component add clippy
 ```
+
 If it says that it can't find the `clippy` component, please run `rustup self update`.
 
 #### Step 3: Run Clippy
@@ -143,16 +158,16 @@ line. (You can swap `clippy::all` with the specific lint category you are target
 
 You can add options to your code to `allow`/`warn`/`deny` Clippy lints:
 
-*   the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy::all)]`).
+* the whole set of `Warn` lints using the `clippy` lint group (`#![deny(clippy::all)]`).
     Note that `rustc` has additional [lint groups](https://doc.rust-lang.org/rustc/lints/groups.html).
 
-*   all lints using both the `clippy` and `clippy::pedantic` lint groups (`#![deny(clippy::all)]`,
+* all lints using both the `clippy` and `clippy::pedantic` lint groups (`#![deny(clippy::all)]`,
     `#![deny(clippy::pedantic)]`). Note that `clippy::pedantic` contains some very aggressive
     lints prone to false positives.
 
-*   only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc.)
+* only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc.)
 
-*   `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc.
+* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc.
 
 Note: `allow` means to suppress the lint for your code. With `warn` the lint
 will only emit a warning, while with `deny` the lint will emit an error, when
@@ -176,12 +191,14 @@ cargo clippy -- -W clippy::lint_name
 
 This also works with lint groups. For example, you
 can run Clippy with warnings for all lints enabled:
+
 ```terminal
 cargo clippy -- -W clippy::pedantic
 ```
 
 If you care only about a single lint, you can allow all others and then explicitly warn on
 the lint(s) you are interested in:
+
 ```terminal
 cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::...
 ```
diff --git a/src/tools/clippy/book/src/development/infrastructure/backport.md b/src/tools/clippy/book/src/development/infrastructure/backport.md
index 15f3d1f0806..6920c4e4656 100644
--- a/src/tools/clippy/book/src/development/infrastructure/backport.md
+++ b/src/tools/clippy/book/src/development/infrastructure/backport.md
@@ -28,6 +28,7 @@ repository. You can do this with:
 ```bash
 # Assuming the current directory corresponds to the Rust repository
 $ git checkout beta
+# Make sure to change `your-github-name` to your github name in the following command
 $ git subtree pull -p src/tools/clippy https://github.com/<your-github-name>/rust-clippy backport
 $ ./x.py test src/tools/clippy
 ```
diff --git a/src/tools/clippy/book/src/development/infrastructure/sync.md b/src/tools/clippy/book/src/development/infrastructure/sync.md
index 5a0f7409a2e..02cfc11b55a 100644
--- a/src/tools/clippy/book/src/development/infrastructure/sync.md
+++ b/src/tools/clippy/book/src/development/infrastructure/sync.md
@@ -79,8 +79,7 @@ to be run inside the `rust` directory):
    `rustup check`.
 3. Sync the changes to the rust-copy of Clippy to your Clippy fork:
     ```bash
-    # Make sure to change `your-github-name` to your github name in the following command. Also be
-    # sure to either use a net-new branch, e.g. `sync-from-rust`, or delete the branch beforehand
+    # Be sure to either use a net-new branch, e.g. `sync-from-rust`, or delete the branch beforehand
     # because changes cannot be fast forwarded and you have to run this command again.
     git subtree push -P src/tools/clippy clippy-local sync-from-rust
     ```
diff --git a/src/tools/clippy/book/src/lint_configuration.md b/src/tools/clippy/book/src/lint_configuration.md
index 32e8e218c40..995dd2f04b1 100644
--- a/src/tools/clippy/book/src/lint_configuration.md
+++ b/src/tools/clippy/book/src/lint_configuration.md
@@ -53,6 +53,7 @@ Please use that command to update the file and do not edit it by hand.
 | [ignore-interior-mutability](#ignore-interior-mutability) | `["bytes::Bytes"]` |
 | [allow-mixed-uninlined-format-args](#allow-mixed-uninlined-format-args) | `true` |
 | [suppress-restriction-lint-in-const](#suppress-restriction-lint-in-const) | `false` |
+| [missing-docs-in-crate-items](#missing-docs-in-crate-items) | `false` |
 
 ### arithmetic-side-effects-allowed
 Suppress checking of the passed type names in all types of operations.
@@ -305,7 +306,7 @@ The maximum number of lines a function or method can have
 ### array-size-threshold
 The maximum allowed size for arrays on the stack
 
-**Default Value:** `512000` (`u128`)
+**Default Value:** `512000` (`u64`)
 
 * [large_stack_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays)
 * [large_const_arrays](https://rust-lang.github.io/rust-clippy/master/index.html#large_const_arrays)
@@ -471,7 +472,7 @@ The maximum size of a file included via `include_bytes!()` or `include_str!()`,
 
 
 ### allow-expect-in-tests
-Whether `expect` should be allowed within `#[cfg(test)]`
+Whether `expect` should be allowed in test functions or `#[cfg(test)]`
 
 **Default Value:** `false` (`bool`)
 
@@ -479,7 +480,7 @@ Whether `expect` should be allowed within `#[cfg(test)]`
 
 
 ### allow-unwrap-in-tests
-Whether `unwrap` should be allowed in test cfg
+Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
 
 **Default Value:** `false` (`bool`)
 
@@ -487,7 +488,7 @@ Whether `unwrap` should be allowed in test cfg
 
 
 ### allow-dbg-in-tests
-Whether `dbg!` should be allowed in test functions
+Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
 
 **Default Value:** `false` (`bool`)
 
@@ -495,7 +496,7 @@ Whether `dbg!` should be allowed in test functions
 
 
 ### allow-print-in-tests
-Whether print macros (ex. `println!`) should be allowed in test functions
+Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
 
 **Default Value:** `false` (`bool`)
 
@@ -540,4 +541,13 @@ if no suggestion can be made.
 * [indexing_slicing](https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing)
 
 
+### missing-docs-in-crate-items
+Whether to **only** check for missing documentation in items visible within the current
+crate. For example, `pub(crate)` items.
+
+**Default Value:** `false` (`bool`)
+
+* [missing_docs_in_private_items](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items)
+
+
 
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index ec7f1dd0d84..420214d9256 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -1,5 +1,6 @@
 use crate::clippy_project_root;
 use indoc::{formatdoc, writedoc};
+use std::fmt;
 use std::fmt::Write as _;
 use std::fs::{self, OpenOptions};
 use std::io::prelude::*;
@@ -256,7 +257,7 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
         )
     });
 
-    let _ = write!(result, "{}", get_lint_declaration(&name_upper, category));
+    let _: fmt::Result = write!(result, "{}", get_lint_declaration(&name_upper, category));
 
     result.push_str(&if enable_msrv {
         formatdoc!(
@@ -353,7 +354,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
     let mut lint_file_contents = String::new();
 
     if enable_msrv {
-        let _ = writedoc!(
+        let _: fmt::Result = writedoc!(
             lint_file_contents,
             r#"
                 use clippy_utils::msrvs::{{self, Msrv}};
@@ -373,7 +374,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
             name_upper = name_upper,
         );
     } else {
-        let _ = writedoc!(
+        let _: fmt::Result = writedoc!(
             lint_file_contents,
             r#"
                 use rustc_lint::{{{context_import}, LintContext}};
@@ -521,7 +522,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
         .chain(std::iter::once(&*lint_name_upper))
         .filter(|s| !s.is_empty())
     {
-        let _ = write!(new_arr_content, "\n    {ident},");
+        let _: fmt::Result = write!(new_arr_content, "\n    {ident},");
     }
     new_arr_content.push('\n');
 
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index 837618c9294..779e4d0e1e3 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -5,7 +5,7 @@ use itertools::Itertools;
 use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
 use std::collections::{HashMap, HashSet};
 use std::ffi::OsStr;
-use std::fmt::Write;
+use std::fmt::{self, Write};
 use std::fs::{self, OpenOptions};
 use std::io::{self, Read, Seek, SeekFrom, Write as _};
 use std::ops::Range;
@@ -691,7 +691,7 @@ fn gen_deprecated(lints: &[DeprecatedLint]) -> String {
     let mut output = GENERATED_FILE_COMMENT.to_string();
     output.push_str("{\n");
     for lint in lints {
-        let _ = write!(
+        let _: fmt::Result = write!(
             output,
             concat!(
                 "    store.register_removed(\n",
@@ -726,7 +726,7 @@ fn gen_declared_lints<'a>(
         if !is_public {
             output.push_str("    #[cfg(feature = \"internal\")]\n");
         }
-        let _ = writeln!(output, "    crate::{module_name}::{lint_name}_INFO,");
+        let _: fmt::Result = writeln!(output, "    crate::{module_name}::{lint_name}_INFO,");
     }
     output.push_str("];\n");
 
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
index 9d98a6bab71..dfa949d1af2 100644
--- a/src/tools/clippy/clippy_lints/src/box_default.rs
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -117,7 +117,8 @@ fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
         ) => {
             if let Some(index) = args.iter().position(|arg| arg.hir_id == expr.hir_id) &&
                 let Some(sig) = expr_sig(cx, path) &&
-                let Some(input) = sig.input(index)
+                let Some(input) = sig.input(index) &&
+                !cx.typeck_results().expr_ty_adjusted(expr).boxed_ty().is_trait()
             {
                 input.no_bound_vars().is_some()
             } else {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
index f3f8b8d8798..823970e35ab 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs
@@ -168,7 +168,7 @@ pub(super) fn check(
     let suggestion = format!("{cast_to_snip}::try_from({name_of_cast_from})");
 
     span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
-        diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...");
+        diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...");
         diag.span_suggestion_with_style(
             expr.span,
             "... or use `try_from` and handle the error accordingly",
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 457a25826e7..cd5dd7a5706 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -179,6 +179,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::from_raw_with_void_ptr::FROM_RAW_WITH_VOID_PTR_INFO,
     crate::from_str_radix_10::FROM_STR_RADIX_10_INFO,
     crate::functions::DOUBLE_MUST_USE_INFO,
+    crate::functions::IMPL_TRAIT_IN_PARAMS_INFO,
     crate::functions::MISNAMED_GETTERS_INFO,
     crate::functions::MUST_USE_CANDIDATE_INFO,
     crate::functions::MUST_USE_UNIT_INFO,
@@ -224,6 +225,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::let_underscore::LET_UNDERSCORE_FUTURE_INFO,
     crate::let_underscore::LET_UNDERSCORE_LOCK_INFO,
     crate::let_underscore::LET_UNDERSCORE_MUST_USE_INFO,
+    crate::let_underscore::LET_UNDERSCORE_UNTYPED_INFO,
     crate::lifetimes::EXTRA_UNUSED_LIFETIMES_INFO,
     crate::lifetimes::NEEDLESS_LIFETIMES_INFO,
     crate::literal_representation::DECIMAL_LITERAL_REPRESENTATION_INFO,
@@ -378,6 +380,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::methods::SKIP_WHILE_NEXT_INFO,
     crate::methods::STABLE_SORT_PRIMITIVE_INFO,
     crate::methods::STRING_EXTEND_CHARS_INFO,
+    crate::methods::SUSPICIOUS_COMMAND_ARG_SPACE_INFO,
     crate::methods::SUSPICIOUS_MAP_INFO,
     crate::methods::SUSPICIOUS_SPLITN_INFO,
     crate::methods::SUSPICIOUS_TO_OWNED_INFO,
@@ -447,6 +450,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::no_effect::NO_EFFECT_INFO,
     crate::no_effect::NO_EFFECT_UNDERSCORE_BINDING_INFO,
     crate::no_effect::UNNECESSARY_OPERATION_INFO,
+    crate::no_mangle_with_rust_abi::NO_MANGLE_WITH_RUST_ABI_INFO,
     crate::non_copy_const::BORROW_INTERIOR_MUTABLE_CONST_INFO,
     crate::non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST_INFO,
     crate::non_expressive_names::JUST_UNDERSCORES_AND_DIGITS_INFO,
@@ -506,6 +510,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::ptr_offset_with_cast::PTR_OFFSET_WITH_CAST_INFO,
     crate::pub_use::PUB_USE_INFO,
     crate::question_mark::QUESTION_MARK_INFO,
+    crate::question_mark_used::QUESTION_MARK_USED_INFO,
     crate::ranges::MANUAL_RANGE_CONTAINS_INFO,
     crate::ranges::RANGE_MINUS_ONE_INFO,
     crate::ranges::RANGE_PLUS_ONE_INFO,
@@ -536,6 +541,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::shadow::SHADOW_REUSE_INFO,
     crate::shadow::SHADOW_SAME_INFO,
     crate::shadow::SHADOW_UNRELATED_INFO,
+    crate::significant_drop_tightening::SIGNIFICANT_DROP_TIGHTENING_INFO,
     crate::single_char_lifetime_names::SINGLE_CHAR_LIFETIME_NAMES_INFO,
     crate::single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS_INFO,
     crate::size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT_INFO,
@@ -573,6 +579,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::transmute::TRANSMUTE_INT_TO_BOOL_INFO,
     crate::transmute::TRANSMUTE_INT_TO_CHAR_INFO,
     crate::transmute::TRANSMUTE_INT_TO_FLOAT_INFO,
+    crate::transmute::TRANSMUTE_INT_TO_NON_ZERO_INFO,
     crate::transmute::TRANSMUTE_NULL_TO_FN_INFO,
     crate::transmute::TRANSMUTE_NUM_TO_BYTES_INFO,
     crate::transmute::TRANSMUTE_PTR_TO_PTR_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 644604a2e3f..47501980e66 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -3,7 +3,7 @@ use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exact
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
 use clippy_utils::sugg::has_enclosing_paren;
-use clippy_utils::ty::{expr_sig, is_copy, peel_mid_ty_refs, ty_sig, variant_of_res};
+use clippy_utils::ty::{adt_and_variant_of_res, expr_sig, is_copy, peel_mid_ty_refs, ty_sig};
 use clippy_utils::{
     fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, path_to_local, walk_to_expr_usage,
 };
@@ -26,8 +26,8 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::{Rvalue, StatementKind};
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
 use rustc_middle::ty::{
-    self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
-    ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults,
+    self, Binder, BoundVariableKind, Clause, EarlyBinder, FnSig, GenericArgKind, List, ParamEnv, ParamTy,
+    PredicateKind, ProjectionPredicate, Ty, TyCtxt, TypeVisitableExt, TypeckResults,
 };
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{symbol::sym, Span, Symbol};
@@ -736,7 +736,7 @@ fn walk_parents<'tcx>(
                 ..
             }) if span.ctxt() == ctxt => {
                 let ty = cx.tcx.type_of(owner_id.def_id).subst_identity();
-                Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx))
+                Some(ty_auto_deref_stability(cx.tcx, cx.param_env, ty, precedence).position_for_result(cx))
             },
 
             Node::Item(&Item {
@@ -760,7 +760,7 @@ fn walk_parents<'tcx>(
                 let output = cx
                     .tcx
                     .erase_late_bound_regions(cx.tcx.fn_sig(owner_id).subst_identity().output());
-                Some(ty_auto_deref_stability(cx, output, precedence).position_for_result(cx))
+                Some(ty_auto_deref_stability(cx.tcx, cx.param_env, output, precedence).position_for_result(cx))
             },
 
             Node::ExprField(field) if field.span.ctxt() == ctxt => match get_parent_expr_for_hir(cx, field.hir_id) {
@@ -768,10 +768,23 @@ fn walk_parents<'tcx>(
                     hir_id,
                     kind: ExprKind::Struct(path, ..),
                     ..
-                }) => variant_of_res(cx, cx.qpath_res(path, *hir_id))
-                    .and_then(|variant| variant.fields.iter().find(|f| f.name == field.ident.name))
-                    .map(|field_def| {
-                        ty_auto_deref_stability(cx, cx.tcx.type_of(field_def.did).subst_identity(), precedence).position_for_arg()
+                }) => adt_and_variant_of_res(cx, cx.qpath_res(path, *hir_id))
+                    .and_then(|(adt, variant)| {
+                        variant
+                            .fields
+                            .iter()
+                            .find(|f| f.name == field.ident.name)
+                            .map(|f| (adt, f))
+                    })
+                    .map(|(adt, field_def)| {
+                        ty_auto_deref_stability(
+                            cx.tcx,
+                            // Use the param_env of the target type.
+                            cx.tcx.param_env(adt.did()),
+                            cx.tcx.type_of(field_def.did).subst_identity(),
+                            precedence,
+                        )
+                        .position_for_arg()
                     }),
                 _ => None,
             },
@@ -792,7 +805,7 @@ fn walk_parents<'tcx>(
                             let output = cx
                                 .tcx
                                 .erase_late_bound_regions(cx.tcx.fn_sig(owner_id).subst_identity().output());
-                            ty_auto_deref_stability(cx, output, precedence).position_for_result(cx)
+                            ty_auto_deref_stability(cx.tcx, cx.param_env, output, precedence).position_for_result(cx)
                         },
                     )
                 },
@@ -835,15 +848,20 @@ fn walk_parents<'tcx>(
                                             msrv,
                                         )
                                     } else {
-                                        ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence)
-                                            .position_for_arg()
+                                        ty_auto_deref_stability(
+                                            cx.tcx,
+                                            // Use the param_env of the target function.
+                                            sig.predicates_id().map_or(ParamEnv::empty(), |id| cx.tcx.param_env(id)),
+                                            cx.tcx.erase_late_bound_regions(ty),
+                                            precedence
+                                        ).position_for_arg()
                                     }
                                 },
                             }
                         })
                     }),
                 ExprKind::MethodCall(method, receiver, args, _) => {
-                    let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
+                    let fn_id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
                     if receiver.hir_id == child_id {
                         // Check for calls to trait methods where the trait is implemented on a reference.
                         // Two cases need to be handled:
@@ -852,13 +870,17 @@ fn walk_parents<'tcx>(
                         //   priority.
                         if e.hir_id != child_id {
                             return Some(Position::ReborrowStable(precedence))
-                        } else if let Some(trait_id) = cx.tcx.trait_of_item(id)
+                        } else if let Some(trait_id) = cx.tcx.trait_of_item(fn_id)
                             && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e))
                             && let ty::Ref(_, sub_ty, _) = *arg_ty.kind()
                             && let subs = cx
                                 .typeck_results()
                                 .node_substs_opt(parent.hir_id).map(|subs| &subs[1..]).unwrap_or_default()
-                            && let impl_ty = if cx.tcx.fn_sig(id).subst_identity().skip_binder().inputs()[0].is_ref() {
+                            && let impl_ty = if cx.tcx.fn_sig(fn_id)
+                                .subst_identity()
+                                .skip_binder()
+                                .inputs()[0].is_ref()
+                            {
                                 // Trait methods taking `&self`
                                 sub_ty
                             } else {
@@ -879,10 +901,13 @@ fn walk_parents<'tcx>(
                         return Some(Position::MethodReceiver);
                     }
                     args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
-                        let ty = cx.tcx.fn_sig(id).subst_identity().skip_binder().inputs()[i + 1];
+                        let ty = cx.tcx.fn_sig(fn_id).subst_identity().input(i + 1);
                         // `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
                         // `method.args.is_none()` for https://github.com/rust-lang/rust-clippy/issues/9782
-                        if e.hir_id == child_id && method.args.is_none() && let ty::Param(param_ty) = ty.kind() {
+                        if e.hir_id == child_id
+                            && method.args.is_none()
+                            && let ty::Param(param_ty) = ty.skip_binder().kind()
+                        {
                             needless_borrow_impl_arg_position(
                                 cx,
                                 possible_borrowers,
@@ -895,8 +920,10 @@ fn walk_parents<'tcx>(
                             )
                         } else {
                             ty_auto_deref_stability(
-                                cx,
-                                cx.tcx.erase_late_bound_regions(cx.tcx.fn_sig(id).subst_identity().input(i + 1)),
+                                cx.tcx,
+                                // Use the param_env of the target function.
+                                cx.tcx.param_env(fn_id),
+                                cx.tcx.erase_late_bound_regions(ty),
                                 precedence,
                             )
                             .position_for_arg()
@@ -1378,11 +1405,18 @@ impl<'tcx> TyPosition<'tcx> {
 }
 
 // Checks whether a type is stable when switching to auto dereferencing,
-fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedence: i8) -> TyPosition<'tcx> {
+fn ty_auto_deref_stability<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+    precedence: i8,
+) -> TyPosition<'tcx> {
     let ty::Ref(_, mut ty, _) = *ty.kind() else {
         return Position::Other(precedence).into();
     };
 
+    ty = tcx.try_normalize_erasing_regions(param_env, ty).unwrap_or(ty);
+
     loop {
         break match *ty.kind() {
             ty::Ref(_, ref_ty, _) => {
@@ -1423,9 +1457,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
             | ty::Closure(..)
             | ty::Never
             | ty::Tuple(_)
-            | ty::Alias(ty::Projection, _) => {
-                Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds())).into()
-            },
+            | ty::Alias(ty::Projection, _) => Position::DerefStable(precedence, ty.is_sized(tcx, param_env)).into(),
         };
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index f95b8ccf067..c5f4e943f4f 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -8,7 +8,7 @@ use rustc_hir::{
     Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, Ty, TyKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::{AdtDef, DefIdTree};
+use rustc_middle::ty::AdtDef;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::sym;
 
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index 6fdb7de25cc..384aca7fead 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -6,6 +6,11 @@ use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
 use clippy_utils::{is_entrypoint_fn, method_chain_args, return_ty};
 use if_chain::if_chain;
 use itertools::Itertools;
+use pulldown_cmark::Event::{
+    Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
+};
+use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
+use pulldown_cmark::{BrokenLink, CodeBlockKind, CowStr, Options};
 use rustc_ast::ast::{Async, AttrKind, Attribute, Fn, FnRetTy, ItemKind};
 use rustc_ast::token::CommentKind;
 use rustc_data_structures::fx::FxHashSet;
@@ -497,7 +502,6 @@ struct DocHeaders {
 }
 
 fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[Attribute]) -> Option<DocHeaders> {
-    use pulldown_cmark::{BrokenLink, CowStr, Options};
     /// We don't want the parser to choke on intra doc links. Since we don't
     /// actually care about rendering them, just pretend that all broken links are
     /// point to a fake address.
@@ -538,8 +542,6 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &[
         pulldown_cmark::Parser::new_with_broken_link_callback(&doc, Options::empty(), Some(&mut cb)).into_offset_iter();
     // Iterate over all `Events` and combine consecutive events into one
     let events = parser.coalesce(|previous, current| {
-        use pulldown_cmark::Event::Text;
-
         let previous_range = previous.1;
         let current_range = current.1;
 
@@ -564,12 +566,6 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
     spans: &[(usize, Span)],
 ) -> DocHeaders {
     // true if a safety header was found
-    use pulldown_cmark::Event::{
-        Code, End, FootnoteReference, HardBreak, Html, Rule, SoftBreak, Start, TaskListMarker, Text,
-    };
-    use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
-    use pulldown_cmark::{CodeBlockKind, CowStr};
-
     let mut headers = DocHeaders::default();
     let mut in_code = false;
     let mut in_link = None;
@@ -660,6 +656,12 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
                     check_link_quotes(cx, in_link.is_some(), trimmed_text, span, &range, begin, text.len());
                     // Adjust for the beginning of the current `Event`
                     let span = span.with_lo(span.lo() + BytePos::from_usize(range.start - begin));
+                    if let Some(link) = in_link.as_ref()
+                      && let Ok(url) = Url::parse(link)
+                      && (url.scheme() == "https" || url.scheme() == "http") {
+                        // Don't check the text associated with external URLs
+                        continue;
+                    }
                     text_to_check.push((text, span));
                 }
             },
@@ -704,10 +706,8 @@ fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
                 let filename = FileName::anon_source_code(&code);
 
                 let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
-                let fallback_bundle = rustc_errors::fallback_fluent_bundle(
-                    rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
-                    false
-                );
+                let fallback_bundle =
+                    rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
                 let emitter = EmitterWriter::new(
                     Box::new(io::sink()),
                     None,
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index b44e6243588..48a54f60253 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -6,7 +6,7 @@ use clippy_utils::{
     source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context},
     SpanlessEq,
 };
-use core::fmt::Write;
+use core::fmt::{self, Write};
 use rustc_errors::Applicability;
 use rustc_hir::{
     hir_id::HirIdSet,
@@ -65,6 +65,10 @@ declare_lint_pass!(HashMapPass => [MAP_ENTRY]);
 impl<'tcx> LateLintPass<'tcx> for HashMapPass {
     #[expect(clippy::too_many_lines)]
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if expr.span.from_expansion() {
+            return;
+        }
+
         let Some(higher::If { cond: cond_expr, then: then_expr, r#else: else_expr }) = higher::If::hir(expr) else {
             return
         };
@@ -532,7 +536,7 @@ impl<'tcx> InsertSearchResults<'tcx> {
             if is_expr_used_or_unified(cx.tcx, insertion.call) {
                 write_wrapped(&mut res, insertion, ctxt, app);
             } else {
-                let _ = write!(
+                let _: fmt::Result = write!(
                     res,
                     "e.insert({})",
                     snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0
@@ -548,7 +552,7 @@ impl<'tcx> InsertSearchResults<'tcx> {
         (
             self.snippet(cx, span, app, |res, insertion, ctxt, app| {
                 // Insertion into a map would return `Some(&mut value)`, but the entry returns `&mut value`
-                let _ = write!(
+                let _: fmt::Result = write!(
                     res,
                     "Some(e.insert({}))",
                     snippet_with_context(cx, insertion.value.span, ctxt, "..", app).0
@@ -562,7 +566,7 @@ impl<'tcx> InsertSearchResults<'tcx> {
         (
             self.snippet(cx, span, app, |res, insertion, ctxt, app| {
                 // Insertion into a map would return `None`, but the entry returns a mutable reference.
-                let _ = if is_expr_final_block_expr(cx.tcx, insertion.call) {
+                let _: fmt::Result = if is_expr_final_block_expr(cx.tcx, insertion.call) {
                     write!(
                         res,
                         "e.insert({});\n{}None",
diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
index 2fdd8a71466..20565e1d232 100644
--- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs
@@ -4,12 +4,17 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::MultiSpan;
 use rustc_hir::intravisit::{walk_impl_item, walk_item, walk_param_bound, walk_ty, Visitor};
 use rustc_hir::{
-    GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind, PredicateOrigin, Ty, TyKind, WherePredicate,
+    BodyId, ExprKind, GenericBound, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind,
+    PredicateOrigin, Ty, TyKind, WherePredicate,
 };
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::nested_filter;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{def_id::DefId, Span};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{
+    def_id::{DefId, LocalDefId},
+    Span,
+};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -21,7 +26,6 @@ declare_clippy_lint! {
     ///
     /// ### Example
     /// ```rust
-    /// // unused type parameters
     /// fn unused_ty<T>(x: u8) {
     ///     // ..
     /// }
@@ -37,13 +41,35 @@ declare_clippy_lint! {
     complexity,
     "unused type parameters in function definitions"
 }
-declare_lint_pass!(ExtraUnusedTypeParameters => [EXTRA_UNUSED_TYPE_PARAMETERS]);
+
+pub struct ExtraUnusedTypeParameters {
+    avoid_breaking_exported_api: bool,
+}
+
+impl ExtraUnusedTypeParameters {
+    pub fn new(avoid_breaking_exported_api: bool) -> Self {
+        Self {
+            avoid_breaking_exported_api,
+        }
+    }
+
+    /// Don't lint external macros or functions with empty bodies. Also, don't lint public items if
+    /// the `avoid_breaking_exported_api` config option is set.
+    fn check_false_positive(&self, cx: &LateContext<'_>, span: Span, def_id: LocalDefId, body_id: BodyId) -> bool {
+        let body = cx.tcx.hir().body(body_id).value;
+        let fn_empty = matches!(&body.kind, ExprKind::Block(blk, None) if blk.stmts.is_empty() && blk.expr.is_none());
+        let is_exported = cx.effective_visibilities.is_exported(def_id);
+        in_external_macro(cx.sess(), span) || (self.avoid_breaking_exported_api && is_exported) || fn_empty
+    }
+}
+
+impl_lint_pass!(ExtraUnusedTypeParameters => [EXTRA_UNUSED_TYPE_PARAMETERS]);
 
 /// A visitor struct that walks a given function and gathers generic type parameters, plus any
 /// trait bounds those parameters have.
 struct TypeWalker<'cx, 'tcx> {
     cx: &'cx LateContext<'tcx>,
-    /// Collection of all the type parameters and their spans.
+    /// Collection of all the function's type parameters.
     ty_params: FxHashMap<DefId, Span>,
     /// Collection of any (inline) trait bounds corresponding to each type parameter.
     bounds: FxHashMap<DefId, Span>,
@@ -64,8 +90,8 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
             .params
             .iter()
             .filter_map(|param| {
-                if let GenericParamKind::Type { .. } = param.kind {
-                    Some((param.def_id.into(), param.span))
+                if let GenericParamKind::Type { synthetic, .. } = param.kind {
+                    (!synthetic).then_some((param.def_id.into(), param.span))
                 } else {
                     if !param.is_elided_lifetime() {
                         all_params_unused = false;
@@ -74,6 +100,7 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
                 }
             })
             .collect();
+
         Self {
             cx,
             ty_params,
@@ -83,6 +110,12 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
         }
     }
 
+    fn mark_param_used(&mut self, def_id: DefId) {
+        if self.ty_params.remove(&def_id).is_some() {
+            self.all_params_unused = false;
+        }
+    }
+
     fn emit_lint(&self) {
         let (msg, help) = match self.ty_params.len() {
             0 => return,
@@ -96,7 +129,7 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
             ),
         };
 
-        let source_map = self.cx.tcx.sess.source_map();
+        let source_map = self.cx.sess().source_map();
         let span = if self.all_params_unused {
             self.generics.span.into() // Remove the entire list of generics
         } else {
@@ -118,14 +151,18 @@ impl<'cx, 'tcx> TypeWalker<'cx, 'tcx> {
     }
 }
 
+/// Given a generic bound, if the bound is for a trait that's not a `LangItem`, return the
+/// `LocalDefId` for that trait.
+fn bound_to_trait_def_id(bound: &GenericBound<'_>) -> Option<LocalDefId> {
+    bound.trait_ref()?.trait_def_id()?.as_local()
+}
+
 impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
     type NestedFilter = nested_filter::OnlyBodies;
 
     fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) {
         if let Some((def_id, _)) = t.peel_refs().as_generic_param() {
-            if self.ty_params.remove(&def_id).is_some() {
-                self.all_params_unused = false;
-            }
+            self.mark_param_used(def_id);
         } else if let TyKind::OpaqueDef(id, _, _) = t.kind {
             // Explicitly walk OpaqueDef. Normally `walk_ty` would do the job, but it calls
             // `visit_nested_item`, which checks that `Self::NestedFilter::INTER` is set. We're
@@ -139,12 +176,21 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
 
     fn visit_where_predicate(&mut self, predicate: &'tcx WherePredicate<'tcx>) {
         if let WherePredicate::BoundPredicate(predicate) = predicate {
-            // Collect spans for bounds that appear in the list of generics (not in a where-clause)
-            // for use in forming the help message
-            if let Some((def_id, _)) = predicate.bounded_ty.peel_refs().as_generic_param()
-                && let PredicateOrigin::GenericParam = predicate.origin
-            {
-                self.bounds.insert(def_id, predicate.span);
+            // Collect spans for any bounds on type parameters. We only keep bounds that appear in
+            // the list of generics (not in a where-clause).
+            if let Some((def_id, _)) = predicate.bounded_ty.peel_refs().as_generic_param() {
+                // If the bound contains non-public traits, err on the safe side and don't lint the
+                // corresponding parameter.
+                if !predicate
+                    .bounds
+                    .iter()
+                    .filter_map(bound_to_trait_def_id)
+                    .all(|id| self.cx.effective_visibilities.is_exported(id))
+                {
+                    self.mark_param_used(def_id);
+                } else if let PredicateOrigin::GenericParam = predicate.origin {
+                    self.bounds.insert(def_id, predicate.span);
+                }
             }
             // Only walk the right-hand side of where-bounds
             for bound in predicate.bounds {
@@ -160,7 +206,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for TypeWalker<'cx, 'tcx> {
 
 impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
-        if let ItemKind::Fn(_, generics, _) = item.kind {
+        if let ItemKind::Fn(_, generics, body_id) = item.kind
+            && !self.check_false_positive(cx, item.span, item.owner_id.def_id, body_id)
+        {
             let mut walker = TypeWalker::new(cx, generics);
             walk_item(&mut walker, item);
             walker.emit_lint();
@@ -169,7 +217,10 @@ impl<'tcx> LateLintPass<'tcx> for ExtraUnusedTypeParameters {
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'tcx>) {
         // Only lint on inherent methods, not trait methods.
-        if let ImplItemKind::Fn(..) = item.kind && trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
+        if let ImplItemKind::Fn(.., body_id) = item.kind
+            && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
+            && !self.check_false_positive(cx, item.span, item.owner_id.def_id, body_id)
+        {
             let mut walker = TypeWalker::new(cx, item.generics);
             walk_impl_item(&mut walker, item);
             walker.emit_lint();
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index ea26b96ee07..c511d85e9cf 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -340,6 +340,7 @@ fn check_one_arg(
     if matches!(param.kind, Implicit | Starred | Named(_) | Numbered)
         && let ExprKind::Path(QPath::Resolved(None, path)) = param.value.kind
         && let [segment] = path.segments
+        && segment.args.is_none()
         && let Some(arg_span) = args.value_with_prev_comma_span(param.value.hir_id)
     {
         let replacement = match param.usage {
diff --git a/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
new file mode 100644
index 00000000000..2811a73f6c1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/functions/impl_trait_in_params.rs
@@ -0,0 +1,50 @@
+use clippy_utils::{diagnostics::span_lint_and_then, is_in_test_function};
+
+use rustc_hir::{intravisit::FnKind, Body, HirId};
+use rustc_lint::LateContext;
+use rustc_span::Span;
+
+use super::IMPL_TRAIT_IN_PARAMS;
+
+pub(super) fn check_fn<'tcx>(cx: &LateContext<'_>, kind: &'tcx FnKind<'_>, body: &'tcx Body<'_>, hir_id: HirId) {
+    if cx.tcx.visibility(cx.tcx.hir().body_owner_def_id(body.id())).is_public() && !is_in_test_function(cx.tcx, hir_id)
+    {
+        if let FnKind::ItemFn(ident, generics, _) = kind {
+            for param in generics.params {
+                if param.is_impl_trait() {
+                    // No generics with nested generics, and no generics like FnMut(x)
+                    span_lint_and_then(
+                        cx,
+                        IMPL_TRAIT_IN_PARAMS,
+                        param.span,
+                        "'`impl Trait` used as a function parameter'",
+                        |diag| {
+                            if let Some(gen_span) = generics.span_for_param_suggestion() {
+                                diag.span_suggestion_with_style(
+                                    gen_span,
+                                    "add a type paremeter",
+                                    format!(", {{ /* Generic name */ }}: {}", &param.name.ident().as_str()[5..]),
+                                    rustc_errors::Applicability::HasPlaceholders,
+                                    rustc_errors::SuggestionStyle::ShowAlways,
+                                );
+                            } else {
+                                diag.span_suggestion_with_style(
+                                    Span::new(
+                                        body.params[0].span.lo() - rustc_span::BytePos(1),
+                                        ident.span.hi(),
+                                        ident.span.ctxt(),
+                                        ident.span.parent(),
+                                    ),
+                                    "add a type paremeter",
+                                    format!("<{{ /* Generic name */ }}: {}>", &param.name.ident().as_str()[5..]),
+                                    rustc_errors::Applicability::HasPlaceholders,
+                                    rustc_errors::SuggestionStyle::ShowAlways,
+                                );
+                            }
+                        },
+                    );
+                }
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/functions/mod.rs b/src/tools/clippy/clippy_lints/src/functions/mod.rs
index 4399c68e130..d2852b4acad 100644
--- a/src/tools/clippy/clippy_lints/src/functions/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/mod.rs
@@ -1,3 +1,4 @@
+mod impl_trait_in_params;
 mod misnamed_getters;
 mod must_use;
 mod not_unsafe_ptr_arg_deref;
@@ -327,6 +328,32 @@ declare_clippy_lint! {
     "getter method returning the wrong field"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Lints when `impl Trait` is being used in a function's paremeters.
+    /// ### Why is this bad?
+    /// Turbofish syntax (`::<>`) cannot be used when `impl Trait` is being used, making `impl Trait` less powerful. Readability may also be a factor.
+    ///
+    /// ### Example
+    /// ```rust
+    /// trait MyTrait {}
+    /// fn foo(a: impl MyTrait) {
+    /// 	// [...]
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// trait MyTrait {}
+    /// fn foo<T: MyTrait>(a: T) {
+    /// 	// [...]
+    /// }
+    /// ```
+    #[clippy::version = "1.68.0"]
+    pub IMPL_TRAIT_IN_PARAMS,
+    restriction,
+    "`impl Trait` is used in the function's parameters"
+}
+
 #[derive(Copy, Clone)]
 pub struct Functions {
     too_many_arguments_threshold: u64,
@@ -354,6 +381,7 @@ impl_lint_pass!(Functions => [
     RESULT_UNIT_ERR,
     RESULT_LARGE_ERR,
     MISNAMED_GETTERS,
+    IMPL_TRAIT_IN_PARAMS,
 ]);
 
 impl<'tcx> LateLintPass<'tcx> for Functions {
@@ -371,6 +399,7 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
         too_many_lines::check_fn(cx, kind, span, body, self.too_many_lines_threshold);
         not_unsafe_ptr_arg_deref::check_fn(cx, kind, decl, body, def_id);
         misnamed_getters::check_fn(cx, kind, decl, body, span);
+        impl_trait_in_params::check_fn(cx, &kind, body, hir_id);
     }
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
index e2f2d3d42e6..1ad886f2cf3 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -7,7 +7,7 @@ use rustc_hir::{self as hir, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::symbol::Symbol;
-use std::fmt::Write as _;
+use std::fmt::{self, Write as _};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -90,7 +90,7 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
                 let mut fields_snippet = String::new();
                 let (last_ident, idents) = ordered_fields.split_last().unwrap();
                 for ident in idents {
-                    let _ = write!(fields_snippet, "{ident}, ");
+                    let _: fmt::Result = write!(fields_snippet, "{ident}, ");
                 }
                 fields_snippet.push_str(&last_ident.to_string());
 
diff --git a/src/tools/clippy/clippy_lints/src/let_underscore.rs b/src/tools/clippy/clippy_lints/src/let_underscore.rs
index f8e35950980..7600777fab9 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -90,7 +90,45 @@ declare_clippy_lint! {
     "non-binding `let` on a future"
 }
 
-declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE]);
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `let _ = <expr>` without a type annotation, and suggests to either provide one,
+    /// or remove the `let` keyword altogether.
+    ///
+    /// ### Why is this bad?
+    /// The `let _ = <expr>` expression ignores the value of `<expr>` but will remain doing so even
+    /// if the type were to change, thus potentially introducing subtle bugs. By supplying a type
+    /// annotation, one will be forced to re-visit the decision to ignore the value in such cases.
+    ///
+    /// ### Known problems
+    /// The `_ = <expr>` is not properly supported by some tools (e.g. IntelliJ) and may seem odd
+    /// to many developers. This lint also partially overlaps with the other `let_underscore_*`
+    /// lints.
+    ///
+    /// ### Example
+    /// ```rust
+    /// fn foo() -> Result<u32, ()> {
+    ///     Ok(123)
+    /// }
+    /// let _ = foo();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// fn foo() -> Result<u32, ()> {
+    ///     Ok(123)
+    /// }
+    /// // Either provide a type annotation:
+    /// let _: Result<u32, ()> = foo();
+    /// // …or drop the let keyword:
+    /// _ = foo();
+    /// ```
+    #[clippy::version = "1.69.0"]
+    pub LET_UNDERSCORE_UNTYPED,
+    pedantic,
+    "non-binding `let` without a type annotation"
+}
+
+declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE, LET_UNDERSCORE_UNTYPED]);
 
 const SYNC_GUARD_PATHS: [&[&str]; 3] = [
     &paths::PARKING_LOT_MUTEX_GUARD,
@@ -148,6 +186,18 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
                     "consider explicitly using function result",
                 );
             }
+
+            if local.pat.default_binding_modes && local.ty.is_none() {
+                // When `default_binding_modes` is true, the `let` keyword is present.
+                span_lint_and_help(
+                    cx,
+                    LET_UNDERSCORE_UNTYPED,
+                    local.span,
+                    "non-binding `let` without a type annotation",
+                    None,
+                    "consider adding a type annotation or removing the `let` keyword",
+                );
+            }
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 9011f0896a0..c626e0bd998 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -2,6 +2,7 @@
 #![feature(binary_heap_into_iter_sorted)]
 #![feature(box_patterns)]
 #![feature(drain_filter)]
+#![feature(if_let_guard)]
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
 #![feature(lint_reasons)]
@@ -219,6 +220,7 @@ mod neg_cmp_op_on_partial_ord;
 mod neg_multiply;
 mod new_without_default;
 mod no_effect;
+mod no_mangle_with_rust_abi;
 mod non_copy_const;
 mod non_expressive_names;
 mod non_octal_unix_permissions;
@@ -243,6 +245,7 @@ mod ptr;
 mod ptr_offset_with_cast;
 mod pub_use;
 mod question_mark;
+mod question_mark_used;
 mod ranges;
 mod rc_clone_in_vec_init;
 mod read_zero_byte_vec;
@@ -264,6 +267,7 @@ mod semicolon_block;
 mod semicolon_if_nothing_returned;
 mod serde_api;
 mod shadow;
+mod significant_drop_tightening;
 mod single_char_lifetime_names;
 mod single_component_path_imports;
 mod size_of_in_element_count;
@@ -559,6 +563,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(eta_reduction::EtaReduction));
     store.register_late_pass(|_| Box::new(mut_mut::MutMut));
     store.register_late_pass(|_| Box::new(mut_reference::UnnecessaryMutPassed));
+    store.register_late_pass(|_| Box::<significant_drop_tightening::SignificantDropTightening<'_>>::default());
     store.register_late_pass(|_| Box::new(len_zero::LenZero));
     store.register_late_pass(|_| Box::new(attrs::Attributes));
     store.register_late_pass(|_| Box::new(blocks_in_if_conditions::BlocksInIfConditions));
@@ -665,12 +670,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         ))
     });
     let doc_valid_idents = conf.doc_valid_idents.iter().cloned().collect::<FxHashSet<_>>();
+    let missing_docs_in_crate_items = conf.missing_docs_in_crate_items;
     store.register_late_pass(move |_| Box::new(doc::DocMarkdown::new(doc_valid_idents.clone())));
     store.register_late_pass(|_| Box::new(neg_multiply::NegMultiply));
     store.register_late_pass(|_| Box::new(mem_forget::MemForget));
     store.register_late_pass(|_| Box::new(let_if_seq::LetIfSeq));
     store.register_late_pass(|_| Box::new(mixed_read_write_in_expression::EvalOrderDependence));
-    store.register_late_pass(|_| Box::new(missing_doc::MissingDoc::new()));
+    store.register_late_pass(move |_| Box::new(missing_doc::MissingDoc::new(missing_docs_in_crate_items)));
     store.register_late_pass(|_| Box::new(missing_inline::MissingInline));
     store.register_late_pass(move |_| Box::new(exhaustive_items::ExhaustiveItems));
     store.register_late_pass(|_| Box::new(match_result_ok::MatchResultOk));
@@ -694,6 +700,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(implicit_hasher::ImplicitHasher));
     store.register_late_pass(|_| Box::new(fallible_impl_from::FallibleImplFrom));
     store.register_late_pass(|_| Box::new(question_mark::QuestionMark));
+    store.register_late_pass(|_| Box::new(question_mark_used::QuestionMarkUsed));
     store.register_early_pass(|| Box::new(suspicious_operation_groupings::SuspiciousOperationGroupings));
     store.register_late_pass(|_| Box::new(suspicious_trait_impl::SuspiciousImpl));
     store.register_late_pass(|_| Box::new(map_unit_fn::MapUnit));
@@ -770,7 +777,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
     store.register_late_pass(|_| Box::new(exit::Exit));
     store.register_late_pass(|_| Box::new(to_digit_is_some::ToDigitIsSome));
-    let array_size_threshold = conf.array_size_threshold;
+    let array_size_threshold = u128::from(conf.array_size_threshold);
     store.register_late_pass(move |_| Box::new(large_stack_arrays::LargeStackArrays::new(array_size_threshold)));
     store.register_late_pass(move |_| Box::new(large_const_arrays::LargeConstArrays::new(array_size_threshold)));
     store.register_late_pass(|_| Box::new(floating_point_arithmetic::FloatingPointArithmetic));
@@ -911,7 +918,12 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
     store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
     store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock));
-    store.register_late_pass(|_| Box::new(extra_unused_type_parameters::ExtraUnusedTypeParameters));
+    store.register_late_pass(move |_| {
+        Box::new(extra_unused_type_parameters::ExtraUnusedTypeParameters::new(
+            avoid_breaking_exported_api,
+        ))
+    });
+    store.register_late_pass(|_| Box::new(no_mangle_with_rust_abi::NoMangleWithRustAbi));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 43a1a65a43a..986ffcad883 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -144,6 +144,10 @@ fn check_fn_inner<'tcx>(
         .filter(|param| matches!(param.kind, GenericParamKind::Type { .. }));
 
     for typ in types {
+        if !typ.span.eq_ctxt(span) {
+            return;
+        }
+
         for pred in generics.bounds_for_param(typ.def_id) {
             if pred.origin == PredicateOrigin::WhereClause {
                 // has_where_lifetimes checked that this predicate contains no lifetime.
@@ -181,6 +185,10 @@ fn check_fn_inner<'tcx>(
     }
 
     if let Some((elidable_lts, usages)) = could_use_elision(cx, sig.decl, body, trait_sig, generics.params) {
+        if usages.iter().any(|usage| !usage.ident.span.eq_ctxt(span)) {
+            return;
+        }
+
         let lts = elidable_lts
             .iter()
             // In principle, the result of the call to `Node::ident` could be `unwrap`ped, as `DefId` should refer to a
diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs
index 3a7b7835c99..dadcd9c5135 100644
--- a/src/tools/clippy/clippy_lints/src/literal_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs
@@ -210,7 +210,7 @@ impl WarningType {
                 cx,
                 UNUSUAL_BYTE_GROUPINGS,
                 span,
-                "digits of hex or binary literal not grouped by four",
+                "digits of hex, binary or octal literal not in groups of equal size",
                 "consider",
                 suggested_format,
                 Applicability::MachineApplicable,
@@ -427,8 +427,12 @@ impl LiteralDigitGrouping {
 
         let first = groups.next().expect("At least one group");
 
-        if (radix == Radix::Binary || radix == Radix::Hexadecimal) && groups.any(|i| i != 4 && i != 2) {
-            return Err(WarningType::UnusualByteGroupings);
+        if radix == Radix::Binary || radix == Radix::Octal || radix == Radix::Hexadecimal {
+            if let Some(second_size) = groups.next() {
+                if !groups.all(|i| i == second_size) || first > second_size {
+                    return Err(WarningType::UnusualByteGroupings);
+                }
+            }
         }
 
         if let Some(second) = groups.next() {
@@ -484,7 +488,7 @@ impl DecimalLiteralRepresentation {
             then {
                 let hex = format!("{val:#X}");
                 let num_lit = NumericLiteral::new(&hex, num_lit.suffix, false);
-                let _ = Self::do_lint(num_lit.integer).map_err(|warning_type| {
+                let _: Result<(), ()> = Self::do_lint(num_lit.integer).map_err(|warning_type| {
                     warning_type.display(num_lit.format(), cx, span);
                 });
             }
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
index 8c27c09404b..1e02a30e35f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
@@ -9,7 +9,7 @@ use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, Pat, PatKind};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, DefIdTree};
+use rustc_middle::ty;
 use rustc_span::source_map::Span;
 
 /// Check for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index d7e00047312..b1bc10802e1 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -39,6 +39,7 @@ pub(super) fn check(
             });
         },
         NeverLoopResult::MayContinueMainLoop | NeverLoopResult::Otherwise => (),
+        NeverLoopResult::IgnoreUntilEnd(_) => unreachable!(),
     }
 }
 
@@ -48,6 +49,8 @@ enum NeverLoopResult {
     AlwaysBreak,
     // A continue may occur for the main loop.
     MayContinueMainLoop,
+    // Ignore everything until the end of the block with this id
+    IgnoreUntilEnd(HirId),
     Otherwise,
 }
 
@@ -56,6 +59,7 @@ fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult {
     match arg {
         NeverLoopResult::AlwaysBreak | NeverLoopResult::Otherwise => NeverLoopResult::Otherwise,
         NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop,
+        NeverLoopResult::IgnoreUntilEnd(id) => NeverLoopResult::IgnoreUntilEnd(id),
     }
 }
 
@@ -63,27 +67,26 @@ fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult {
 #[must_use]
 fn combine_seq(first: NeverLoopResult, second: NeverLoopResult) -> NeverLoopResult {
     match first {
-        NeverLoopResult::AlwaysBreak | NeverLoopResult::MayContinueMainLoop => first,
-        NeverLoopResult::Otherwise => second,
-    }
-}
-
-// Combine two results where both parts are called but not necessarily in order.
-#[must_use]
-fn combine_both(left: NeverLoopResult, right: NeverLoopResult) -> NeverLoopResult {
-    match (left, right) {
-        (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => {
-            NeverLoopResult::MayContinueMainLoop
+        NeverLoopResult::AlwaysBreak | NeverLoopResult::MayContinueMainLoop | NeverLoopResult::IgnoreUntilEnd(_) => {
+            first
         },
-        (NeverLoopResult::AlwaysBreak, _) | (_, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak,
-        (NeverLoopResult::Otherwise, NeverLoopResult::Otherwise) => NeverLoopResult::Otherwise,
+        NeverLoopResult::Otherwise => second,
     }
 }
 
 // Combine two results where only one of the part may have been executed.
 #[must_use]
-fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult {
+fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult, ignore_ids: &[HirId]) -> NeverLoopResult {
     match (b1, b2) {
+        (NeverLoopResult::IgnoreUntilEnd(a), NeverLoopResult::IgnoreUntilEnd(b)) => {
+            if ignore_ids.iter().find(|&e| e == &a || e == &b).unwrap() == &a {
+                NeverLoopResult::IgnoreUntilEnd(b)
+            } else {
+                NeverLoopResult::IgnoreUntilEnd(a)
+            }
+        },
+        (i @ NeverLoopResult::IgnoreUntilEnd(_), NeverLoopResult::AlwaysBreak)
+        | (NeverLoopResult::AlwaysBreak, i @ NeverLoopResult::IgnoreUntilEnd(_)) => i,
         (NeverLoopResult::AlwaysBreak, NeverLoopResult::AlwaysBreak) => NeverLoopResult::AlwaysBreak,
         (NeverLoopResult::MayContinueMainLoop, _) | (_, NeverLoopResult::MayContinueMainLoop) => {
             NeverLoopResult::MayContinueMainLoop
@@ -103,7 +106,7 @@ fn never_loop_block(block: &Block<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id
         let e = never_loop_expr(e, ignore_ids, main_loop_id);
         // els is an else block in a let...else binding
         els.map_or(e, |els| {
-            combine_branches(e, never_loop_block(els, ignore_ids, main_loop_id))
+            combine_branches(e, never_loop_block(els, ignore_ids, main_loop_id), ignore_ids)
         })
     })
     .fold(NeverLoopResult::Otherwise, combine_seq)
@@ -139,7 +142,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
         ExprKind::Struct(_, fields, base) => {
             let fields = never_loop_expr_all(&mut fields.iter().map(|f| f.expr), ignore_ids, main_loop_id);
             if let Some(base) = base {
-                combine_both(fields, never_loop_expr(base, ignore_ids, main_loop_id))
+                combine_seq(fields, never_loop_expr(base, ignore_ids, main_loop_id))
             } else {
                 fields
             }
@@ -159,7 +162,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
             let e3 = e3.as_ref().map_or(NeverLoopResult::Otherwise, |e| {
                 never_loop_expr(e, ignore_ids, main_loop_id)
             });
-            combine_seq(e1, combine_branches(e2, e3))
+            combine_seq(e1, combine_branches(e2, e3, ignore_ids))
         },
         ExprKind::Match(e, arms, _) => {
             let e = never_loop_expr(e, ignore_ids, main_loop_id);
@@ -175,8 +178,13 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
                 ignore_ids.push(b.hir_id);
             }
             let ret = never_loop_block(b, ignore_ids, main_loop_id);
-            ignore_ids.pop();
-            ret
+            if l.is_some() {
+                ignore_ids.pop();
+            }
+            match ret {
+                NeverLoopResult::IgnoreUntilEnd(a) if a == b.hir_id => NeverLoopResult::Otherwise,
+                _ => ret,
+            }
         },
         ExprKind::Continue(d) => {
             let id = d
@@ -190,8 +198,8 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
         },
         // checks if break targets a block instead of a loop
         ExprKind::Break(Destination { target_id: Ok(t), .. }, e) if ignore_ids.contains(&t) => e
-            .map_or(NeverLoopResult::Otherwise, |e| {
-                combine_seq(never_loop_expr(e, ignore_ids, main_loop_id), NeverLoopResult::Otherwise)
+            .map_or(NeverLoopResult::IgnoreUntilEnd(t), |e| {
+                never_loop_expr(e, ignore_ids, main_loop_id)
             }),
         ExprKind::Break(_, e) | ExprKind::Ret(e) => e.as_ref().map_or(NeverLoopResult::AlwaysBreak, |e| {
             combine_seq(
@@ -218,7 +226,7 @@ fn never_loop_expr(expr: &Expr<'_>, ignore_ids: &mut Vec<HirId>, main_loop_id: H
                 | InlineAsmOperand::SymFn { .. }
                 | InlineAsmOperand::SymStatic { .. } => NeverLoopResult::Otherwise,
             })
-            .fold(NeverLoopResult::Otherwise, combine_both),
+            .fold(NeverLoopResult::Otherwise, combine_seq),
         ExprKind::Yield(_, _)
         | ExprKind::Closure { .. }
         | ExprKind::Path(_)
@@ -234,7 +242,7 @@ fn never_loop_expr_all<'a, T: Iterator<Item = &'a Expr<'a>>>(
     main_loop_id: HirId,
 ) -> NeverLoopResult {
     es.map(|e| never_loop_expr(e, ignore_ids, main_loop_id))
-        .fold(NeverLoopResult::Otherwise, combine_both)
+        .fold(NeverLoopResult::Otherwise, combine_seq)
 }
 
 fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(
@@ -242,8 +250,9 @@ fn never_loop_expr_branch<'a, T: Iterator<Item = &'a Expr<'a>>>(
     ignore_ids: &mut Vec<HirId>,
     main_loop_id: HirId,
 ) -> NeverLoopResult {
-    e.map(|e| never_loop_expr(e, ignore_ids, main_loop_id))
-        .fold(NeverLoopResult::AlwaysBreak, combine_branches)
+    e.fold(NeverLoopResult::AlwaysBreak, |a, b| {
+        combine_branches(a, never_loop_expr(b, ignore_ids, main_loop_id), ignore_ids)
+    })
 }
 
 fn for_to_if_let_sugg(cx: &LateContext<'_>, iterator: &Expr<'_>, pat: &Pat<'_>) -> String {
diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
index 9c6f8b43c07..98e698c6c2a 100644
--- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs
@@ -4,11 +4,12 @@ use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::peel_blocks;
 use clippy_utils::source::snippet_with_context;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::visitors::{Descend, Visitable};
 use if_chain::if_chain;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind};
+use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::{Expr, ExprKind, HirId, ItemId, Local, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, Ty};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -115,6 +116,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
                     .enumerate()
                     .find(|(_, arm)| expr_diverges(cx, arm.body) && pat_allowed_for_else(cx, arm.pat, check_types));
                 let Some((idx, diverging_arm)) = diverging_arm_opt else { return; };
+                // If the non-diverging arm is the first one, its pattern can be reused in a let/else statement.
+                // However, if it arrives in second position, its pattern may cover some cases already covered
+                // by the diverging one.
+                // TODO: accept the non-diverging arm as a second position if patterns are disjointed.
+                if idx == 0 {
+                    return;
+                }
                 let pat_arm = &arms[1 - idx];
                 if !expr_is_simple_identity(pat_arm.pat, pat_arm.body) {
                     return;
@@ -162,61 +170,102 @@ fn emit_manual_let_else(cx: &LateContext<'_>, span: Span, expr: &Expr<'_>, pat:
     );
 }
 
-fn expr_diverges(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
-    fn is_never(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
-        if let Some(ty) = cx.typeck_results().expr_ty_opt(expr) {
-            return ty.is_never();
-        }
-        false
+/// Check whether an expression is divergent. May give false negatives.
+fn expr_diverges(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    struct V<'cx, 'tcx> {
+        cx: &'cx LateContext<'tcx>,
+        res: ControlFlow<(), Descend>,
     }
-    // We can't just call is_never on expr and be done, because the type system
-    // sometimes coerces the ! type to something different before we can get
-    // our hands on it. So instead, we do a manual search. We do fall back to
-    // is_never in some places when there is no better alternative.
-    for_each_expr(expr, |ex| {
-        match ex.kind {
-            ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => ControlFlow::Break(()),
-            ExprKind::Call(call, _) => {
-                if is_never(cx, ex) || is_never(cx, call) {
-                    return ControlFlow::Break(());
-                }
-                ControlFlow::Continue(Descend::Yes)
-            },
-            ExprKind::MethodCall(..) => {
-                if is_never(cx, ex) {
-                    return ControlFlow::Break(());
-                }
-                ControlFlow::Continue(Descend::Yes)
-            },
-            ExprKind::If(if_expr, if_then, if_else) => {
-                let else_diverges = if_else.map_or(false, |ex| expr_diverges(cx, ex));
-                let diverges = expr_diverges(cx, if_expr) || (else_diverges && expr_diverges(cx, if_then));
-                if diverges {
-                    return ControlFlow::Break(());
+    impl<'tcx> Visitor<'tcx> for V<'_, '_> {
+        fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
+            fn is_never(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
+                if let Some(ty) = cx.typeck_results().expr_ty_opt(expr) {
+                    return ty.is_never();
                 }
-                ControlFlow::Continue(Descend::No)
-            },
-            ExprKind::Match(match_expr, match_arms, _) => {
-                let diverges = expr_diverges(cx, match_expr)
-                    || match_arms.iter().all(|arm| {
-                        let guard_diverges = arm.guard.as_ref().map_or(false, |g| expr_diverges(cx, g.body()));
-                        guard_diverges || expr_diverges(cx, arm.body)
-                    });
-                if diverges {
-                    return ControlFlow::Break(());
-                }
-                ControlFlow::Continue(Descend::No)
-            },
+                false
+            }
 
-            // Don't continue into loops or labeled blocks, as they are breakable,
-            // and we'd have to start checking labels.
-            ExprKind::Block(_, Some(_)) | ExprKind::Loop(..) => ControlFlow::Continue(Descend::No),
+            if self.res.is_break() {
+                return;
+            }
 
-            // Default: descend
-            _ => ControlFlow::Continue(Descend::Yes),
+            // We can't just call is_never on expr and be done, because the type system
+            // sometimes coerces the ! type to something different before we can get
+            // our hands on it. So instead, we do a manual search. We do fall back to
+            // is_never in some places when there is no better alternative.
+            self.res = match e.kind {
+                ExprKind::Continue(_) | ExprKind::Break(_, _) | ExprKind::Ret(_) => ControlFlow::Break(()),
+                ExprKind::Call(call, _) => {
+                    if is_never(self.cx, e) || is_never(self.cx, call) {
+                        ControlFlow::Break(())
+                    } else {
+                        ControlFlow::Continue(Descend::Yes)
+                    }
+                },
+                ExprKind::MethodCall(..) => {
+                    if is_never(self.cx, e) {
+                        ControlFlow::Break(())
+                    } else {
+                        ControlFlow::Continue(Descend::Yes)
+                    }
+                },
+                ExprKind::If(if_expr, if_then, if_else) => {
+                    let else_diverges = if_else.map_or(false, |ex| expr_diverges(self.cx, ex));
+                    let diverges =
+                        expr_diverges(self.cx, if_expr) || (else_diverges && expr_diverges(self.cx, if_then));
+                    if diverges {
+                        ControlFlow::Break(())
+                    } else {
+                        ControlFlow::Continue(Descend::No)
+                    }
+                },
+                ExprKind::Match(match_expr, match_arms, _) => {
+                    let diverges = expr_diverges(self.cx, match_expr)
+                        || match_arms.iter().all(|arm| {
+                            let guard_diverges = arm.guard.as_ref().map_or(false, |g| expr_diverges(self.cx, g.body()));
+                            guard_diverges || expr_diverges(self.cx, arm.body)
+                        });
+                    if diverges {
+                        ControlFlow::Break(())
+                    } else {
+                        ControlFlow::Continue(Descend::No)
+                    }
+                },
+
+                // Don't continue into loops or labeled blocks, as they are breakable,
+                // and we'd have to start checking labels.
+                ExprKind::Block(_, Some(_)) | ExprKind::Loop(..) => ControlFlow::Continue(Descend::No),
+
+                // Default: descend
+                _ => ControlFlow::Continue(Descend::Yes),
+            };
+            if let ControlFlow::Continue(Descend::Yes) = self.res {
+                walk_expr(self, e);
+            }
+        }
+
+        fn visit_local(&mut self, local: &'tcx Local<'_>) {
+            // Don't visit the else block of a let/else statement as it will not make
+            // the statement divergent even though the else block is divergent.
+            if let Some(init) = local.init {
+                self.visit_expr(init);
+            }
         }
-    })
-    .is_some()
+
+        // Avoid unnecessary `walk_*` calls.
+        fn visit_ty(&mut self, _: &'tcx Ty<'tcx>) {}
+        fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) {}
+        fn visit_qpath(&mut self, _: &'tcx QPath<'tcx>, _: HirId, _: Span) {}
+        // Avoid monomorphising all `visit_*` functions.
+        fn visit_nested_item(&mut self, _: ItemId) {}
+    }
+
+    let mut v = V {
+        cx,
+        res: ControlFlow::Continue(Descend::Yes),
+    };
+    expr.visit(&mut v);
+    v.res.is_break()
 }
 
 fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: bool) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
index 9a84068d448..0e22485db2c 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -8,7 +8,6 @@ use rustc_errors::Applicability;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::{self as hir, Expr, ExprKind, QPath};
 use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::DefIdTree;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::{sym, Span};
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
index 587c926dc01..6447899f2b9 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -10,7 +10,6 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::LangItem::{OptionNone, ResultErr};
 use rustc_hir::{Arm, Expr, PatKind};
 use rustc_lint::LateContext;
-use rustc_middle::ty::DefIdTree;
 use rustc_span::sym;
 
 use super::MANUAL_UNWRAP_OR;
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index 81bebff34c8..df0ea7f5b86 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -12,7 +12,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
 use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
 use rustc_lint::LateContext;
-use rustc_middle::ty::{self, subst::GenericArgKind, DefIdTree, Ty};
+use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
 use rustc_span::{sym, Symbol};
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index 4720a6e6888..8e1130cf8df 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -8,7 +8,6 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::{LangItem, QPath};
 use rustc_lint::LateContext;
-use rustc_middle::ty::DefIdTree;
 use rustc_span::Span;
 
 pub(crate) struct OptionAndThenSome;
diff --git a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
index d512cc4eeae..c5fc145b289 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
@@ -5,6 +5,8 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, LangItem};
 use rustc_lint::LateContext;
 
+use crate::methods::method_call;
+
 use super::BYTES_NTH;
 
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx Expr<'tcx>, n_arg: &'tcx Expr<'tcx>) {
@@ -16,18 +18,32 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
     } else {
         return;
     };
+
     let mut applicability = Applicability::MachineApplicable;
-    span_lint_and_sugg(
-        cx,
-        BYTES_NTH,
-        expr.span,
-        &format!("called `.bytes().nth()` on a `{caller_type}`"),
-        "try",
-        format!(
-            "{}.as_bytes().get({})",
-            snippet_with_applicability(cx, recv.span, "..", &mut applicability),
-            snippet_with_applicability(cx, n_arg.span, "..", &mut applicability)
-        ),
-        applicability,
-    );
+    let receiver = snippet_with_applicability(cx, recv.span, "..", &mut applicability);
+    let n = snippet_with_applicability(cx, n_arg.span, "..", &mut applicability);
+
+    if let Some(parent) = clippy_utils::get_parent_expr(cx, expr)
+      && let Some((name, _, _, _, _)) = method_call(parent)
+      && name == "unwrap" {
+        span_lint_and_sugg(
+            cx,
+            BYTES_NTH,
+            parent.span,
+            &format!("called `.bytes().nth().unwrap()` on a `{caller_type}`"),
+            "try",
+            format!("{receiver}.as_bytes()[{n}]",),
+            applicability
+        );
+    } else {
+        span_lint_and_sugg(
+            cx,
+            BYTES_NTH,
+            expr.span,
+            &format!("called `.bytes().nth()` on a `{caller_type}`"),
+            "try",
+            format!("{receiver}.as_bytes().get({n}).copied()"), 
+            applicability
+        );
+    };
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
index 56b7fbb9d4b..079df2226d1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
@@ -6,7 +6,7 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_lint::Lint;
-use rustc_middle::ty::{self, DefIdTree};
+use rustc_middle::ty;
 
 /// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
 pub(super) fn check(
diff --git a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
index cce8f797e98..614610335a1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/expect_used.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::is_in_cfg_test;
 use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::{is_in_cfg_test, is_in_test_function};
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::sym;
@@ -27,7 +27,7 @@ pub(super) fn check(
 
     let method = if is_err { "expect_err" } else { "expect" };
 
-    if allow_expect_in_tests && is_in_cfg_test(cx.tcx, expr.hir_id) {
+    if allow_expect_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
         return;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
index 374eb29fc52..5a78a416877 100644
--- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
@@ -53,7 +53,9 @@ pub fn is_clone_like(cx: &LateContext<'_>, method_name: &str, method_def_id: hir
         "to_vec" => cx
             .tcx
             .impl_of_method(method_def_id)
-            .filter(|&impl_did| cx.tcx.type_of(impl_did).subst_identity().is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none())
+            .filter(|&impl_did| {
+                cx.tcx.type_of(impl_did).subst_identity().is_slice() && cx.tcx.impl_trait_ref(impl_did).is_none()
+            })
             .is_some(),
         _ => false,
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 6301b3ded20..702df4b282b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -80,6 +80,7 @@ mod skip_while_next;
 mod stable_sort_primitive;
 mod str_splitn;
 mod string_extend_chars;
+mod suspicious_command_arg_space;
 mod suspicious_map;
 mod suspicious_splitn;
 mod suspicious_to_owned;
@@ -3162,6 +3163,32 @@ declare_clippy_lint! {
     "collecting an iterator when collect is not needed"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Checks for `Command::arg()` invocations that look like they
+    /// should be multiple arguments instead, such as `arg("-t ext2")`.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// `Command::arg()` does not split arguments by space. An argument like `arg("-t ext2")`
+    /// will be passed as a single argument to the command,
+    /// which is likely not what was intended.
+    ///
+    /// ### Example
+    /// ```rust
+    /// std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap();
+    /// ```
+    #[clippy::version = "1.67.0"]
+    pub SUSPICIOUS_COMMAND_ARG_SPACE,
+    suspicious,
+    "single command line argument that looks like it should be multiple arguments"
+}
+
 pub struct Methods {
     avoid_breaking_exported_api: bool,
     msrv: Msrv,
@@ -3289,6 +3316,7 @@ impl_lint_pass!(Methods => [
     SEEK_FROM_CURRENT,
     SEEK_TO_START_INSTEAD_OF_REWIND,
     NEEDLESS_COLLECT,
+    SUSPICIOUS_COMMAND_ARG_SPACE,
 ]);
 
 /// Extracts a method call name, args, and `Span` of the method name.
@@ -3496,6 +3524,9 @@ impl Methods {
                         unnecessary_lazy_eval::check(cx, expr, recv, arg, "and");
                     }
                 },
+                ("arg", [arg]) => {
+                    suspicious_command_arg_space::check(cx, recv, arg, span);
+                }
                 ("as_deref" | "as_deref_mut", []) => {
                     needless_option_as_deref::check(cx, expr, recv, name);
                 },
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 3a23ecc50dc..41ceef19e3a 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
@@ -6,7 +6,6 @@ use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_lint::LateContext;
-use rustc_middle::ty::DefIdTree;
 use rustc_span::symbol::sym;
 
 use super::OPTION_MAP_OR_NONE;
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
new file mode 100644
index 00000000000..73632c5a357
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs
@@ -0,0 +1,39 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::paths;
+use clippy_utils::ty::match_type;
+use rustc_ast as ast;
+use rustc_errors::{Applicability, Diagnostic};
+use rustc_hir as hir;
+use rustc_lint::LateContext;
+use rustc_span::Span;
+
+use super::SUSPICIOUS_COMMAND_ARG_SPACE;
+
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>, span: Span) {
+    let ty = cx.typeck_results().expr_ty(recv).peel_refs();
+
+    if match_type(cx, ty, &paths::STD_PROCESS_COMMAND)
+        && let hir::ExprKind::Lit(lit) = &arg.kind
+        && let ast::LitKind::Str(s, _) = &lit.node
+        && let Some((arg1, arg2)) = s.as_str().split_once(' ')
+        && arg1.starts_with('-')
+        && arg1.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-')
+    {
+        span_lint_and_then(
+            cx,
+            SUSPICIOUS_COMMAND_ARG_SPACE,
+            arg.span,
+            "single argument that looks like it should be multiple arguments",
+            |diag: &mut Diagnostic| {
+                diag.multipart_suggestion_verbose(
+                    "consider splitting the argument",
+                    vec![
+                        (span, "args".to_string()),
+                        (arg.span, format!("[{arg1:?}, {arg2:?}]")),
+                    ],
+                    Applicability::MaybeIncorrect,
+                );
+            }
+        );
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
index 90983f249cd..5e4c3daee64 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unwrap_used.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_in_cfg_test, is_lint_allowed};
+use clippy_utils::{is_in_cfg_test, is_in_test_function, is_lint_allowed};
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_span::sym;
@@ -27,7 +27,7 @@ pub(super) fn check(
 
     let method_suffix = if is_err { "_err" } else { "" };
 
-    if allow_unwrap_in_tests && is_in_cfg_test(cx.tcx, expr.hir_id) {
+    if allow_unwrap_in_tests && (is_in_test_function(cx.tcx, expr.hir_id) || is_in_cfg_test(cx.tcx, expr.hir_id)) {
         return;
     }
 
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 6fd100762b4..5b1f03fc16c 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -8,10 +8,12 @@
 use clippy_utils::attrs::is_doc_hidden;
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::is_from_proc_macro;
+use hir::def_id::LocalDefId;
+use if_chain::if_chain;
 use rustc_ast::ast::{self, MetaItem, MetaItemKind};
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass, LintContext};
-use rustc_middle::ty::DefIdTree;
+use rustc_middle::ty::Visibility;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::source_map::Span;
@@ -34,6 +36,9 @@ declare_clippy_lint! {
 }
 
 pub struct MissingDoc {
+    /// Whether to **only** check for missing documentation in items visible within the current
+    /// crate. For example, `pub(crate)` items.
+    crate_items_only: bool,
     /// Stack of whether #[doc(hidden)] is set
     /// at each level which has lint attributes.
     doc_hidden_stack: Vec<bool>,
@@ -42,14 +47,15 @@ pub struct MissingDoc {
 impl Default for MissingDoc {
     #[must_use]
     fn default() -> Self {
-        Self::new()
+        Self::new(false)
     }
 }
 
 impl MissingDoc {
     #[must_use]
-    pub fn new() -> Self {
+    pub fn new(crate_items_only: bool) -> Self {
         Self {
+            crate_items_only,
             doc_hidden_stack: vec![false],
         }
     }
@@ -75,6 +81,7 @@ impl MissingDoc {
     fn check_missing_docs_attrs(
         &self,
         cx: &LateContext<'_>,
+        def_id: LocalDefId,
         attrs: &[ast::Attribute],
         sp: Span,
         article: &'static str,
@@ -95,6 +102,13 @@ impl MissingDoc {
             return;
         }
 
+        if self.crate_items_only && def_id != CRATE_DEF_ID {
+            let vis = cx.tcx.visibility(def_id);
+            if vis == Visibility::Public || vis != Visibility::Restricted(CRATE_DEF_ID.into()) {
+                return;
+            }
+        }
+
         let has_doc = attrs
             .iter()
             .any(|a| a.doc_str().is_some() || Self::has_include(a.meta()));
@@ -123,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
     fn check_crate(&mut self, cx: &LateContext<'tcx>) {
         let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
-        self.check_missing_docs_attrs(cx, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate");
+        self.check_missing_docs_attrs(cx, CRATE_DEF_ID, attrs, cx.tcx.def_span(CRATE_DEF_ID), "the", "crate");
     }
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
@@ -159,7 +173,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
         let attrs = cx.tcx.hir().attrs(it.hir_id());
         if !is_from_proc_macro(cx, it) {
-            self.check_missing_docs_attrs(cx, attrs, it.span, article, desc);
+            self.check_missing_docs_attrs(cx, it.owner_id.def_id, attrs, it.span, article, desc);
         }
     }
 
@@ -168,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
 
         let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
         if !is_from_proc_macro(cx, trait_item) {
-            self.check_missing_docs_attrs(cx, attrs, trait_item.span, article, desc);
+            self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, attrs, trait_item.span, article, desc);
         }
     }
 
@@ -185,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
         let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
         if !is_from_proc_macro(cx, impl_item) {
-            self.check_missing_docs_attrs(cx, attrs, impl_item.span, article, desc);
+            self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, attrs, impl_item.span, article, desc);
         }
     }
 
@@ -193,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
         if !sf.is_positional() {
             let attrs = cx.tcx.hir().attrs(sf.hir_id);
             if !is_from_proc_macro(cx, sf) {
-                self.check_missing_docs_attrs(cx, attrs, sf.span, "a", "struct field");
+                self.check_missing_docs_attrs(cx, sf.def_id, attrs, sf.span, "a", "struct field");
             }
         }
     }
@@ -201,7 +215,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
     fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
         let attrs = cx.tcx.hir().attrs(v.hir_id);
         if !is_from_proc_macro(cx, v) {
-            self.check_missing_docs_attrs(cx, attrs, v.span, "a", "variant");
+            self.check_missing_docs_attrs(cx, v.def_id, attrs, v.span, "a", "variant");
         }
     }
 }
diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs
index 0742943dff2..349fcd2274d 100644
--- a/src/tools/clippy/clippy_lints/src/module_style.rs
+++ b/src/tools/clippy/clippy_lints/src/module_style.rs
@@ -134,7 +134,7 @@ fn process_paths_for_mod_files<'a>(
     mod_folders: &mut FxHashSet<&'a OsStr>,
 ) {
     let mut comp = path.components().rev().peekable();
-    let _ = comp.next();
+    let _: Option<_> = comp.next();
     if path.ends_with("mod.rs") {
         mod_folders.insert(comp.peek().map(|c| c.as_os_str()).unwrap_or_default());
     }
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index 5a533261cad..8aa814b7405 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -166,7 +166,8 @@ impl MutableKeyType {
             Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || self.is_interior_mutable_type(cx, inner_ty),
             Slice(inner_ty) => self.is_interior_mutable_type(cx, inner_ty),
             Array(inner_ty, size) => {
-                size.try_eval_target_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0)
+                size.try_eval_target_usize(cx.tcx, cx.param_env)
+                    .map_or(true, |u| u != 0)
                     && self.is_interior_mutable_type(cx, inner_ty)
             },
             Tuple(fields) => fields.iter().any(|ty| self.is_interior_mutable_type(cx, ty)),
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index da3b6fa9899..1ab81aee7b8 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -149,7 +149,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
         };
 
         let fn_sig = cx.tcx.fn_sig(fn_def_id).subst_identity();
-        let fn_sig = cx.tcx.erase_late_bound_regions(fn_sig);
+        let fn_sig = cx.tcx.liberate_late_bound_regions(fn_def_id.to_def_id(), fn_sig);
 
         for (idx, ((input, &ty), arg)) in decl.inputs.iter().zip(fn_sig.inputs()).zip(body.params).enumerate() {
             // All spans generated from a proc-macro invocation are the same...
diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
index 97c8cfbd3eb..e2a7ba02a04 100644
--- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
@@ -6,7 +6,6 @@ use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{AsyncGeneratorKind, Block, Body, Expr, ExprKind, GeneratorKind, LangItem, MatchSource, QPath};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::DefIdTree;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
diff --git a/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
new file mode 100644
index 00000000000..bc64ccb295c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/no_mangle_with_rust_abi.rs
@@ -0,0 +1,65 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_with_applicability;
+use rustc_errors::Applicability;
+use rustc_hir::{Item, ItemKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_target::spec::abi::Abi;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for Rust ABI functions with the `#[no_mangle]` attribute.
+    ///
+    /// ### Why is this bad?
+    /// The Rust ABI is not stable, but in many simple cases matches
+    /// enough with the C ABI that it is possible to forget to add
+    /// `extern "C"` to a function called from C. Changes to the
+    /// Rust ABI can break this at any point.
+    ///
+    /// ### Example
+    /// ```rust
+    ///  #[no_mangle]
+    ///  fn example(arg_one: u32, arg_two: usize) {}
+    /// ```
+    ///
+    /// Use instead:
+    /// ```rust
+    ///  #[no_mangle]
+    ///  extern "C" fn example(arg_one: u32, arg_two: usize) {}
+    /// ```
+    #[clippy::version = "1.69.0"]
+    pub NO_MANGLE_WITH_RUST_ABI,
+    pedantic,
+    "convert Rust ABI functions to C ABI"
+}
+declare_lint_pass!(NoMangleWithRustAbi => [NO_MANGLE_WITH_RUST_ABI]);
+
+impl<'tcx> LateLintPass<'tcx> for NoMangleWithRustAbi {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        if let ItemKind::Fn(fn_sig, _, _) = &item.kind {
+            let attrs = cx.tcx.hir().attrs(item.hir_id());
+            let mut applicability = Applicability::MachineApplicable;
+            let snippet = snippet_with_applicability(cx, fn_sig.span, "..", &mut applicability);
+            for attr in attrs {
+                if let Some(ident) = attr.ident()
+                    && ident.name == rustc_span::sym::no_mangle
+                    && fn_sig.header.abi == Abi::Rust
+                    && !snippet.contains("extern") {
+
+                    let suggestion = snippet.split_once("fn")
+                        .map_or(String::new(), |(first, second)| format!(r#"{first}extern "C" fn{second}"#));
+
+                    span_lint_and_sugg(
+                        cx,
+                        NO_MANGLE_WITH_RUST_ABI,
+                        fn_sig.span,
+                        "attribute #[no_mangle] set on a Rust ABI function",
+                        "try",
+                        suggestion,
+                        applicability
+                    );
+                }
+            }
+        }
+    }
+}
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 d592f6e814c..87a8a2ed12b 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,8 +1,8 @@
 use super::ARITHMETIC_SIDE_EFFECTS;
 use clippy_utils::{
-    consts::{constant, constant_simple},
+    consts::{constant, constant_simple, Constant},
     diagnostics::span_lint,
-    peel_hir_expr_refs, peel_hir_expr_unary,
+    is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary,
 };
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -97,17 +97,19 @@ impl ArithmeticSideEffects {
         self.expr_span = Some(expr.span);
     }
 
-    /// If `expr` is not a literal integer like `1`, returns `None`.
+    /// Returns the numeric value of a literal integer originated from `expr`, if any.
     ///
-    /// Returns the absolute value of the expression, if this is an integer literal.
-    fn literal_integer(expr: &hir::Expr<'_>) -> Option<u128> {
+    /// Literal integers can be originated from adhoc declarations like `1`, associated constants
+    /// like `i32::MAX` or constant references like `N` from `const N: i32 = 1;`,
+    fn literal_integer(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<u128> {
         let actual = peel_hir_expr_unary(expr).0;
         if let hir::ExprKind::Lit(ref lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
-            Some(n)
+            return Some(n)
         }
-        else {
-            None
+        if let Some((Constant::Int(n), _)) = constant(cx, cx.typeck_results(), expr) {
+            return Some(n);
         }
+        None
     }
 
     /// Manages when the lint should be triggered. Operations in constant environments, hard coded
@@ -143,7 +145,10 @@ impl ArithmeticSideEffects {
         let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
             let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
             let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
-            match (Self::literal_integer(actual_lhs), Self::literal_integer(actual_rhs)) {
+            match (
+                Self::literal_integer(cx, actual_lhs),
+                Self::literal_integer(cx, actual_rhs),
+            ) {
                 (None, None) => false,
                 (None, Some(n)) | (Some(n), None) => match (&op.node, n) {
                     (hir::BinOpKind::Div | hir::BinOpKind::Rem, 0) => false,
@@ -180,20 +185,22 @@ impl ArithmeticSideEffects {
             return;
         }
         let actual_un_expr = peel_hir_expr_refs(un_expr).0;
-        if Self::literal_integer(actual_un_expr).is_some() {
+        if Self::literal_integer(cx, actual_un_expr).is_some() {
             return;
         }
         self.issue_lint(cx, expr);
     }
 
-    fn should_skip_expr(&mut self, expr: &hir::Expr<'_>) -> bool {
-        self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span))
+    fn should_skip_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
+        is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id)
+            || self.expr_span.is_some()
+            || self.const_span.map_or(false, |sp| sp.contains(expr.span))
     }
 }
 
 impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
-        if self.should_skip_expr(expr) {
+        if self.should_skip_expr(cx, expr) {
             return;
         }
         match &expr.kind {
diff --git a/src/tools/clippy/clippy_lints/src/question_mark_used.rs b/src/tools/clippy/clippy_lints/src/question_mark_used.rs
new file mode 100644
index 00000000000..9b678e8d753
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/question_mark_used.rs
@@ -0,0 +1,52 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+
+use clippy_utils::macros::span_is_local;
+use rustc_hir::{Expr, ExprKind, MatchSource};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for expressions that use the question mark operator and rejects them.
+    ///
+    /// ### Why is this bad?
+    /// Sometimes code wants to avoid the question mark operator because for instance a local
+    /// block requires a macro to re-throw errors to attach additional information to the
+    /// error.
+    ///
+    /// ### Example
+    /// ```ignore
+    /// let result = expr?;
+    /// ```
+    ///
+    /// Could be written:
+    ///
+    /// ```ignore
+    /// utility_macro!(expr);
+    /// ```
+    #[clippy::version = "pre 1.29.0"]
+    pub QUESTION_MARK_USED,
+    restriction,
+    "complains if the question mark operator is used"
+}
+
+declare_lint_pass!(QuestionMarkUsed => [QUESTION_MARK_USED]);
+
+impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if let ExprKind::Match(_, _, MatchSource::TryDesugar) = expr.kind {
+            if !span_is_local(expr.span) {
+                return;
+            }
+
+            span_lint_and_help(
+                cx,
+                QUESTION_MARK_USED,
+                expr.span,
+                "question mark operator was used",
+                None,
+                "consider using a custom macro or match expression",
+            );
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 84a0c6b9558..f0d7dd23a67 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -14,6 +14,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map::Span;
 use rustc_span::{BytePos, Pos};
+use std::borrow::Cow;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -69,31 +70,41 @@ declare_clippy_lint! {
     "using a return statement like `return expr;` where an expression would suffice"
 }
 
-#[derive(PartialEq, Eq, Copy, Clone)]
-enum RetReplacement {
+#[derive(PartialEq, Eq, Clone)]
+enum RetReplacement<'tcx> {
     Empty,
     Block,
     Unit,
+    IfSequence(Cow<'tcx, str>, Applicability),
+    Expr(Cow<'tcx, str>, Applicability),
 }
 
-impl RetReplacement {
+impl<'tcx> RetReplacement<'tcx> {
     fn sugg_help(self) -> &'static str {
         match self {
-            Self::Empty => "remove `return`",
+            Self::Empty | Self::Expr(..) => "remove `return`",
             Self::Block => "replace `return` with an empty block",
             Self::Unit => "replace `return` with a unit value",
+            Self::IfSequence(..) => "remove `return` and wrap the sequence with parentheses",
+        }
+    }
+    fn applicability(&self) -> Option<Applicability> {
+        match self {
+            Self::Expr(_, ap) | Self::IfSequence(_, ap) => Some(*ap),
+            _ => None,
         }
     }
 }
 
-impl ToString for RetReplacement {
+impl<'tcx> ToString for RetReplacement<'tcx> {
     fn to_string(&self) -> String {
-        match *self {
-            Self::Empty => "",
-            Self::Block => "{}",
-            Self::Unit => "()",
+        match self {
+            Self::Empty => String::new(),
+            Self::Block => "{}".to_string(),
+            Self::Unit => "()".to_string(),
+            Self::IfSequence(inner, _) => format!("({inner})"),
+            Self::Expr(inner, _) => inner.to_string(),
         }
-        .to_string()
     }
 }
 
@@ -204,19 +215,38 @@ fn check_final_expr<'tcx>(
     expr: &'tcx Expr<'tcx>,
     semi_spans: Vec<Span>, /* containing all the places where we would need to remove semicolons if finding an
                             * needless return */
-    replacement: RetReplacement,
+    replacement: RetReplacement<'tcx>,
 ) {
     let peeled_drop_expr = expr.peel_drop_temps();
     match &peeled_drop_expr.kind {
         // simple return is always "bad"
         ExprKind::Ret(ref inner) => {
-            // if desugar of `do yeet`, don't lint
-            if let Some(inner_expr) = inner
-                && let ExprKind::Call(path_expr, _) = inner_expr.kind
-                && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind
-            {
-                return;
-            }
+            // check if expr return nothing
+            let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
+                extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
+            } else {
+                peeled_drop_expr.span
+            };
+
+            let replacement = if let Some(inner_expr) = inner {
+                // if desugar of `do yeet`, don't lint
+                if let ExprKind::Call(path_expr, _) = inner_expr.kind
+                    && let ExprKind::Path(QPath::LangItem(LangItem::TryTraitFromYeet, _, _)) = path_expr.kind
+                {
+                    return;
+                }
+
+                let mut applicability = Applicability::MachineApplicable;
+                let (snippet, _) = snippet_with_context(cx, inner_expr.span, ret_span.ctxt(), "..", &mut applicability);
+                if expr_contains_conjunctive_ifs(inner_expr) {
+                    RetReplacement::IfSequence(snippet, applicability)
+                } else {
+                    RetReplacement::Expr(snippet, applicability)
+                }
+            } else {
+                replacement
+            };
+
             if !cx.tcx.hir().attrs(expr.hir_id).is_empty() {
                 return;
             }
@@ -224,14 +254,8 @@ fn check_final_expr<'tcx>(
             if borrows {
                 return;
             }
-            // check if expr return nothing
-            let ret_span = if inner.is_none() && replacement == RetReplacement::Empty {
-                extend_span_to_previous_non_ws(cx, peeled_drop_expr.span)
-            } else {
-                peeled_drop_expr.span
-            };
 
-            emit_return_lint(cx, ret_span, semi_spans, inner.as_ref().map(|i| i.span), replacement);
+            emit_return_lint(cx, ret_span, semi_spans, replacement);
         },
         ExprKind::If(_, then, else_clause_opt) => {
             check_block_return(cx, &then.kind, peeled_drop_expr.span, semi_spans.clone());
@@ -253,29 +277,25 @@ fn check_final_expr<'tcx>(
     }
 }
 
-fn emit_return_lint(
-    cx: &LateContext<'_>,
-    ret_span: Span,
-    semi_spans: Vec<Span>,
-    inner_span: Option<Span>,
-    replacement: RetReplacement,
-) {
+fn expr_contains_conjunctive_ifs<'tcx>(expr: &'tcx Expr<'tcx>) -> bool {
+    fn contains_if(expr: &Expr<'_>, on_if: bool) -> bool {
+        match expr.kind {
+            ExprKind::If(..) => on_if,
+            ExprKind::Binary(_, left, right) => contains_if(left, true) || contains_if(right, true),
+            _ => false,
+        }
+    }
+
+    contains_if(expr, false)
+}
+
+fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, semi_spans: Vec<Span>, replacement: RetReplacement<'_>) {
     if ret_span.from_expansion() {
         return;
     }
-    let mut applicability = Applicability::MachineApplicable;
-    let return_replacement = inner_span.map_or_else(
-        || replacement.to_string(),
-        |inner_span| {
-            let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability);
-            snippet.to_string()
-        },
-    );
-    let sugg_help = if inner_span.is_some() {
-        "remove `return`"
-    } else {
-        replacement.sugg_help()
-    };
+    let applicability = replacement.applicability().unwrap_or(Applicability::MachineApplicable);
+    let return_replacement = replacement.to_string();
+    let sugg_help = replacement.sugg_help();
     span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded `return` statement", |diag| {
         diag.span_suggestion_hidden(ret_span, sugg_help, return_replacement, applicability);
         // for each parent statement, we need to remove the semicolon
diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
new file mode 100644
index 00000000000..e2d90edec5a
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs
@@ -0,0 +1,399 @@
+use crate::FxHashSet;
+use clippy_utils::{
+    diagnostics::span_lint_and_then,
+    get_attr,
+    source::{indent_of, snippet},
+};
+use rustc_errors::{Applicability, Diagnostic};
+use rustc_hir::{
+    self as hir,
+    intravisit::{walk_expr, Visitor},
+};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::ty::{subst::GenericArgKind, Ty, TypeAndMut};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{symbol::Ident, Span, DUMMY_SP};
+
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Searches for elements marked with `#[clippy::significant_drop]` that could be early
+    /// dropped but are in fact dropped at the end of their scopes. In other words, enforces the
+    /// "tightening" of their possible lifetimes.
+    ///
+    /// ### Why is this bad?
+    ///
+    /// Elements marked with `#[clippy::has_significant_drop]` are generally synchronizing
+    /// primitives that manage shared resources, as such, it is desired to release them as soon as
+    /// possible to avoid unnecessary resource contention.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore
+    /// fn main() {
+    ///   let lock = some_sync_resource.lock();
+    ///   let owned_rslt = lock.do_stuff_with_resource();
+    ///   // Only `owned_rslt` is needed but `lock` is still held.
+    ///   do_heavy_computation_that_takes_time(owned_rslt);
+    /// }
+    /// ```
+    ///
+    /// Use instead:
+    ///
+    /// ```rust,ignore
+    /// fn main() {
+    ///     let owned_rslt = some_sync_resource.lock().do_stuff_with_resource();
+    ///     do_heavy_computation_that_takes_time(owned_rslt);
+    /// }
+    /// ```
+    #[clippy::version = "1.67.0"]
+    pub SIGNIFICANT_DROP_TIGHTENING,
+    nursery,
+    "Searches for elements marked with `#[clippy::has_significant_drop]` that could be early dropped but are in fact dropped at the end of their scopes"
+}
+
+impl_lint_pass!(SignificantDropTightening<'_> => [SIGNIFICANT_DROP_TIGHTENING]);
+
+#[derive(Default)]
+pub struct SignificantDropTightening<'tcx> {
+    /// Auxiliary structure used to avoid having to verify the same type multiple times.
+    seen_types: FxHashSet<Ty<'tcx>>,
+}
+
+impl<'tcx> SignificantDropTightening<'tcx> {
+    /// Unifies the statements of a block with its return expression.
+    fn all_block_stmts<'ret, 'rslt, 'stmts>(
+        block_stmts: &'stmts [hir::Stmt<'tcx>],
+        dummy_ret_stmt: Option<&'ret hir::Stmt<'tcx>>,
+    ) -> impl Iterator<Item = &'rslt hir::Stmt<'tcx>>
+    where
+        'ret: 'rslt,
+        'stmts: 'rslt,
+    {
+        block_stmts.iter().chain(dummy_ret_stmt)
+    }
+
+    /// Searches for at least one statement that could slow down the release of a significant drop.
+    fn at_least_one_stmt_is_expensive<'stmt>(stmts: impl Iterator<Item = &'stmt hir::Stmt<'tcx>>) -> bool
+    where
+        'tcx: 'stmt,
+    {
+        for stmt in stmts {
+            match stmt.kind {
+                hir::StmtKind::Expr(expr) if let hir::ExprKind::Path(_) = expr.kind => {}
+                hir::StmtKind::Local(local) if let Some(expr) = local.init
+                    && let hir::ExprKind::Path(_) = expr.kind => {},
+                _ => return true
+            };
+        }
+        false
+    }
+
+    /// Verifies if the expression is of type `drop(some_lock_path)` to assert that the temporary
+    /// is already being dropped before the end of its scope.
+    fn has_drop(expr: &'tcx hir::Expr<'_>, init_bind_ident: Ident) -> bool {
+        if let hir::ExprKind::Call(fun, args) = expr.kind
+            && let hir::ExprKind::Path(hir::QPath::Resolved(_, fun_path)) = &fun.kind
+            && let [fun_ident, ..] = fun_path.segments
+            && fun_ident.ident.name == rustc_span::sym::drop
+            && let [first_arg, ..] = args
+            && let hir::ExprKind::Path(hir::QPath::Resolved(_, arg_path)) = &first_arg.kind
+            && let [first_arg_ps, .. ] = arg_path.segments
+        {
+            first_arg_ps.ident == init_bind_ident
+        }
+        else {
+            false
+        }
+    }
+
+    /// Tries to find types marked with `#[has_significant_drop]` of an expression `expr` that is
+    /// originated from `stmt` and then performs common logic on `sdap`.
+    fn modify_sdap_if_sig_drop_exists(
+        &mut self,
+        cx: &LateContext<'tcx>,
+        expr: &'tcx hir::Expr<'_>,
+        idx: usize,
+        sdap: &mut SigDropAuxParams,
+        stmt: &hir::Stmt<'_>,
+        cb: impl Fn(&mut SigDropAuxParams),
+    ) {
+        let mut sig_drop_finder = SigDropFinder::new(cx, &mut self.seen_types);
+        sig_drop_finder.visit_expr(expr);
+        if sig_drop_finder.has_sig_drop {
+            cb(sdap);
+            if sdap.number_of_stmts > 0 {
+                sdap.last_use_stmt_idx = idx;
+                sdap.last_use_stmt_span = stmt.span;
+                if let hir::ExprKind::MethodCall(_, _, _, span) = expr.kind {
+                    sdap.last_use_method_span = span;
+                }
+            }
+            sdap.number_of_stmts = sdap.number_of_stmts.wrapping_add(1);
+        }
+    }
+
+    /// Shows generic overall messages as well as specialized messages depending on the usage.
+    fn set_suggestions(cx: &LateContext<'tcx>, block_span: Span, diag: &mut Diagnostic, sdap: &SigDropAuxParams) {
+        match sdap.number_of_stmts {
+            0 | 1 => {},
+            2 => {
+                let indent = " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0));
+                let init_method = snippet(cx, sdap.init_method_span, "..");
+                let usage_method = snippet(cx, sdap.last_use_method_span, "..");
+                let stmt = if let Some(last_use_bind_span) = sdap.last_use_bind_span {
+                    format!(
+                        "\n{indent}let {} = {init_method}.{usage_method};",
+                        snippet(cx, last_use_bind_span, ".."),
+                    )
+                } else {
+                    format!("\n{indent}{init_method}.{usage_method};")
+                };
+                diag.span_suggestion_verbose(
+                    sdap.init_stmt_span,
+                    "merge the temporary construction with its single usage",
+                    stmt,
+                    Applicability::MaybeIncorrect,
+                );
+                diag.span_suggestion(
+                    sdap.last_use_stmt_span,
+                    "remove separated single usage",
+                    "",
+                    Applicability::MaybeIncorrect,
+                );
+            },
+            _ => {
+                diag.span_suggestion(
+                    sdap.last_use_stmt_span.shrink_to_hi(),
+                    "drop the temporary after the end of its last usage",
+                    format!(
+                        "\n{}drop({});",
+                        " ".repeat(indent_of(cx, sdap.last_use_stmt_span).unwrap_or(0)),
+                        sdap.init_bind_ident
+                    ),
+                    Applicability::MaybeIncorrect,
+                );
+            },
+        }
+        diag.note("this might lead to unnecessary resource contention");
+        diag.span_label(
+            block_span,
+            format!(
+                "temporary `{}` is currently being dropped at the end of its contained scope",
+                sdap.init_bind_ident
+            ),
+        );
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for SignificantDropTightening<'tcx> {
+    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
+        let dummy_ret_stmt = block.expr.map(|expr| hir::Stmt {
+            hir_id: hir::HirId::INVALID,
+            kind: hir::StmtKind::Expr(expr),
+            span: DUMMY_SP,
+        });
+        let mut sdap = SigDropAuxParams::default();
+        for (idx, stmt) in Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).enumerate() {
+            match stmt.kind {
+                hir::StmtKind::Expr(expr) => self.modify_sdap_if_sig_drop_exists(
+                    cx,
+                    expr,
+                    idx,
+                    &mut sdap,
+                    stmt,
+                    |_| {}
+                ),
+                hir::StmtKind::Local(local) if let Some(expr) = local.init => self.modify_sdap_if_sig_drop_exists(
+                    cx,
+                    expr,
+                    idx,
+                    &mut sdap,
+                    stmt,
+                    |local_sdap| {
+                        if local_sdap.number_of_stmts == 0 {
+                            if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
+                                local_sdap.init_bind_ident = ident;
+                            }
+                            if let hir::ExprKind::MethodCall(_, local_expr, _, span) = expr.kind {
+                                local_sdap.init_method_span = local_expr.span.to(span);
+                            }
+                            local_sdap.init_stmt_span = stmt.span;
+                        }
+                        else if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind {
+                            local_sdap.last_use_bind_span = Some(ident.span);
+                        }
+                    }
+                ),
+                hir::StmtKind::Semi(expr) => {
+                    if Self::has_drop(expr, sdap.init_bind_ident) {
+                        return;
+                    }
+                    self.modify_sdap_if_sig_drop_exists(cx, expr, idx, &mut sdap, stmt, |_| {});
+                },
+                _ => {}
+            };
+        }
+
+        let idx = sdap.last_use_stmt_idx.wrapping_add(1);
+        let stmts_after_last_use = Self::all_block_stmts(block.stmts, dummy_ret_stmt.as_ref()).skip(idx);
+        if sdap.number_of_stmts > 1 && Self::at_least_one_stmt_is_expensive(stmts_after_last_use) {
+            span_lint_and_then(
+                cx,
+                SIGNIFICANT_DROP_TIGHTENING,
+                sdap.init_bind_ident.span,
+                "temporary with significant `Drop` can be early dropped",
+                |diag| {
+                    Self::set_suggestions(cx, block.span, diag, &sdap);
+                },
+            );
+        }
+    }
+}
+
+/// Auxiliary parameters used on each block check.
+struct SigDropAuxParams {
+    /// The binding or variable that references the initial construction of the type marked with
+    /// `#[has_significant_drop]`.
+    init_bind_ident: Ident,
+    /// Similar to `init_bind_ident` but encompasses the right-hand method call.
+    init_method_span: Span,
+    /// Similar to `init_bind_ident` but encompasses the whole contained statement.
+    init_stmt_span: Span,
+
+    /// The last visited binding or variable span within a block that had any referenced inner type
+    /// marked with `#[has_significant_drop]`.
+    last_use_bind_span: Option<Span>,
+    /// Index of the last visited statement within a block that had any referenced inner type
+    /// marked with `#[has_significant_drop]`.
+    last_use_stmt_idx: usize,
+    /// Similar to `last_use_bind_span` but encompasses the whole contained statement.
+    last_use_stmt_span: Span,
+    /// Similar to `last_use_bind_span` but encompasses the right-hand method call.
+    last_use_method_span: Span,
+
+    /// Total number of statements within a block that have any referenced inner type marked with
+    /// `#[has_significant_drop]`.
+    number_of_stmts: usize,
+}
+
+impl Default for SigDropAuxParams {
+    fn default() -> Self {
+        Self {
+            init_bind_ident: Ident::empty(),
+            init_method_span: DUMMY_SP,
+            init_stmt_span: DUMMY_SP,
+            last_use_bind_span: None,
+            last_use_method_span: DUMMY_SP,
+            last_use_stmt_idx: 0,
+            last_use_stmt_span: DUMMY_SP,
+            number_of_stmts: 0,
+        }
+    }
+}
+
+/// Checks the existence of the `#[has_significant_drop]` attribute
+struct SigDropChecker<'cx, 'sdt, 'tcx> {
+    cx: &'cx LateContext<'tcx>,
+    seen_types: &'sdt mut FxHashSet<Ty<'tcx>>,
+}
+
+impl<'cx, 'sdt, 'tcx> SigDropChecker<'cx, 'sdt, 'tcx> {
+    pub(crate) fn new(cx: &'cx LateContext<'tcx>, seen_types: &'sdt mut FxHashSet<Ty<'tcx>>) -> Self {
+        seen_types.clear();
+        Self { cx, seen_types }
+    }
+
+    pub(crate) fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
+        if let Some(adt) = ty.ty_adt_def() {
+            let mut iter = get_attr(
+                self.cx.sess(),
+                self.cx.tcx.get_attrs_unchecked(adt.did()),
+                "has_significant_drop",
+            );
+            if iter.next().is_some() {
+                return true;
+            }
+        }
+        match ty.kind() {
+            rustc_middle::ty::Adt(a, b) => {
+                for f in a.all_fields() {
+                    let ty = f.ty(self.cx.tcx, b);
+                    if !self.has_seen_ty(ty) && self.has_sig_drop_attr(ty) {
+                        return true;
+                    }
+                }
+                for generic_arg in b.iter() {
+                    if let GenericArgKind::Type(ty) = generic_arg.unpack() {
+                        if self.has_sig_drop_attr(ty) {
+                            return true;
+                        }
+                    }
+                }
+                false
+            },
+            rustc_middle::ty::Array(ty, _)
+            | rustc_middle::ty::RawPtr(TypeAndMut { ty, .. })
+            | rustc_middle::ty::Ref(_, ty, _)
+            | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty),
+            _ => false,
+        }
+    }
+
+    fn has_seen_ty(&mut self, ty: Ty<'tcx>) -> bool {
+        !self.seen_types.insert(ty)
+    }
+}
+
+/// Performs recursive calls to find any inner type marked with `#[has_significant_drop]`.
+struct SigDropFinder<'cx, 'sdt, 'tcx> {
+    cx: &'cx LateContext<'tcx>,
+    has_sig_drop: bool,
+    sig_drop_checker: SigDropChecker<'cx, 'sdt, 'tcx>,
+}
+
+impl<'cx, 'sdt, 'tcx> SigDropFinder<'cx, 'sdt, 'tcx> {
+    fn new(cx: &'cx LateContext<'tcx>, seen_types: &'sdt mut FxHashSet<Ty<'tcx>>) -> Self {
+        Self {
+            cx,
+            has_sig_drop: false,
+            sig_drop_checker: SigDropChecker::new(cx, seen_types),
+        }
+    }
+}
+
+impl<'cx, 'sdt, 'tcx> Visitor<'tcx> for SigDropFinder<'cx, 'sdt, 'tcx> {
+    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'_>) {
+        if self
+            .sig_drop_checker
+            .has_sig_drop_attr(self.cx.typeck_results().expr_ty(ex))
+        {
+            self.has_sig_drop = true;
+            return;
+        }
+
+        match ex.kind {
+            hir::ExprKind::MethodCall(_, expr, ..) => {
+                self.visit_expr(expr);
+            },
+            hir::ExprKind::Array(..)
+            | hir::ExprKind::Assign(..)
+            | hir::ExprKind::AssignOp(..)
+            | hir::ExprKind::Binary(..)
+            | hir::ExprKind::Box(..)
+            | hir::ExprKind::Call(..)
+            | hir::ExprKind::Field(..)
+            | hir::ExprKind::If(..)
+            | hir::ExprKind::Index(..)
+            | hir::ExprKind::Match(..)
+            | hir::ExprKind::Repeat(..)
+            | hir::ExprKind::Ret(..)
+            | hir::ExprKind::Tup(..)
+            | hir::ExprKind::Unary(..)
+            | hir::ExprKind::Yield(..) => {
+                walk_expr(self, ex);
+            },
+            _ => {},
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index d6b336bef94..a13bc7a5188 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -2,7 +2,6 @@ use clippy_utils::diagnostics::span_lint_and_help;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{def::Res, HirId, Path, PathSegment};
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::DefIdTree;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, symbol::kw, Span};
 
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 17e9cc5f6b7..0f062cecf88 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -10,7 +10,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Spanned;
-use rustc_span::{sym, Span};
+use rustc_span::{sym, symbol::Ident, Span};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -174,53 +174,74 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) {
 
 /// Implementation of the `ALMOST_SWAPPED` lint.
 fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
-    for w in block.stmts.windows(2) {
-        if_chain! {
-            if let StmtKind::Semi(first) = w[0].kind;
-            if let StmtKind::Semi(second) = w[1].kind;
-            if first.span.ctxt() == second.span.ctxt();
-            if let ExprKind::Assign(lhs0, rhs0, _) = first.kind;
-            if let ExprKind::Assign(lhs1, rhs1, _) = second.kind;
-            if eq_expr_value(cx, lhs0, rhs1);
-            if eq_expr_value(cx, lhs1, rhs0);
-            then {
-                let lhs0 = Sugg::hir_opt(cx, lhs0);
-                let rhs0 = Sugg::hir_opt(cx, rhs0);
-                let (what, lhs, rhs) = if let (Some(first), Some(second)) = (lhs0, rhs0) {
-                    (
-                        format!(" `{first}` and `{second}`"),
-                        first.mut_addr().to_string(),
-                        second.mut_addr().to_string(),
-                    )
-                } else {
-                    (String::new(), String::new(), String::new())
-                };
+    for [first, second] in block.stmts.array_windows() {
+        if let Some((lhs0, rhs0)) = parse(first)
+            && let Some((lhs1, rhs1)) = parse(second)
+            && first.span.eq_ctxt(second.span)
+            && is_same(cx, lhs0, rhs1)
+            && is_same(cx, lhs1, rhs0)
+            && let Some(lhs_sugg) = match &lhs0 {
+                ExprOrIdent::Expr(expr) => Sugg::hir_opt(cx, expr),
+                ExprOrIdent::Ident(ident) => Some(Sugg::NonParen(ident.as_str().into())),
+            }
+            && let Some(rhs_sugg) = Sugg::hir_opt(cx, rhs0)
+        {
+            let span = first.span.to(rhs1.span);
+            let Some(sugg) = std_or_core(cx) else { return };
+            span_lint_and_then(
+                cx,
+                ALMOST_SWAPPED,
+                span,
+                &format!("this looks like you are trying to swap `{lhs_sugg}` and `{rhs_sugg}`"),
+                |diag| {
+                    diag.span_suggestion(
+                        span,
+                        "try",
+                        format!("{sugg}::mem::swap({}, {})", lhs_sugg.mut_addr(), rhs_sugg.mut_addr()),
+                        Applicability::MaybeIncorrect,
+                    );
+                    diag.note(format!("or maybe you should use `{sugg}::mem::replace`?"));
+                },
+            );
+        }
+    }
+}
+
+fn is_same(cx: &LateContext<'_>, lhs: ExprOrIdent<'_>, rhs: &Expr<'_>) -> bool {
+    match lhs {
+        ExprOrIdent::Expr(expr) => eq_expr_value(cx, expr, rhs),
+        ExprOrIdent::Ident(ident) => {
+            if let ExprKind::Path(QPath::Resolved(None, path)) = rhs.kind
+                && let [segment] = &path.segments
+                && segment.ident == ident
+            {
+                true
+            } else {
+                false
+            }
+        }
+    }
+}
 
-                let span = first.span.to(second.span);
-                let Some(sugg) = std_or_core(cx) else { return };
+#[derive(Debug, Clone, Copy)]
+enum ExprOrIdent<'a> {
+    Expr(&'a Expr<'a>),
+    Ident(Ident),
+}
 
-                span_lint_and_then(cx,
-                    ALMOST_SWAPPED,
-                    span,
-                    &format!("this looks like you are trying to swap{what}"),
-                    |diag| {
-                        if !what.is_empty() {
-                            diag.span_suggestion(
-                                span,
-                                "try",
-                                format!(
-                                    "{sugg}::mem::swap({lhs}, {rhs})",
-                                ),
-                                Applicability::MaybeIncorrect,
-                            );
-                            diag.note(
-                                format!("or maybe you should use `{sugg}::mem::replace`?")
-                            );
-                        }
-                    });
+fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr<'hir>)> {
+    if let StmtKind::Semi(expr) = stmt.kind {
+        if let ExprKind::Assign(lhs, rhs, _) = expr.kind {
+            return Some((ExprOrIdent::Expr(lhs), rhs));
+        }
+    } else if let StmtKind::Local(expr) = stmt.kind {
+        if let Some(rhs) = expr.init {
+            if let PatKind::Binding(_, _, ident_l, _) = expr.pat.kind {
+                return Some((ExprOrIdent::Ident(ident_l), rhs));
             }
         }
     }
+    None
 }
 
 /// Implementation of the xor case for `MANUAL_SWAP` lint.
diff --git a/src/tools/clippy/clippy_lints/src/transmute/mod.rs b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
index c0d290b5adc..c01cbe5090f 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/mod.rs
@@ -3,6 +3,7 @@ mod transmute_float_to_int;
 mod transmute_int_to_bool;
 mod transmute_int_to_char;
 mod transmute_int_to_float;
+mod transmute_int_to_non_zero;
 mod transmute_null_to_fn;
 mod transmute_num_to_bytes;
 mod transmute_ptr_to_ptr;
@@ -255,6 +256,31 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
+    /// Checks for transmutes from integers to `NonZero*` types, and suggests their `new_unchecked`
+    /// method instead.
+    ///
+    /// ### Why is this bad?
+    /// Transmutes work on any types and thus might cause unsoundness when those types change
+    /// elsewhere. `new_unchecked` only works for the appropriate types instead.
+    ///
+    /// ### Example
+    /// ```rust
+    /// # use core::num::NonZeroU32;
+    /// let _non_zero: NonZeroU32 = unsafe { std::mem::transmute(123) };
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # use core::num::NonZeroU32;
+    /// let _non_zero = unsafe { NonZeroU32::new_unchecked(123) };
+    /// ```
+    #[clippy::version = "1.69.0"]
+    pub TRANSMUTE_INT_TO_NON_ZERO,
+    complexity,
+    "transmutes from an integer to a non-zero wrapper"
+}
+
+declare_clippy_lint! {
+    /// ### What it does
     /// Checks for transmutes from a float to an integer.
     ///
     /// ### Why is this bad?
@@ -451,6 +477,7 @@ impl_lint_pass!(Transmute => [
     TRANSMUTE_BYTES_TO_STR,
     TRANSMUTE_INT_TO_BOOL,
     TRANSMUTE_INT_TO_FLOAT,
+    TRANSMUTE_INT_TO_NON_ZERO,
     TRANSMUTE_FLOAT_TO_INT,
     TRANSMUTE_NUM_TO_BYTES,
     UNSOUND_COLLECTION_TRANSMUTE,
@@ -501,6 +528,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
                     | transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg)
                     | transmute_int_to_bool::check(cx, e, from_ty, to_ty, arg)
                     | transmute_int_to_float::check(cx, e, from_ty, to_ty, arg, const_context)
+                    | transmute_int_to_non_zero::check(cx, e, from_ty, to_ty, arg)
                     | transmute_float_to_int::check(cx, e, from_ty, to_ty, arg, const_context)
                     | transmute_num_to_bytes::check(cx, e, from_ty, to_ty, arg, const_context)
                     | (
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
new file mode 100644
index 00000000000..5503653253c
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_non_zero.rs
@@ -0,0 +1,61 @@
+use super::TRANSMUTE_INT_TO_NON_ZERO;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::sugg;
+use rustc_errors::Applicability;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_middle::{
+    query::Key,
+    ty::{self, Ty},
+};
+use rustc_span::symbol::sym;
+
+/// Checks for `transmute_int_to_non_zero` lint.
+/// Returns `true` if it's triggered, otherwise returns `false`.
+pub(super) fn check<'tcx>(
+    cx: &LateContext<'tcx>,
+    e: &'tcx Expr<'_>,
+    from_ty: Ty<'tcx>,
+    to_ty: Ty<'tcx>,
+    arg: &'tcx Expr<'_>,
+) -> bool {
+    let (ty::Int(_) | ty::Uint(_), Some(to_ty_id)) = (&from_ty.kind(), to_ty.ty_adt_id()) else {
+        return false;
+    };
+    let Some(to_type_sym) = cx.tcx.get_diagnostic_name(to_ty_id) else {
+        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
+    ) {
+        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}`"),
+        |diag| {
+            let arg = sugg::Sugg::hir(cx, arg, "..");
+            diag.span_suggestion(
+                e.span,
+                "consider using",
+                format!("{to_type_sym}::{}({arg})", sym::new_unchecked),
+                Applicability::Unspecified,
+            );
+        },
+    );
+    true
+}
diff --git a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
index 06d248204c1..a57bf7ee822 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -400,7 +400,7 @@ fn drain_matching(
 
     // If `ThinVec` had the `drain_filter` method, this loop could be rewritten
     // like so:
-    // 
+    //
     //   for pat in alternatives.drain_filter(|p| {
     //       // Check if we should extract, but only if `idx >= start`.
     //       idx += 1;
@@ -412,12 +412,12 @@ fn drain_matching(
     while i < alternatives.len() {
         idx += 1;
         // Check if we should extract, but only if `idx >= start`.
-	if idx > start && predicate(&alternatives[i].kind) {
-	    let pat = alternatives.remove(i);
+        if idx > start && predicate(&alternatives[i].kind) {
+            let pat = alternatives.remove(i);
             tail_or.push(extract(pat.into_inner().kind));
-	} else {
-	    i += 1;
-	}
+        } else {
+            i += 1;
+        }
     }
 
     tail_or
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index 1d78c7cfae0..1c7f3e96db8 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -334,7 +334,7 @@ define_Conf! {
     /// Lint: LARGE_STACK_ARRAYS, LARGE_CONST_ARRAYS.
     ///
     /// The maximum allowed size for arrays on the stack
-    (array_size_threshold: u128 = 512_000),
+    (array_size_threshold: u64 = 512_000),
     /// Lint: VEC_BOX.
     ///
     /// The size of the boxed type in bytes, where boxing in a `Vec` is allowed
@@ -419,19 +419,19 @@ define_Conf! {
     (max_include_file_size: u64 = 1_000_000),
     /// Lint: EXPECT_USED.
     ///
-    /// Whether `expect` should be allowed within `#[cfg(test)]`
+    /// Whether `expect` should be allowed in test functions or `#[cfg(test)]`
     (allow_expect_in_tests: bool = false),
     /// Lint: UNWRAP_USED.
     ///
-    /// Whether `unwrap` should be allowed in test cfg
+    /// Whether `unwrap` should be allowed in test functions or `#[cfg(test)]`
     (allow_unwrap_in_tests: bool = false),
     /// Lint: DBG_MACRO.
     ///
-    /// Whether `dbg!` should be allowed in test functions
+    /// Whether `dbg!` should be allowed in test functions or `#[cfg(test)]`
     (allow_dbg_in_tests: bool = false),
     /// Lint: PRINT_STDOUT, PRINT_STDERR.
     ///
-    /// Whether print macros (ex. `println!`) should be allowed in test functions
+    /// Whether print macros (ex. `println!`) should be allowed in test functions or `#[cfg(test)]`
     (allow_print_in_tests: bool = false),
     /// Lint: RESULT_LARGE_ERR.
     ///
@@ -454,6 +454,11 @@ define_Conf! {
     /// configuration will cause restriction lints to trigger even
     /// if no suggestion can be made.
     (suppress_restriction_lint_in_const: bool = false),
+    /// Lint: MISSING_DOCS_IN_PRIVATE_ITEMS.
+    ///
+    /// Whether to **only** check for missing documentation in items visible within the current
+    /// crate. For example, `pub(crate)` items.
+    (missing_docs_in_crate_items: bool = false),
 }
 
 /// Search for the configuration file.
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
index 688a8b865f3..f8978e30a8e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -11,7 +11,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::interpret::ConstValue;
-use rustc_middle::ty::{self};
+use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::Symbol;
 
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index ee5e42bae0f..14ed1368e03 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -3,7 +3,7 @@ use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{def_path_def_ids, is_lint_allowed, match_any_def_paths, peel_hir_expr_refs};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -11,7 +11,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::{Expr, ExprKind, Local, Mutability, Node};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::mir::interpret::{Allocation, ConstValue, GlobalAlloc};
-use rustc_middle::ty::{self, DefIdTree, Ty};
+use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
@@ -44,7 +44,7 @@ impl_lint_pass!(UnnecessaryDefPath => [UNNECESSARY_DEF_PATH]);
 
 #[derive(Default)]
 pub struct UnnecessaryDefPath {
-    array_def_ids: FxHashSet<(DefId, Span)>,
+    array_def_ids: FxIndexSet<(DefId, Span)>,
     linted_def_ids: FxHashSet<DefId>,
 }
 
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 4604ae5c2c7..50bef370930 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -287,15 +287,12 @@ impl<'a> VecArgs<'a> {
                     Some(VecArgs::Repeat(&args[0], &args[1]))
                 } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
                     // `vec![a, b, c]` case
-                    if_chain! {
-                        if let hir::ExprKind::Box(boxed) = args[0].kind;
-                        if let hir::ExprKind::Array(args) = boxed.kind;
-                        then {
-                            return Some(VecArgs::Vec(args));
-                        }
+                    if let hir::ExprKind::Call(_, [arg]) = &args[0].kind
+                        && let hir::ExprKind::Array(args) = arg.kind {
+                        Some(VecArgs::Vec(args))
+                    } else {
+                        None
                     }
-
-                    None
                 } else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() {
                     Some(VecArgs::Vec(&[]))
                 } else {
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index f02f8ecb43d..bcfedd07ed1 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -104,7 +104,7 @@ use rustc_middle::ty::fast_reject::SimplifiedType::{
     PtrSimplifiedType, SliceSimplifiedType, StrSimplifiedType, UintSimplifiedType,
 };
 use rustc_middle::ty::{
-    layout::IntegerExt, BorrowKind, ClosureKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UpvarCapture,
+    layout::IntegerExt, BorrowKind, ClosureKind, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, UpvarCapture,
 };
 use rustc_middle::ty::{FloatTy, IntTy, UintTy};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 63dccbf697c..be6133d3202 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -391,11 +391,18 @@ impl FormatString {
         };
 
         let mut unescaped = String::with_capacity(inner.len());
+        // Sometimes the original string comes from a macro which accepts a malformed string, such as in a
+        // #[display(""somestring)] attribute (accepted by the `displaythis` crate). Reconstructing the
+        // string from the span will not be possible, so we will just return None here.
+        let mut unparsable = false;
         unescape_literal(inner, mode, &mut |_, ch| match ch {
             Ok(ch) => unescaped.push(ch),
             Err(e) if !e.is_fatal() => (),
-            Err(e) => panic!("{e:?}"),
+            Err(_) => unparsable = true,
         });
+        if unparsable {
+            return None;
+        }
 
         let mut parts = Vec::new();
         let _: Option<!> = for_each_expr(pieces, |expr| {
diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
index 42bdfd4827f..c225398ad2a 100644
--- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs
+++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
@@ -186,7 +186,7 @@ impl<'a> NumericLiteral<'a> {
         // The exponent may have a sign, output it early, otherwise it will be
         // treated as a digit
         if digits.clone().next() == Some('-') {
-            let _ = digits.next();
+            let _: Option<char> = digits.next();
             output.push('-');
         }
 
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 95eebab7567..4aae0f7284e 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -115,6 +115,7 @@ pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
 pub const STD_IO_SEEK: [&str; 3] = ["std", "io", "Seek"];
 pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
 pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
+pub const STD_PROCESS_COMMAND: [&str; 3] = ["std", "process", "Command"];
 pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
 pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
 pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index 11ca81cfe6c..07feadca2b0 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -20,7 +20,7 @@ use rustc_middle::mir::{FakeReadCause, Mutability};
 use rustc_middle::ty;
 use rustc_span::source_map::{BytePos, CharPos, Pos, Span, SyntaxContext};
 use std::borrow::Cow;
-use std::fmt::{Display, Write as _};
+use std::fmt::{self, Display, Write as _};
 use std::ops::{Add, Neg, Not, Sub};
 
 /// A helper type to build suggestion correctly handling parentheses.
@@ -932,7 +932,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
             if cmt.place.projections.is_empty() {
                 // handle item without any projection, that needs an explicit borrowing
                 // i.e.: suggest `&x` instead of `x`
-                let _ = write!(self.suggestion_start, "{start_snip}&{ident_str}");
+                let _: fmt::Result = write!(self.suggestion_start, "{start_snip}&{ident_str}");
             } else {
                 // cases where a parent `Call` or `MethodCall` is using the item
                 // i.e.: suggest `.contains(&x)` for `.find(|x| [1, 2, 3].contains(x)).is_none()`
@@ -947,7 +947,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                         // given expression is the self argument and will be handled completely by the compiler
                         // i.e.: `|x| x.is_something()`
                         ExprKind::MethodCall(_, self_expr, ..) if self_expr.hir_id == cmt.hir_id => {
-                            let _ = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
+                            let _: fmt::Result = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
                             self.next_pos = span.hi();
                             return;
                         },
@@ -1055,7 +1055,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
                     }
                 }
 
-                let _ = write!(self.suggestion_start, "{start_snip}{replacement_str}");
+                let _: fmt::Result = write!(self.suggestion_start, "{start_snip}{replacement_str}");
             }
             self.next_pos = span.hi();
         }
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index f8ec4bb5493..41e34eba0ad 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -16,9 +16,9 @@ use rustc_infer::infer::{
 use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::{
-    self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, DefIdTree, FnSig, IntTy, List, ParamEnv, Predicate,
-    PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy,
-    VariantDef, VariantDiscr, TypeVisitableExt,
+    self, AdtDef, AliasTy, AssocKind, Binder, BoundRegion, FnSig, IntTy, List, ParamEnv, Predicate,
+    PredicateKind, Region, RegionKind, SubstsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+    TypeVisitor, UintTy, VariantDef, VariantDiscr,
 };
 use rustc_middle::ty::{GenericArg, GenericArgKind};
 use rustc_span::symbol::Ident;
@@ -894,16 +894,29 @@ impl AdtVariantInfo {
 }
 
 /// Gets the struct or enum variant from the given `Res`
-pub fn variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option<&'tcx VariantDef> {
+pub fn adt_and_variant_of_res<'tcx>(cx: &LateContext<'tcx>, res: Res) -> Option<(AdtDef<'tcx>, &'tcx VariantDef)> {
     match res {
-        Res::Def(DefKind::Struct, id) => Some(cx.tcx.adt_def(id).non_enum_variant()),
-        Res::Def(DefKind::Variant, id) => Some(cx.tcx.adt_def(cx.tcx.parent(id)).variant_with_id(id)),
-        Res::Def(DefKind::Ctor(CtorOf::Struct, _), id) => Some(cx.tcx.adt_def(cx.tcx.parent(id)).non_enum_variant()),
+        Res::Def(DefKind::Struct, id) => {
+            let adt = cx.tcx.adt_def(id);
+            Some((adt, adt.non_enum_variant()))
+        },
+        Res::Def(DefKind::Variant, id) => {
+            let adt = cx.tcx.adt_def(cx.tcx.parent(id));
+            Some((adt, adt.variant_with_id(id)))
+        },
+        Res::Def(DefKind::Ctor(CtorOf::Struct, _), id) => {
+            let adt = cx.tcx.adt_def(cx.tcx.parent(id));
+            Some((adt, adt.non_enum_variant()))
+        },
         Res::Def(DefKind::Ctor(CtorOf::Variant, _), id) => {
             let var_id = cx.tcx.parent(id);
-            Some(cx.tcx.adt_def(cx.tcx.parent(var_id)).variant_with_id(var_id))
+            let adt = cx.tcx.adt_def(cx.tcx.parent(var_id));
+            Some((adt, adt.variant_with_id(var_id)))
+        },
+        Res::SelfCtor(id) => {
+            let adt = cx.tcx.type_of(id).subst_identity().ty_adt_def().unwrap();
+            Some((adt, adt.non_enum_variant()))
         },
-        Res::SelfCtor(id) => Some(cx.tcx.type_of(id).subst_identity().ty_adt_def().unwrap().non_enum_variant()),
         _ => None,
     }
 }
diff --git a/src/tools/clippy/lintcheck/src/config.rs b/src/tools/clippy/lintcheck/src/config.rs
index b8824024e6c..e0244ddcecb 100644
--- a/src/tools/clippy/lintcheck/src/config.rs
+++ b/src/tools/clippy/lintcheck/src/config.rs
@@ -35,7 +35,7 @@ fn get_clap_config() -> ArgMatches {
                 .long("markdown")
                 .help("Change the reports table to use markdown links"),
             Arg::new("recursive")
-                .long("--recursive")
+                .long("recursive")
                 .help("Run clippy on the dependencies of crates specified in crates-toml")
                 .conflicts_with("threads")
                 .conflicts_with("fix"),
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index bd49f096072..23c85298027 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -17,9 +17,9 @@ use crate::recursive::LintcheckServer;
 use std::collections::{HashMap, HashSet};
 use std::env;
 use std::env::consts::EXE_SUFFIX;
-use std::fmt::Write as _;
+use std::fmt::{self, Write as _};
 use std::fs;
-use std::io::ErrorKind;
+use std::io::{self, ErrorKind};
 use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::sync::atomic::{AtomicUsize, Ordering};
@@ -145,8 +145,8 @@ impl ClippyWarning {
             }
 
             let mut output = String::from("| ");
-            let _ = write!(output, "[`{file_with_pos}`]({file}#L{})", self.line);
-            let _ = write!(output, r#" | `{:<50}` | "{}" |"#, self.lint_type, self.message);
+            let _: fmt::Result = write!(output, "[`{file_with_pos}`]({file}#L{})", self.line);
+            let _: fmt::Result = write!(output, r#" | `{:<50}` | "{}" |"#, self.lint_type, self.message);
             output.push('\n');
             output
         } else {
@@ -632,7 +632,7 @@ fn main() {
         .unwrap();
 
     let server = config.recursive.then(|| {
-        let _ = fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive");
+        let _: io::Result<()> = fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive");
 
         LintcheckServer::spawn(recursive_options)
     });
@@ -689,7 +689,7 @@ fn main() {
     write!(text, "{}", all_msgs.join("")).unwrap();
     text.push_str("\n\n### ICEs:\n");
     for (cratename, msg) in &ices {
-        let _ = write!(text, "{cratename}: '{msg}'");
+        let _: fmt::Result = write!(text, "{cratename}: '{msg}'");
     }
 
     println!("Writing logs to {}", config.lintcheck_results_path.display());
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index adea8c53df2..cfe845ec78f 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-02-10"
+channel = "nightly-2023-02-25"
 components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 9ac849aecf1..dd183362f27 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -209,10 +209,7 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
     // Separate the output with an empty line
     eprintln!();
 
-    let fallback_bundle = rustc_errors::fallback_fluent_bundle(
-        rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(),
-        false
-    );
+    let fallback_bundle = rustc_errors::fallback_fluent_bundle(rustc_driver::DEFAULT_LOCALE_RESOURCES.to_vec(), false);
     let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr(
         rustc_errors::ColorConfig::Auto,
         None,
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
index 4be04f77f5b..837811bdf1e 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
@@ -1,8 +1,9 @@
 // rustc-env:RUST_BACKTRACE=0
 // normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo"
-// normalize-stderr-test: "internal_lints.rs:\d*:\d*" -> "internal_lints.rs"
+// normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs"
 // normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
 // normalize-stderr-test: "'rustc'" -> "'<unnamed>'"
+// normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> ""
 
 #![deny(clippy::internal)]
 #![allow(clippy::missing_clippy_version_attribute)]
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
index 2ba5890660f..7ed0ef0274f 100644
--- a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
+++ b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
@@ -1,4 +1,4 @@
-thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs:28:9
+thread '<unnamed>' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 
 error: internal compiler error: unexpected panic
@@ -9,5 +9,3 @@ note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy
 
 note: Clippy version: foo
 
-query stack during panic:
-end of query stack
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
index c1a10ba55ef..3ca45404e44 100644
--- a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -1,19 +1,11 @@
 error: hardcoded path to a diagnostic item
-  --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
-   |
-LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: convert all references to use `sym::deref_method`
-   = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
-
-error: hardcoded path to a diagnostic item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
    |
 LL |     const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: convert all references to use `sym::Deref`
+   = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
 
 error: hardcoded path to a language item
   --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
@@ -23,5 +15,13 @@ LL |     const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"]
    |
    = help: convert all references to use `LangItem::DerefMut`
 
+error: hardcoded path to a diagnostic item
+  --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
+   |
+LL |     const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: convert all references to use `sym::deref_method`
+
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
index bff97d97df7..89f142a150d 100644
--- a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
+++ b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.rs
@@ -16,6 +16,18 @@ fn main() {
     expect_result();
 }
 
+#[test]
+fn test_expect_option() {
+    let opt = Some(0);
+    let _ = opt.expect("");
+}
+
+#[test]
+fn test_expect_result() {
+    let res: Result<u8, ()> = Ok(0);
+    let _ = res.expect("");
+}
+
 #[cfg(test)]
 mod issue9612 {
     // should not lint in `#[cfg(test)]` modules
diff --git a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/clippy.toml b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/clippy.toml
new file mode 100644
index 00000000000..ec210a98783
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/clippy.toml
@@ -0,0 +1 @@
+missing-docs-in-crate-items = true
diff --git a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs
new file mode 100644
index 00000000000..830d71f61dd
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.rs
@@ -0,0 +1,59 @@
+//! this is crate
+#![allow(missing_docs)]
+#![warn(clippy::missing_docs_in_private_items)]
+
+/// this is mod
+mod my_mod {
+    /// some docs
+    fn priv_with_docs() {}
+    fn priv_no_docs() {}
+    /// some docs
+    pub(crate) fn crate_with_docs() {}
+    pub(crate) fn crate_no_docs() {}
+    /// some docs
+    pub(super) fn super_with_docs() {}
+    pub(super) fn super_no_docs() {}
+
+    mod my_sub {
+        /// some docs
+        fn sub_priv_with_docs() {}
+        fn sub_priv_no_docs() {}
+        /// some docs
+        pub(crate) fn sub_crate_with_docs() {}
+        pub(crate) fn sub_crate_no_docs() {}
+        /// some docs
+        pub(super) fn sub_super_with_docs() {}
+        pub(super) fn sub_super_no_docs() {}
+    }
+
+    /// some docs
+    pub(crate) struct CrateStructWithDocs {
+        /// some docs
+        pub(crate) crate_field_with_docs: (),
+        pub(crate) crate_field_no_docs: (),
+        /// some docs
+        priv_field_with_docs: (),
+        priv_field_no_docs: (),
+    }
+
+    pub(crate) struct CrateStructNoDocs {
+        /// some docs
+        pub(crate) crate_field_with_docs: (),
+        pub(crate) crate_field_no_docs: (),
+        /// some docs
+        priv_field_with_docs: (),
+        priv_field_no_docs: (),
+    }
+}
+
+/// some docs
+type CrateTypedefWithDocs = String;
+type CrateTypedefNoDocs = String;
+/// some docs
+pub type PubTypedefWithDocs = String;
+pub type PubTypedefNoDocs = String;
+
+fn main() {
+    my_mod::crate_with_docs();
+    my_mod::crate_no_docs();
+}
diff --git a/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr
new file mode 100644
index 00000000000..a474187050c
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/pub_crate_missing_docs/pub_crate_missing_doc.stderr
@@ -0,0 +1,52 @@
+error: missing documentation for a function
+  --> $DIR/pub_crate_missing_doc.rs:12:5
+   |
+LL |     pub(crate) fn crate_no_docs() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
+
+error: missing documentation for a function
+  --> $DIR/pub_crate_missing_doc.rs:15:5
+   |
+LL |     pub(super) fn super_no_docs() {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a function
+  --> $DIR/pub_crate_missing_doc.rs:23:9
+   |
+LL |         pub(crate) fn sub_crate_no_docs() {}
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct field
+  --> $DIR/pub_crate_missing_doc.rs:33:9
+   |
+LL |         pub(crate) crate_field_no_docs: (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a struct
+  --> $DIR/pub_crate_missing_doc.rs:39:5
+   |
+LL | /     pub(crate) struct CrateStructNoDocs {
+LL | |         /// some docs
+LL | |         pub(crate) crate_field_with_docs: (),
+LL | |         pub(crate) crate_field_no_docs: (),
+...  |
+LL | |         priv_field_no_docs: (),
+LL | |     }
+   | |_____^
+
+error: missing documentation for a struct field
+  --> $DIR/pub_crate_missing_doc.rs:42:9
+   |
+LL |         pub(crate) crate_field_no_docs: (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: missing documentation for a type alias
+  --> $DIR/pub_crate_missing_doc.rs:51:1
+   |
+LL | type CrateTypedefNoDocs = String;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
+
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 a22c6a5a060..6a246afac76 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
@@ -33,6 +33,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
            max-struct-bools
            max-suggested-slice-pattern-length
            max-trait-bounds
+           missing-docs-in-crate-items
            msrv
            pass-by-value-size-limit
            single-char-binding-names-threshold
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
index bc8e8c1f070..6525ea5bfc3 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.rs
@@ -66,6 +66,12 @@ fn main() {
     }
 }
 
+#[test]
+fn test() {
+    let boxed_slice: Box<[u8]> = Box::new([0, 1, 2, 3]);
+    let _ = boxed_slice.get(1).unwrap();
+}
+
 #[cfg(test)]
 mod issue9612 {
     // should not lint in `#[cfg(test)]` modules
diff --git a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
index 94b5ef663ad..8a32750e3c9 100644
--- a/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/unwrap_used/unwrap_used.stderr
@@ -188,10 +188,16 @@ LL |         let _ = some_vec.get_mut(0..1).unwrap().to_vec();
    = help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
 
 error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
-  --> $DIR/unwrap_used.rs:84:17
+  --> $DIR/unwrap_used.rs:72:13
+   |
+LL |     let _ = boxed_slice.get(1).unwrap();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&boxed_slice[1]`
+
+error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
+  --> $DIR/unwrap_used.rs:90:17
    |
 LL |         let _ = Box::new([0]).get(1).unwrap();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&Box::new([0])[1]`
 
-error: aborting due to 27 previous errors
+error: aborting due to 28 previous errors
 
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index 918cf81c600..2611e3a785f 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -13,6 +13,9 @@
 
 use core::num::{Saturating, Wrapping};
 
+const ONE: i32 = 1;
+const ZERO: i32 = 0;
+
 #[derive(Clone, Copy)]
 pub struct Custom;
 
@@ -182,6 +185,10 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
     _n += &0;
     _n -= 0;
     _n -= &0;
+    _n += ZERO;
+    _n += &ZERO;
+    _n -= ZERO;
+    _n -= &ZERO;
     _n /= 99;
     _n /= &99;
     _n %= 99;
@@ -190,10 +197,18 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
     _n *= &0;
     _n *= 1;
     _n *= &1;
+    _n *= ZERO;
+    _n *= &ZERO;
+    _n *= ONE;
+    _n *= &ONE;
     _n += -0;
     _n += &-0;
     _n -= -0;
     _n -= &-0;
+    _n += -ZERO;
+    _n += &-ZERO;
+    _n -= -ZERO;
+    _n -= &-ZERO;
     _n /= -99;
     _n /= &-99;
     _n %= -99;
@@ -208,10 +223,18 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
     _n = _n + &0;
     _n = 0 + _n;
     _n = &0 + _n;
+    _n = _n + ZERO;
+    _n = _n + &ZERO;
+    _n = ZERO + _n;
+    _n = &ZERO + _n;
     _n = _n - 0;
     _n = _n - &0;
     _n = 0 - _n;
     _n = &0 - _n;
+    _n = _n - ZERO;
+    _n = _n - &ZERO;
+    _n = ZERO - _n;
+    _n = &ZERO - _n;
     _n = _n / 99;
     _n = _n / &99;
     _n = _n % 99;
@@ -222,6 +245,10 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
     _n = &0 * _n;
     _n = _n * 1;
     _n = _n * &1;
+    _n = ZERO * _n;
+    _n = &ZERO * _n;
+    _n = _n * ONE;
+    _n = _n * &ONE;
     _n = 1 * _n;
     _n = &1 * _n;
     _n = 23 + 85;
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 5e349f6b497..17a2448fbfc 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -1,5 +1,5 @@
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:243:5
+  --> $DIR/arithmetic_side_effects.rs:270:5
    |
 LL |     _n += 1;
    |     ^^^^^^^
@@ -7,589 +7,589 @@ LL |     _n += 1;
    = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:244:5
+  --> $DIR/arithmetic_side_effects.rs:271:5
    |
 LL |     _n += &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:245:5
+  --> $DIR/arithmetic_side_effects.rs:272:5
    |
 LL |     _n -= 1;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:246:5
+  --> $DIR/arithmetic_side_effects.rs:273:5
    |
 LL |     _n -= &1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:247:5
+  --> $DIR/arithmetic_side_effects.rs:274:5
    |
 LL |     _n /= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:248:5
+  --> $DIR/arithmetic_side_effects.rs:275:5
    |
 LL |     _n /= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:249:5
+  --> $DIR/arithmetic_side_effects.rs:276:5
    |
 LL |     _n %= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:250:5
+  --> $DIR/arithmetic_side_effects.rs:277:5
    |
 LL |     _n %= &0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:251:5
+  --> $DIR/arithmetic_side_effects.rs:278:5
    |
 LL |     _n *= 2;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:252:5
+  --> $DIR/arithmetic_side_effects.rs:279:5
    |
 LL |     _n *= &2;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:253:5
+  --> $DIR/arithmetic_side_effects.rs:280:5
    |
 LL |     _n += -1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:254:5
+  --> $DIR/arithmetic_side_effects.rs:281:5
    |
 LL |     _n += &-1;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:255:5
+  --> $DIR/arithmetic_side_effects.rs:282:5
    |
 LL |     _n -= -1;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:256:5
+  --> $DIR/arithmetic_side_effects.rs:283:5
    |
 LL |     _n -= &-1;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:257:5
+  --> $DIR/arithmetic_side_effects.rs:284:5
    |
 LL |     _n /= -0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:258:5
+  --> $DIR/arithmetic_side_effects.rs:285:5
    |
 LL |     _n /= &-0;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:259:5
+  --> $DIR/arithmetic_side_effects.rs:286:5
    |
 LL |     _n %= -0;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:260:5
+  --> $DIR/arithmetic_side_effects.rs:287:5
    |
 LL |     _n %= &-0;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:261:5
+  --> $DIR/arithmetic_side_effects.rs:288:5
    |
 LL |     _n *= -2;
    |     ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:262:5
+  --> $DIR/arithmetic_side_effects.rs:289:5
    |
 LL |     _n *= &-2;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:263:5
+  --> $DIR/arithmetic_side_effects.rs:290:5
    |
 LL |     _custom += Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:264:5
+  --> $DIR/arithmetic_side_effects.rs:291:5
    |
 LL |     _custom += &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:265:5
+  --> $DIR/arithmetic_side_effects.rs:292:5
    |
 LL |     _custom -= Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:266:5
+  --> $DIR/arithmetic_side_effects.rs:293:5
    |
 LL |     _custom -= &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:267:5
+  --> $DIR/arithmetic_side_effects.rs:294:5
    |
 LL |     _custom /= Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:268:5
+  --> $DIR/arithmetic_side_effects.rs:295:5
    |
 LL |     _custom /= &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:269:5
+  --> $DIR/arithmetic_side_effects.rs:296:5
    |
 LL |     _custom %= Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:270:5
+  --> $DIR/arithmetic_side_effects.rs:297:5
    |
 LL |     _custom %= &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:271:5
+  --> $DIR/arithmetic_side_effects.rs:298:5
    |
 LL |     _custom *= Custom;
    |     ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:272:5
+  --> $DIR/arithmetic_side_effects.rs:299:5
    |
 LL |     _custom *= &Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:273:5
+  --> $DIR/arithmetic_side_effects.rs:300:5
    |
 LL |     _custom += -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:274:5
+  --> $DIR/arithmetic_side_effects.rs:301:5
    |
 LL |     _custom += &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:275:5
+  --> $DIR/arithmetic_side_effects.rs:302:5
    |
 LL |     _custom -= -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:276:5
+  --> $DIR/arithmetic_side_effects.rs:303:5
    |
 LL |     _custom -= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:277:5
+  --> $DIR/arithmetic_side_effects.rs:304:5
    |
 LL |     _custom /= -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:278:5
+  --> $DIR/arithmetic_side_effects.rs:305:5
    |
 LL |     _custom /= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:279:5
+  --> $DIR/arithmetic_side_effects.rs:306:5
    |
 LL |     _custom %= -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:280:5
+  --> $DIR/arithmetic_side_effects.rs:307:5
    |
 LL |     _custom %= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:281:5
+  --> $DIR/arithmetic_side_effects.rs:308:5
    |
 LL |     _custom *= -Custom;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:282:5
+  --> $DIR/arithmetic_side_effects.rs:309:5
    |
 LL |     _custom *= &-Custom;
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:285:10
+  --> $DIR/arithmetic_side_effects.rs:312:10
    |
 LL |     _n = _n + 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:286:10
+  --> $DIR/arithmetic_side_effects.rs:313:10
    |
 LL |     _n = _n + &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:287:10
+  --> $DIR/arithmetic_side_effects.rs:314:10
    |
 LL |     _n = 1 + _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:288:10
+  --> $DIR/arithmetic_side_effects.rs:315:10
    |
 LL |     _n = &1 + _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:289:10
+  --> $DIR/arithmetic_side_effects.rs:316:10
    |
 LL |     _n = _n - 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:290:10
+  --> $DIR/arithmetic_side_effects.rs:317:10
    |
 LL |     _n = _n - &1;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:291:10
+  --> $DIR/arithmetic_side_effects.rs:318:10
    |
 LL |     _n = 1 - _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:292:10
+  --> $DIR/arithmetic_side_effects.rs:319:10
    |
 LL |     _n = &1 - _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:293:10
+  --> $DIR/arithmetic_side_effects.rs:320:10
    |
 LL |     _n = _n / 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:294:10
+  --> $DIR/arithmetic_side_effects.rs:321:10
    |
 LL |     _n = _n / &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:295:10
+  --> $DIR/arithmetic_side_effects.rs:322:10
    |
 LL |     _n = _n % 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:296:10
+  --> $DIR/arithmetic_side_effects.rs:323:10
    |
 LL |     _n = _n % &0;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:297:10
+  --> $DIR/arithmetic_side_effects.rs:324:10
    |
 LL |     _n = _n * 2;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:298:10
+  --> $DIR/arithmetic_side_effects.rs:325:10
    |
 LL |     _n = _n * &2;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:299:10
+  --> $DIR/arithmetic_side_effects.rs:326:10
    |
 LL |     _n = 2 * _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:300:10
+  --> $DIR/arithmetic_side_effects.rs:327:10
    |
 LL |     _n = &2 * _n;
    |          ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:301:10
+  --> $DIR/arithmetic_side_effects.rs:328:10
    |
 LL |     _n = 23 + &85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:302:10
+  --> $DIR/arithmetic_side_effects.rs:329:10
    |
 LL |     _n = &23 + 85;
    |          ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:303:10
+  --> $DIR/arithmetic_side_effects.rs:330:10
    |
 LL |     _n = &23 + &85;
    |          ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:304:15
+  --> $DIR/arithmetic_side_effects.rs:331:15
    |
 LL |     _custom = _custom + _custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:305:15
+  --> $DIR/arithmetic_side_effects.rs:332:15
    |
 LL |     _custom = _custom + &_custom;
    |               ^^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:306:15
+  --> $DIR/arithmetic_side_effects.rs:333:15
    |
 LL |     _custom = Custom + _custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:307:15
+  --> $DIR/arithmetic_side_effects.rs:334:15
    |
 LL |     _custom = &Custom + _custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:308:15
+  --> $DIR/arithmetic_side_effects.rs:335:15
    |
 LL |     _custom = _custom - Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:309:15
+  --> $DIR/arithmetic_side_effects.rs:336:15
    |
 LL |     _custom = _custom - &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:310:15
+  --> $DIR/arithmetic_side_effects.rs:337:15
    |
 LL |     _custom = Custom - _custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:311:15
+  --> $DIR/arithmetic_side_effects.rs:338:15
    |
 LL |     _custom = &Custom - _custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:312:15
+  --> $DIR/arithmetic_side_effects.rs:339:15
    |
 LL |     _custom = _custom / Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:313:15
+  --> $DIR/arithmetic_side_effects.rs:340:15
    |
 LL |     _custom = _custom / &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:314:15
+  --> $DIR/arithmetic_side_effects.rs:341:15
    |
 LL |     _custom = _custom % Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:315:15
+  --> $DIR/arithmetic_side_effects.rs:342:15
    |
 LL |     _custom = _custom % &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:316:15
+  --> $DIR/arithmetic_side_effects.rs:343:15
    |
 LL |     _custom = _custom * Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:317:15
+  --> $DIR/arithmetic_side_effects.rs:344:15
    |
 LL |     _custom = _custom * &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:318:15
+  --> $DIR/arithmetic_side_effects.rs:345:15
    |
 LL |     _custom = Custom * _custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:319:15
+  --> $DIR/arithmetic_side_effects.rs:346:15
    |
 LL |     _custom = &Custom * _custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:320:15
+  --> $DIR/arithmetic_side_effects.rs:347:15
    |
 LL |     _custom = Custom + &Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:321:15
+  --> $DIR/arithmetic_side_effects.rs:348:15
    |
 LL |     _custom = &Custom + Custom;
    |               ^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:322:15
+  --> $DIR/arithmetic_side_effects.rs:349:15
    |
 LL |     _custom = &Custom + &Custom;
    |               ^^^^^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:325:10
+  --> $DIR/arithmetic_side_effects.rs:352:10
    |
 LL |     _n = -_n;
    |          ^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:326:10
+  --> $DIR/arithmetic_side_effects.rs:353:10
    |
 LL |     _n = -&_n;
    |          ^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:327:15
+  --> $DIR/arithmetic_side_effects.rs:354:15
    |
 LL |     _custom = -_custom;
    |               ^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:328:15
+  --> $DIR/arithmetic_side_effects.rs:355:15
    |
 LL |     _custom = -&_custom;
    |               ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:337:5
+  --> $DIR/arithmetic_side_effects.rs:364:5
    |
 LL |     1 + i;
    |     ^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:338:5
+  --> $DIR/arithmetic_side_effects.rs:365:5
    |
 LL |     i * 2;
    |     ^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:340:5
+  --> $DIR/arithmetic_side_effects.rs:367:5
    |
 LL |     i - 2 + 2 - i;
    |     ^^^^^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:341:5
+  --> $DIR/arithmetic_side_effects.rs:368:5
    |
 LL |     -i;
    |     ^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:342:5
+  --> $DIR/arithmetic_side_effects.rs:369:5
    |
 LL |     i >> 1;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:343:5
+  --> $DIR/arithmetic_side_effects.rs:370:5
    |
 LL |     i << 1;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:352:5
+  --> $DIR/arithmetic_side_effects.rs:379:5
    |
 LL |     i += 1;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:353:5
+  --> $DIR/arithmetic_side_effects.rs:380:5
    |
 LL |     i -= 1;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:354:5
+  --> $DIR/arithmetic_side_effects.rs:381:5
    |
 LL |     i *= 2;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:356:5
+  --> $DIR/arithmetic_side_effects.rs:383:5
    |
 LL |     i /= 0;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:358:5
+  --> $DIR/arithmetic_side_effects.rs:385:5
    |
 LL |     i /= var1;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:359:5
+  --> $DIR/arithmetic_side_effects.rs:386:5
    |
 LL |     i /= var2;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:361:5
+  --> $DIR/arithmetic_side_effects.rs:388:5
    |
 LL |     i %= 0;
    |     ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:363:5
+  --> $DIR/arithmetic_side_effects.rs:390:5
    |
 LL |     i %= var1;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:364:5
+  --> $DIR/arithmetic_side_effects.rs:391:5
    |
 LL |     i %= var2;
    |     ^^^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:365:5
+  --> $DIR/arithmetic_side_effects.rs:392:5
    |
 LL |     i <<= 3;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:366:5
+  --> $DIR/arithmetic_side_effects.rs:393:5
    |
 LL |     i >>= 2;
    |     ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed
index 7e9f074fdca..59c0baf8718 100644
--- a/src/tools/clippy/tests/ui/box_default.fixed
+++ b/src/tools/clippy/tests/ui/box_default.fixed
@@ -33,6 +33,7 @@ fn main() {
     let _vec4: Box<_> = Box::<Vec<bool>>::default();
     let _more = ret_ty_fn();
     call_ty_fn(Box::default());
+    issue_10381();
 }
 
 fn ret_ty_fn() -> Box<bool> {
@@ -65,3 +66,20 @@ fn issue_10089() {
         let _ = Box::<WeirdPathed>::default();
     };
 }
+
+fn issue_10381() {
+    #[derive(Default)]
+    pub struct Foo {}
+    pub trait Bar {}
+    impl Bar for Foo {}
+
+    fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> {
+        if i % 2 == 0 {
+            Some(Box::<Foo>::default())
+        } else {
+            None
+        }
+    }
+
+    assert!(maybe_get_bar(2).is_some());
+}
diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs
index 5c8d0b8354c..f7d832193a3 100644
--- a/src/tools/clippy/tests/ui/box_default.rs
+++ b/src/tools/clippy/tests/ui/box_default.rs
@@ -33,6 +33,7 @@ fn main() {
     let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
     let _more = ret_ty_fn();
     call_ty_fn(Box::new(u8::default()));
+    issue_10381();
 }
 
 fn ret_ty_fn() -> Box<bool> {
@@ -65,3 +66,20 @@ fn issue_10089() {
         let _ = Box::new(WeirdPathed::default());
     };
 }
+
+fn issue_10381() {
+    #[derive(Default)]
+    pub struct Foo {}
+    pub trait Bar {}
+    impl Bar for Foo {}
+
+    fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> {
+        if i % 2 == 0 {
+            Some(Box::new(Foo::default()))
+        } else {
+            None
+        }
+    }
+
+    assert!(maybe_get_bar(2).is_some());
+}
diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr
index 249eb340f96..78e17b9f035 100644
--- a/src/tools/clippy/tests/ui/box_default.stderr
+++ b/src/tools/clippy/tests/ui/box_default.stderr
@@ -73,22 +73,28 @@ LL |     call_ty_fn(Box::new(u8::default()));
    |                ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:39:5
+  --> $DIR/box_default.rs:40:5
    |
 LL |     Box::new(bool::default())
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:56:28
+  --> $DIR/box_default.rs:57:28
    |
 LL |     let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
 
 error: `Box::new(_)` of default value
-  --> $DIR/box_default.rs:65:17
+  --> $DIR/box_default.rs:66:17
    |
 LL |         let _ = Box::new(WeirdPathed::default());
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
 
-error: aborting due to 15 previous errors
+error: `Box::new(_)` of default value
+  --> $DIR/box_default.rs:78:18
+   |
+LL |             Some(Box::new(Foo::default()))
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Foo>::default()`
+
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/bytes_nth.fixed b/src/tools/clippy/tests/ui/bytes_nth.fixed
index b1fb2e16bd5..a35c679afb7 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.fixed
+++ b/src/tools/clippy/tests/ui/bytes_nth.fixed
@@ -5,7 +5,7 @@
 
 fn main() {
     let s = String::from("String");
-    let _ = s.as_bytes().get(3);
-    let _ = &s.as_bytes().get(3);
-    let _ = s[..].as_bytes().get(3);
+    let _ = s.as_bytes().get(3).copied();
+    let _ = &s.as_bytes()[3];
+    let _ = s[..].as_bytes().get(3).copied();
 }
diff --git a/src/tools/clippy/tests/ui/bytes_nth.rs b/src/tools/clippy/tests/ui/bytes_nth.rs
index 034c54e6a42..1ecffea5303 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.rs
+++ b/src/tools/clippy/tests/ui/bytes_nth.rs
@@ -6,6 +6,6 @@
 fn main() {
     let s = String::from("String");
     let _ = s.bytes().nth(3);
-    let _ = &s.bytes().nth(3);
+    let _ = &s.bytes().nth(3).unwrap();
     let _ = s[..].bytes().nth(3);
 }
diff --git a/src/tools/clippy/tests/ui/bytes_nth.stderr b/src/tools/clippy/tests/ui/bytes_nth.stderr
index 9851d4791d8..e8b15027829 100644
--- a/src/tools/clippy/tests/ui/bytes_nth.stderr
+++ b/src/tools/clippy/tests/ui/bytes_nth.stderr
@@ -2,21 +2,21 @@ error: called `.bytes().nth()` on a `String`
   --> $DIR/bytes_nth.rs:8:13
    |
 LL |     let _ = s.bytes().nth(3);
-   |             ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
+   |             ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3).copied()`
    |
    = note: `-D clippy::bytes-nth` implied by `-D warnings`
 
-error: called `.bytes().nth()` on a `String`
+error: called `.bytes().nth().unwrap()` on a `String`
   --> $DIR/bytes_nth.rs:9:14
    |
-LL |     let _ = &s.bytes().nth(3);
-   |              ^^^^^^^^^^^^^^^^ help: try: `s.as_bytes().get(3)`
+LL |     let _ = &s.bytes().nth(3).unwrap();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.as_bytes()[3]`
 
 error: called `.bytes().nth()` on a `str`
   --> $DIR/bytes_nth.rs:10:13
    |
 LL |     let _ = s[..].bytes().nth(3);
-   |             ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3)`
+   |             ^^^^^^^^^^^^^^^^^^^^ help: try: `s[..].as_bytes().get(3).copied()`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr
index 4af1de9aa38..451078de23b 100644
--- a/src/tools/clippy/tests/ui/cast.stderr
+++ b/src/tools/clippy/tests/ui/cast.stderr
@@ -42,7 +42,7 @@ error: casting `f32` to `i32` may truncate the value
 LL |     1f32 as i32;
    |     ^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
    = note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
 help: ... or use `try_from` and handle the error accordingly
    |
@@ -55,7 +55,7 @@ error: casting `f32` to `u32` may truncate the value
 LL |     1f32 as u32;
    |     ^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     u32::try_from(1f32);
@@ -75,7 +75,7 @@ error: casting `f64` to `f32` may truncate the value
 LL |     1f64 as f32;
    |     ^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     f32::try_from(1f64);
@@ -87,7 +87,7 @@ error: casting `i32` to `i8` may truncate the value
 LL |     1i32 as i8;
    |     ^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     i8::try_from(1i32);
@@ -99,7 +99,7 @@ error: casting `i32` to `u8` may truncate the value
 LL |     1i32 as u8;
    |     ^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     u8::try_from(1i32);
@@ -111,7 +111,7 @@ error: casting `f64` to `isize` may truncate the value
 LL |     1f64 as isize;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     isize::try_from(1f64);
@@ -123,7 +123,7 @@ error: casting `f64` to `usize` may truncate the value
 LL |     1f64 as usize;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     usize::try_from(1f64);
@@ -141,7 +141,7 @@ error: casting `u32` to `u16` may truncate the value
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     u16::try_from(1f32 as u32);
@@ -153,7 +153,7 @@ error: casting `f32` to `u32` may truncate the value
 LL |     1f32 as u32 as u16;
    |     ^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     u32::try_from(1f32) as u16;
@@ -215,7 +215,7 @@ error: casting `i64` to `i8` may truncate the value
 LL |     (-99999999999i64).min(1) as i8; // should be linted because signed
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     i8::try_from((-99999999999i64).min(1)); // should be linted because signed
@@ -227,7 +227,7 @@ error: casting `u64` to `u8` may truncate the value
 LL |     999999u64.clamp(0, 256) as u8; // should still be linted
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     u8::try_from(999999u64.clamp(0, 256)); // should still be linted
@@ -239,7 +239,7 @@ error: casting `main::E2` to `u8` may truncate the value
 LL |             let _ = self as u8;
    |                     ^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |             let _ = u8::try_from(self);
@@ -259,7 +259,7 @@ error: casting `main::E5` to `i8` may truncate the value
 LL |             let _ = self as i8;
    |                     ^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |             let _ = i8::try_from(self);
@@ -277,7 +277,7 @@ error: casting `main::E6` to `i16` may truncate the value
 LL |             let _ = self as i16;
    |                     ^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |             let _ = i16::try_from(self);
@@ -289,7 +289,7 @@ error: casting `main::E7` to `usize` may truncate the value on targets with 32-b
 LL |             let _ = self as usize;
    |                     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |             let _ = usize::try_from(self);
@@ -301,7 +301,7 @@ error: casting `main::E10` to `u16` may truncate the value
 LL |             let _ = self as u16;
    |                     ^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |             let _ = u16::try_from(self);
@@ -313,7 +313,7 @@ error: casting `u32` to `u8` may truncate the value
 LL |     let c = (q >> 16) as u8;
    |             ^^^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     let c = u8::try_from((q >> 16));
@@ -325,7 +325,7 @@ error: casting `u32` to `u8` may truncate the value
 LL |     let c = (q / 1000) as u8;
    |             ^^^^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     let c = u8::try_from((q / 1000));
diff --git a/src/tools/clippy/tests/ui/cast_size.stderr b/src/tools/clippy/tests/ui/cast_size.stderr
index 8acf26049f4..6d2d49d9ed2 100644
--- a/src/tools/clippy/tests/ui/cast_size.stderr
+++ b/src/tools/clippy/tests/ui/cast_size.stderr
@@ -4,7 +4,7 @@ error: casting `isize` to `i8` may truncate the value
 LL |     1isize as i8;
    |     ^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
    = note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
 help: ... or use `try_from` and handle the error accordingly
    |
@@ -43,7 +43,7 @@ error: casting `isize` to `i32` may truncate the value on targets with 64-bit wi
 LL |     1isize as i32;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     i32::try_from(1isize);
@@ -55,7 +55,7 @@ error: casting `isize` to `u32` may truncate the value on targets with 64-bit wi
 LL |     1isize as u32;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     u32::try_from(1isize);
@@ -67,7 +67,7 @@ error: casting `usize` to `u32` may truncate the value on targets with 64-bit wi
 LL |     1usize as u32;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     u32::try_from(1usize);
@@ -79,7 +79,7 @@ error: casting `usize` to `i32` may truncate the value on targets with 64-bit wi
 LL |     1usize as i32;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     i32::try_from(1usize);
@@ -99,7 +99,7 @@ error: casting `i64` to `isize` may truncate the value on targets with 32-bit wi
 LL |     1i64 as isize;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     isize::try_from(1i64);
@@ -111,7 +111,7 @@ error: casting `i64` to `usize` may truncate the value on targets with 32-bit wi
 LL |     1i64 as usize;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     usize::try_from(1i64);
@@ -123,7 +123,7 @@ error: casting `u64` to `isize` may truncate the value on targets with 32-bit wi
 LL |     1u64 as isize;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     isize::try_from(1u64);
@@ -141,7 +141,7 @@ error: casting `u64` to `usize` may truncate the value on targets with 32-bit wi
 LL |     1u64 as usize;
    |     ^^^^^^^^^^^^^
    |
-   = help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
+   = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
 help: ... or use `try_from` and handle the error accordingly
    |
 LL |     usize::try_from(1u64);
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10044.rs b/src/tools/clippy/tests/ui/crashes/ice-10044.rs
deleted file mode 100644
index 65f38fe7118..00000000000
--- a/src/tools/clippy/tests/ui/crashes/ice-10044.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-fn main() {
-    [0; usize::MAX];
-}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10044.stderr b/src/tools/clippy/tests/ui/crashes/ice-10044.stderr
deleted file mode 100644
index 731f8265ad6..00000000000
--- a/src/tools/clippy/tests/ui/crashes/ice-10044.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: statement with no effect
-  --> $DIR/ice-10044.rs:2:5
-   |
-LL |     [0; usize::MAX];
-   |     ^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::no-effect` implied by `-D warnings`
-
-error: aborting due to previous error
-
diff --git a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs
new file mode 100644
index 00000000000..dd3d8b8b6d1
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.rs
@@ -0,0 +1,9 @@
+// https://github.com/rust-lang/rust/issues/107147
+
+#![warn(clippy::needless_pass_by_value)]
+
+struct Foo<'a>(&'a [(); 100]);
+
+fn test(x: Foo<'_>) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
new file mode 100644
index 00000000000..7a0a648974f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/needless_pass_by_value-w-late-bound.stderr
@@ -0,0 +1,15 @@
+error: this argument is passed by value, but not consumed in the function body
+  --> $DIR/needless_pass_by_value-w-late-bound.rs:7:12
+   |
+LL | fn test(x: Foo<'_>) {}
+   |            ^^^^^^^ help: consider taking a reference instead: `&Foo<'_>`
+   |
+help: consider marking this type as `Copy`
+  --> $DIR/needless_pass_by_value-w-late-bound.rs:5:1
+   |
+LL | struct Foo<'a>(&'a [(); 100]);
+   | ^^^^^^^^^^^^^^
+   = note: `-D clippy::needless-pass-by-value` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
index 747801b40ee..ecb0bf3644e 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.fixed
@@ -78,7 +78,7 @@ fn test_allowed() {
 /// This test has [a `link_with_underscores`][chunked-example] inside it. See #823.
 /// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
 /// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
-/// It can also be [`inline_link2`].
+/// It can also be [inline_link2]. A link to [StackOverflow](https://stackoverflow.com) is also acceptable.
 ///
 /// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
 /// [inline_link]: https://foobar
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.rs b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
index f3cf966157a..11c48dd103d 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.rs
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.rs
@@ -75,10 +75,10 @@ fn test_units() {
 fn test_allowed() {
 }
 
-/// This test has [a link_with_underscores][chunked-example] inside it. See #823.
+/// This test has [a `link_with_underscores`][chunked-example] inside it. See #823.
 /// See also [the issue tracker](https://github.com/rust-lang/rust-clippy/search?q=clippy::doc_markdown&type=Issues)
 /// on GitHub (which is a camel-cased word, but is OK). And here is another [inline link][inline_link].
-/// It can also be [inline_link2].
+/// It can also be [inline_link2]. A link to [StackOverflow](https://stackoverflow.com) is also acceptable.
 ///
 /// [chunked-example]: https://en.wikipedia.org/wiki/Chunked_transfer_encoding#Example
 /// [inline_link]: https://foobar
diff --git a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
index 40345370c04..6c67c903c75 100644
--- a/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
+++ b/src/tools/clippy/tests/ui/doc/doc-fixable.stderr
@@ -143,28 +143,6 @@ LL | /// `be_sure_we_got_to_the_end_of_it`
    |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:78:22
-   |
-LL | /// This test has [a link_with_underscores][chunked-example] inside it. See #823.
-   |                      ^^^^^^^^^^^^^^^^^^^^^
-   |
-help: try
-   |
-LL | /// This test has [a `link_with_underscores`][chunked-example] inside it. See #823.
-   |                      ~~~~~~~~~~~~~~~~~~~~~~~
-
-error: item in documentation is missing backticks
-  --> $DIR/doc-fixable.rs:81:21
-   |
-LL | /// It can also be [inline_link2].
-   |                     ^^^^^^^^^^^^
-   |
-help: try
-   |
-LL | /// It can also be [`inline_link2`].
-   |                     ~~~~~~~~~~~~~~
-
-error: item in documentation is missing backticks
   --> $DIR/doc-fixable.rs:91:5
    |
 LL | /// be_sure_we_got_to_the_end_of_it
@@ -329,5 +307,5 @@ help: try
 LL | /// An iterator over `mycrate::Collection`'s values.
    |                      ~~~~~~~~~~~~~~~~~~~~~
 
-error: aborting due to 30 previous errors
+error: aborting due to 28 previous errors
 
diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed
index 79c29c04e05..dbe09e0ff3c 100644
--- a/src/tools/clippy/tests/ui/entry.fixed
+++ b/src/tools/clippy/tests/ui/entry.fixed
@@ -152,4 +152,18 @@ fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMa
     });
 }
 
+// Issue 10331
+// do not suggest a bad expansion because the compiler unrolls the first
+// occurrence of the loop
+pub fn issue_10331() {
+    let mut m = HashMap::new();
+    let mut i = 0;
+    let mut x = 0;
+    while !m.contains_key(&x) {
+        m.insert(x, i);
+        i += 1;
+        x += 1;
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs
index 2d7985457d8..30fed34fc5d 100644
--- a/src/tools/clippy/tests/ui/entry.rs
+++ b/src/tools/clippy/tests/ui/entry.rs
@@ -156,4 +156,18 @@ fn hash_map<K: Eq + Hash + Copy, V: Copy>(m: &mut HashMap<K, V>, m2: &mut HashMa
     }
 }
 
+// Issue 10331
+// do not suggest a bad expansion because the compiler unrolls the first
+// occurrence of the loop
+pub fn issue_10331() {
+    let mut m = HashMap::new();
+    let mut i = 0;
+    let mut x = 0;
+    while !m.contains_key(&x) {
+        m.insert(x, i);
+        i += 1;
+        x += 1;
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
index 475fae5e823..5d40c850424 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.fixed
@@ -269,6 +269,9 @@ fn main() {
 
     trait WithAssoc {
         type Assoc: ?Sized;
+        fn to_assoc(&self) -> &Self::Assoc {
+            panic!()
+        }
     }
     impl WithAssoc for String {
         type Assoc = str;
@@ -281,4 +284,15 @@ fn main() {
     // Issue #9901
     fn takes_ref(_: &i32) {}
     takes_ref(*Box::new(&0i32));
+
+    // Issue #10384
+    impl<'a> WithAssoc for &'a u32 {
+        type Assoc = dyn core::fmt::Display;
+        fn to_assoc(&self) -> &Self::Assoc {
+            *self
+        }
+    }
+    fn return_dyn_assoc<'a>(x: &'a &'a u32) -> &'a <&'a u32 as WithAssoc>::Assoc {
+        *x
+    }
 }
diff --git a/src/tools/clippy/tests/ui/explicit_auto_deref.rs b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
index c1894258f4d..79e03f4d76c 100644
--- a/src/tools/clippy/tests/ui/explicit_auto_deref.rs
+++ b/src/tools/clippy/tests/ui/explicit_auto_deref.rs
@@ -269,6 +269,9 @@ fn main() {
 
     trait WithAssoc {
         type Assoc: ?Sized;
+        fn to_assoc(&self) -> &Self::Assoc {
+            panic!()
+        }
     }
     impl WithAssoc for String {
         type Assoc = str;
@@ -281,4 +284,15 @@ fn main() {
     // Issue #9901
     fn takes_ref(_: &i32) {}
     takes_ref(*Box::new(&0i32));
+
+    // Issue #10384
+    impl<'a> WithAssoc for &'a u32 {
+        type Assoc = dyn core::fmt::Display;
+        fn to_assoc(&self) -> &Self::Assoc {
+            *self
+        }
+    }
+    fn return_dyn_assoc<'a>(x: &'a &'a u32) -> &'a <&'a u32 as WithAssoc>::Assoc {
+        *x
+    }
 }
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
index 5cb80cb6233..48017434276 100644
--- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.rs
@@ -1,11 +1,17 @@
 #![allow(unused, clippy::needless_lifetimes)]
 #![warn(clippy::extra_unused_type_parameters)]
 
-fn unused_ty<T>(x: u8) {}
+fn unused_ty<T>(x: u8) {
+    unimplemented!()
+}
 
-fn unused_multi<T, U>(x: u8) {}
+fn unused_multi<T, U>(x: u8) {
+    unimplemented!()
+}
 
-fn unused_with_lt<'a, T>(x: &'a u8) {}
+fn unused_with_lt<'a, T>(x: &'a u8) {
+    unimplemented!()
+}
 
 fn used_ty<T>(x: T, y: u8) {}
 
@@ -15,15 +21,20 @@ fn used_ret<T: Default>(x: u8) -> T {
     T::default()
 }
 
-fn unused_bounded<T: Default, U>(x: U) {}
+fn unused_bounded<T: Default, U>(x: U) {
+    unimplemented!();
+}
 
 fn unused_where_clause<T, U>(x: U)
 where
     T: Default,
 {
+    unimplemented!();
 }
 
-fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {}
+fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {
+    unimplemented!();
+}
 
 fn used_opaque<A>(iter: impl Iterator<Item = A>) -> usize {
     iter.count()
@@ -46,7 +57,9 @@ fn used_closure<T: Default + ToString>() -> impl Fn() {
 struct S;
 
 impl S {
-    fn unused_ty_impl<T>(&self) {}
+    fn unused_ty_impl<T>(&self) {
+        unimplemented!()
+    }
 }
 
 // Don't lint on trait methods
@@ -66,4 +79,32 @@ where
         .filter_map(move |(i, a)| if i == index { None } else { Some(a) })
 }
 
+fn unused_opaque<A, B>(dummy: impl Default) {
+    unimplemented!()
+}
+
+mod unexported_trait_bounds {
+    mod private {
+        pub trait Private {}
+    }
+
+    fn priv_trait_bound<T: private::Private>() {
+        unimplemented!();
+    }
+
+    fn unused_with_priv_trait_bound<T: private::Private, U>() {
+        unimplemented!();
+    }
+}
+
+mod issue10319 {
+    fn assert_send<T: Send>() {}
+
+    fn assert_send_where<T>()
+    where
+        T: Send,
+    {
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
index 1c8dd53e638..86c88fc9bf0 100644
--- a/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
+++ b/src/tools/clippy/tests/ui/extra_unused_type_parameters.stderr
@@ -1,38 +1,38 @@
 error: type parameter goes unused in function definition
   --> $DIR/extra_unused_type_parameters.rs:4:13
    |
-LL | fn unused_ty<T>(x: u8) {}
+LL | fn unused_ty<T>(x: u8) {
    |             ^^^
    |
    = help: consider removing the parameter
    = note: `-D clippy::extra-unused-type-parameters` implied by `-D warnings`
 
 error: type parameters go unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:6:16
+  --> $DIR/extra_unused_type_parameters.rs:8:16
    |
-LL | fn unused_multi<T, U>(x: u8) {}
+LL | fn unused_multi<T, U>(x: u8) {
    |                ^^^^^^
    |
    = help: consider removing the parameters
 
 error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:8:23
+  --> $DIR/extra_unused_type_parameters.rs:12:23
    |
-LL | fn unused_with_lt<'a, T>(x: &'a u8) {}
+LL | fn unused_with_lt<'a, T>(x: &'a u8) {
    |                       ^
    |
    = help: consider removing the parameter
 
 error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:18:19
+  --> $DIR/extra_unused_type_parameters.rs:24:19
    |
-LL | fn unused_bounded<T: Default, U>(x: U) {}
+LL | fn unused_bounded<T: Default, U>(x: U) {
    |                   ^^^^^^^^^^^
    |
    = help: consider removing the parameter
 
 error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:20:24
+  --> $DIR/extra_unused_type_parameters.rs:28:24
    |
 LL | fn unused_where_clause<T, U>(x: U)
    |                        ^^
@@ -40,20 +40,36 @@ LL | fn unused_where_clause<T, U>(x: U)
    = help: consider removing the parameter
 
 error: type parameters go unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:26:16
+  --> $DIR/extra_unused_type_parameters.rs:35:16
    |
-LL | fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {}
+LL | fn some_unused<A, B, C, D: Iterator<Item = (B, C)>, E>(b: B, c: C) {
    |                ^^       ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
    |
    = help: consider removing the parameters
 
 error: type parameter goes unused in function definition
-  --> $DIR/extra_unused_type_parameters.rs:49:22
+  --> $DIR/extra_unused_type_parameters.rs:60:22
    |
-LL |     fn unused_ty_impl<T>(&self) {}
+LL |     fn unused_ty_impl<T>(&self) {
    |                      ^^^
    |
    = help: consider removing the parameter
 
-error: aborting due to 7 previous errors
+error: type parameters go unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:82:17
+   |
+LL | fn unused_opaque<A, B>(dummy: impl Default) {
+   |                 ^^^^^^
+   |
+   = help: consider removing the parameters
+
+error: type parameter goes unused in function definition
+  --> $DIR/extra_unused_type_parameters.rs:95:58
+   |
+LL |     fn unused_with_priv_trait_bound<T: private::Private, U>() {
+   |                                                          ^
+   |
+   = help: consider removing the parameter
+
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/clippy/tests/ui/format.fixed b/src/tools/clippy/tests/ui/format.fixed
index beedf2c1db2..cd2f70ee8b0 100644
--- a/src/tools/clippy/tests/ui/format.fixed
+++ b/src/tools/clippy/tests/ui/format.fixed
@@ -1,4 +1,5 @@
 // run-rustfix
+// aux-build: proc_macro_with_span.rs
 #![warn(clippy::useless_format)]
 #![allow(
     unused_tuple_struct_fields,
@@ -9,6 +10,8 @@
     clippy::uninlined_format_args
 )]
 
+extern crate proc_macro_with_span;
+
 struct Foo(pub String);
 
 macro_rules! foo {
@@ -87,4 +90,7 @@ fn main() {
     let _ = abc.to_string();
     let xx = "xx";
     let _ = xx.to_string();
+
+    // Issue #10148
+    println!(proc_macro_with_span::with_span!(""something ""));
 }
diff --git a/src/tools/clippy/tests/ui/format.rs b/src/tools/clippy/tests/ui/format.rs
index e805f181889..c22345a79d4 100644
--- a/src/tools/clippy/tests/ui/format.rs
+++ b/src/tools/clippy/tests/ui/format.rs
@@ -1,4 +1,5 @@
 // run-rustfix
+// aux-build: proc_macro_with_span.rs
 #![warn(clippy::useless_format)]
 #![allow(
     unused_tuple_struct_fields,
@@ -9,6 +10,8 @@
     clippy::uninlined_format_args
 )]
 
+extern crate proc_macro_with_span;
+
 struct Foo(pub String);
 
 macro_rules! foo {
@@ -89,4 +92,7 @@ fn main() {
     let _ = format!("{abc}");
     let xx = "xx";
     let _ = format!("{xx}");
+
+    // Issue #10148
+    println!(proc_macro_with_span::with_span!(""something ""));
 }
diff --git a/src/tools/clippy/tests/ui/format.stderr b/src/tools/clippy/tests/ui/format.stderr
index 0ef0ac655d3..a0e5d5c8ad2 100644
--- a/src/tools/clippy/tests/ui/format.stderr
+++ b/src/tools/clippy/tests/ui/format.stderr
@@ -1,5 +1,5 @@
 error: useless use of `format!`
-  --> $DIR/format.rs:19:5
+  --> $DIR/format.rs:22:5
    |
 LL |     format!("foo");
    |     ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
@@ -7,19 +7,19 @@ LL |     format!("foo");
    = note: `-D clippy::useless-format` implied by `-D warnings`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:20:5
+  --> $DIR/format.rs:23:5
    |
 LL |     format!("{{}}");
    |     ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{}".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:21:5
+  --> $DIR/format.rs:24:5
    |
 LL |     format!("{{}} abc {{}}");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"{} abc {}".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:22:5
+  --> $DIR/format.rs:25:5
    |
 LL | /     format!(
 LL | |         r##"foo {{}}
@@ -34,67 +34,67 @@ LL ~ " bar"##.to_string();
    |
 
 error: useless use of `format!`
-  --> $DIR/format.rs:27:13
+  --> $DIR/format.rs:30:13
    |
 LL |     let _ = format!("");
    |             ^^^^^^^^^^^ help: consider using `String::new()`: `String::new()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:29:5
+  --> $DIR/format.rs:32:5
    |
 LL |     format!("{}", "foo");
    |     ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:37:5
+  --> $DIR/format.rs:40:5
    |
 LL |     format!("{}", arg);
    |     ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:67:5
+  --> $DIR/format.rs:70:5
    |
 LL |     format!("{}", 42.to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:69:5
+  --> $DIR/format.rs:72:5
    |
 LL |     format!("{}", x.display().to_string());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:73:18
+  --> $DIR/format.rs:76:18
    |
 LL |     let _ = Some(format!("{}", a + "bar"));
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:77:22
+  --> $DIR/format.rs:80:22
    |
 LL |     let _s: String = format!("{}", &*v.join("/n"));
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `(&*v.join("/n")).to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:83:13
+  --> $DIR/format.rs:86:13
    |
 LL |     let _ = format!("{x}");
    |             ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:85:13
+  --> $DIR/format.rs:88:13
    |
 LL |     let _ = format!("{y}", y = x);
    |             ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:89:13
+  --> $DIR/format.rs:92:13
    |
 LL |     let _ = format!("{abc}");
    |             ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()`
 
 error: useless use of `format!`
-  --> $DIR/format.rs:91:13
+  --> $DIR/format.rs:94:13
    |
 LL |     let _ = format!("{xx}");
    |             ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()`
diff --git a/src/tools/clippy/tests/ui/impl_trait_in_params.rs b/src/tools/clippy/tests/ui/impl_trait_in_params.rs
new file mode 100644
index 00000000000..07560101a41
--- /dev/null
+++ b/src/tools/clippy/tests/ui/impl_trait_in_params.rs
@@ -0,0 +1,17 @@
+#![allow(unused)]
+#![warn(clippy::impl_trait_in_params)]
+
+pub trait Trait {}
+pub trait AnotherTrait<T> {}
+
+// Should warn
+pub fn a(_: impl Trait) {}
+pub fn c<C: Trait>(_: C, _: impl Trait) {}
+fn d(_: impl AnotherTrait<u32>) {}
+
+// Shouldn't warn
+
+pub fn b<B: Trait>(_: B) {}
+fn e<T: AnotherTrait<u32>>(_: T) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/impl_trait_in_params.stderr b/src/tools/clippy/tests/ui/impl_trait_in_params.stderr
new file mode 100644
index 00000000000..acfcc21445e
--- /dev/null
+++ b/src/tools/clippy/tests/ui/impl_trait_in_params.stderr
@@ -0,0 +1,25 @@
+error: '`impl Trait` used as a function parameter'
+  --> $DIR/impl_trait_in_params.rs:8:13
+   |
+LL | pub fn a(_: impl Trait) {}
+   |             ^^^^^^^^^^
+   |
+   = note: `-D clippy::impl-trait-in-params` implied by `-D warnings`
+help: add a type paremeter
+   |
+LL | pub fn a<{ /* Generic name */ }: Trait>(_: impl Trait) {}
+   |         +++++++++++++++++++++++++++++++
+
+error: '`impl Trait` used as a function parameter'
+  --> $DIR/impl_trait_in_params.rs:9:29
+   |
+LL | pub fn c<C: Trait>(_: C, _: impl Trait) {}
+   |                             ^^^^^^^^^^
+   |
+help: add a type paremeter
+   |
+LL | pub fn c<C: Trait, { /* Generic name */ }: Trait>(_: C, _: impl Trait) {}
+   |                  +++++++++++++++++++++++++++++++
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/large_digit_groups.fixed b/src/tools/clippy/tests/ui/large_digit_groups.fixed
index 3430c137ec2..ea18dac0683 100644
--- a/src/tools/clippy/tests/ui/large_digit_groups.fixed
+++ b/src/tools/clippy/tests/ui/large_digit_groups.fixed
@@ -11,7 +11,7 @@ fn main() {
     let _good = (
         0b1011_i64,
         0o1_234_u32,
-        0x0123_4567,
+        0x1_234_567,
         1_2345_6789,
         1234_f32,
         1_234.12_f32,
@@ -19,7 +19,7 @@ fn main() {
         1.123_4_f32,
     );
     let _bad = (
-        0b11_0110_i64,
+        0b1_10110_i64,
         0xdead_beef_usize,
         123_456_f32,
         123_456.12_f32,
diff --git a/src/tools/clippy/tests/ui/large_digit_groups.stderr b/src/tools/clippy/tests/ui/large_digit_groups.stderr
index 13d108b56e0..19c0fae98a6 100644
--- a/src/tools/clippy/tests/ui/large_digit_groups.stderr
+++ b/src/tools/clippy/tests/ui/large_digit_groups.stderr
@@ -1,22 +1,10 @@
-error: digits of hex or binary literal not grouped by four
-  --> $DIR/large_digit_groups.rs:14:9
-   |
-LL |         0x1_234_567,
-   |         ^^^^^^^^^^^ help: consider: `0x0123_4567`
-   |
-   = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
-
-error: digits of hex or binary literal not grouped by four
-  --> $DIR/large_digit_groups.rs:22:9
-   |
-LL |         0b1_10110_i64,
-   |         ^^^^^^^^^^^^^ help: consider: `0b11_0110_i64`
-
-error: digits of hex or binary literal not grouped by four
+error: digits of hex, binary or octal literal not in groups of equal size
   --> $DIR/large_digit_groups.rs:23:9
    |
 LL |         0xd_e_adbee_f_usize,
    |         ^^^^^^^^^^^^^^^^^^^ help: consider: `0xdead_beef_usize`
+   |
+   = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
 
 error: digit groups should be smaller
   --> $DIR/large_digit_groups.rs:24:9
@@ -44,5 +32,5 @@ error: digit groups should be smaller
 LL |         1_23456.12345_6_f64,
    |         ^^^^^^^^^^^^^^^^^^^ help: consider: `123_456.123_456_f64`
 
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/large_stack_arrays.rs b/src/tools/clippy/tests/ui/large_stack_arrays.rs
index 6790765f803..99787ffd3d3 100644
--- a/src/tools/clippy/tests/ui/large_stack_arrays.rs
+++ b/src/tools/clippy/tests/ui/large_stack_arrays.rs
@@ -24,6 +24,7 @@ fn main() {
         [S { data: [0; 32] }; 5000],
         [Some(""); 20_000_000],
         [E::T(0); 5000],
+        [0u8; usize::MAX],
     );
 
     let good = (
diff --git a/src/tools/clippy/tests/ui/large_stack_arrays.stderr b/src/tools/clippy/tests/ui/large_stack_arrays.stderr
index c7bf941ad00..24e90094982 100644
--- a/src/tools/clippy/tests/ui/large_stack_arrays.stderr
+++ b/src/tools/clippy/tests/ui/large_stack_arrays.stderr
@@ -31,5 +31,13 @@ LL |         [E::T(0); 5000],
    |
    = help: consider allocating on the heap with `vec![E::T(0); 5000].into_boxed_slice()`
 
-error: aborting due to 4 previous errors
+error: allocating a local array larger than 512000 bytes
+  --> $DIR/large_stack_arrays.rs:27:9
+   |
+LL |         [0u8; usize::MAX],
+   |         ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider allocating on the heap with `vec![0u8; usize::MAX].into_boxed_slice()`
+
+error: aborting due to 5 previous errors
 
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.rs b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
new file mode 100644
index 00000000000..bcb33c5c7e3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.rs
@@ -0,0 +1,54 @@
+#![allow(unused)]
+#![warn(clippy::let_underscore_untyped)]
+
+use std::future::Future;
+use std::{boxed::Box, fmt::Display};
+
+fn a() -> u32 {
+    1
+}
+
+fn b<T>(x: T) -> T {
+    x
+}
+
+fn c() -> impl Display {
+    1
+}
+
+fn d(x: &u32) -> &u32 {
+    x
+}
+
+fn e() -> Result<u32, ()> {
+    Ok(1)
+}
+
+fn f() -> Box<dyn Display> {
+    Box::new(1)
+}
+
+fn main() {
+    let _ = a();
+    let _ = b(1);
+    let _ = c();
+    let _ = d(&1);
+    let _ = e();
+    let _ = f();
+
+    _ = a();
+    _ = b(1);
+    _ = c();
+    _ = d(&1);
+    _ = e();
+    _ = f();
+
+    let _: u32 = a();
+    let _: u32 = b(1);
+    let _: &u32 = d(&1);
+    let _: Result<_, _> = e();
+    let _: Box<_> = f();
+
+    #[allow(clippy::let_underscore_untyped)]
+    let _ = a();
+}
diff --git a/src/tools/clippy/tests/ui/let_underscore_untyped.stderr b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
new file mode 100644
index 00000000000..36c3d1214d6
--- /dev/null
+++ b/src/tools/clippy/tests/ui/let_underscore_untyped.stderr
@@ -0,0 +1,51 @@
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:32:5
+   |
+LL |     let _ = a();
+   |     ^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+   = note: `-D clippy::let-underscore-untyped` implied by `-D warnings`
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:33:5
+   |
+LL |     let _ = b(1);
+   |     ^^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:34:5
+   |
+LL |     let _ = c();
+   |     ^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:35:5
+   |
+LL |     let _ = d(&1);
+   |     ^^^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:36:5
+   |
+LL |     let _ = e();
+   |     ^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: non-binding `let` without a type annotation
+  --> $DIR/let_underscore_untyped.rs:37:5
+   |
+LL |     let _ = f();
+   |     ^^^^^^^^^^^^
+   |
+   = help: consider adding a type annotation or removing the `let` keyword
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/literals.stderr b/src/tools/clippy/tests/ui/literals.stderr
index 603d47bacca..9bc7948c7cc 100644
--- a/src/tools/clippy/tests/ui/literals.stderr
+++ b/src/tools/clippy/tests/ui/literals.stderr
@@ -121,7 +121,7 @@ error: digits grouped inconsistently by underscores
 LL |     let fail23 = 3__16___23;
    |                  ^^^^^^^^^^ help: consider: `31_623`
 
-error: digits of hex or binary literal not grouped by four
+error: digits of hex, binary or octal literal not in groups of equal size
   --> $DIR/literals.rs:38:18
    |
 LL |     let fail24 = 0xAB_ABC_AB;
@@ -129,12 +129,6 @@ LL |     let fail24 = 0xAB_ABC_AB;
    |
    = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
 
-error: digits of hex or binary literal not grouped by four
-  --> $DIR/literals.rs:39:18
-   |
-LL |     let fail25 = 0b01_100_101;
-   |                  ^^^^^^^^^^^^ help: consider: `0b0110_0101`
-
 error: this is a decimal constant
   --> $DIR/literals.rs:46:13
    |
@@ -168,5 +162,5 @@ help: if you mean to use a decimal constant, remove the `0` to avoid confusion
 LL |     let _ = 89;
    |             ~~
 
-error: aborting due to 21 previous errors
+error: aborting due to 20 previous errors
 
diff --git a/src/tools/clippy/tests/ui/manual_let_else.rs b/src/tools/clippy/tests/ui/manual_let_else.rs
index 48a162c1360..d175597a44a 100644
--- a/src/tools/clippy/tests/ui/manual_let_else.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else.rs
@@ -248,4 +248,15 @@ fn not_fire() {
         Some(value) => value,
         _ => macro_call!(),
     };
+
+    // Issue 10296
+    // The let/else block in the else part is not divergent despite the presence of return
+    let _x = if let Some(x) = Some(1) {
+        x
+    } else {
+        let Some(_z) = Some(3) else {
+            return
+        };
+        1
+    };
 }
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.rs b/src/tools/clippy/tests/ui/manual_let_else_match.rs
index 28caed9d79d..73b74679125 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.rs
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.rs
@@ -42,13 +42,13 @@ fn fire() {
     loop {
         // More complex pattern for the identity arm and diverging arm
         let v = match h() {
-            (Some(_), Some(_)) | (None, None) => continue,
             (Some(v), None) | (None, Some(v)) => v,
+            (Some(_), Some(_)) | (None, None) => continue,
         };
         // Custom enums are supported as long as the "else" arm is a simple _
         let v = match build_enum() {
-            _ => continue,
             Variant::Bar(v) | Variant::Baz(v) => v,
+            _ => continue,
         };
     }
 
@@ -71,6 +71,12 @@ fn fire() {
         Variant::Bar(_) | Variant::Baz(_) => (),
         _ => return,
     };
+
+    let data = [1_u8, 2, 3, 4, 0, 0, 0, 0];
+    let data = match data.as_slice() {
+        [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data,
+        _ => return,
+    };
 }
 
 fn not_fire() {
@@ -125,4 +131,23 @@ fn not_fire() {
         Ok(v) | Err(Variant::Bar(v) | Variant::Baz(v)) => v,
         Err(Variant::Foo) => return,
     };
+
+    // Issue 10241
+    // The non-divergent arm arrives in second position and
+    // may cover values already matched in the first arm.
+    let v = match h() {
+        (Some(_), Some(_)) | (None, None) => return,
+        (Some(v), _) | (None, Some(v)) => v,
+    };
+
+    let v = match build_enum() {
+        _ => return,
+        Variant::Bar(v) | Variant::Baz(v) => v,
+    };
+
+    let data = [1_u8, 2, 3, 4, 0, 0, 0, 0];
+    let data = match data.as_slice() {
+        [] | [0, 0] => return,
+        [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ ..] => data,
+    };
 }
diff --git a/src/tools/clippy/tests/ui/manual_let_else_match.stderr b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
index cd5e9a9ac39..7abaa0b85d2 100644
--- a/src/tools/clippy/tests/ui/manual_let_else_match.stderr
+++ b/src/tools/clippy/tests/ui/manual_let_else_match.stderr
@@ -22,8 +22,8 @@ error: this could be rewritten as `let...else`
   --> $DIR/manual_let_else_match.rs:44:9
    |
 LL | /         let v = match h() {
-LL | |             (Some(_), Some(_)) | (None, None) => continue,
 LL | |             (Some(v), None) | (None, Some(v)) => v,
+LL | |             (Some(_), Some(_)) | (None, None) => continue,
 LL | |         };
    | |__________^ help: consider writing: `let ((Some(v), None) | (None, Some(v))) = h() else { continue };`
 
@@ -31,8 +31,8 @@ error: this could be rewritten as `let...else`
   --> $DIR/manual_let_else_match.rs:49:9
    |
 LL | /         let v = match build_enum() {
-LL | |             _ => continue,
 LL | |             Variant::Bar(v) | Variant::Baz(v) => v,
+LL | |             _ => continue,
 LL | |         };
    | |__________^ help: consider writing: `let (Variant::Bar(v) | Variant::Baz(v)) = build_enum() else { continue };`
 
@@ -63,5 +63,14 @@ LL | |         _ => return,
 LL | |     };
    | |______^ help: consider writing: `let (Variant::Bar(_) | Variant::Baz(_)) = f else { return };`
 
-error: aborting due to 7 previous errors
+error: this could be rewritten as `let...else`
+  --> $DIR/manual_let_else_match.rs:76:5
+   |
+LL | /     let data = match data.as_slice() {
+LL | |         [data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0] => data,
+LL | |         _ => return,
+LL | |     };
+   | |______^ help: consider writing: `let ([data @ .., 0, 0, 0, 0] | [data @ .., 0, 0] | [data @ .., 0]) = data.as_slice() else { return };`
+
+error: aborting due to 8 previous errors
 
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
index 53628ef6531..8e2f11389f8 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.fixed
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::let_underscore_untyped)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::redundant_closure)]
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.rs b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
index 76016c8ed3c..a783a99c4ff 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.rs
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.rs
@@ -1,6 +1,7 @@
 // run-rustfix
 
 #![warn(clippy::all, clippy::pedantic)]
+#![allow(clippy::let_underscore_untyped)]
 #![allow(clippy::missing_docs_in_private_items)]
 #![allow(clippy::map_identity)]
 #![allow(clippy::redundant_closure)]
diff --git a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
index b6b0c4d09c3..c91f0b9ae94 100644
--- a/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
+++ b/src/tools/clippy/tests/ui/map_flatten_fixable.stderr
@@ -1,5 +1,5 @@
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:17:47
+  --> $DIR/map_flatten_fixable.rs:18:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)`
@@ -7,43 +7,43 @@ LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll
    = note: `-D clippy::map-flatten` implied by `-D warnings`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:18:47
+  --> $DIR/map_flatten_fixable.rs:19:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:19:47
+  --> $DIR/map_flatten_fixable.rs:20:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:20:47
+  --> $DIR/map_flatten_fixable.rs:21:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:23:47
+  --> $DIR/map_flatten_fixable.rs:24:47
    |
 LL |     let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect();
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)`
 
 error: called `map(..).flatten()` on `Option`
-  --> $DIR/map_flatten_fixable.rs:26:40
+  --> $DIR/map_flatten_fixable.rs:27:40
    |
 LL |     let _: Option<_> = (Some(Some(1))).map(|x| x).flatten();
    |                                        ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Result`
-  --> $DIR/map_flatten_fixable.rs:29:42
+  --> $DIR/map_flatten_fixable.rs:30:42
    |
 LL |     let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten();
    |                                          ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)`
 
 error: called `map(..).flatten()` on `Iterator`
-  --> $DIR/map_flatten_fixable.rs:38:10
+  --> $DIR/map_flatten_fixable.rs:39:10
    |
 LL |           .map(|n| match n {
    |  __________^
@@ -72,7 +72,7 @@ LL ~         });
    |
 
 error: called `map(..).flatten()` on `Option`
-  --> $DIR/map_flatten_fixable.rs:58:10
+  --> $DIR/map_flatten_fixable.rs:59:10
    |
 LL |           .map(|_| {
    |  __________^
diff --git a/src/tools/clippy/tests/ui/methods.rs b/src/tools/clippy/tests/ui/methods.rs
index 6f22366eab2..1519e4da934 100644
--- a/src/tools/clippy/tests/ui/methods.rs
+++ b/src/tools/clippy/tests/ui/methods.rs
@@ -4,6 +4,7 @@
 #![allow(
     clippy::disallowed_names,
     clippy::default_trait_access,
+    clippy::let_underscore_untyped,
     clippy::missing_docs_in_private_items,
     clippy::missing_safety_doc,
     clippy::non_ascii_literal,
diff --git a/src/tools/clippy/tests/ui/methods.stderr b/src/tools/clippy/tests/ui/methods.stderr
index b63672dd6fd..4643e09e270 100644
--- a/src/tools/clippy/tests/ui/methods.stderr
+++ b/src/tools/clippy/tests/ui/methods.stderr
@@ -1,5 +1,5 @@
 error: methods called `new` usually return `Self`
-  --> $DIR/methods.rs:104:5
+  --> $DIR/methods.rs:105:5
    |
 LL | /     fn new() -> i32 {
 LL | |         0
@@ -9,7 +9,7 @@ LL | |     }
    = note: `-D clippy::new-ret-no-self` implied by `-D warnings`
 
 error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
-  --> $DIR/methods.rs:125:13
+  --> $DIR/methods.rs:126:13
    |
 LL |       let _ = v.iter().filter(|&x| {
    |  _____________^
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.fixed b/src/tools/clippy/tests/ui/must_use_candidates.fixed
index 04a74a009e0..bbbb3cf621e 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.fixed
+++ b/src/tools/clippy/tests/ui/must_use_candidates.fixed
@@ -84,7 +84,7 @@ pub unsafe fn mutates_static() -> usize {
 }
 
 #[no_mangle]
-pub fn unmangled(i: bool) -> bool {
+pub extern "C" fn unmangled(i: bool) -> bool {
     !i
 }
 
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.rs b/src/tools/clippy/tests/ui/must_use_candidates.rs
index f04122f4eea..94d3c83bdb9 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.rs
+++ b/src/tools/clippy/tests/ui/must_use_candidates.rs
@@ -84,7 +84,7 @@ pub unsafe fn mutates_static() -> usize {
 }
 
 #[no_mangle]
-pub fn unmangled(i: bool) -> bool {
+pub extern "C" fn unmangled(i: bool) -> bool {
     !i
 }
 
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.fixed b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
index d286ef4ba37..f0f1f9298ac 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.fixed
@@ -516,6 +516,16 @@ mod in_macro {
 
     // no lint on external macro
     macro_rules::needless_lifetime!();
+
+    macro_rules! expanded_lifetime {
+        ($l:lifetime) => {
+            fn f<$l>(arg: &$l str) -> &$l str {
+                arg
+            }
+        }
+    }
+
+    expanded_lifetime!('a);
 }
 
 mod issue5787 {
diff --git a/src/tools/clippy/tests/ui/needless_lifetimes.rs b/src/tools/clippy/tests/ui/needless_lifetimes.rs
index 409528b291d..ddfd1043003 100644
--- a/src/tools/clippy/tests/ui/needless_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/needless_lifetimes.rs
@@ -516,6 +516,16 @@ mod in_macro {
 
     // no lint on external macro
     macro_rules::needless_lifetime!();
+
+    macro_rules! expanded_lifetime {
+        ($l:lifetime) => {
+            fn f<$l>(arg: &$l str) -> &$l str {
+                arg
+            }
+        }
+    }
+
+    expanded_lifetime!('a);
 }
 
 mod issue5787 {
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index 079e3531def..0f525dd294c 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -297,4 +297,14 @@ fn issue10051() -> Result<String, String> {
     }
 }
 
+mod issue10049 {
+    fn single() -> u32 {
+        if true { 1 } else { 2 }
+    }
+
+    fn multiple(b1: bool, b2: bool, b3: bool) -> u32 {
+        (if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 })
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index c1c48284f08..a1db8375d95 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -307,4 +307,14 @@ fn issue10051() -> Result<String, String> {
     }
 }
 
+mod issue10049 {
+    fn single() -> u32 {
+        return if true { 1 } else { 2 };
+    }
+
+    fn multiple(b1: bool, b2: bool, b3: bool) -> u32 {
+        return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
+    }
+}
+
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index 08b04bfe9d8..87d0cd3e14c 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -418,5 +418,21 @@ LL |         return Err(format!("err!"));
    |
    = help: remove `return`
 
-error: aborting due to 50 previous errors
+error: unneeded `return` statement
+  --> $DIR/needless_return.rs:312:9
+   |
+LL |         return if true { 1 } else { 2 };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: remove `return`
+
+error: unneeded `return` statement
+  --> $DIR/needless_return.rs:316:9
+   |
+LL |         return if b1 { 0 } else { 1 } | if b2 { 2 } else { 3 } | if b3 { 4 } else { 5 };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: remove `return` and wrap the sequence with parentheses
+
+error: aborting due to 52 previous errors
 
diff --git a/src/tools/clippy/tests/ui/never_loop.rs b/src/tools/clippy/tests/ui/never_loop.rs
index 28e8f459d44..29821ff96fc 100644
--- a/src/tools/clippy/tests/ui/never_loop.rs
+++ b/src/tools/clippy/tests/ui/never_loop.rs
@@ -250,6 +250,51 @@ pub fn test20() {
     }
 }
 
+pub fn test21() {
+    loop {
+        'a: {
+            {}
+            break 'a;
+        }
+    }
+}
+
+// Issue 10304: code after break from block was not considered
+// unreachable code and was considered for further analysis of
+// whether the loop would ever be executed or not.
+pub fn test22() {
+    for _ in 0..10 {
+        'block: {
+            break 'block;
+            return;
+        }
+        println!("looped");
+    }
+}
+
+pub fn test23() {
+    for _ in 0..10 {
+        'block: {
+            for _ in 0..20 {
+                break 'block;
+            }
+        }
+        println!("looped");
+    }
+}
+
+pub fn test24() {
+    'a: for _ in 0..10 {
+        'b: {
+            let x = Some(1);
+            match x {
+                None => break 'a,
+                Some(_) => break 'b,
+            }
+        }
+    }
+}
+
 fn main() {
     test1();
     test2();
diff --git a/src/tools/clippy/tests/ui/never_loop.stderr b/src/tools/clippy/tests/ui/never_loop.stderr
index b7029bf8bed..704d448644e 100644
--- a/src/tools/clippy/tests/ui/never_loop.stderr
+++ b/src/tools/clippy/tests/ui/never_loop.stderr
@@ -126,5 +126,18 @@ LL | |         }
 LL | |     }
    | |_____^
 
-error: aborting due to 11 previous errors
+error: this loop never actually loops
+  --> $DIR/never_loop.rs:278:13
+   |
+LL | /             for _ in 0..20 {
+LL | |                 break 'block;
+LL | |             }
+   | |_____________^
+   |
+help: if you need the first element of the iterator, try writing
+   |
+LL |             if let Some(_) = (0..20).next() {
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 12 previous errors
 
diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.fixed b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.fixed
new file mode 100644
index 00000000000..d18dec22a8b
--- /dev/null
+++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.fixed
@@ -0,0 +1,48 @@
+// run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::no_mangle_with_rust_abi)]
+
+#[no_mangle]
+extern "C" fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+pub extern "C" fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+pub unsafe extern "C" fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+unsafe extern "C" fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+extern "C" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+    arg_one: u32,
+    arg_two: usize,
+) -> u32 {
+    0
+}
+
+// Must not run on functions that explicitly opt in to Rust ABI with `extern "Rust"`
+#[no_mangle]
+#[rustfmt::skip]
+extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {}
+
+fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {}
+
+extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+extern "C" {
+    fn c_abi_in_block(arg_one: u32, arg_two: usize);
+}
+
+fn main() {
+    // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
new file mode 100644
index 00000000000..481e1b6d961
--- /dev/null
+++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.rs
@@ -0,0 +1,48 @@
+// run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::no_mangle_with_rust_abi)]
+
+#[no_mangle]
+fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+
+/// # Safety
+/// This function shouldn't be called unless the horsemen are ready
+#[no_mangle]
+unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+    arg_one: u32,
+    arg_two: usize,
+) -> u32 {
+    0
+}
+
+// Must not run on functions that explicitly opt in to Rust ABI with `extern "Rust"`
+#[no_mangle]
+#[rustfmt::skip]
+extern "Rust" fn rust_abi_fn_explicit_opt_in(arg_one: u32, arg_two: usize) {}
+
+fn rust_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+#[no_mangle]
+extern "C" fn c_abi_fn(arg_one: u32, arg_two: usize) {}
+
+extern "C" fn c_abi_fn_again(arg_one: u32, arg_two: usize) {}
+
+extern "C" {
+    fn c_abi_in_block(arg_one: u32, arg_two: usize);
+}
+
+fn main() {
+    // test code goes here
+}
diff --git a/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr
new file mode 100644
index 00000000000..71517d31809
--- /dev/null
+++ b/src/tools/clippy/tests/ui/no_mangle_with_rust_abi.stderr
@@ -0,0 +1,45 @@
+error: attribute #[no_mangle] set on a Rust ABI function
+  --> $DIR/no_mangle_with_rust_abi.rs:7:1
+   |
+LL | fn rust_abi_fn_one(arg_one: u32, arg_two: usize) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `extern "C" fn rust_abi_fn_one(arg_one: u32, arg_two: usize)`
+   |
+   = note: `-D clippy::no-mangle-with-rust-abi` implied by `-D warnings`
+
+error: attribute #[no_mangle] set on a Rust ABI function
+  --> $DIR/no_mangle_with_rust_abi.rs:10:1
+   |
+LL | pub fn rust_abi_fn_two(arg_one: u32, arg_two: usize) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `pub extern "C" fn rust_abi_fn_two(arg_one: u32, arg_two: usize)`
+
+error: attribute #[no_mangle] set on a Rust ABI function
+  --> $DIR/no_mangle_with_rust_abi.rs:15:1
+   |
+LL | pub unsafe fn rust_abi_fn_three(arg_one: u32, arg_two: usize) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `pub unsafe extern "C" fn rust_abi_fn_three(arg_one: u32, arg_two: usize)`
+
+error: attribute #[no_mangle] set on a Rust ABI function
+  --> $DIR/no_mangle_with_rust_abi.rs:20:1
+   |
+LL | unsafe fn rust_abi_fn_four(arg_one: u32, arg_two: usize) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe extern "C" fn rust_abi_fn_four(arg_one: u32, arg_two: usize)`
+
+error: attribute #[no_mangle] set on a Rust ABI function
+  --> $DIR/no_mangle_with_rust_abi.rs:23:1
+   |
+LL | / fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+LL | |     arg_one: u32,
+LL | |     arg_two: usize,
+LL | | ) -> u32 {
+   | |________^
+   |
+help: try
+   |
+LL + extern "C" fn rust_abi_multiline_function_really_long_name_to_overflow_args_to_multiple_lines(
+LL +     arg_one: u32,
+LL +     arg_two: usize,
+LL ~ ) -> u32 {
+   |
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui/question_mark_used.rs b/src/tools/clippy/tests/ui/question_mark_used.rs
new file mode 100644
index 00000000000..8c3ef789697
--- /dev/null
+++ b/src/tools/clippy/tests/ui/question_mark_used.rs
@@ -0,0 +1,15 @@
+// non rustfixable
+#![allow(unreachable_code)]
+#![allow(dead_code)]
+#![warn(clippy::question_mark_used)]
+
+fn other_function() -> Option<i32> {
+    Some(32)
+}
+
+fn my_function() -> Option<i32> {
+    other_function()?;
+    None
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/question_mark_used.stderr b/src/tools/clippy/tests/ui/question_mark_used.stderr
new file mode 100644
index 00000000000..8b5fcbcdbfd
--- /dev/null
+++ b/src/tools/clippy/tests/ui/question_mark_used.stderr
@@ -0,0 +1,11 @@
+error: question mark operator was used
+  --> $DIR/question_mark_used.rs:11:5
+   |
+LL |     other_function()?;
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = help: consider using a custom macro or match expression
+   = note: `-D clippy::question-mark-used` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.fixed b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
new file mode 100644
index 00000000000..da998c610bd
--- /dev/null
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.fixed
@@ -0,0 +1,84 @@
+// run-rustfix
+
+#![warn(clippy::significant_drop_tightening)]
+
+use std::sync::Mutex;
+
+pub fn complex_return_triggers_the_lint() -> i32 {
+    fn foo() -> i32 {
+        1
+    }
+    let mutex = Mutex::new(1);
+    let lock = mutex.lock().unwrap();
+    let _ = *lock;
+    let _ = *lock;
+    drop(lock);
+    foo()
+}
+
+pub fn path_return_can_be_ignored() -> i32 {
+    let mutex = Mutex::new(1);
+    let lock = mutex.lock().unwrap();
+    let rslt = *lock;
+    let _ = *lock;
+    rslt
+}
+
+pub fn post_bindings_can_be_ignored() {
+    let mutex = Mutex::new(1);
+    let lock = mutex.lock().unwrap();
+    let rslt = *lock;
+    let another = rslt;
+    let _ = another;
+}
+
+pub fn unnecessary_contention_with_multiple_owned_results() {
+    {
+        let mutex = Mutex::new(1i32);
+        let lock = mutex.lock().unwrap();
+        let _ = lock.abs();
+        let _ = lock.is_positive();
+    }
+
+    {
+        let mutex = Mutex::new(1i32);
+        let lock = mutex.lock().unwrap();
+        let rslt0 = lock.abs();
+        let rslt1 = lock.is_positive();
+        drop(lock);
+        do_heavy_computation_that_takes_time((rslt0, rslt1));
+    }
+}
+
+pub fn unnecessary_contention_with_single_owned_results() {
+    {
+        let mutex = Mutex::new(1i32);
+        let lock = mutex.lock().unwrap();
+        let _ = lock.abs();
+    }
+    {
+        let mutex = Mutex::new(vec![1i32]);
+        let mut lock = mutex.lock().unwrap();
+        lock.clear();
+    }
+
+    {
+        let mutex = Mutex::new(1i32);
+        
+        let rslt0 = mutex.lock().unwrap().abs();
+        
+        do_heavy_computation_that_takes_time(rslt0);
+    }
+    {
+        let mutex = Mutex::new(vec![1i32]);
+        
+        mutex.lock().unwrap().clear();
+        
+        do_heavy_computation_that_takes_time(());
+    }
+}
+
+// Marker used for illustration purposes.
+pub fn do_heavy_computation_that_takes_time<T>(_: T) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.rs b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
new file mode 100644
index 00000000000..83823f95f68
--- /dev/null
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.rs
@@ -0,0 +1,80 @@
+// run-rustfix
+
+#![warn(clippy::significant_drop_tightening)]
+
+use std::sync::Mutex;
+
+pub fn complex_return_triggers_the_lint() -> i32 {
+    fn foo() -> i32 {
+        1
+    }
+    let mutex = Mutex::new(1);
+    let lock = mutex.lock().unwrap();
+    let _ = *lock;
+    let _ = *lock;
+    foo()
+}
+
+pub fn path_return_can_be_ignored() -> i32 {
+    let mutex = Mutex::new(1);
+    let lock = mutex.lock().unwrap();
+    let rslt = *lock;
+    let _ = *lock;
+    rslt
+}
+
+pub fn post_bindings_can_be_ignored() {
+    let mutex = Mutex::new(1);
+    let lock = mutex.lock().unwrap();
+    let rslt = *lock;
+    let another = rslt;
+    let _ = another;
+}
+
+pub fn unnecessary_contention_with_multiple_owned_results() {
+    {
+        let mutex = Mutex::new(1i32);
+        let lock = mutex.lock().unwrap();
+        let _ = lock.abs();
+        let _ = lock.is_positive();
+    }
+
+    {
+        let mutex = Mutex::new(1i32);
+        let lock = mutex.lock().unwrap();
+        let rslt0 = lock.abs();
+        let rslt1 = lock.is_positive();
+        do_heavy_computation_that_takes_time((rslt0, rslt1));
+    }
+}
+
+pub fn unnecessary_contention_with_single_owned_results() {
+    {
+        let mutex = Mutex::new(1i32);
+        let lock = mutex.lock().unwrap();
+        let _ = lock.abs();
+    }
+    {
+        let mutex = Mutex::new(vec![1i32]);
+        let mut lock = mutex.lock().unwrap();
+        lock.clear();
+    }
+
+    {
+        let mutex = Mutex::new(1i32);
+        let lock = mutex.lock().unwrap();
+        let rslt0 = lock.abs();
+        do_heavy_computation_that_takes_time(rslt0);
+    }
+    {
+        let mutex = Mutex::new(vec![1i32]);
+        let mut lock = mutex.lock().unwrap();
+        lock.clear();
+        do_heavy_computation_that_takes_time(());
+    }
+}
+
+// Marker used for illustration purposes.
+pub fn do_heavy_computation_that_takes_time<T>(_: T) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/significant_drop_tightening.stderr b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
new file mode 100644
index 00000000000..ab8ce356ec7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/significant_drop_tightening.stderr
@@ -0,0 +1,94 @@
+error: temporary with significant `Drop` can be early dropped
+  --> $DIR/significant_drop_tightening.rs:12:9
+   |
+LL |   pub fn complex_return_triggers_the_lint() -> i32 {
+   |  __________________________________________________-
+LL | |     fn foo() -> i32 {
+LL | |         1
+LL | |     }
+LL | |     let mutex = Mutex::new(1);
+LL | |     let lock = mutex.lock().unwrap();
+   | |         ^^^^
+...  |
+LL | |     foo()
+LL | | }
+   | |_- temporary `lock` is currently being dropped at the end of its contained scope
+   |
+   = note: this might lead to unnecessary resource contention
+   = note: `-D clippy::significant-drop-tightening` implied by `-D warnings`
+help: drop the temporary after the end of its last usage
+   |
+LL ~     let _ = *lock;
+LL +     drop(lock);
+   |
+
+error: temporary with significant `Drop` can be early dropped
+  --> $DIR/significant_drop_tightening.rs:44:13
+   |
+LL | /     {
+LL | |         let mutex = Mutex::new(1i32);
+LL | |         let lock = mutex.lock().unwrap();
+   | |             ^^^^
+LL | |         let rslt0 = lock.abs();
+LL | |         let rslt1 = lock.is_positive();
+LL | |         do_heavy_computation_that_takes_time((rslt0, rslt1));
+LL | |     }
+   | |_____- temporary `lock` is currently being dropped at the end of its contained scope
+   |
+   = note: this might lead to unnecessary resource contention
+help: drop the temporary after the end of its last usage
+   |
+LL ~         let rslt1 = lock.is_positive();
+LL +         drop(lock);
+   |
+
+error: temporary with significant `Drop` can be early dropped
+  --> $DIR/significant_drop_tightening.rs:65:13
+   |
+LL | /     {
+LL | |         let mutex = Mutex::new(1i32);
+LL | |         let lock = mutex.lock().unwrap();
+   | |             ^^^^
+LL | |         let rslt0 = lock.abs();
+LL | |         do_heavy_computation_that_takes_time(rslt0);
+LL | |     }
+   | |_____- temporary `lock` is currently being dropped at the end of its contained scope
+   |
+   = note: this might lead to unnecessary resource contention
+help: merge the temporary construction with its single usage
+   |
+LL ~         
+LL +         let rslt0 = mutex.lock().unwrap().abs();
+   |
+help: remove separated single usage
+   |
+LL -         let rslt0 = lock.abs();
+LL +         
+   |
+
+error: temporary with significant `Drop` can be early dropped
+  --> $DIR/significant_drop_tightening.rs:71:17
+   |
+LL | /     {
+LL | |         let mutex = Mutex::new(vec![1i32]);
+LL | |         let mut lock = mutex.lock().unwrap();
+   | |                 ^^^^
+LL | |         lock.clear();
+LL | |         do_heavy_computation_that_takes_time(());
+LL | |     }
+   | |_____- temporary `lock` is currently being dropped at the end of its contained scope
+   |
+   = note: this might lead to unnecessary resource contention
+help: merge the temporary construction with its single usage
+   |
+LL ~         
+LL +         mutex.lock().unwrap().clear();
+   |
+help: remove separated single usage
+   |
+LL -         lock.clear();
+LL +         
+   |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs b/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs
new file mode 100644
index 00000000000..bdc6113a250
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_command_arg_space.rs
@@ -0,0 +1,10 @@
+fn main() {
+    // Things it should warn about:
+    std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
+    std::process::Command::new("cat").arg("--number file").spawn().unwrap();
+
+    // Things it should not warn about:
+    std::process::Command::new("echo").arg("hello world").spawn().unwrap();
+    std::process::Command::new("a").arg("--fmt=%a %b %c").spawn().unwrap();
+    std::process::Command::new("b").arg("-ldflags=-s -w").spawn().unwrap();
+}
diff --git a/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr b/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr
new file mode 100644
index 00000000000..9bc0ca93aec
--- /dev/null
+++ b/src/tools/clippy/tests/ui/suspicious_command_arg_space.stderr
@@ -0,0 +1,25 @@
+error: single argument that looks like it should be multiple arguments
+  --> $DIR/suspicious_command_arg_space.rs:3:44
+   |
+LL |     std::process::Command::new("echo").arg("-n hello").spawn().unwrap();
+   |                                            ^^^^^^^^^^
+   |
+   = note: `-D clippy::suspicious-command-arg-space` implied by `-D warnings`
+help: consider splitting the argument
+   |
+LL |     std::process::Command::new("echo").args(["-n", "hello"]).spawn().unwrap();
+   |                                        ~~~~ ~~~~~~~~~~~~~~~
+
+error: single argument that looks like it should be multiple arguments
+  --> $DIR/suspicious_command_arg_space.rs:4:43
+   |
+LL |     std::process::Command::new("cat").arg("--number file").spawn().unwrap();
+   |                                           ^^^^^^^^^^^^^^^
+   |
+help: consider splitting the argument
+   |
+LL |     std::process::Command::new("cat").args(["--number", "file"]).spawn().unwrap();
+   |                                       ~~~~ ~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/swap.fixed b/src/tools/clippy/tests/ui/swap.fixed
index 805a2ba5a59..fa89706a815 100644
--- a/src/tools/clippy/tests/ui/swap.fixed
+++ b/src/tools/clippy/tests/ui/swap.fixed
@@ -7,7 +7,8 @@
     clippy::redundant_clone,
     redundant_semicolons,
     dead_code,
-    unused_assignments
+    unused_assignments,
+    unused_variables
 )]
 
 struct Foo(u32);
@@ -121,6 +122,27 @@ fn main() {
     std::mem::swap(&mut c.0, &mut a);
 
     ; std::mem::swap(&mut c.0, &mut a);
+
+    std::mem::swap(&mut a, &mut b);
+
+    let mut c = 1;
+    let mut d = 2;
+    std::mem::swap(&mut d, &mut c);
+
+    let mut b = 1;
+    std::mem::swap(&mut a, &mut b);
+
+    let b = 1;
+    let a = 2;
+
+    let t = b;
+    let b = a;
+    let a = t;
+
+    let mut b = 1;
+    let mut a = 2;
+
+    std::mem::swap(&mut b, &mut a);
 }
 
 fn issue_8154() {
diff --git a/src/tools/clippy/tests/ui/swap.rs b/src/tools/clippy/tests/ui/swap.rs
index a8c87847952..ef8a81c8341 100644
--- a/src/tools/clippy/tests/ui/swap.rs
+++ b/src/tools/clippy/tests/ui/swap.rs
@@ -7,7 +7,8 @@
     clippy::redundant_clone,
     redundant_semicolons,
     dead_code,
-    unused_assignments
+    unused_assignments,
+    unused_variables
 )]
 
 struct Foo(u32);
@@ -143,6 +144,32 @@ fn main() {
     ; let t = c.0;
     c.0 = a;
     a = t;
+
+    let a = b;
+    let b = a;
+
+    let mut c = 1;
+    let mut d = 2;
+    d = c;
+    c = d;
+
+    let mut b = 1;
+    let a = b;
+    b = a;
+
+    let b = 1;
+    let a = 2;
+
+    let t = b;
+    let b = a;
+    let a = t;
+
+    let mut b = 1;
+    let mut a = 2;
+
+    let t = b;
+    b = a;
+    a = t;
 }
 
 fn issue_8154() {
diff --git a/src/tools/clippy/tests/ui/swap.stderr b/src/tools/clippy/tests/ui/swap.stderr
index ee4b7a508a5..f0acbfe253f 100644
--- a/src/tools/clippy/tests/ui/swap.stderr
+++ b/src/tools/clippy/tests/ui/swap.stderr
@@ -1,5 +1,5 @@
 error: this looks like you are swapping `bar.a` and `bar.b` manually
-  --> $DIR/swap.rs:24:5
+  --> $DIR/swap.rs:25:5
    |
 LL | /     let temp = bar.a;
 LL | |     bar.a = bar.b;
@@ -10,7 +10,7 @@ LL | |     bar.b = temp;
    = note: `-D clippy::manual-swap` implied by `-D warnings`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:36:5
+  --> $DIR/swap.rs:37:5
    |
 LL | /     let temp = foo[0];
 LL | |     foo[0] = foo[1];
@@ -18,7 +18,7 @@ LL | |     foo[1] = temp;
    | |_________________^ help: try: `foo.swap(0, 1)`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:45:5
+  --> $DIR/swap.rs:46:5
    |
 LL | /     let temp = foo[0];
 LL | |     foo[0] = foo[1];
@@ -26,7 +26,7 @@ LL | |     foo[1] = temp;
    | |_________________^ help: try: `foo.swap(0, 1)`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:64:5
+  --> $DIR/swap.rs:65:5
    |
 LL | /     let temp = foo[0];
 LL | |     foo[0] = foo[1];
@@ -34,7 +34,7 @@ LL | |     foo[1] = temp;
    | |_________________^ help: try: `foo.swap(0, 1)`
 
 error: this looks like you are swapping `a` and `b` manually
-  --> $DIR/swap.rs:75:5
+  --> $DIR/swap.rs:76:5
    |
 LL | /     a ^= b;
 LL | |     b ^= a;
@@ -42,7 +42,7 @@ LL | |     a ^= b;
    | |___________^ help: try: `std::mem::swap(&mut a, &mut b)`
 
 error: this looks like you are swapping `bar.a` and `bar.b` manually
-  --> $DIR/swap.rs:83:5
+  --> $DIR/swap.rs:84:5
    |
 LL | /     bar.a ^= bar.b;
 LL | |     bar.b ^= bar.a;
@@ -50,7 +50,7 @@ LL | |     bar.a ^= bar.b;
    | |___________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b)`
 
 error: this looks like you are swapping elements of `foo` manually
-  --> $DIR/swap.rs:91:5
+  --> $DIR/swap.rs:92:5
    |
 LL | /     foo[0] ^= foo[1];
 LL | |     foo[1] ^= foo[0];
@@ -58,7 +58,7 @@ LL | |     foo[0] ^= foo[1];
    | |_____________________^ help: try: `foo.swap(0, 1)`
 
 error: this looks like you are swapping `foo[0][1]` and `bar[1][0]` manually
-  --> $DIR/swap.rs:120:5
+  --> $DIR/swap.rs:121:5
    |
 LL | /     let temp = foo[0][1];
 LL | |     foo[0][1] = bar[1][0];
@@ -68,7 +68,7 @@ LL | |     bar[1][0] = temp;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `a` and `b` manually
-  --> $DIR/swap.rs:134:7
+  --> $DIR/swap.rs:135:7
    |
 LL |       ; let t = a;
    |  _______^
@@ -79,7 +79,7 @@ LL | |     b = t;
    = note: or maybe you should use `std::mem::replace`?
 
 error: this looks like you are swapping `c.0` and `a` manually
-  --> $DIR/swap.rs:143:7
+  --> $DIR/swap.rs:144:7
    |
 LL |       ; let t = c.0;
    |  _______^
@@ -89,8 +89,18 @@ LL | |     a = t;
    |
    = note: or maybe you should use `std::mem::replace`?
 
+error: this looks like you are swapping `b` and `a` manually
+  --> $DIR/swap.rs:170:5
+   |
+LL | /     let t = b;
+LL | |     b = a;
+LL | |     a = t;
+   | |_________^ help: try: `std::mem::swap(&mut b, &mut a)`
+   |
+   = note: or maybe you should use `std::mem::replace`?
+
 error: this looks like you are trying to swap `a` and `b`
-  --> $DIR/swap.rs:131:5
+  --> $DIR/swap.rs:132:5
    |
 LL | /     a = b;
 LL | |     b = a;
@@ -100,7 +110,7 @@ LL | |     b = a;
    = note: `-D clippy::almost-swapped` implied by `-D warnings`
 
 error: this looks like you are trying to swap `c.0` and `a`
-  --> $DIR/swap.rs:140:5
+  --> $DIR/swap.rs:141:5
    |
 LL | /     c.0 = a;
 LL | |     a = c.0;
@@ -108,8 +118,35 @@ LL | |     a = c.0;
    |
    = note: or maybe you should use `std::mem::replace`?
 
+error: this looks like you are trying to swap `a` and `b`
+  --> $DIR/swap.rs:148:5
+   |
+LL | /     let a = b;
+LL | |     let b = a;
+   | |_____________^ help: try: `std::mem::swap(&mut a, &mut b)`
+   |
+   = note: or maybe you should use `std::mem::replace`?
+
+error: this looks like you are trying to swap `d` and `c`
+  --> $DIR/swap.rs:153:5
+   |
+LL | /     d = c;
+LL | |     c = d;
+   | |_________^ help: try: `std::mem::swap(&mut d, &mut c)`
+   |
+   = note: or maybe you should use `std::mem::replace`?
+
+error: this looks like you are trying to swap `a` and `b`
+  --> $DIR/swap.rs:157:5
+   |
+LL | /     let a = b;
+LL | |     b = a;
+   | |_________^ help: try: `std::mem::swap(&mut a, &mut b)`
+   |
+   = note: or maybe you should use `std::mem::replace`?
+
 error: this looks like you are swapping `s.0.x` and `s.0.y` manually
-  --> $DIR/swap.rs:178:5
+  --> $DIR/swap.rs:205:5
    |
 LL | /     let t = s.0.x;
 LL | |     s.0.x = s.0.y;
@@ -118,5 +155,5 @@ LL | |     s.0.y = t;
    |
    = note: or maybe you should use `std::mem::replace`?
 
-error: aborting due to 13 previous errors
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs
new file mode 100644
index 00000000000..a3840678250
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.rs
@@ -0,0 +1,41 @@
+#![warn(clippy::transmute_int_to_non_zero)]
+
+use core::num::*;
+
+fn main() {
+    let int_u8: u8 = 1;
+    let int_u16: u16 = 1;
+    let int_u32: u32 = 1;
+    let int_u64: u64 = 1;
+    let int_u128: u128 = 1;
+
+    let int_i8: i8 = 1;
+    let int_i16: i16 = 1;
+    let int_i32: i32 = 1;
+    let int_i64: i64 = 1;
+    let int_i128: i128 = 1;
+
+    let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) };
+    let _: NonZeroU16 = unsafe { std::mem::transmute(int_u16) };
+    let _: NonZeroU32 = unsafe { std::mem::transmute(int_u32) };
+    let _: NonZeroU64 = unsafe { std::mem::transmute(int_u64) };
+    let _: NonZeroU128 = unsafe { std::mem::transmute(int_u128) };
+
+    let _: NonZeroI8 = unsafe { std::mem::transmute(int_i8) };
+    let _: NonZeroI16 = unsafe { std::mem::transmute(int_i16) };
+    let _: NonZeroI32 = unsafe { std::mem::transmute(int_i32) };
+    let _: NonZeroI64 = unsafe { std::mem::transmute(int_i64) };
+    let _: NonZeroI128 = unsafe { std::mem::transmute(int_i128) };
+
+    let _: NonZeroU8 = unsafe { NonZeroU8::new_unchecked(int_u8) };
+    let _: NonZeroU16 = unsafe { NonZeroU16::new_unchecked(int_u16) };
+    let _: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(int_u32) };
+    let _: NonZeroU64 = unsafe { NonZeroU64::new_unchecked(int_u64) };
+    let _: NonZeroU128 = unsafe { NonZeroU128::new_unchecked(int_u128) };
+
+    let _: NonZeroI8 = unsafe { NonZeroI8::new_unchecked(int_i8) };
+    let _: NonZeroI16 = unsafe { NonZeroI16::new_unchecked(int_i16) };
+    let _: NonZeroI32 = unsafe { NonZeroI32::new_unchecked(int_i32) };
+    let _: NonZeroI64 = unsafe { NonZeroI64::new_unchecked(int_i64) };
+    let _: NonZeroI128 = unsafe { NonZeroI128::new_unchecked(int_i128) };
+}
diff --git a/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr
new file mode 100644
index 00000000000..33f8ce79ea7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/transmute_int_to_non_zero.stderr
@@ -0,0 +1,64 @@
+error: transmute from a `u8` to a `NonZeroU8`
+  --> $DIR/transmute_int_to_non_zero.rs:18:33
+   |
+LL |     let _: NonZeroU8 = unsafe { std::mem::transmute(int_u8) };
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU8::new_unchecked(int_u8)`
+   |
+   = note: `-D clippy::transmute-int-to-non-zero` implied by `-D warnings`
+
+error: transmute from a `u16` to a `NonZeroU16`
+  --> $DIR/transmute_int_to_non_zero.rs:19:34
+   |
+LL |     let _: NonZeroU16 = unsafe { std::mem::transmute(int_u16) };
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU16::new_unchecked(int_u16)`
+
+error: transmute from a `u32` to a `NonZeroU32`
+  --> $DIR/transmute_int_to_non_zero.rs:20:34
+   |
+LL |     let _: NonZeroU32 = unsafe { std::mem::transmute(int_u32) };
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU32::new_unchecked(int_u32)`
+
+error: transmute from a `u64` to a `NonZeroU64`
+  --> $DIR/transmute_int_to_non_zero.rs:21:34
+   |
+LL |     let _: NonZeroU64 = unsafe { std::mem::transmute(int_u64) };
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU64::new_unchecked(int_u64)`
+
+error: transmute from a `u128` to a `NonZeroU128`
+  --> $DIR/transmute_int_to_non_zero.rs:22:35
+   |
+LL |     let _: NonZeroU128 = unsafe { std::mem::transmute(int_u128) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroU128::new_unchecked(int_u128)`
+
+error: transmute from a `i8` to a `NonZeroI8`
+  --> $DIR/transmute_int_to_non_zero.rs:24:33
+   |
+LL |     let _: NonZeroI8 = unsafe { std::mem::transmute(int_i8) };
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI8::new_unchecked(int_i8)`
+
+error: transmute from a `i16` to a `NonZeroI16`
+  --> $DIR/transmute_int_to_non_zero.rs:25:34
+   |
+LL |     let _: NonZeroI16 = unsafe { std::mem::transmute(int_i16) };
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI16::new_unchecked(int_i16)`
+
+error: transmute from a `i32` to a `NonZeroI32`
+  --> $DIR/transmute_int_to_non_zero.rs:26:34
+   |
+LL |     let _: NonZeroI32 = unsafe { std::mem::transmute(int_i32) };
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI32::new_unchecked(int_i32)`
+
+error: transmute from a `i64` to a `NonZeroI64`
+  --> $DIR/transmute_int_to_non_zero.rs:27:34
+   |
+LL |     let _: NonZeroI64 = unsafe { std::mem::transmute(int_i64) };
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI64::new_unchecked(int_i64)`
+
+error: transmute from a `i128` to a `NonZeroI128`
+  --> $DIR/transmute_int_to_non_zero.rs:28:35
+   |
+LL |     let _: NonZeroI128 = unsafe { std::mem::transmute(int_i128) };
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `NonZeroI128::new_unchecked(int_i128)`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.fixed b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
index 9d08e80cf9a..cbd5cc5fcee 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.fixed
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
@@ -174,3 +174,7 @@ fn _meets_msrv() {
     let local_i32 = 1;
     println!("expand='{local_i32}'");
 }
+
+fn _do_not_fire() {
+    println!("{:?}", None::<()>);
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.rs b/src/tools/clippy/tests/ui/uninlined_format_args.rs
index 35b3677a896..cf0ea5be481 100644
--- a/src/tools/clippy/tests/ui/uninlined_format_args.rs
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.rs
@@ -179,3 +179,7 @@ fn _meets_msrv() {
     let local_i32 = 1;
     println!("expand='{}'", local_i32);
 }
+
+fn _do_not_fire() {
+    println!("{:?}", None::<()>);
+}
diff --git a/src/tools/clippy/tests/ui/unreadable_literal.fixed b/src/tools/clippy/tests/ui/unreadable_literal.fixed
index a67363b09ea..13e5feb1926 100644
--- a/src/tools/clippy/tests/ui/unreadable_literal.fixed
+++ b/src/tools/clippy/tests/ui/unreadable_literal.fixed
@@ -23,7 +23,7 @@ fn main() {
     let _good = (
         0b1011_i64,
         0o1_234_u32,
-        0x0123_4567,
+        0x1_234_567,
         65536,
         1_2345_6789,
         1234_f32,
diff --git a/src/tools/clippy/tests/ui/unreadable_literal.stderr b/src/tools/clippy/tests/ui/unreadable_literal.stderr
index b51130c6a6a..450121b1c5a 100644
--- a/src/tools/clippy/tests/ui/unreadable_literal.stderr
+++ b/src/tools/clippy/tests/ui/unreadable_literal.stderr
@@ -1,11 +1,3 @@
-error: digits of hex or binary literal not grouped by four
-  --> $DIR/unreadable_literal.rs:26:9
-   |
-LL |         0x1_234_567,
-   |         ^^^^^^^^^^^ help: consider: `0x0123_4567`
-   |
-   = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
-
 error: long literal lacking separators
   --> $DIR/unreadable_literal.rs:34:17
    |
@@ -68,5 +60,5 @@ error: long literal lacking separators
 LL |     let _fail5 = 1.100300400;
    |                  ^^^^^^^^^^^ help: consider: `1.100_300_400`
 
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 7824ef81d7a..41c23ff86b2 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1432,12 +1432,13 @@ impl<'test> TestCx<'test> {
         expect_help: bool,
         expect_note: bool,
     ) -> bool {
-        match actual_error.kind {
-            Some(ErrorKind::Help) => expect_help,
-            Some(ErrorKind::Note) => expect_note,
-            Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true,
-            Some(ErrorKind::Suggestion) | None => false,
-        }
+        !actual_error.msg.is_empty()
+            && match actual_error.kind {
+                Some(ErrorKind::Help) => expect_help,
+                Some(ErrorKind::Note) => expect_note,
+                Some(ErrorKind::Error) | Some(ErrorKind::Warning) => true,
+                Some(ErrorKind::Suggestion) | None => false,
+            }
     }
 
     fn should_emit_metadata(&self, pm: Option<PassMode>) -> Emit {
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 8bbf9f87b43..969c81f7e32 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -777,10 +777,11 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     type Provenance = Provenance;
     type ProvenanceExtra = ProvenanceExtra;
+    type Bytes = Box<[u8]>;
 
     type MemoryMap = MonoHashMap<
         AllocId,
-        (MemoryKind<MiriMemoryKind>, Allocation<Provenance, Self::AllocExtra>),
+        (MemoryKind<MiriMemoryKind>, Allocation<Provenance, Self::AllocExtra, Self::Bytes>),
     >;
 
     const GLOBAL_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Global);
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index 3da4fed33e1..ea5780f66d7 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -138,8 +138,20 @@ function valueCheck(fullPath, expected, result, error_text, queryName) {
                 error_text.push('==> Unknown key "' + key + '"');
                 break;
             }
+            let result_v = result[key];
+            if (result_v !== null && key === "error") {
+                result_v.forEach((value, index) => {
+                    value = value.split("&nbsp;").join(" ");
+                    if (index % 2 === 1) {
+                        result_v[index] = "`" + value + "`";
+                    } else {
+                        result_v[index] = value;
+                    }
+                });
+                result_v = result_v.join("");
+            }
             const obj_path = fullPath + (fullPath.length > 0 ? '.' : '') + key;
-            valueCheck(obj_path, expected[key], result[key], error_text, queryName);
+            valueCheck(obj_path, expected[key], result_v, error_text, queryName);
         }
     } else {
         expectedValue = JSON.stringify(expected);
diff --git a/src/version b/src/version
index 49349856550..832e9afb6c1 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.69.0
+1.70.0
diff --git a/tests/codegen/array-equality.rs b/tests/codegen/array-equality.rs
index cd5e82a9205..abfe295f8b6 100644
--- a/tests/codegen/array-equality.rs
+++ b/tests/codegen/array-equality.rs
@@ -1,4 +1,4 @@
-// compile-flags: -O
+// compile-flags: -O -Z merge-functions=disabled
 // only-x86_64
 
 #![crate_type = "lib"]
@@ -43,6 +43,15 @@ pub fn array_eq_long(a: &[u16; 1234], b: &[u16; 1234]) -> bool {
     a == b
 }
 
+// CHECK-LABEL: @array_char_eq
+#[no_mangle]
+pub fn array_char_eq(a: [char; 2], b: [char; 2]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i64 %0, %1
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    a == b
+}
+
 // CHECK-LABEL: @array_eq_zero_short(i48
 #[no_mangle]
 pub fn array_eq_zero_short(x: [u16; 3]) -> bool {
@@ -52,6 +61,25 @@ pub fn array_eq_zero_short(x: [u16; 3]) -> bool {
     x == [0; 3]
 }
 
+// CHECK-LABEL: @array_eq_none_short(i40
+#[no_mangle]
+pub fn array_eq_none_short(x: [Option<std::num::NonZeroU8>; 5]) -> bool {
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %[[EQ:.+]] = icmp eq i40 %0, 0
+    // CHECK-NEXT: ret i1 %[[EQ]]
+    x == [None; 5]
+}
+
+// CHECK-LABEL: @array_eq_zero_nested(
+#[no_mangle]
+pub fn array_eq_zero_nested(x: [[u8; 3]; 3]) -> bool {
+    // CHECK: %[[VAL:.+]] = load i72
+    // CHECK-SAME: align 1
+    // CHECK: %[[EQ:.+]] = icmp eq i72 %[[VAL]], 0
+    // CHECK: ret i1 %[[EQ]]
+    x == [[0; 3]; 3]
+}
+
 // CHECK-LABEL: @array_eq_zero_mid(
 #[no_mangle]
 pub fn array_eq_zero_mid(x: [u16; 8]) -> bool {
diff --git a/tests/codegen/consts.rs b/tests/codegen/consts.rs
index d0418d11142..dd22fd0f7e8 100644
--- a/tests/codegen/consts.rs
+++ b/tests/codegen/consts.rs
@@ -9,11 +9,11 @@
 // CHECK: @STATIC = {{.*}}, align 4
 
 // This checks the constants from inline_enum_const
-// CHECK: @alloc12 = {{.*}}, align 2
+// CHECK: @alloc_76bfe2f13a3e3b01074971d122eac57e = {{.*}}, align 2
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@alloc[0-9]+]] = {{.*}}, align 4
+// CHECK: [[LOW_HIGH:@alloc_[a-f0-9]+]] = {{.*}}, align 4
 
 #[derive(Copy, Clone)]
 // repr(i16) is required for the {low,high}_align_const test
diff --git a/tests/codegen/option-as-slice.rs b/tests/codegen/option-as-slice.rs
new file mode 100644
index 00000000000..d5077dbf6cc
--- /dev/null
+++ b/tests/codegen/option-as-slice.rs
@@ -0,0 +1,28 @@
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "lib"]
+#![feature(option_as_slice)]
+
+extern crate core;
+
+use core::num::NonZeroU64;
+use core::option::Option;
+
+// CHECK-LABEL: @u64_opt_as_slice
+#[no_mangle]
+pub fn u64_opt_as_slice(o: &Option<u64>) -> &[u64] {
+    // CHECK: start:
+    // CHECK-NOT: select
+    // CHECK: ret
+    o.as_slice()
+}
+
+// CHECK-LABEL: @nonzero_u64_opt_as_slice
+#[no_mangle]
+pub fn nonzero_u64_opt_as_slice(o: &Option<NonZeroU64>) -> &[NonZeroU64] {
+    // CHECK: start:
+    // CHECK-NOT: select
+    // CHECK: ret
+    o.as_slice()
+}
diff --git a/tests/codegen/remap_path_prefix/main.rs b/tests/codegen/remap_path_prefix/main.rs
index 78ebbccfce1..6c0cd6997d0 100644
--- a/tests/codegen/remap_path_prefix/main.rs
+++ b/tests/codegen/remap_path_prefix/main.rs
@@ -12,7 +12,7 @@ mod aux_mod;
 include!("aux_mod.rs");
 
 // Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
+// CHECK: @alloc_92a59126a55aa3c0019b6c8a007fe001 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
 pub static FILE_PATH: &'static str = file!();
 
 fn main() {
diff --git a/tests/codegen/slice-ref-equality.rs b/tests/codegen/slice-ref-equality.rs
index 47fde12bf30..8f0adab35e7 100644
--- a/tests/codegen/slice-ref-equality.rs
+++ b/tests/codegen/slice-ref-equality.rs
@@ -1,7 +1,10 @@
-// compile-flags: -C opt-level=3 -Zmerge-functions=disabled
+// compile-flags: -O -Zmerge-functions=disabled
+// ignore-debug (the extra assertions get in the way)
 
 #![crate_type = "lib"]
 
+use std::num::{NonZeroI16, NonZeroU32};
+
 // #71602 reported a simple array comparison just generating a loop.
 // This was originally fixed by ensuring it generates a single bcmp,
 // but we now generate it as a load+icmp instead. `is_zero_slice` was
@@ -36,3 +39,54 @@ pub fn is_zero_array(data: &[u8; 4]) -> bool {
     // CHECK-NEXT: ret i1 %[[EQ]]
     *data == [0; 4]
 }
+
+// The following test the extra specializations to make sure that slice
+// equality for non-byte types also just emit a `bcmp`, not a loop.
+
+// CHECK-LABEL: @eq_slice_of_nested_u8(
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
+#[no_mangle]
+fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool {
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %1, 3
+    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i8\*|ptr}}
+    // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
+    x == y
+}
+
+// CHECK-LABEL: @eq_slice_of_i32(
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
+#[no_mangle]
+fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool {
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
+    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
+    // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
+    x == y
+}
+
+// CHECK-LABEL: @eq_slice_of_nonzero(
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
+#[no_mangle]
+fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool {
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
+    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i32\*|ptr}}
+    // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
+    x == y
+}
+
+// CHECK-LABEL: @eq_slice_of_option_of_nonzero(
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
+#[no_mangle]
+fn eq_slice_of_option_of_nonzero(x: &[Option<NonZeroI16>], y: &[Option<NonZeroI16>]) -> bool {
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 1
+    // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}({{i16\*|ptr}}
+    // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
+    x == y
+}
diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs
index 0f1b29ca79b..aa7fab7fb17 100644
--- a/tests/codegen/thread-local.rs
+++ b/tests/codegen/thread-local.rs
@@ -4,6 +4,7 @@
 // ignore-wasm globals are used instead of thread locals
 // ignore-emscripten globals are used instead of thread locals
 // ignore-android does not use #[thread_local]
+// ignore-nto does not use #[thread_local]
 
 #![crate_type = "lib"]
 
diff --git a/tests/debuginfo/captured-fields-1.rs b/tests/debuginfo/captured-fields-1.rs
index afbf942d404..b71734c2354 100644
--- a/tests/debuginfo/captured-fields-1.rs
+++ b/tests/debuginfo/captured-fields-1.rs
@@ -1,5 +1,5 @@
 // compile-flags:-g
-
+// edition:2021
 // === GDB TESTS ===================================================================================
 
 // gdb-command:run
@@ -44,7 +44,6 @@
 // lldbg-check:(captured_fields_1::main::{closure_env#5}) $5 = { my_var = { my_field1 = 11 my_field2 = 22 } }
 // lldb-command:continue
 
-#![feature(capture_disjoint_fields)]
 #![allow(unused)]
 
 struct MyStruct {
diff --git a/tests/debuginfo/captured-fields-2.rs b/tests/debuginfo/captured-fields-2.rs
index c872354a924..8d463fb2451 100644
--- a/tests/debuginfo/captured-fields-2.rs
+++ b/tests/debuginfo/captured-fields-2.rs
@@ -1,5 +1,5 @@
 // compile-flags:-g
-
+// edition:2021
 // === GDB TESTS ===================================================================================
 
 // gdb-command:run
@@ -20,7 +20,6 @@
 // lldbg-check:(unsigned int) $1 = 22
 // lldb-command:continue
 
-#![feature(capture_disjoint_fields)]
 #![allow(unused)]
 
 struct MyStruct {
@@ -29,10 +28,7 @@ struct MyStruct {
 }
 
 fn main() {
-    let mut my_var = MyStruct {
-        my_field1: 11,
-        my_field2: 22,
-    };
+    let mut my_var = MyStruct { my_field1: 11, my_field2: 22 };
     let my_ref = &mut my_var;
 
     let test = || {
diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
new file mode 100644
index 00000000000..61a934685cd
--- /dev/null
+++ b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
@@ -0,0 +1,85 @@
+- // MIR for `main` before ElaborateDrops
++ // MIR for `main` after ElaborateDrops
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/basic_assignment.rs:+0:11: +0:11
+      let _1: bool;                        // in scope 0 at $DIR/basic_assignment.rs:+1:9: +1:17
+      let mut _3: bool;                    // in scope 0 at $DIR/basic_assignment.rs:+6:16: +6:24
+      let mut _6: std::option::Option<std::boxed::Box<u32>>; // in scope 0 at $DIR/basic_assignment.rs:+13:14: +13:20
+      scope 1 {
+          debug nodrop_x => _1;            // in scope 1 at $DIR/basic_assignment.rs:+1:9: +1:17
+          let _2: bool;                    // in scope 1 at $DIR/basic_assignment.rs:+2:9: +2:17
+          scope 2 {
+              debug nodrop_y => _2;        // in scope 2 at $DIR/basic_assignment.rs:+2:9: +2:17
+              let _4: std::option::Option<std::boxed::Box<u32>>; // in scope 2 at $DIR/basic_assignment.rs:+8:9: +8:15
+              scope 3 {
+                  debug drop_x => _4;      // in scope 3 at $DIR/basic_assignment.rs:+8:9: +8:15
+                  let _5: std::option::Option<std::boxed::Box<u32>>; // in scope 3 at $DIR/basic_assignment.rs:+9:9: +9:15
+                  scope 4 {
+                      debug drop_y => _5;  // in scope 4 at $DIR/basic_assignment.rs:+9:9: +9:15
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/basic_assignment.rs:+1:9: +1:17
+          _1 = const false;                // scope 0 at $DIR/basic_assignment.rs:+1:20: +1:25
+          StorageLive(_2);                 // scope 1 at $DIR/basic_assignment.rs:+2:9: +2:17
+          StorageLive(_3);                 // scope 2 at $DIR/basic_assignment.rs:+6:16: +6:24
+          _3 = _1;                         // scope 2 at $DIR/basic_assignment.rs:+6:16: +6:24
+          _2 = move _3;                    // scope 2 at $DIR/basic_assignment.rs:+6:5: +6:24
+          StorageDead(_3);                 // scope 2 at $DIR/basic_assignment.rs:+6:23: +6:24
+          StorageLive(_4);                 // scope 2 at $DIR/basic_assignment.rs:+8:9: +8:15
+          _4 = Option::<Box<u32>>::None;   // scope 2 at $DIR/basic_assignment.rs:+8:36: +8:40
+          StorageLive(_5);                 // scope 3 at $DIR/basic_assignment.rs:+9:9: +9:15
+          StorageLive(_6);                 // scope 4 at $DIR/basic_assignment.rs:+13:14: +13:20
+          _6 = move _4;                    // scope 4 at $DIR/basic_assignment.rs:+13:14: +13:20
+-         drop(_5) -> [return: bb1, unwind: bb2]; // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
++         goto -> bb1;                     // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
+      }
+  
+      bb1: {
+          _5 = move _6;                    // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
+-         drop(_6) -> [return: bb3, unwind: bb6]; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
++         goto -> bb3;                     // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
+      }
+  
+      bb2 (cleanup): {
+          _5 = move _6;                    // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
+          drop(_6) -> bb6;                 // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
+      }
+  
+      bb3: {
+          StorageDead(_6);                 // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
+          _0 = const ();                   // scope 0 at $DIR/basic_assignment.rs:+0:11: +14:2
+          drop(_5) -> [return: bb4, unwind: bb7]; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
+      }
+  
+      bb4: {
+          StorageDead(_5);                 // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
+-         drop(_4) -> bb5;                 // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
++         goto -> bb5;                     // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
+      }
+  
+      bb5: {
+          StorageDead(_4);                 // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
+          StorageDead(_2);                 // scope 1 at $DIR/basic_assignment.rs:+14:1: +14:2
+          StorageDead(_1);                 // scope 0 at $DIR/basic_assignment.rs:+14:1: +14:2
+          return;                          // scope 0 at $DIR/basic_assignment.rs:+14:2: +14:2
+      }
+  
+      bb6 (cleanup): {
+          drop(_5) -> bb7;                 // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
+      }
+  
+      bb7 (cleanup): {
+-         drop(_4) -> bb8;                 // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
++         goto -> bb8;                     // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
+      }
+  
+      bb8 (cleanup): {
+          resume;                          // scope 0 at $DIR/basic_assignment.rs:+0:1: +14:2
+      }
+  }
+  
diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
index 1f099cd5e83..f20b534259a 100644
--- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after SimplifyCfg-initial
 
 | User Type Annotations
-| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<std::boxed::Box<u32>>) }, span: $DIR/basic_assignment.rs:18:17: 18:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
-| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<std::boxed::Box<u32>>) }, span: $DIR/basic_assignment.rs:18:17: 18:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
+| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<std::boxed::Box<u32>>) }, span: $DIR/basic_assignment.rs:20:17: 20:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
+| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<std::boxed::Box<u32>>) }, span: $DIR/basic_assignment.rs:20:17: 20:33, inferred_ty: std::option::Option<std::boxed::Box<u32>>
 |
 fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/basic_assignment.rs:+0:11: +0:11
@@ -41,35 +41,37 @@ fn main() -> () {
         StorageLive(_5);                 // scope 3 at $DIR/basic_assignment.rs:+9:9: +9:15
         StorageLive(_6);                 // scope 4 at $DIR/basic_assignment.rs:+13:14: +13:20
         _6 = move _4;                    // scope 4 at $DIR/basic_assignment.rs:+13:14: +13:20
-        replace(_5 <- move _6) -> [return: bb1, unwind: bb5]; // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
+        drop(_5) -> [return: bb1, unwind: bb2]; // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
     }
 
     bb1: {
-        drop(_6) -> [return: bb2, unwind: bb6]; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
+        _5 = move _6;                    // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
+        drop(_6) -> [return: bb3, unwind: bb6]; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
     }
 
-    bb2: {
+    bb2 (cleanup): {
+        _5 = move _6;                    // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
+        drop(_6) -> bb6;                 // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
+    }
+
+    bb3: {
         StorageDead(_6);                 // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
         _0 = const ();                   // scope 0 at $DIR/basic_assignment.rs:+0:11: +14:2
-        drop(_5) -> [return: bb3, unwind: bb7]; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
+        drop(_5) -> [return: bb4, unwind: bb7]; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
     }
 
-    bb3: {
+    bb4: {
         StorageDead(_5);                 // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
-        drop(_4) -> [return: bb4, unwind: bb8]; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
+        drop(_4) -> [return: bb5, unwind: bb8]; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
     }
 
-    bb4: {
+    bb5: {
         StorageDead(_4);                 // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
         StorageDead(_2);                 // scope 1 at $DIR/basic_assignment.rs:+14:1: +14:2
         StorageDead(_1);                 // scope 0 at $DIR/basic_assignment.rs:+14:1: +14:2
         return;                          // scope 0 at $DIR/basic_assignment.rs:+14:2: +14:2
     }
 
-    bb5 (cleanup): {
-        drop(_6) -> bb6;                 // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
-    }
-
     bb6 (cleanup): {
         drop(_5) -> bb7;                 // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
     }
diff --git a/tests/mir-opt/basic_assignment.rs b/tests/mir-opt/basic_assignment.rs
index ac350271e9f..92434e44aa9 100644
--- a/tests/mir-opt/basic_assignment.rs
+++ b/tests/mir-opt/basic_assignment.rs
@@ -1,5 +1,7 @@
+// needs-unwind
 // this tests move up progration, which is not yet implemented
 
+// EMIT_MIR basic_assignment.main.ElaborateDrops.diff
 // EMIT_MIR basic_assignment.main.SimplifyCfg-initial.after.mir
 
 // Check codegen for assignments (`a = b`) where the left-hand-side is
diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
index 79e3d073be5..3dd1a9bbab5 100644
--- a/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
+++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
@@ -38,37 +38,39 @@
           StorageLive(_5);                 // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
 +         _6 = const false;                // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
           _5 = move _1;                    // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
--         replace(_2 <- move _5) -> [return: bb2, unwind: bb6]; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
-+         goto -> bb12;                    // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
+-         drop(_2) -> [return: bb2, unwind: bb3]; // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
++         goto -> bb2;                     // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
       }
   
       bb2: {
--         drop(_5) -> [return: bb3, unwind: bb8]; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
-+         goto -> bb3;                     // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
+          _2 = move _5;                    // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
+-         drop(_5) -> [return: bb4, unwind: bb8]; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
++         goto -> bb4;                     // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
+      }
+  
+      bb3 (cleanup): {
+          _2 = move _5;                    // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
+          drop(_5) -> bb8;                 // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
       }
   
-      bb3: {
+      bb4: {
           StorageDead(_5);                 // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
           _0 = const ();                   // scope 0 at $DIR/issue_41110.rs:+0:15: +5:2
-          drop(_2) -> [return: bb4, unwind: bb9]; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
+          drop(_2) -> [return: bb5, unwind: bb9]; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   
-      bb4: {
+      bb5: {
           StorageDead(_2);                 // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
--         drop(_1) -> bb5;                 // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
-+         goto -> bb5;                     // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+-         drop(_1) -> bb6;                 // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++         goto -> bb6;                     // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   
-      bb5: {
+      bb6: {
 +         _6 = const false;                // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
           StorageDead(_1);                 // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
           return;                          // scope 0 at $DIR/issue_41110.rs:+5:2: +5:2
       }
   
-      bb6 (cleanup): {
-          drop(_5) -> bb8;                 // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
-      }
-  
       bb7 (cleanup): {
 -         drop(_4) -> bb8;                 // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
 +         goto -> bb8;                     // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
@@ -81,7 +83,7 @@
   
       bb9 (cleanup): {
 -         drop(_1) -> bb10;                // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
-+         goto -> bb14;                    // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++         goto -> bb12;                    // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   
       bb10 (cleanup): {
@@ -89,21 +91,11 @@
 +     }
 + 
 +     bb11 (cleanup): {
-+         _2 = move _5;                    // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
-+         goto -> bb10;                    // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
-+     }
-+ 
-+     bb12: {
-+         _2 = move _5;                    // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
-+         goto -> bb2;                     // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
-+     }
-+ 
-+     bb13 (cleanup): {
 +         drop(_1) -> bb10;                // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
 +     }
 + 
-+     bb14 (cleanup): {
-+         switchInt(_6) -> [0: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++     bb12 (cleanup): {
++         switchInt(_6) -> [0: bb10, otherwise: bb11]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   }
   
diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
index 257f0b1e6e8..4e38659a90b 100644
--- a/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
+++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
@@ -34,7 +34,7 @@
       }
   
       bb1: {
-          switchInt(move _2) -> [0: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
+          switchInt(move _2) -> [0: bb8, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
       }
   
       bb2: {
@@ -43,47 +43,56 @@
           _4 = K;                          // scope 1 at $DIR/issue_41888.rs:+3:18: +3:19
           _3 = E::F(move _4);              // scope 1 at $DIR/issue_41888.rs:+3:13: +3:20
           StorageDead(_4);                 // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
--         replace(_1 <- move _3) -> [return: bb3, unwind: bb10]; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+         goto -> bb14;                    // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
+-         drop(_1) -> [return: bb3, unwind: bb4]; // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++         goto -> bb3;                     // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
       }
   
       bb3: {
--         drop(_3) -> [return: bb4, unwind: bb11]; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
-+         goto -> bb4;                     // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
++         _7 = const true;                 // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++         _8 = const true;                 // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
++         _9 = const true;                 // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
+          _1 = move _3;                    // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
+-         drop(_3) -> [return: bb5, unwind: bb11]; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
++         goto -> bb5;                     // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
+      }
+  
+      bb4 (cleanup): {
+          _1 = move _3;                    // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
+          drop(_3) -> bb11;                // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
       }
   
-      bb4: {
+      bb5: {
           StorageDead(_3);                 // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
           _5 = discriminant(_1);           // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
-          switchInt(move _5) -> [0: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
+          switchInt(move _5) -> [0: bb6, otherwise: bb7]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
       }
   
-      bb5: {
+      bb6: {
           StorageLive(_6);                 // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
 +         _9 = const false;                // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
           _6 = move ((_1 as F).0: K);      // scope 2 at $DIR/issue_41888.rs:+4:21: +4:23
           _0 = const ();                   // scope 2 at $DIR/issue_41888.rs:+4:29: +7:10
           StorageDead(_6);                 // scope 1 at $DIR/issue_41888.rs:+7:9: +7:10
-          goto -> bb8;                     // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10
+          goto -> bb9;                     // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10
       }
   
-      bb6: {
+      bb7: {
           _0 = const ();                   // scope 1 at $DIR/issue_41888.rs:+7:10: +7:10
-          goto -> bb8;                     // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10
+          goto -> bb9;                     // scope 1 at $DIR/issue_41888.rs:+4:9: +7:10
       }
   
-      bb7: {
+      bb8: {
           _0 = const ();                   // scope 1 at $DIR/issue_41888.rs:+8:6: +8:6
-          goto -> bb8;                     // scope 1 at $DIR/issue_41888.rs:+2:5: +8:6
+          goto -> bb9;                     // scope 1 at $DIR/issue_41888.rs:+2:5: +8:6
       }
   
-      bb8: {
+      bb9: {
           StorageDead(_2);                 // scope 1 at $DIR/issue_41888.rs:+8:5: +8:6
--         drop(_1) -> bb9;                 // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         goto -> bb20;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+-         drop(_1) -> bb10;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         goto -> bb18;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
       }
   
-      bb9: {
+      bb10: {
 +         _7 = const false;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +         _8 = const false;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +         _9 = const false;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
@@ -91,10 +100,6 @@
           return;                          // scope 0 at $DIR/issue_41888.rs:+9:2: +9:2
       }
   
-      bb10 (cleanup): {
-          drop(_3) -> bb11;                // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
-      }
-  
       bb11 (cleanup): {
 -         drop(_1) -> bb12;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +         goto -> bb12;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
@@ -104,55 +109,39 @@
           resume;                          // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2
 +     }
 + 
-+     bb13 (cleanup): {
-+         _7 = const true;                 // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+         _8 = const true;                 // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+         _9 = const true;                 // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+         _1 = move _3;                    // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+         goto -> bb12;                    // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+     }
-+ 
-+     bb14: {
-+         _7 = const true;                 // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+         _8 = const true;                 // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+         _9 = const true;                 // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+         _1 = move _3;                    // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+         goto -> bb3;                     // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-+     }
-+ 
-+     bb15: {
++     bb13: {
 +         _7 = const false;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         goto -> bb9;                     // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         goto -> bb10;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb16 (cleanup): {
++     bb14 (cleanup): {
 +         goto -> bb12;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb17: {
-+         drop(_1) -> [return: bb15, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb15: {
++         drop(_1) -> [return: bb13, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb18 (cleanup): {
++     bb16 (cleanup): {
 +         drop(_1) -> bb12;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb19: {
++     bb17: {
 +         _10 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         switchInt(move _10) -> [0: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         switchInt(move _10) -> [0: bb13, otherwise: bb15]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb20: {
-+         switchInt(_7) -> [0: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb18: {
++         switchInt(_7) -> [0: bb13, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb21 (cleanup): {
++     bb19 (cleanup): {
 +         _11 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         switchInt(move _11) -> [0: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         switchInt(move _11) -> [0: bb14, otherwise: bb16]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb22 (cleanup): {
-+         switchInt(_7) -> [0: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb20 (cleanup): {
++         switchInt(_7) -> [0: bb12, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
       }
   }
   
diff --git a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
index 210f178a0a9..56cb9166c37 100644
--- a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
@@ -28,21 +28,21 @@ fn main() -> () {
         StorageDead(_5);                 // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:28: +2:29
         StorageLive(_6);                 // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
         _6 = move (_1.0: Aligned);       // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
-        drop(_6) -> [return: bb4, unwind: bb3]; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
+        drop(_6) -> [return: bb4, unwind: bb1]; // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
     }
 
-    bb1: {
-        StorageDead(_1);                 // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
-        return;                          // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:2: +3:2
+    bb1 (cleanup): {
+        (_1.0: Aligned) = move _4;       // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
+        drop(_1) -> bb3;                 // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
     }
 
-    bb2 (cleanup): {
-        resume;                          // scope 0 at $DIR/packed_struct_drop_aligned.rs:+0:1: +3:2
+    bb2: {
+        StorageDead(_1);                 // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
+        return;                          // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:2: +3:2
     }
 
     bb3 (cleanup): {
-        (_1.0: Aligned) = move _4;       // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
-        drop(_1) -> bb2;                 // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
+        resume;                          // scope 0 at $DIR/packed_struct_drop_aligned.rs:+0:1: +3:2
     }
 
     bb4: {
@@ -50,6 +50,6 @@ fn main() -> () {
         (_1.0: Aligned) = move _4;       // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
         StorageDead(_4);                 // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:28: +2:29
         _0 = const ();                   // scope 0 at $DIR/packed_struct_drop_aligned.rs:+0:11: +3:2
-        drop(_1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
+        drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
     }
 }
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure.txt b/tests/run-make/coverage-reports/expected_show_coverage.closure.txt
index e463099a5ee..002ecec3b91 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.closure.txt
+++ b/tests/run-make/coverage-reports/expected_show_coverage.closure.txt
@@ -29,8 +29,8 @@
    29|      1|    some_string = Some(String::from("the string content"));
    30|      1|    let
    31|      1|        a
-   32|      1|    =
-   33|      1|        ||
+   32|       |    =
+   33|       |        ||
    34|      0|    {
    35|      0|        let mut countdown = 0;
    36|      0|        if is_false {
diff --git a/tests/rustdoc-gui/search-error.goml b/tests/rustdoc-gui/search-error.goml
new file mode 100644
index 00000000000..2a10a647b53
--- /dev/null
+++ b/tests/rustdoc-gui/search-error.goml
@@ -0,0 +1,39 @@
+// Checks that the crate search filtering is handled correctly and changes the results.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds"
+show-text: true
+
+define-function: (
+    "check-colors",
+    (theme, error_background),
+    block {
+        // Setting the theme.
+        local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        // We reload the page so the local storage settings are being used.
+        reload:
+
+        wait-for: "#search .error code"
+        assert-css: ("#search .error code", {"background-color": |error_background|})
+    }
+)
+
+call-function: (
+    "check-colors",
+    {
+        "theme": "ayu",
+        "error_background": "rgb(79, 76, 76)",
+    },
+)
+call-function: (
+    "check-colors",
+    {
+        "theme": "dark",
+        "error_background": "rgb(72, 72, 72)",
+    },
+)
+call-function: (
+    "check-colors",
+    {
+        "theme": "light",
+        "error_background": "rgb(208, 204, 204)",
+    },
+)
diff --git a/tests/rustdoc-js-std/option-type-signatures.js b/tests/rustdoc-js-std/option-type-signatures.js
new file mode 100644
index 00000000000..dee4819e81a
--- /dev/null
+++ b/tests/rustdoc-js-std/option-type-signatures.js
@@ -0,0 +1,7 @@
+const QUERY = 'option, fnonce -> option';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'std::option::Option', 'name': 'map' },
+    ],
+};
diff --git a/tests/rustdoc-js-std/parser-errors.js b/tests/rustdoc-js-std/parser-errors.js
index dc42031e05f..98c6f27ca61 100644
--- a/tests/rustdoc-js-std/parser-errors.js
+++ b/tests/rustdoc-js-std/parser-errors.js
@@ -37,6 +37,9 @@ const QUERY = [
     "mod : :",
     "a!a",
     "a!!",
+    "mod:a!",
+    "a!::a",
+    "a<",
 ];
 
 const PARSED = [
@@ -65,7 +68,7 @@ const PARSED = [
         returned: [],
         typeFilter: -1,
         userQuery: "a<\"p\">",
-        error: "`\"` cannot be used in generics",
+        error: "Unexpected `\"` in generics",
     },
     {
         elems: [],
@@ -371,7 +374,7 @@ const PARSED = [
         returned: [],
         typeFilter: -1,
         userQuery: "a!a",
-        error: '`!` can only be at the end of an ident',
+        error: 'Unexpected `!`: it can only be at the end of an ident',
     },
     {
         elems: [],
@@ -382,4 +385,31 @@ const PARSED = [
         userQuery: "a!!",
         error: 'Cannot have more than one `!` in an ident',
     },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "mod:a!",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "mod:a!",
+        error: 'Invalid search type: macro `!` and `mod` both specified',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a!::a",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a!::a",
+        error: 'Cannot have associated items in macros',
+    },
+    {
+        elems: [],
+        foundElems: 0,
+        original: "a<",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "a<",
+        error: "Unclosed `<`",
+    },
 ];
diff --git a/tests/rustdoc-js-std/parser-filter.js b/tests/rustdoc-js-std/parser-filter.js
index e5a87a415ac..01f65b478f8 100644
--- a/tests/rustdoc-js-std/parser-filter.js
+++ b/tests/rustdoc-js-std/parser-filter.js
@@ -1,4 +1,4 @@
-const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo'];
+const QUERY = ['fn:foo', 'enum : foo', 'macro<f>:foo', 'macro!', 'macro:mac!', 'a::mac!'];
 
 const PARSED = [
     {
@@ -40,4 +40,49 @@ const PARSED = [
         userQuery: "macro<f>:foo",
         error: "Unexpected `:`",
     },
+    {
+        elems: [{
+            name: "macro",
+            fullPath: ["macro"],
+            pathWithoutLast: [],
+            pathLast: "macro",
+            generics: [],
+        }],
+        foundElems: 1,
+        original: "macro!",
+        returned: [],
+        typeFilter: 14,
+        userQuery: "macro!",
+        error: null,
+    },
+    {
+        elems: [{
+            name: "mac",
+            fullPath: ["mac"],
+            pathWithoutLast: [],
+            pathLast: "mac",
+            generics: [],
+        }],
+        foundElems: 1,
+        original: "macro:mac!",
+        returned: [],
+        typeFilter: 14,
+        userQuery: "macro:mac!",
+        error: null,
+    },
+    {
+        elems: [{
+            name: "a::mac",
+            fullPath: ["a", "mac"],
+            pathWithoutLast: ["a"],
+            pathLast: "mac",
+            generics: [],
+        }],
+        foundElems: 1,
+        original: "a::mac!",
+        returned: [],
+        typeFilter: 14,
+        userQuery: "a::mac!",
+        error: null,
+    },
 ];
diff --git a/tests/rustdoc-js-std/parser-ident.js b/tests/rustdoc-js-std/parser-ident.js
index 4b5ab01ac76..6c17d00f16e 100644
--- a/tests/rustdoc-js-std/parser-ident.js
+++ b/tests/rustdoc-js-std/parser-ident.js
@@ -3,6 +3,7 @@ const QUERY = [
     "!",
     "a!",
     "a!::b",
+    "!::b",
     "a!::b!",
 ];
 
@@ -47,47 +48,50 @@ const PARSED = [
     },
     {
         elems: [{
-            name: "a!",
-            fullPath: ["a!"],
+            name: "a",
+            fullPath: ["a"],
             pathWithoutLast: [],
-            pathLast: "a!",
+            pathLast: "a",
             generics: [],
         }],
         foundElems: 1,
         original: "a!",
         returned: [],
-        typeFilter: -1,
+        typeFilter: 14,
         userQuery: "a!",
         error: null,
     },
     {
-        elems: [{
-            name: "a!::b",
-            fullPath: ["a!", "b"],
-            pathWithoutLast: ["a!"],
-            pathLast: "b",
-            generics: [],
-        }],
-        foundElems: 1,
+        elems: [],
+        foundElems: 0,
         original: "a!::b",
         returned: [],
         typeFilter: -1,
         userQuery: "a!::b",
-        error: null,
+        error: "Cannot have associated items in macros",
     },
     {
         elems: [{
-            name: "a!::b!",
-            fullPath: ["a!", "b!"],
-            pathWithoutLast: ["a!"],
-            pathLast: "b!",
+            name: "!::b",
+            fullPath: ["!", "b"],
+            pathWithoutLast: ["!"],
+            pathLast: "b",
             generics: [],
         }],
         foundElems: 1,
+        original: "!::b",
+        returned: [],
+        typeFilter: -1,
+        userQuery: "!::b",
+        error: null,
+    },
+    {
+        elems: [],
+        foundElems: 0,
         original: "a!::b!",
         returned: [],
         typeFilter: -1,
         userQuery: "a!::b!",
-        error: null,
+        error: "Cannot have associated items in macros",
     },
 ];
diff --git a/tests/rustdoc-js/macro-search.js b/tests/rustdoc-js/macro-search.js
new file mode 100644
index 00000000000..2b179ce146b
--- /dev/null
+++ b/tests/rustdoc-js/macro-search.js
@@ -0,0 +1,10 @@
+// exact-check
+
+const QUERY = 'abracadabra!';
+
+const EXPECTED = {
+    'others': [
+        { 'path': 'macro_search', 'name': 'abracadabra' },
+        { 'path': 'macro_search', 'name': 'abracadabra_b' },
+    ],
+};
diff --git a/tests/rustdoc-js/macro-search.rs b/tests/rustdoc-js/macro-search.rs
new file mode 100644
index 00000000000..dc397490cf5
--- /dev/null
+++ b/tests/rustdoc-js/macro-search.rs
@@ -0,0 +1,10 @@
+#[macro_export]
+macro_rules! abracadabra {
+    () => {}
+}
+#[macro_export]
+macro_rules! abracadabra_b {
+    () => {}
+}
+pub fn abracadabra() {}
+pub fn abracadabra_c() {}
diff --git a/tests/rustdoc-js/where-clause.js b/tests/rustdoc-js/where-clause.js
new file mode 100644
index 00000000000..6cb42a455a3
--- /dev/null
+++ b/tests/rustdoc-js/where-clause.js
@@ -0,0 +1,19 @@
+const QUERY = ['trait<nested>', '-> trait<nested>', 't1, t2'];
+
+const EXPECTED = [
+    {
+        'in_args': [
+           { 'path': 'where_clause', 'name': 'abracadabra' },
+        ],
+    },
+    {
+        'others': [
+            { 'path': 'where_clause', 'name': 'alacazam' },
+        ],
+    },
+    {
+        'others': [
+            { 'path': 'where_clause', 'name': 'presto' },
+        ],
+    },
+];
diff --git a/tests/rustdoc-js/where-clause.rs b/tests/rustdoc-js/where-clause.rs
new file mode 100644
index 00000000000..808561feee2
--- /dev/null
+++ b/tests/rustdoc-js/where-clause.rs
@@ -0,0 +1,16 @@
+pub struct Nested;
+
+pub trait Trait<T> {
+    fn thank_you(x: T);
+}
+
+pub fn abracadabra<X>(_: X) where X: Trait<Nested> {}
+
+pub fn alacazam<X>() -> X where X: Trait<Nested> {}
+
+pub trait T1 {}
+pub trait T2<'a, T> {
+    fn please(_: &'a T);
+}
+
+pub fn presto<A, B>(_: A, _: B) where A: T1, B: for <'b> T2<'b, Nested> {}
diff --git a/tests/rustdoc-ui/z-help.stdout b/tests/rustdoc-ui/z-help.stdout
index 6aa9785f44e..79e6b94f1ac 100644
--- a/tests/rustdoc-ui/z-help.stdout
+++ b/tests/rustdoc-ui/z-help.stdout
@@ -87,6 +87,7 @@
     -Z                          llvm-plugins=val -- a list LLVM plugins to enable (space separated)
     -Z                       llvm-time-trace=val -- generate JSON tracing data file from LLVM data (default: no)
     -Z                       location-detail=val -- what location details should be tracked when using caller_location, either `none`, or a comma separated list of location details, for which valid options are `file`, `line`, and `column` (default: `file,line,column`)
+    -Z lower-impl-trait-in-trait-to-assoc-ty=val -- modify the lowering strategy for `impl Trait` in traits so that they are lowered to generic associated types
     -Z                                    ls=val -- list the symbols defined by a library crate (default: no)
     -Z                       macro-backtrace=val -- show macro backtraces (default: no)
     -Z           maximal-hir-to-mir-coverage=val -- save as much information as possible about the correspondence between MIR and HIR as source scopes (default: no)
diff --git a/tests/rustdoc/type-layout.rs b/tests/rustdoc/type-layout.rs
index 5e0a0411a62..bd88e73af5c 100644
--- a/tests/rustdoc/type-layout.rs
+++ b/tests/rustdoc/type-layout.rs
@@ -83,3 +83,11 @@ pub enum WithNiche {
     None,
     Some(std::num::NonZeroU32),
 }
+
+// @hasraw type_layout/enum.Uninhabited.html 'Size: '
+// @hasraw - '0 bytes (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>)'
+pub enum Uninhabited {}
+
+// @hasraw type_layout/struct.Uninhabited2.html 'Size: '
+// @hasraw - '8 bytes (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>)'
+pub struct Uninhabited2(std::convert::Infallible, u64);
diff --git a/tests/ui-toml/array_size_threshold/array_size_threshold.rs b/tests/ui-toml/array_size_threshold/array_size_threshold.rs
new file mode 100644
index 00000000000..7f623c7a9ec
--- /dev/null
+++ b/tests/ui-toml/array_size_threshold/array_size_threshold.rs
@@ -0,0 +1,10 @@
+#![allow(unused)]
+#![warn(clippy::large_const_arrays, clippy::large_stack_arrays)]
+
+const ABOVE: [u8; 11] = [0; 11];
+const BELOW: [u8; 10] = [0; 10];
+
+fn main() {
+    let above = [0u8; 11];
+    let below = [0u8; 10];
+}
diff --git a/tests/ui-toml/array_size_threshold/array_size_threshold.stderr b/tests/ui-toml/array_size_threshold/array_size_threshold.stderr
new file mode 100644
index 00000000000..ac017b20916
--- /dev/null
+++ b/tests/ui-toml/array_size_threshold/array_size_threshold.stderr
@@ -0,0 +1,29 @@
+error: large array defined as const
+  --> $DIR/array_size_threshold.rs:4:1
+   |
+LL | const ABOVE: [u8; 11] = [0; 11];
+   | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | help: make this a static item: `static`
+   |
+   = note: `-D clippy::large-const-arrays` implied by `-D warnings`
+
+error: allocating a local array larger than 10 bytes
+  --> $DIR/array_size_threshold.rs:4:25
+   |
+LL | const ABOVE: [u8; 11] = [0; 11];
+   |                         ^^^^^^^
+   |
+   = help: consider allocating on the heap with `vec![0; 11].into_boxed_slice()`
+   = note: `-D clippy::large-stack-arrays` implied by `-D warnings`
+
+error: allocating a local array larger than 10 bytes
+  --> $DIR/array_size_threshold.rs:8:17
+   |
+LL |     let above = [0u8; 11];
+   |                 ^^^^^^^^^
+   |
+   = help: consider allocating on the heap with `vec![0u8; 11].into_boxed_slice()`
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui-toml/array_size_threshold/clippy.toml b/tests/ui-toml/array_size_threshold/clippy.toml
new file mode 100644
index 00000000000..3f1fe9a1209
--- /dev/null
+++ b/tests/ui-toml/array_size_threshold/clippy.toml
@@ -0,0 +1 @@
+array-size-threshold = 10
diff --git a/tests/ui/abi/stack-probes-lto.rs b/tests/ui/abi/stack-probes-lto.rs
index 6d934538f4c..a455eef42ea 100644
--- a/tests/ui/abi/stack-probes-lto.rs
+++ b/tests/ui/abi/stack-probes-lto.rs
@@ -13,5 +13,6 @@
 // ignore-fuchsia no exception handler registered for segfault
 // compile-flags: -C lto
 // no-prefer-dynamic
+// ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino
 
 include!("stack-probes.rs");
diff --git a/tests/ui/abi/stack-probes.rs b/tests/ui/abi/stack-probes.rs
index e7b91644b3b..8dba54c3f81 100644
--- a/tests/ui/abi/stack-probes.rs
+++ b/tests/ui/abi/stack-probes.rs
@@ -9,6 +9,7 @@
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-fuchsia no exception handler registered for segfault
+// ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino
 
 use std::env;
 use std::mem::MaybeUninit;
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
new file mode 100644
index 00000000000..afd3db5e052
--- /dev/null
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
@@ -0,0 +1,71 @@
+// edition: 2021
+// known-bug: #108309
+
+#![feature(async_fn_in_trait)]
+#![feature(min_specialization)]
+
+struct MyStruct;
+
+trait MyTrait<T> {
+    async fn foo(_: T) -> &'static str;
+}
+
+impl<T> MyTrait<T> for MyStruct {
+    default async fn foo(_: T) -> &'static str {
+        "default"
+    }
+}
+
+impl MyTrait<i32> for MyStruct {
+    async fn foo(_: i32) -> &'static str {
+        "specialized"
+    }
+}
+
+async fn async_main() {
+    assert_eq!(MyStruct::foo(42).await, "specialized");
+    assert_eq!(indirection(42).await, "specialized");
+}
+
+async fn indirection<T>(x: T) -> &'static str {
+    //explicit type coercion is currently necessary
+    // because of https://github.com/rust-lang/rust/issues/67918
+    <MyStruct as MyTrait<T>>::foo(x).await
+}
+
+// ------------------------------------------------------------------------- //
+// Implementation Details Below...
+
+use std::future::Future;
+use std::pin::Pin;
+use std::task::*;
+
+pub fn noop_waker() -> Waker {
+    let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE);
+
+    // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld
+    unsafe { Waker::from_raw(raw) }
+}
+
+const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
+
+unsafe fn noop_clone(_p: *const ()) -> RawWaker {
+    RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE)
+}
+
+unsafe fn noop(_p: *const ()) {}
+
+fn main() {
+    let mut fut = async_main();
+
+    // Poll loop, just to test the future...
+    let waker = noop_waker();
+    let ctx = &mut Context::from_waker(&waker);
+
+    loop {
+        match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
+            Poll::Pending => {}
+            Poll::Ready(()) => break,
+        }
+    }
+}
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
new file mode 100644
index 00000000000..f71fd9980a2
--- /dev/null
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
@@ -0,0 +1,19 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/dont-project-to-specializable-projection.rs:4:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: async associated function in trait cannot be specialized
+  --> $DIR/dont-project-to-specializable-projection.rs:14:5
+   |
+LL |     default async fn foo(_: T) -> &'static str {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: specialization behaves in inconsistent and surprising ways with `#![feature(async_fn_in_trait)]`, and for now is disallowed
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/async-await/issues/issue-107280.rs b/tests/ui/async-await/issues/issue-107280.rs
new file mode 100644
index 00000000000..85fce87403a
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-107280.rs
@@ -0,0 +1,15 @@
+// edition:2021
+
+async fn foo() {
+    inner::<false>().await
+    //~^ ERROR: function takes 2 generic arguments but 1 generic argument was supplied
+    //~| ERROR: type inside `async fn` body must be known in this context
+    //~| ERROR: type inside `async fn` body must be known in this context
+    //~| ERROR: type inside `async fn` body must be known in this context
+    //~| ERROR: type inside `async fn` body must be known in this context
+    //~| ERROR: type inside `async fn` body must be known in this context
+}
+
+async fn inner<T, const PING: bool>() {}
+
+fn main() {}
diff --git a/tests/ui/async-await/issues/issue-107280.stderr b/tests/ui/async-await/issues/issue-107280.stderr
new file mode 100644
index 00000000000..dd3e10fcc18
--- /dev/null
+++ b/tests/ui/async-await/issues/issue-107280.stderr
@@ -0,0 +1,82 @@
+error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied
+  --> $DIR/issue-107280.rs:4:5
+   |
+LL |     inner::<false>().await
+   |     ^^^^^   ----- supplied 1 generic argument
+   |     |
+   |     expected 2 generic arguments
+   |
+note: function defined here, with 2 generic parameters: `T`, `PING`
+  --> $DIR/issue-107280.rs:13:10
+   |
+LL | async fn inner<T, const PING: bool>() {}
+   |          ^^^^^ -  ----------------
+help: add missing generic argument
+   |
+LL |     inner::<false, PING>().await
+   |                  ++++++
+
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/issue-107280.rs:4:5
+   |
+LL |     inner::<false>().await
+   |     ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/issue-107280.rs:4:21
+   |
+LL |     inner::<false>().await
+   |                     ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/issue-107280.rs:4:5
+   |
+LL |     inner::<false>().await
+   |     ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/issue-107280.rs:4:21
+   |
+LL |     inner::<false>().await
+   |                     ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/issue-107280.rs:4:5
+   |
+LL |     inner::<false>().await
+   |     ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/issue-107280.rs:4:21
+   |
+LL |     inner::<false>().await
+   |                     ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/issue-107280.rs:4:5
+   |
+LL |     inner::<false>().await
+   |     ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/issue-107280.rs:4:21
+   |
+LL |     inner::<false>().await
+   |                     ^^^^^^
+
+error[E0698]: type inside `async fn` body must be known in this context
+  --> $DIR/issue-107280.rs:4:5
+   |
+LL |     inner::<false>().await
+   |     ^^^^^^^^^^^^^^ cannot infer the value of const parameter `PING` declared on the function `inner`
+   |
+note: the type is part of the `async fn` body because of this `await`
+  --> $DIR/issue-107280.rs:4:21
+   |
+LL |     inner::<false>().await
+   |                     ^^^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0107, E0698.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
index ae4d0d5853c..5ae1d78a92b 100644
--- a/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
+++ b/tests/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
@@ -17,8 +17,9 @@ error[E0700]: hidden type for `impl Trait<'a>` captures lifetime that does not a
   --> $DIR/ret-impl-trait-one.rs:16:80
    |
 LL |   async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
-   |  ____________________________________--__________________________________________^
-   | |                                    |
+   |  ____________________________________--___________________________--------------_^
+   | |                                    |                            |
+   | |                                    |                            opaque type defined here
    | |                                    hidden type `(&'a u8, &'b u8)` captures the lifetime `'b` as defined here
 LL | |
 LL | |     (a, b)
diff --git a/tests/ui/attributes/rustc-box.rs b/tests/ui/attributes/rustc-box.rs
new file mode 100644
index 00000000000..b3726fb3867
--- /dev/null
+++ b/tests/ui/attributes/rustc-box.rs
@@ -0,0 +1,18 @@
+#![feature(rustc_attrs, stmt_expr_attributes)]
+
+fn foo(_: u32, _: u32) {}
+fn bar(_: u32) {}
+
+fn main() {
+    #[rustc_box]
+    Box::new(1); // OK
+    #[rustc_box]
+    Box::pin(1); //~ ERROR `#[rustc_box]` attribute used incorrectly
+    #[rustc_box]
+    foo(1, 1); //~ ERROR `#[rustc_box]` attribute used incorrectly
+    #[rustc_box]
+    bar(1); //~ ERROR `#[rustc_box]` attribute used incorrectly
+    #[rustc_box] //~ ERROR `#[rustc_box]` attribute used incorrectly
+    #[rustfmt::skip]
+    Box::new(1);
+}
diff --git a/tests/ui/attributes/rustc-box.stderr b/tests/ui/attributes/rustc-box.stderr
new file mode 100644
index 00000000000..073a18c7d58
--- /dev/null
+++ b/tests/ui/attributes/rustc-box.stderr
@@ -0,0 +1,34 @@
+error: `#[rustc_box]` attribute used incorrectly
+  --> $DIR/rustc-box.rs:10:5
+   |
+LL |     Box::pin(1);
+   |     ^^^^^^^^^^^
+   |
+   = note: `#[rustc_box]` may only be applied to a `Box::new()` call
+
+error: `#[rustc_box]` attribute used incorrectly
+  --> $DIR/rustc-box.rs:12:5
+   |
+LL |     foo(1, 1);
+   |     ^^^^^^^^^
+   |
+   = note: `#[rustc_box]` may only be applied to a `Box::new()` call
+
+error: `#[rustc_box]` attribute used incorrectly
+  --> $DIR/rustc-box.rs:14:5
+   |
+LL |     bar(1);
+   |     ^^^^^^
+   |
+   = note: `#[rustc_box]` may only be applied to a `Box::new()` call
+
+error: `#[rustc_box]` attribute used incorrectly
+  --> $DIR/rustc-box.rs:15:5
+   |
+LL |     #[rustc_box]
+   |     ^^^^^^^^^^^^
+   |
+   = note: no other attributes may be applied
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
index 1bda7a49713..127a3f5b2dc 100644
--- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
+++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.rs
@@ -8,6 +8,7 @@ fn a() {
         //~^ NOTE `vec[_]` is borrowed here
             vec[0] = Box::new(4); //~ ERROR cannot assign
             //~^ NOTE `vec[_]` is assigned to here
+            //~| NOTE in this expansion of desugaring of drop and replace
             _a.use_ref();
             //~^ NOTE borrow later used here
         }
@@ -22,6 +23,7 @@ fn b() {
         //~^ `vec[_]` is borrowed here
             vec[0] = Box::new(4); //~ ERROR cannot assign
             //~^ NOTE `vec[_]` is assigned to here
+            //~| NOTE in this expansion of desugaring of drop and replace
             _b.use_ref();
             //~^ NOTE borrow later used here
         }
diff --git a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
index 70b9e4f4433..5e1251b0590 100644
--- a/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
+++ b/tests/ui/borrowck/borrowck-vec-pattern-nesting.stderr
@@ -6,24 +6,24 @@ LL |         [box ref _a, _, _] => {
 LL |
 LL |             vec[0] = Box::new(4);
    |             ^^^^^^ `vec[_]` is assigned to here but it was already borrowed
-LL |
+...
 LL |             _a.use_ref();
    |             ------------ borrow later used here
 
 error[E0506]: cannot assign to `vec[_]` because it is borrowed
-  --> $DIR/borrowck-vec-pattern-nesting.rs:23:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:24:13
    |
 LL |         &mut [ref _b @ ..] => {
    |               ------ `vec[_]` is borrowed here
 LL |
 LL |             vec[0] = Box::new(4);
    |             ^^^^^^ `vec[_]` is assigned to here but it was already borrowed
-LL |
+...
 LL |             _b.use_ref();
    |             ------------ borrow later used here
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:34:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:36:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -41,7 +41,7 @@ LL +         [_a,
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:46:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:48:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -55,7 +55,7 @@ LL |     let a = &vec[0];
    |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:55:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:57:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -73,7 +73,7 @@ LL +         [
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:65:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:67:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
@@ -87,7 +87,7 @@ LL |     let a = &vec[0];
    |             +
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:74:11
+  --> $DIR/borrowck-vec-pattern-nesting.rs:76:11
    |
 LL |     match vec {
    |           ^^^ cannot move out of here
@@ -106,7 +106,7 @@ LL +         [_a, _b, _c] => {}
    |
 
 error[E0508]: cannot move out of type `[Box<isize>]`, a non-copy slice
-  --> $DIR/borrowck-vec-pattern-nesting.rs:85:13
+  --> $DIR/borrowck-vec-pattern-nesting.rs:87:13
    |
 LL |     let a = vec[0];
    |             ^^^^^^
diff --git a/tests/ui/borrowck/issue-45199.rs b/tests/ui/borrowck/issue-45199.rs
index ded46e56e34..6a6b25541f3 100644
--- a/tests/ui/borrowck/issue-45199.rs
+++ b/tests/ui/borrowck/issue-45199.rs
@@ -5,6 +5,7 @@ fn test_drop_replace() {
     b = Box::new(1);    //~ NOTE first assignment
     b = Box::new(2);    //~ ERROR cannot assign twice to immutable variable `b`
                         //~| NOTE cannot assign twice to immutable
+                        //~| NOTE in this expansion of desugaring of drop and replace
 }
 
 fn test_call() {
@@ -13,12 +14,14 @@ fn test_call() {
                             //~| SUGGESTION mut b
     b = Box::new(2);        //~ ERROR cannot assign twice to immutable variable `b`
                             //~| NOTE cannot assign twice to immutable
+                            //~| NOTE in this expansion of desugaring of drop and replace
 }
 
 fn test_args(b: Box<i32>) {  //~ HELP consider making this binding mutable
                                 //~| SUGGESTION mut b
     b = Box::new(2);            //~ ERROR cannot assign to immutable argument `b`
                                 //~| NOTE cannot assign to immutable argument
+                                //~| NOTE in this expansion of desugaring of drop and replace
 }
 
 fn main() {}
diff --git a/tests/ui/borrowck/issue-45199.stderr b/tests/ui/borrowck/issue-45199.stderr
index 47aa3090827..163f2370ba0 100644
--- a/tests/ui/borrowck/issue-45199.stderr
+++ b/tests/ui/borrowck/issue-45199.stderr
@@ -10,7 +10,7 @@ LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign twice to immutable variable `b`
-  --> $DIR/issue-45199.rs:14:5
+  --> $DIR/issue-45199.rs:15:5
    |
 LL |     let b = Box::new(1);
    |         -
@@ -22,7 +22,7 @@ LL |     b = Box::new(2);
    |     ^ cannot assign twice to immutable variable
 
 error[E0384]: cannot assign to immutable argument `b`
-  --> $DIR/issue-45199.rs:20:5
+  --> $DIR/issue-45199.rs:22:5
    |
 LL | fn test_args(b: Box<i32>) {
    |              - help: consider making this binding mutable: `mut b`
diff --git a/tests/ui/borrowck/issue-58776-borrowck-scans-children.rs b/tests/ui/borrowck/issue-58776-borrowck-scans-children.rs
index efa313a9d23..0b2372d1274 100644
--- a/tests/ui/borrowck/issue-58776-borrowck-scans-children.rs
+++ b/tests/ui/borrowck/issue-58776-borrowck-scans-children.rs
@@ -5,7 +5,6 @@ fn main() {
     greeting = "DEALLOCATED".to_string();
     //~^ ERROR cannot assign
     drop(greeting);
-    //~^ ERROR cannot move
 
     println!("thread result: {:?}", res);
 }
diff --git a/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr b/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr
index 0870b423769..967451c68be 100644
--- a/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr
+++ b/tests/ui/borrowck/issue-58776-borrowck-scans-children.stderr
@@ -12,21 +12,6 @@ LL |     greeting = "DEALLOCATED".to_string();
 LL |     println!("thread result: {:?}", res);
    |                                     --- borrow later used here
 
-error[E0505]: cannot move out of `greeting` because it is borrowed
-  --> $DIR/issue-58776-borrowck-scans-children.rs:7:10
-   |
-LL |     let res = (|| (|| &greeting)())();
-   |                --      -------- borrow occurs due to use in closure
-   |                |
-   |                borrow of `greeting` occurs here
-...
-LL |     drop(greeting);
-   |          ^^^^^^^^ move out of `greeting` occurs here
-...
-LL |     println!("thread result: {:?}", res);
-   |                                     --- borrow later used here
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0505, E0506.
-For more information about an error, try `rustc --explain E0505`.
+For more information about this error, try `rustc --explain E0506`.
diff --git a/tests/ui/closures/2229_closure_analysis/issue_88118.rs b/tests/ui/closures/2229_closure_analysis/issue_88118.rs
index 453b7e04a36..bfb487649a3 100644
--- a/tests/ui/closures/2229_closure_analysis/issue_88118.rs
+++ b/tests/ui/closures/2229_closure_analysis/issue_88118.rs
@@ -1,10 +1,7 @@
 // Regression test for #88118. Used to ICE.
-//
+// edition:2021
 // check-pass
 
-#![allow(incomplete_features)]
-#![feature(capture_disjoint_fields)]
-
 fn foo<MsU>(handler: impl FnOnce() -> MsU + Clone + 'static) {
     Box::new(move |value| {
         (|_| handler.clone()())(value);
diff --git a/tests/ui/command/command-setgroups.rs b/tests/ui/command/command-setgroups.rs
index aff67f91bba..7e321f2f0cd 100644
--- a/tests/ui/command/command-setgroups.rs
+++ b/tests/ui/command/command-setgroups.rs
@@ -3,6 +3,7 @@
 // ignore-emscripten
 // ignore-sgx
 // ignore-musl - returns dummy result for _SC_NGROUPS_MAX
+// ignore-nto - does not have `/bin/id`, expects groups to be i32 (not u32)
 
 #![feature(rustc_private)]
 #![feature(setgroups)]
diff --git a/tests/ui/const-generics/issues/issue-105821.rs b/tests/ui/const-generics/issues/issue-105821.rs
new file mode 100644
index 00000000000..cba2e22c460
--- /dev/null
+++ b/tests/ui/const-generics/issues/issue-105821.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+#![allow(incomplete_features)]
+#![feature(adt_const_params, const_ptr_read, generic_const_exprs)]
+#![allow(dead_code)]
+
+const fn catone<const M: usize>(_a: &[u8; M]) -> [u8; M + 1]
+where
+    [(); M + 1]:,
+{
+    unimplemented!()
+}
+
+struct Catter<const A: &'static [u8]>;
+impl<const A: &'static [u8]> Catter<A>
+where
+    [(); A.len() + 1]:,
+{
+    const ZEROS: &'static [u8; A.len()] = &[0_u8; A.len()];
+    const R: &'static [u8] = &catone(Self::ZEROS);
+}
+
+fn main() {}
diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs
index 5134c672f5f..0fbd851431e 100644
--- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs
+++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.rs
@@ -18,11 +18,85 @@ struct Burrito<F> {
     filling: F,
 }
 
+impl<It: Iterator> T1 for Option<It> {}
+
+impl<'a, A: T1> T1 for &'a A {}
+
 fn want<V: T1>(_x: V) {}
 
+enum ExampleTuple<T> {
+    ExampleTupleVariant(T),
+}
+use ExampleDifferentTupleVariantName as ExampleYetAnotherTupleVariantName;
+use ExampleTuple as ExampleOtherTuple;
+use ExampleTuple::ExampleTupleVariant as ExampleDifferentTupleVariantName;
+use ExampleTuple::*;
+
+impl<A> T1 for ExampleTuple<A> where A: T3 {}
+
+enum ExampleStruct<T> {
+    ExampleStructVariant { field: T },
+}
+use ExampleDifferentStructVariantName as ExampleYetAnotherStructVariantName;
+use ExampleStruct as ExampleOtherStruct;
+use ExampleStruct::ExampleStructVariant as ExampleDifferentStructVariantName;
+use ExampleStruct::*;
+
+impl<A> T1 for ExampleStruct<A> where A: T3 {}
+
+struct ExampleActuallyTupleStruct<T>(T, i32);
+use ExampleActuallyTupleStruct as ExampleActuallyTupleStructOther;
+
+impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
+
 fn example<Q>(q: Q) {
     want(Wrapper { value: Burrito { filling: q } });
     //~^ ERROR the trait bound `Q: T3` is not satisfied [E0277]
+
+    want(Some(()));
+    //~^ ERROR `()` is not an iterator [E0277]
+
+    want(Some(q));
+    //~^ ERROR `Q` is not an iterator [E0277]
+
+    want(&Some(q));
+    //~^ ERROR `Q` is not an iterator [E0277]
+
+    want(&ExampleTuple::ExampleTupleVariant(q));
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleTupleVariant(q));
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleOtherTuple::ExampleTupleVariant(q));
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleDifferentTupleVariantName(q));
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleYetAnotherTupleVariantName(q));
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleStruct::ExampleStructVariant { field: q });
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleStructVariant { field: q });
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleOtherStruct::ExampleStructVariant { field: q });
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleDifferentStructVariantName { field: q });
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleYetAnotherStructVariantName { field: q });
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleActuallyTupleStruct(q, 0));
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
+
+    want(&ExampleActuallyTupleStructOther(q, 0));
+    //~^ ERROR `Q: T3` is not satisfied [E0277]
 }
 
 fn main() {}
diff --git a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
index 27b002db130..9228a047e87 100644
--- a/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
+++ b/tests/ui/errors/trait-bound-error-spans/blame-trait-error.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `Q: T3` is not satisfied
-  --> $DIR/blame-trait-error.rs:24:46
+  --> $DIR/blame-trait-error.rs:53:46
    |
 LL |     want(Wrapper { value: Burrito { filling: q } });
    |     ----                                     ^ the trait `T3` is not implemented for `Q`
@@ -21,7 +21,7 @@ LL | impl<B: T2> T1 for Wrapper<B> {}
    |         |
    |         unsatisfied trait bound introduced here
 note: required by a bound in `want`
-  --> $DIR/blame-trait-error.rs:21:12
+  --> $DIR/blame-trait-error.rs:25:12
    |
 LL | fn want<V: T1>(_x: V) {}
    |            ^^ required by this bound in `want`
@@ -30,6 +30,373 @@ help: consider restricting type parameter `Q`
 LL | fn example<Q: T3>(q: Q) {
    |             ++++
 
-error: aborting due to previous error
+error[E0277]: `()` is not an iterator
+  --> $DIR/blame-trait-error.rs:56:15
+   |
+LL |     want(Some(()));
+   |     ----      ^^ `()` is not an iterator
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Iterator` is not implemented for `()`
+   = help: the trait `T1` is implemented for `Option<It>`
+note: required for `Option<()>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:21:20
+   |
+LL | impl<It: Iterator> T1 for Option<It> {}
+   |          --------  ^^     ^^^^^^^^^^
+   |          |
+   |          unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+
+error[E0277]: `Q` is not an iterator
+  --> $DIR/blame-trait-error.rs:59:15
+   |
+LL |     want(Some(q));
+   |     ----      ^ `Q` is not an iterator
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `Option<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:21:20
+   |
+LL | impl<It: Iterator> T1 for Option<It> {}
+   |          --------  ^^     ^^^^^^^^^^
+   |          |
+   |          unsatisfied trait bound introduced here
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: std::iter::Iterator>(q: Q) {
+   |             +++++++++++++++++++++
+
+error[E0277]: `Q` is not an iterator
+  --> $DIR/blame-trait-error.rs:62:16
+   |
+LL |     want(&Some(q));
+   |     ----       ^ `Q` is not an iterator
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `Option<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:21:20
+   |
+LL | impl<It: Iterator> T1 for Option<It> {}
+   |          --------  ^^     ^^^^^^^^^^
+   |          |
+   |          unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&Option<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: std::iter::Iterator>(q: Q) {
+   |             +++++++++++++++++++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:65:45
+   |
+LL |     want(&ExampleTuple::ExampleTupleVariant(q));
+   |     ----                                    ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `ExampleTuple<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:35:9
+   |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:68:31
+   |
+LL |     want(&ExampleTupleVariant(q));
+   |     ----                      ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `ExampleTuple<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:35:9
+   |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:71:50
+   |
+LL |     want(&ExampleOtherTuple::ExampleTupleVariant(q));
+   |     ----                                         ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `ExampleTuple<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:35:9
+   |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:74:44
+   |
+LL |     want(&ExampleDifferentTupleVariantName(q));
+   |     ----                                   ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `ExampleTuple<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:35:9
+   |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:77:45
+   |
+LL |     want(&ExampleYetAnotherTupleVariantName(q));
+   |     ----                                    ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `ExampleTuple<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:35:9
+   |
+LL | impl<A> T1 for ExampleTuple<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleTuple<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:80:56
+   |
+LL |     want(&ExampleStruct::ExampleStructVariant { field: q });
+   |     ---- required by a bound introduced by this call   ^ the trait `T3` is not implemented for `Q`
+   |
+note: required for `ExampleStruct<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:45:9
+   |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:83:41
+   |
+LL |     want(&ExampleStructVariant { field: q });
+   |     ----                                ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `ExampleStruct<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:45:9
+   |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:86:61
+   |
+LL |     want(&ExampleOtherStruct::ExampleStructVariant { field: q });
+   |     ---- required by a bound introduced by this call        ^ the trait `T3` is not implemented for `Q`
+   |
+note: required for `ExampleStruct<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:45:9
+   |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:89:54
+   |
+LL |     want(&ExampleDifferentStructVariantName { field: q });
+   |     ---- required by a bound introduced by this call ^ the trait `T3` is not implemented for `Q`
+   |
+note: required for `ExampleStruct<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:45:9
+   |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:92:55
+   |
+LL |     want(&ExampleYetAnotherStructVariantName { field: q });
+   |     ---- required by a bound introduced by this call  ^ the trait `T3` is not implemented for `Q`
+   |
+note: required for `ExampleStruct<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:45:9
+   |
+LL | impl<A> T1 for ExampleStruct<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:95:38
+   |
+LL |     want(&ExampleActuallyTupleStruct(q, 0));
+   |     ----                             ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `ExampleActuallyTupleStruct<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:50:9
+   |
+LL | impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleActuallyTupleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error[E0277]: the trait bound `Q: T3` is not satisfied
+  --> $DIR/blame-trait-error.rs:98:43
+   |
+LL |     want(&ExampleActuallyTupleStructOther(q, 0));
+   |     ----                                  ^ the trait `T3` is not implemented for `Q`
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required for `ExampleActuallyTupleStruct<Q>` to implement `T1`
+  --> $DIR/blame-trait-error.rs:50:9
+   |
+LL | impl<A> T1 for ExampleActuallyTupleStruct<A> where A: T3 {}
+   |         ^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^          -- unsatisfied trait bound introduced here
+   = note: 1 redundant requirement hidden
+   = note: required for `&ExampleActuallyTupleStruct<Q>` to implement `T1`
+note: required by a bound in `want`
+  --> $DIR/blame-trait-error.rs:25:12
+   |
+LL | fn want<V: T1>(_x: V) {}
+   |            ^^ required by this bound in `want`
+help: consider restricting type parameter `Q`
+   |
+LL | fn example<Q: T3>(q: Q) {
+   |             ++++
+
+error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
index 6913771f288..b6a24e12bcc 100644
--- a/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
+++ b/tests/ui/errors/traits/blame-trait-error-spans-on-exprs.stderr
@@ -91,10 +91,10 @@ LL | fn example<Q: T3>(q: Q) {
    |             ++++
 
 error[E0277]: the trait bound `Q: T3` is not satisfied
-  --> $DIR/blame-trait-error-spans-on-exprs.rs:93:27
+  --> $DIR/blame-trait-error-spans-on-exprs.rs:93:53
    |
 LL |     want(Wrapper { value: TacoKinds::OneTaco(false, q) });
-   |     ----                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `T3` is not implemented for `Q`
+   |     ----                                            ^ the trait `T3` is not implemented for `Q`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/tests/ui/extenv/extenv-not-defined-default.rs b/tests/ui/extenv/extenv-not-defined-default.rs
index 30a06a25465..1fb046c78f2 100644
--- a/tests/ui/extenv/extenv-not-defined-default.rs
+++ b/tests/ui/extenv/extenv-not-defined-default.rs
@@ -1,4 +1,4 @@
 fn main() {
-    env!("__HOPEFULLY_NOT_DEFINED__");
-    //~^ ERROR: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined
+    env!("CARGO__HOPEFULLY_NOT_DEFINED__");
+    //~^ ERROR: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined
 }
diff --git a/tests/ui/extenv/extenv-not-defined-default.stderr b/tests/ui/extenv/extenv-not-defined-default.stderr
index 884875dca53..e3dce000530 100644
--- a/tests/ui/extenv/extenv-not-defined-default.stderr
+++ b/tests/ui/extenv/extenv-not-defined-default.stderr
@@ -1,9 +1,10 @@
-error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined
+error: environment variable `CARGO__HOPEFULLY_NOT_DEFINED__` not defined at compile time
   --> $DIR/extenv-not-defined-default.rs:2:5
    |
-LL |     env!("__HOPEFULLY_NOT_DEFINED__");
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     env!("CARGO__HOPEFULLY_NOT_DEFINED__");
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = help: Cargo sets build script variables at run time. Use `std::env::var("CARGO__HOPEFULLY_NOT_DEFINED__")` instead
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
diff --git a/tests/ui/extenv/issue-55897.stderr b/tests/ui/extenv/issue-55897.stderr
index 92e8a44b55f..5752a965e35 100644
--- a/tests/ui/extenv/issue-55897.stderr
+++ b/tests/ui/extenv/issue-55897.stderr
@@ -1,9 +1,10 @@
-error: environment variable `NON_EXISTENT` not defined
+error: environment variable `NON_EXISTENT` not defined at compile time
   --> $DIR/issue-55897.rs:11:22
    |
 LL |     include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
    |                      ^^^^^^^^^^^^^^^^^^^^
    |
+   = help: Use `std::env::var("NON_EXISTENT")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: suffixes on string literals are invalid
diff --git a/tests/ui/for/for-else-err.rs b/tests/ui/for/for-else-err.rs
new file mode 100644
index 00000000000..16252e980e4
--- /dev/null
+++ b/tests/ui/for/for-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+    for _ in 0..1 {
+        //~^ NOTE `else` is attached to this loop
+    } else {
+        //~^ ERROR `for...else` loops are not supported
+        //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+    }
+}
diff --git a/tests/ui/for/for-else-err.stderr b/tests/ui/for/for-else-err.stderr
new file mode 100644
index 00000000000..b330d107647
--- /dev/null
+++ b/tests/ui/for/for-else-err.stderr
@@ -0,0 +1,17 @@
+error: `for...else` loops are not supported
+  --> $DIR/for-else-err.rs:4:7
+   |
+LL |       for _ in 0..1 {
+   |       --- `else` is attached to this loop
+LL |
+LL |       } else {
+   |  _______^
+LL | |
+LL | |
+LL | |     }
+   | |_____^
+   |
+   = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/for/for-else-let-else-err.rs b/tests/ui/for/for-else-let-else-err.rs
new file mode 100644
index 00000000000..c0b96f97294
--- /dev/null
+++ b/tests/ui/for/for-else-let-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let _ = for _ in 0..1 {
+        //~^ NOTE `else` is attached to this loop
+    } else {
+        //~^ ERROR `for...else` loops are not supported
+        //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+    };
+}
diff --git a/tests/ui/for/for-else-let-else-err.stderr b/tests/ui/for/for-else-let-else-err.stderr
new file mode 100644
index 00000000000..a2396a8fbb1
--- /dev/null
+++ b/tests/ui/for/for-else-let-else-err.stderr
@@ -0,0 +1,17 @@
+error: `for...else` loops are not supported
+  --> $DIR/for-else-let-else-err.rs:4:7
+   |
+LL |       let _ = for _ in 0..1 {
+   |               --- `else` is attached to this loop
+LL |
+LL |       } else {
+   |  _______^
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+   = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/impl-trait/hidden-lifetimes.stderr b/tests/ui/impl-trait/hidden-lifetimes.stderr
index 3cc47e1e89d..bc8f559fdee 100644
--- a/tests/ui/impl-trait/hidden-lifetimes.stderr
+++ b/tests/ui/impl-trait/hidden-lifetimes.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not a
   --> $DIR/hidden-lifetimes.rs:29:5
    |
 LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
-   |                 -- hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here
+   |                 --                                   -------------- opaque type defined here
+   |                 |
+   |                 hidden type `&'a mut &'b T` captures the lifetime `'b` as defined here
 LL |     x
    |     ^
    |
@@ -15,7 +17,9 @@ error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not a
   --> $DIR/hidden-lifetimes.rs:46:5
    |
 LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
-   |                        -- hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
+   |                        --                                            -------------- opaque type defined here
+   |                        |
+   |                        hidden type `Rc<RefCell<&'b T>>` captures the lifetime `'b` as defined here
 LL |     x
    |     ^
    |
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
index 433b76b7afa..d56e1273f24 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
@@ -1,6 +1,8 @@
 error[E0700]: hidden type for `impl Debug` captures lifetime that does not appear in bounds
   --> $DIR/impl-fn-hrtb-bounds-2.rs:5:9
    |
+LL | fn a() -> impl Fn(&u8) -> impl Debug {
+   |                           ---------- opaque type defined here
 LL |     |x| x
    |     --- ^
    |     |
diff --git a/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs b/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs
new file mode 100644
index 00000000000..dfce973d770
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/new-lowering-strategy/simple-trait.rs
@@ -0,0 +1,11 @@
+// check-pass
+// compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+trait Foo {
+    fn foo() -> impl Sized;
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.rs b/tests/ui/impl-trait/in-trait/specialization-broken.rs
index 9d27d3710a6..2fcffdf3f9a 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.rs
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.rs
@@ -15,6 +15,7 @@ where
 {
     fn bar(&self) -> U {
         //~^ ERROR method `bar` has an incompatible type for trait
+        //~| ERROR method with return-position `impl Trait` in trait cannot be specialized
         *self
     }
 }
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.stderr
index 37cfd74498d..dc621d6b8a8 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.stderr
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.stderr
@@ -18,6 +18,14 @@ LL |     fn bar(&self) -> impl Sized;
    = note: expected signature `fn(&U) -> impl Sized`
               found signature `fn(&U) -> U`
 
-error: aborting due to previous error
+error: method with return-position `impl Trait` in trait cannot be specialized
+  --> $DIR/specialization-broken.rs:16:5
+   |
+LL |     fn bar(&self) -> U {
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: specialization behaves in inconsistent and surprising ways with `#![feature(return_position_impl_trait_in_trait)]`, and for now is disallowed
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
index 90875708094..5b0b1cc5e42 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
@@ -1,6 +1,9 @@
 error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds
   --> $DIR/error-handling-2.rs:22:5
    |
+LL | type E<'a, 'b> = impl Sized;
+   |                  ---------- opaque type defined here
+LL |
 LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
    |        -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here
 ...
diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
index ec49a61795a..68ac22a05f4 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does n
   --> $DIR/ordinary-bounds-unrelated.rs:28:33
    |
 LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
-   |                     -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+   |                     --                                                   ------------------ opaque type defined here
+   |                     |
+   |                     hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
 ...
 LL |     if condition() { a } else { b }
    |                                 ^
diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
index c36f9bc6957..493a9e66eaf 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does n
   --> $DIR/ordinary-bounds-unsuited.rs:31:33
    |
 LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
-   |                     -- hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
+   |                     --                                       ------------------ opaque type defined here
+   |                     |
+   |                     hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
 ...
 LL |     if condition() { a } else { b }
    |                                 ^
diff --git a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 9c81791fbcb..55e3cd95064 100644
--- a/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/tests/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear
   --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
-   |              ----                 ^
-   |              |
+   |              ----     ---------   ^
+   |              |        |
+   |              |        opaque type defined here
    |              hidden type `&i32` captures the anonymous lifetime defined here
    |
 help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound
@@ -15,8 +16,9 @@ error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear
   --> $DIR/must_outlive_least_region_or_bound.rs:6:44
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-   |             --                             ^
-   |             |
+   |             --                 ---------   ^
+   |             |                  |
+   |             |                  opaque type defined here
    |             hidden type `&'a i32` captures the lifetime `'a` as defined here
    |
 help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound
@@ -100,7 +102,9 @@ error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not
   --> $DIR/must_outlive_least_region_or_bound.rs:38:5
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
-   |                              -- hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here
+   |                              --                             ---------------- opaque type defined here
+   |                              |
+   |                              hidden type `[closure@$DIR/must_outlive_least_region_or_bound.rs:38:5: 38:13]` captures the lifetime `'b` as defined here
 LL |     move |_| println!("{}", y)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/tests/ui/impl-trait/nested-return-type4.stderr b/tests/ui/impl-trait/nested-return-type4.stderr
index e761a60e79c..907822ebbc3 100644
--- a/tests/ui/impl-trait/nested-return-type4.stderr
+++ b/tests/ui/impl-trait/nested-return-type4.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Future<Output = impl Sized>` captures lifeti
   --> $DIR/nested-return-type4.rs:4:5
    |
 LL | fn test<'s: 's>(s: &'s str) -> impl std::future::Future<Output = impl Sized> {
-   |         -- hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here
+   |         --                     --------------------------------------------- opaque type defined here
+   |         |
+   |         hidden type `[async block@$DIR/nested-return-type4.rs:4:5: 4:31]` captures the lifetime `'s` as defined here
 LL |     async move { let _s = s; }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/tests/ui/impl-trait/region-escape-via-bound.stderr b/tests/ui/impl-trait/region-escape-via-bound.stderr
index 44a790cb1a4..e4556bc21a7 100644
--- a/tests/ui/impl-trait/region-escape-via-bound.stderr
+++ b/tests/ui/impl-trait/region-escape-via-bound.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Trait<'y>` captures lifetime that does not a
   --> $DIR/region-escape-via-bound.rs:17:5
    |
 LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
-   |        -- hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here
+   |        --                           -------------- opaque type defined here
+   |        |
+   |        hidden type `Cell<&'x u32>` captures the lifetime `'x` as defined here
 ...
 LL |     x
    |     ^
diff --git a/tests/ui/impl-trait/static-return-lifetime-infered.stderr b/tests/ui/impl-trait/static-return-lifetime-infered.stderr
index c451f8e37c4..488cb821c10 100644
--- a/tests/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/tests/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that
   --> $DIR/static-return-lifetime-infered.rs:7:9
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                         ----- hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here
+   |                         -----     ----------------------- opaque type defined here
+   |                         |
+   |                         hidden type `Map<std::slice::Iter<'_, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
@@ -15,7 +17,9 @@ error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that
   --> $DIR/static-return-lifetime-infered.rs:11:9
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                    -- hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here
+   |                    --               ----------------------- opaque type defined here
+   |                    |
+   |                    hidden type `Map<std::slice::Iter<'a, (u32, u32)>, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here
 LL |         self.x.iter().map(|a| a.0)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs
index c8b1ff1dbce..b99bb39d062 100644
--- a/tests/ui/intrinsics/intrinsic-alignment.rs
+++ b/tests/ui/intrinsics/intrinsic-alignment.rs
@@ -22,7 +22,9 @@ mod rusti {
           target_os = "netbsd",
           target_os = "openbsd",
           target_os = "solaris",
-          target_os = "vxworks"))]
+          target_os = "vxworks",
+          target_os = "nto",
+))]
 mod m {
     #[cfg(target_arch = "x86")]
     pub fn main() {
diff --git a/tests/ui/let-else/let-else-brace-before-else.fixed b/tests/ui/let-else/let-else-brace-before-else.fixed
index a75c770ddf2..2d85e3878cc 100644
--- a/tests/ui/let-else/let-else-brace-before-else.fixed
+++ b/tests/ui/let-else/let-else-brace-before-else.fixed
@@ -7,10 +7,6 @@ fn main() {
         //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
         return;
     };
-    let Some(1) = (loop { break Some(1) }) else {
-        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
-        return;
-    };
     let 2 = 1 + (match 1 { n => n }) else {
         //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
         return;
diff --git a/tests/ui/let-else/let-else-brace-before-else.rs b/tests/ui/let-else/let-else-brace-before-else.rs
index 5603b946f38..5c3375b3f28 100644
--- a/tests/ui/let-else/let-else-brace-before-else.rs
+++ b/tests/ui/let-else/let-else-brace-before-else.rs
@@ -7,10 +7,6 @@ fn main() {
         //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
         return;
     };
-    let Some(1) = loop { break Some(1) } else {
-        //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
-        return;
-    };
     let 2 = 1 + match 1 { n => n } else {
         //~^ ERROR right curly brace `}` before `else` in a `let...else` statement not allowed
         return;
diff --git a/tests/ui/let-else/let-else-brace-before-else.stderr b/tests/ui/let-else/let-else-brace-before-else.stderr
index cb01e4c18a1..ee53213d8c2 100644
--- a/tests/ui/let-else/let-else-brace-before-else.stderr
+++ b/tests/ui/let-else/let-else-brace-before-else.stderr
@@ -10,18 +10,7 @@ LL |     let Some(1) = ({ Some(1) }) else {
    |                   +           +
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/let-else-brace-before-else.rs:10:40
-   |
-LL |     let Some(1) = loop { break Some(1) } else {
-   |                                        ^
-   |
-help: wrap the expression in parentheses
-   |
-LL |     let Some(1) = (loop { break Some(1) }) else {
-   |                   +                      +
-
-error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/let-else-brace-before-else.rs:14:34
+  --> $DIR/let-else-brace-before-else.rs:10:34
    |
 LL |     let 2 = 1 + match 1 { n => n } else {
    |                                  ^
@@ -32,7 +21,7 @@ LL |     let 2 = 1 + (match 1 { n => n }) else {
    |                 +                  +
 
 error: right curly brace `}` before `else` in a `let...else` statement not allowed
-  --> $DIR/let-else-brace-before-else.rs:18:40
+  --> $DIR/let-else-brace-before-else.rs:14:40
    |
 LL |     let Some(1) = unsafe { unsafe_fn() } else {
    |                                        ^
@@ -42,5 +31,5 @@ help: wrap the expression in parentheses
 LL |     let Some(1) = (unsafe { unsafe_fn() }) else {
    |                   +                      +
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/lifetimes/issue-105227.stderr b/tests/ui/lifetimes/issue-105227.stderr
index d2114593735..b514db461b4 100644
--- a/tests/ui/lifetimes/issue-105227.stderr
+++ b/tests/ui/lifetimes/issue-105227.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
   --> $DIR/issue-105227.rs:7:5
    |
 LL | fn chars0(v :(& str, &str)) -> impl Iterator<Item = char> {
-   |               ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
+   |               -----            -------------------------- opaque type defined here
+   |               |
+   |               hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
 LL |
 LL |     v.0.chars().chain(v.1.chars())
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +18,9 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
   --> $DIR/issue-105227.rs:13:5
    |
 LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator<Item = char> {
-   |                ----- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
+   |                -----                -------------------------- opaque type defined here
+   |                |
+   |                hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
 LL |
 LL |     v0.chars().chain(v1.chars())
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -31,7 +35,10 @@ error[E0700]: hidden type for `impl Iterator<Item = char>` captures lifetime tha
    |
 LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) ->
    |                    ---- hidden type `std::iter::Chain<Chars<'_>, Chars<'_>>` captures the anonymous lifetime defined here
-...
+LL |
+LL |     (impl Iterator<Item = char>, &'b str)
+   |      -------------------------- opaque type defined here
+LL | {
 LL |     (v0.chars().chain(v1.chars()), v2)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/tests/ui/lifetimes/issue-107988.rs b/tests/ui/lifetimes/issue-107988.rs
new file mode 100644
index 00000000000..92cb60a06a2
--- /dev/null
+++ b/tests/ui/lifetimes/issue-107988.rs
@@ -0,0 +1,13 @@
+pub trait TraitEngine<'tcx>: 'tcx {}
+
+pub trait TraitEngineExt<'tcx> {
+    fn register_predicate_obligations(&mut self);
+}
+
+impl<T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+  //~^ ERROR use of undeclared lifetime name `'tcx`
+  //~| ERROR use of undeclared lifetime name `'tcx`
+    fn register_predicate_obligations(&mut self) {}
+}
+
+fn main() {}
diff --git a/tests/ui/lifetimes/issue-107988.stderr b/tests/ui/lifetimes/issue-107988.stderr
new file mode 100644
index 00000000000..c2d8c7050e9
--- /dev/null
+++ b/tests/ui/lifetimes/issue-107988.stderr
@@ -0,0 +1,27 @@
+error[E0261]: use of undeclared lifetime name `'tcx`
+  --> $DIR/issue-107988.rs:7:52
+   |
+LL | impl<T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+   |      -                                             ^^^^ undeclared lifetime
+   |      |
+   |      help: consider introducing lifetime `'tcx` here: `'tcx,`
+
+error[E0261]: use of undeclared lifetime name `'tcx`
+  --> $DIR/issue-107988.rs:7:30
+   |
+LL | impl<T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+   |                              ^^^^ undeclared lifetime
+   |
+   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
+help: consider making the bound lifetime-generic with a new `'tcx` lifetime
+   |
+LL | impl<T: ?Sized + for<'tcx> TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+   |                  +++++++++
+help: consider introducing lifetime `'tcx` here
+   |
+LL | impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
+   |      +++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0261`.
diff --git a/tests/ui/lint/issue-104897.rs b/tests/ui/lint/issue-104897.rs
index 5fbc658f155..2d298aff9db 100644
--- a/tests/ui/lint/issue-104897.rs
+++ b/tests/ui/lint/issue-104897.rs
@@ -1,6 +1,5 @@
 // error-pattern: this file contains an unclosed delimiter
 // error-pattern: this file contains an unclosed delimiter
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: format argument must be a string literal
 
 fn f(){(print!(á
diff --git a/tests/ui/lint/issue-104897.stderr b/tests/ui/lint/issue-104897.stderr
index 817a93c2f3b..728d51f34a4 100644
--- a/tests/ui/lint/issue-104897.stderr
+++ b/tests/ui/lint/issue-104897.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-104897.rs:6:18
+  --> $DIR/issue-104897.rs:5:18
    |
 LL | fn f(){(print!(á
    |       --      -  ^
@@ -8,36 +8,5 @@ LL | fn f(){(print!(á
    |       |unclosed delimiter
    |       unclosed delimiter
 
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-104897.rs:6:18
-   |
-LL | fn f(){(print!(á
-   |       --      -  ^
-   |       ||      |
-   |       ||      unclosed delimiter
-   |       |unclosed delimiter
-   |       unclosed delimiter
-
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-104897.rs:6:18
-   |
-LL | fn f(){(print!(á
-   |       --      -  ^
-   |       ||      |
-   |       ||      unclosed delimiter
-   |       |unclosed delimiter
-   |       unclosed delimiter
-
-error: format argument must be a string literal
-  --> $DIR/issue-104897.rs:6:16
-   |
-LL | fn f(){(print!(á
-   |                ^
-   |
-help: you might be missing a string literal to format with
-   |
-LL | fn f(){(print!("{}", á
-   |                +++++
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.rs b/tests/ui/lint/unused_parens_multibyte_recovery.rs
index 8fcfae22a3d..bc03faf3fce 100644
--- a/tests/ui/lint/unused_parens_multibyte_recovery.rs
+++ b/tests/ui/lint/unused_parens_multibyte_recovery.rs
@@ -3,7 +3,6 @@
 // error-pattern: this file contains an unclosed delimiter
 // error-pattern: this file contains an unclosed delimiter
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: format argument must be a string literal
 //
 // Verify that unused parens lint does not try to create a span
 // which points in the middle of a multibyte character.
diff --git a/tests/ui/lint/unused_parens_multibyte_recovery.stderr b/tests/ui/lint/unused_parens_multibyte_recovery.stderr
index a0302b17e25..adbf27fcca2 100644
--- a/tests/ui/lint/unused_parens_multibyte_recovery.stderr
+++ b/tests/ui/lint/unused_parens_multibyte_recovery.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/unused_parens_multibyte_recovery.rs:11:17
+  --> $DIR/unused_parens_multibyte_recovery.rs:10:17
    |
 LL | fn f(){(print!(á
    |       --      - ^
@@ -8,36 +8,5 @@ LL | fn f(){(print!(á
    |       |unclosed delimiter
    |       unclosed delimiter
 
-error: this file contains an unclosed delimiter
-  --> $DIR/unused_parens_multibyte_recovery.rs:11:17
-   |
-LL | fn f(){(print!(á
-   |       --      - ^
-   |       ||      |
-   |       ||      unclosed delimiter
-   |       |unclosed delimiter
-   |       unclosed delimiter
-
-error: this file contains an unclosed delimiter
-  --> $DIR/unused_parens_multibyte_recovery.rs:11:17
-   |
-LL | fn f(){(print!(á
-   |       --      - ^
-   |       ||      |
-   |       ||      unclosed delimiter
-   |       |unclosed delimiter
-   |       unclosed delimiter
-
-error: format argument must be a string literal
-  --> $DIR/unused_parens_multibyte_recovery.rs:11:16
-   |
-LL | fn f(){(print!(á
-   |                ^
-   |
-help: you might be missing a string literal to format with
-   |
-LL | fn f(){(print!("{}", á
-   |                +++++
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
index c9b16e43910..293fdca1cc9 100644
--- a/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
+++ b/tests/ui/liveness/liveness-assign/liveness-assign-imm-local-with-drop.rs
@@ -5,6 +5,7 @@ fn test() {
     drop(b);
     b = Box::new(2); //~ ERROR cannot assign twice to immutable variable `b`
                      //~| NOTE cannot assign twice to immutable
+                     //~| NOTE in this expansion of desugaring of drop and replace
     drop(b);
 }
 
diff --git a/tests/ui/loops/loop-else-break-with-value.rs b/tests/ui/loops/loop-else-break-with-value.rs
new file mode 100644
index 00000000000..670d8a145c0
--- /dev/null
+++ b/tests/ui/loops/loop-else-break-with-value.rs
@@ -0,0 +1,10 @@
+fn main() {
+    let Some(1) = loop {
+        //~^ NOTE `else` is attached to this loop
+        break Some(1)
+    } else {
+        //~^ ERROR `loop...else` loops are not supported
+        //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+        return;
+    };
+}
diff --git a/tests/ui/loops/loop-else-break-with-value.stderr b/tests/ui/loops/loop-else-break-with-value.stderr
new file mode 100644
index 00000000000..972e2d341ec
--- /dev/null
+++ b/tests/ui/loops/loop-else-break-with-value.stderr
@@ -0,0 +1,18 @@
+error: `loop...else` loops are not supported
+  --> $DIR/loop-else-break-with-value.rs:5:7
+   |
+LL |       let Some(1) = loop {
+   |                     ---- `else` is attached to this loop
+...
+LL |       } else {
+   |  _______^
+LL | |
+LL | |
+LL | |         return;
+LL | |     };
+   | |_____^
+   |
+   = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/loops/loop-else-err.rs b/tests/ui/loops/loop-else-err.rs
new file mode 100644
index 00000000000..202a09c255c
--- /dev/null
+++ b/tests/ui/loops/loop-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+    loop {
+        //~^ NOTE `else` is attached to this loop
+    } else {
+        //~^ ERROR `loop...else` loops are not supported
+        //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+    }
+}
diff --git a/tests/ui/loops/loop-else-err.stderr b/tests/ui/loops/loop-else-err.stderr
new file mode 100644
index 00000000000..c2c5c84cded
--- /dev/null
+++ b/tests/ui/loops/loop-else-err.stderr
@@ -0,0 +1,17 @@
+error: `loop...else` loops are not supported
+  --> $DIR/loop-else-err.rs:4:7
+   |
+LL |       loop {
+   |       ---- `else` is attached to this loop
+LL |
+LL |       } else {
+   |  _______^
+LL | |
+LL | |
+LL | |     }
+   | |_____^
+   |
+   = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/loops/loop-else-let-else-err.rs b/tests/ui/loops/loop-else-let-else-err.rs
new file mode 100644
index 00000000000..e828ffef549
--- /dev/null
+++ b/tests/ui/loops/loop-else-let-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let _ = loop {
+        //~^ NOTE `else` is attached to this loop
+    } else {
+        //~^ ERROR `loop...else` loops are not supported
+        //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+    };
+}
diff --git a/tests/ui/loops/loop-else-let-else-err.stderr b/tests/ui/loops/loop-else-let-else-err.stderr
new file mode 100644
index 00000000000..a57c784ff6f
--- /dev/null
+++ b/tests/ui/loops/loop-else-let-else-err.stderr
@@ -0,0 +1,17 @@
+error: `loop...else` loops are not supported
+  --> $DIR/loop-else-let-else-err.rs:4:7
+   |
+LL |       let _ = loop {
+   |               ---- `else` is attached to this loop
+LL |
+LL |       } else {
+   |  _______^
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+   = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/macros/issue-102878.rs b/tests/ui/macros/issue-102878.rs
index aac5891939e..bdd9c256954 100644
--- a/tests/ui/macros/issue-102878.rs
+++ b/tests/ui/macros/issue-102878.rs
@@ -1,9 +1,5 @@
 macro_rules!test{($l:expr,$_:r)=>({const:y y)}
 //~^ ERROR mismatched closing delimiter: `)`
-//~| ERROR invalid fragment specifier `r`
-//~| ERROR expected identifier, found keyword `const`
-//~| ERROR expected identifier, found keyword `const`
-//~| ERROR expected identifier, found `:`
 
 fn s(){test!(1,i)}
 
diff --git a/tests/ui/macros/issue-102878.stderr b/tests/ui/macros/issue-102878.stderr
index e0b8855a38d..034e3731b87 100644
--- a/tests/ui/macros/issue-102878.stderr
+++ b/tests/ui/macros/issue-102878.stderr
@@ -7,54 +7,5 @@ LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
    |                                  |unclosed delimiter
    |                                  closing delimiter possibly meant for this
 
-error: invalid fragment specifier `r`
-  --> $DIR/issue-102878.rs:1:27
-   |
-LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
-   |                           ^^^^
-   |
-   = help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`
-
-error: expected identifier, found keyword `const`
-  --> $DIR/issue-102878.rs:1:36
-   |
-LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
-   |                                    ^^^^^ expected identifier, found keyword
-...
-LL | fn s(){test!(1,i)}
-   |        ---------- in this macro invocation
-   |
-   = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: escape `const` to use it as an identifier
-   |
-LL | macro_rules!test{($l:expr,$_:r)=>({r#const:y y)}
-   |                                    ++
-
-error: expected identifier, found keyword `const`
-  --> $DIR/issue-102878.rs:1:36
-   |
-LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
-   |                                    ^^^^^ expected identifier, found keyword
-...
-LL | fn s(){test!(1,i)}
-   |        ---------- in this macro invocation
-   |
-   = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: escape `const` to use it as an identifier
-   |
-LL | macro_rules!test{($l:expr,$_:r)=>({r#const:y y)}
-   |                                    ++
-
-error: expected identifier, found `:`
-  --> $DIR/issue-102878.rs:1:41
-   |
-LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
-   |                                         ^ expected identifier
-...
-LL | fn s(){test!(1,i)}
-   |        ---------- in this macro invocation
-   |
-   = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/macros/macros-nonfatal-errors.stderr b/tests/ui/macros/macros-nonfatal-errors.stderr
index d42f6c179b7..93fbc9c8a44 100644
--- a/tests/ui/macros/macros-nonfatal-errors.stderr
+++ b/tests/ui/macros/macros-nonfatal-errors.stderr
@@ -150,18 +150,19 @@ error: expected string literal
 LL |     env!(invalid);
    |          ^^^^^^^
 
-error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:105:10
+error: env! takes 1 or 2 arguments
+  --> $DIR/macros-nonfatal-errors.rs:105:5
    |
 LL |     env!(foo, abr, baz);
-   |          ^^^
+   |     ^^^^^^^^^^^^^^^^^^^
 
-error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
+error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined at compile time
   --> $DIR/macros-nonfatal-errors.rs:106:5
    |
 LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
+   = help: Use `std::env::var("RUST_HOPEFULLY_THIS_DOESNT_EXIST")` to read the variable at run time
    = note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: format argument must be a string literal
diff --git a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr
index 0479035171e..89e0d982eaf 100644
--- a/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr
+++ b/tests/ui/malformed/issue-107423-unused-delim-only-one-no-pair.stderr
@@ -8,25 +8,5 @@ LL | fn a(){{{
    |       |unclosed delimiter
    |       unclosed delimiter
 
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
-   |
-LL | fn a(){{{
-   |       --- ^
-   |       |||
-   |       ||unclosed delimiter
-   |       |unclosed delimiter
-   |       unclosed delimiter
-
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-107423-unused-delim-only-one-no-pair.rs:7:11
-   |
-LL | fn a(){{{
-   |       --- ^
-   |       |||
-   |       ||unclosed delimiter
-   |       |unclosed delimiter
-   |       unclosed delimiter
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr
index c340c2d32b3..bd51378cf1a 100644
--- a/tests/ui/methods/method-call-err-msg.stderr
+++ b/tests/ui/methods/method-call-err-msg.stderr
@@ -48,14 +48,17 @@ LL |      .two(0, /* isize */);
 error[E0599]: `Foo` is not an iterator
   --> $DIR/method-call-err-msg.rs:19:7
    |
-LL | pub struct Foo;
-   | --------------
-   | |
-   | method `take` not found for this struct
-   | doesn't satisfy `Foo: Iterator`
+LL |   pub struct Foo;
+   |   --------------
+   |   |
+   |   method `take` not found for this struct
+   |   doesn't satisfy `Foo: Iterator`
 ...
-LL |      .take()
-   |       ^^^^ `Foo` is not an iterator
+LL | /     y.zero()
+LL | |      .take()
+   | |      -^^^^ `Foo` is not an iterator
+   | |______|
+   | 
    |
    = note: the following trait bounds were not satisfied:
            `Foo: Iterator`
diff --git a/tests/ui/mir/validate/storage-live.rs b/tests/ui/mir/validate/storage-live.rs
new file mode 100644
index 00000000000..ed3c26ed6da
--- /dev/null
+++ b/tests/ui/mir/validate/storage-live.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Zvalidate-mir -Ztreat-err-as-bug
+// failure-status: 101
+// error-pattern: broken MIR in
+// error-pattern: StorageLive(_1) which already has storage here
+// normalize-stderr-test "note: .*\n\n" -> ""
+// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+// normalize-stderr-test "storage_live\[....\]" -> "storage_live[HASH]"
+// rustc-env:RUST_BACKTRACE=0
+
+#![feature(custom_mir, core_intrinsics)]
+
+extern crate core;
+use core::intrinsics::mir::*;
+use core::ptr::{addr_of, addr_of_mut};
+
+#[custom_mir(dialect = "built")]
+fn multiple_storage() {
+    mir!(
+        let a: usize;
+        {
+            StorageLive(a);
+            StorageLive(a);
+            Return()
+        }
+    )
+}
+
+fn main() {
+    multiple_storage()
+}
diff --git a/tests/ui/mir/validate/storage-live.stderr b/tests/ui/mir/validate/storage-live.stderr
new file mode 100644
index 00000000000..b586a865849
--- /dev/null
+++ b/tests/ui/mir/validate/storage-live.stderr
@@ -0,0 +1,13 @@
+error: internal compiler error: broken MIR in Item(WithOptConstParam { did: DefId(0:8 ~ storage_live[HASH]::multiple_storage), const_param_did: None }) (before pass CheckPackedRef) at bb0[1]:
+                                StorageLive(_1) which already has storage here
+  --> $DIR/storage-live.rs:22:13
+   |
+LL |             StorageLive(a);
+   |             ^^^^^^^^^^^^^^
+
+error: the compiler unexpectedly panicked. this is a bug.
+
+query stack during panic:
+#0 [mir_const] preparing `multiple_storage` for borrow checking
+#1 [mir_promoted] processing MIR for `multiple_storage`
+end of query stack
diff --git a/tests/ui/nll/issue-73159-rpit-static.stderr b/tests/ui/nll/issue-73159-rpit-static.stderr
index 260b9b59772..4d3a9015316 100644
--- a/tests/ui/nll/issue-73159-rpit-static.stderr
+++ b/tests/ui/nll/issue-73159-rpit-static.stderr
@@ -4,6 +4,7 @@ error[E0700]: hidden type for `impl Iterator<Item = u8>` captures lifetime that
 LL | impl<'a> Foo<'a> {
    |      -- hidden type `Copied<std::slice::Iter<'a, u8>>` captures the lifetime `'a` as defined here
 LL |     fn make_it(&self) -> impl Iterator<Item = u8> {
+   |                          ------------------------ opaque type defined here
 LL |         self.0.iter().copied()
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr
index 1e6ef614dee..e0d476a33b2 100644
--- a/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr
+++ b/tests/ui/nll/member-constraints/min-choice-reject-ambiguous.stderr
@@ -24,7 +24,9 @@ error[E0700]: hidden type for `impl Cap<'b> + Cap<'c>` captures lifetime that do
   --> $DIR/min-choice-reject-ambiguous.rs:39:5
    |
 LL | fn test_ambiguous<'a, 'b, 'c>(s: &'a u8) -> impl Cap<'b> + Cap<'c>
-   |                   -- hidden type `&'a u8` captures the lifetime `'a` as defined here
+   |                   --                        ---------------------- opaque type defined here
+   |                   |
+   |                   hidden type `&'a u8` captures the lifetime `'a` as defined here
 ...
 LL |     s
    |     ^
diff --git a/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr b/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr
index 6824e27ead0..483b5822b9d 100644
--- a/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr
+++ b/tests/ui/nll/member-constraints/nested-impl-trait-fail.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>`
   --> $DIR/nested-impl-trait-fail.rs:17:5
    |
 LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>
-   |                     -- hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here
+   |                     --                        ------------------------------------------------ opaque type defined here
+   |                     |
+   |                     hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here
 ...
 LL |     [a]
    |     ^^^
@@ -20,7 +22,9 @@ error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that do
   --> $DIR/nested-impl-trait-fail.rs:17:5
    |
 LL | fn fail_early_bound<'s, 'a, 'b>(a: &'s u8) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>
-   |                     -- hidden type `&'s u8` captures the lifetime `'s` as defined here
+   |                     --                                                 ---------------------- opaque type defined here
+   |                     |
+   |                     hidden type `&'s u8` captures the lifetime `'s` as defined here
 ...
 LL |     [a]
    |     ^^^
@@ -40,6 +44,8 @@ error[E0700]: hidden type for `impl IntoIterator<Item = impl Cap<'a> + Cap<'b>>`
 LL | fn fail_late_bound<'s, 'a, 'b>(
    |                    -- hidden type `[&'s u8; 1]` captures the lifetime `'s` as defined here
 ...
+LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> {
+   |      ------------------------------------------------ opaque type defined here
 LL |     [a]
    |     ^^^
    |
@@ -58,6 +64,8 @@ error[E0700]: hidden type for `impl Cap<'a> + Cap<'b>` captures lifetime that do
 LL | fn fail_late_bound<'s, 'a, 'b>(
    |                    -- hidden type `&'s u8` captures the lifetime `'s` as defined here
 ...
+LL | ) -> impl IntoIterator<Item = impl Cap<'a> + Cap<'b>> {
+   |                               ---------------------- opaque type defined here
 LL |     [a]
    |     ^^^
    |
diff --git a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr
index 7b9ed171d2d..7fcb68252cf 100644
--- a/tests/ui/nll/ty-outlives/impl-trait-captures.stderr
+++ b/tests/ui/nll/ty-outlives/impl-trait-captures.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::fo
   --> $DIR/impl-trait-captures.rs:11:5
    |
 LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
-   |                  -- hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
+   |                  --     ------------ opaque type defined here
+   |                  |
+   |                  hidden type `&ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime defined here
 LL |     x
    |     ^
    |
diff --git a/tests/ui/numbers-arithmetic/issue-105626.rs b/tests/ui/numbers-arithmetic/issue-105626.rs
new file mode 100644
index 00000000000..f97edd510c9
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/issue-105626.rs
@@ -0,0 +1,17 @@
+// run-pass
+// only-x86
+// min-system-llvm-version: 16
+// compile-flags: -Ctarget-feature=+sse2
+
+use std::hint::black_box;
+
+fn main() {
+    let n: i64 = black_box(0x3fffffdfffffff);
+    let r = f32::from_bits(0x5a7fffff);
+
+    assert_ne!((n as f64) as f32, n as f32);
+
+    // FIXME: these assertions fail if only x87 is enabled
+    assert_eq!(n as i64 as f32, r);
+    assert_eq!(n as u64 as f32, r);
+}
diff --git a/tests/ui/parser/deli-ident-issue-1.rs b/tests/ui/parser/deli-ident-issue-1.rs
index 54485262a0c..224ee6c09e0 100644
--- a/tests/ui/parser/deli-ident-issue-1.rs
+++ b/tests/ui/parser/deli-ident-issue-1.rs
@@ -15,8 +15,6 @@ impl dyn Demo {
         if let Some(b) = val
         && let Some(c) = num {
         && b == c {
-            //~^ ERROR expected struct
-            //~| ERROR mismatched types
         }
     }
 }
diff --git a/tests/ui/parser/deli-ident-issue-1.stderr b/tests/ui/parser/deli-ident-issue-1.stderr
index 1119edb199f..eb5073e14cf 100644
--- a/tests/ui/parser/deli-ident-issue-1.stderr
+++ b/tests/ui/parser/deli-ident-issue-1.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/deli-ident-issue-1.rs:24:66
+  --> $DIR/deli-ident-issue-1.rs:22:66
    |
 LL | impl dyn Demo {
    |               - unclosed delimiter
@@ -13,25 +13,5 @@ LL |     }
 LL | fn main() { }
    |                                                                  ^
 
-error[E0574]: expected struct, variant or union type, found local variable `c`
-  --> $DIR/deli-ident-issue-1.rs:17:17
-   |
-LL |         && b == c {
-   |                 ^ not a struct, variant or union type
-
-error[E0308]: mismatched types
-  --> $DIR/deli-ident-issue-1.rs:17:9
-   |
-LL |       fn check(&self, val: Option<u32>, num: Option<u32>) {
-   |                                                           - expected `()` because of default return type
-...
-LL | /         && b == c {
-LL | |
-LL | |
-LL | |         }
-   | |_________^ expected `()`, found `bool`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0574.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/deli-ident-issue-2.stderr b/tests/ui/parser/deli-ident-issue-2.stderr
index c8f59c9d32b..e0188cdfb4a 100644
--- a/tests/ui/parser/deli-ident-issue-2.stderr
+++ b/tests/ui/parser/deli-ident-issue-2.stderr
@@ -1,3 +1,11 @@
+error: mismatched closing delimiter: `]`
+  --> $DIR/deli-ident-issue-2.rs:2:14
+   |
+LL |     if 1 < 2 {
+   |              ^ unclosed delimiter
+LL |         let _a = vec!];
+   |                      ^ mismatched closing delimiter
+
 error: unexpected closing delimiter: `}`
   --> $DIR/deli-ident-issue-2.rs:5:1
    |
@@ -7,13 +15,5 @@ LL |     }
 LL | }
    | ^ unexpected closing delimiter
 
-error: mismatched closing delimiter: `]`
-  --> $DIR/deli-ident-issue-2.rs:2:14
-   |
-LL |     if 1 < 2 {
-   |              ^ unclosed delimiter
-LL |         let _a = vec!];
-   |                      ^ mismatched closing delimiter
-
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/do-not-suggest-semicolon-before-array.rs b/tests/ui/parser/do-not-suggest-semicolon-before-array.rs
index 7ebf3f6b0d8..7eff7f431be 100644
--- a/tests/ui/parser/do-not-suggest-semicolon-before-array.rs
+++ b/tests/ui/parser/do-not-suggest-semicolon-before-array.rs
@@ -2,7 +2,7 @@ fn foo() {}
 
 fn bar() -> [u8; 2] {
     foo()
-    [1, 3) //~ ERROR expected one of `.`, `?`, `]`, or an operator, found `,`
+    [1, 3) //~ ERROR mismatched closing delimiter
 }
 
 fn main() {}
diff --git a/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr b/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr
index a9dd526321f..7b43c77005e 100644
--- a/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr
+++ b/tests/ui/parser/do-not-suggest-semicolon-before-array.stderr
@@ -1,8 +1,8 @@
-error: expected one of `.`, `?`, `]`, or an operator, found `,`
+error: mismatched closing delimiter: `)`
   --> $DIR/do-not-suggest-semicolon-before-array.rs:5:5
    |
 LL |     [1, 3)
-   |     ^ ^ help: `]` may belong here
+   |     ^    ^ mismatched closing delimiter
    |     |
    |     unclosed delimiter
 
diff --git a/tests/ui/parser/issue-103451.rs b/tests/ui/parser/issue-103451.rs
index 1fdb0014881..be33213f3cb 100644
--- a/tests/ui/parser/issue-103451.rs
+++ b/tests/ui/parser/issue-103451.rs
@@ -1,5 +1,4 @@
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected value, found struct `R`
 struct R { }
 struct S {
     x: [u8; R
diff --git a/tests/ui/parser/issue-103451.stderr b/tests/ui/parser/issue-103451.stderr
index eb3c92fb43d..6aacd5012c1 100644
--- a/tests/ui/parser/issue-103451.stderr
+++ b/tests/ui/parser/issue-103451.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-103451.rs:5:15
+  --> $DIR/issue-103451.rs:4:15
    |
 LL | struct S {
    |          - unclosed delimiter
@@ -8,25 +8,5 @@ LL |     x: [u8; R
    |        |
    |        unclosed delimiter
 
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-103451.rs:5:15
-   |
-LL | struct S {
-   |          - unclosed delimiter
-LL |     x: [u8; R
-   |        -      ^
-   |        |
-   |        unclosed delimiter
-
-error[E0423]: expected value, found struct `R`
-  --> $DIR/issue-103451.rs:5:13
-   |
-LL | struct R { }
-   | ------------ `R` defined here
-LL | struct S {
-LL |     x: [u8; R
-   |             ^ help: use struct literal syntax instead: `R {}`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/parser/issue-107705.rs b/tests/ui/parser/issue-107705.rs
new file mode 100644
index 00000000000..b80984fcdb0
--- /dev/null
+++ b/tests/ui/parser/issue-107705.rs
@@ -0,0 +1,3 @@
+// compile-flags: -C debug-assertions
+
+fn f() {a(b:&, //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issue-107705.stderr b/tests/ui/parser/issue-107705.stderr
new file mode 100644
index 00000000000..d2d61346118
--- /dev/null
+++ b/tests/ui/parser/issue-107705.stderr
@@ -0,0 +1,10 @@
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-107705.rs:3:67
+   |
+LL | fn f() {a(b:&,
+   |        - - unclosed delimiter                                     ^
+   |        |
+   |        unclosed delimiter
+
+error: aborting due to previous error
+
diff --git a/tests/ui/parser/issue-108495-dec.rs b/tests/ui/parser/issue-108495-dec.rs
new file mode 100644
index 00000000000..e0816f84e5c
--- /dev/null
+++ b/tests/ui/parser/issue-108495-dec.rs
@@ -0,0 +1,39 @@
+fn test0() {
+    let mut i = 0;
+    let _ = i + i--; //~ ERROR Rust has no postfix decrement operator
+    // won't suggest since we can not handle the precedences
+}
+
+fn test1() {
+    let mut i = 0;
+    let _ = i-- + i--; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test2() {
+    let mut i = 0;
+    let _ = --i + i--; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test3() {
+    let mut i = 0;
+    let _ = i-- + --i; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test4() {
+    let mut i = 0;
+    let _ = (1 + 2 + i)--; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test5() {
+    let mut i = 0;
+    let _ = (i-- + 1) + 2; //~ ERROR Rust has no postfix decrement operator
+}
+
+fn test6(){
+    let i=10;
+    while i != 0 {
+        i--; //~ ERROR Rust has no postfix decrement operator
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/parser/issue-108495-dec.stderr b/tests/ui/parser/issue-108495-dec.stderr
new file mode 100644
index 00000000000..85b29038f7c
--- /dev/null
+++ b/tests/ui/parser/issue-108495-dec.stderr
@@ -0,0 +1,69 @@
+error: Rust has no postfix decrement operator
+  --> $DIR/issue-108495-dec.rs:3:18
+   |
+LL |     let _ = i + i--;
+   |                  ^^ not a valid postfix operator
+
+error: Rust has no postfix decrement operator
+  --> $DIR/issue-108495-dec.rs:9:14
+   |
+LL |     let _ = i-- + i--;
+   |              ^^ not a valid postfix operator
+   |
+help: use `-= 1` instead
+   |
+LL |     let _ = { let tmp = i; i -= 1; tmp } + i--;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix decrement operator
+  --> $DIR/issue-108495-dec.rs:14:20
+   |
+LL |     let _ = --i + i--;
+   |                    ^^ not a valid postfix operator
+
+error: Rust has no postfix decrement operator
+  --> $DIR/issue-108495-dec.rs:19:14
+   |
+LL |     let _ = i-- + --i;
+   |              ^^ not a valid postfix operator
+   |
+help: use `-= 1` instead
+   |
+LL |     let _ = { let tmp = i; i -= 1; tmp } + --i;
+   |             +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix decrement operator
+  --> $DIR/issue-108495-dec.rs:24:24
+   |
+LL |     let _ = (1 + 2 + i)--;
+   |                        ^^ not a valid postfix operator
+   |
+help: use `-= 1` instead
+   |
+LL |     let _ = { let tmp = (1 + 2 + i); (1 + 2 + i) -= 1; tmp };
+   |             +++++++++++            ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: Rust has no postfix decrement operator
+  --> $DIR/issue-108495-dec.rs:29:15
+   |
+LL |     let _ = (i-- + 1) + 2;
+   |               ^^ not a valid postfix operator
+   |
+help: use `-= 1` instead
+   |
+LL |     let _ = ({ let tmp = i; i -= 1; tmp } + 1) + 2;
+   |              +++++++++++  ~~~~~~~~~~~~~~~
+
+error: Rust has no postfix decrement operator
+  --> $DIR/issue-108495-dec.rs:35:10
+   |
+LL |         i--;
+   |          ^^ not a valid postfix operator
+   |
+help: use `-= 1` instead
+   |
+LL |         i -= 1;
+   |           ~~~~
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-2.stderr b/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
index 2c08d41a15f..0ecb748a0a4 100644
--- a/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
+++ b/tests/ui/parser/issue-68987-unmatch-issue-2.stderr
@@ -1,3 +1,11 @@
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-68987-unmatch-issue-2.rs:3:32
+   |
+LL | async fn obstest() -> Result<> {
+   |                                ^ unclosed delimiter
+LL |     let obs_connect = || -> Result<(), MyError) {
+   |                                               ^ mismatched closing delimiter
+
 error: unexpected closing delimiter: `}`
   --> $DIR/issue-68987-unmatch-issue-2.rs:14:1
    |
@@ -7,13 +15,5 @@ LL |     let obs_connect = || -> Result<(), MyError) {
 LL | }
    | ^ unexpected closing delimiter
 
-error: mismatched closing delimiter: `)`
-  --> $DIR/issue-68987-unmatch-issue-2.rs:3:32
-   |
-LL | async fn obstest() -> Result<> {
-   |                                ^ unclosed delimiter
-LL |     let obs_connect = || -> Result<(), MyError) {
-   |                                               ^ mismatched closing delimiter
-
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/issue-68987-unmatch-issue-3.stderr b/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
index a3fc46a1e88..dfc4407ed65 100644
--- a/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
+++ b/tests/ui/parser/issue-68987-unmatch-issue-3.stderr
@@ -1,3 +1,11 @@
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-68987-unmatch-issue-3.rs:5:19
+   |
+LL |     while cnt < j {
+   |                   ^ unclosed delimiter
+LL |         write!&mut res, " ");
+   |                            ^ mismatched closing delimiter
+
 error: unexpected closing delimiter: `}`
   --> $DIR/issue-68987-unmatch-issue-3.rs:8:1
    |
@@ -7,13 +15,5 @@ LL |     }
 LL | }
    | ^ unexpected closing delimiter
 
-error: mismatched closing delimiter: `)`
-  --> $DIR/issue-68987-unmatch-issue-3.rs:5:19
-   |
-LL |     while cnt < j {
-   |                   ^ unclosed delimiter
-LL |         write!&mut res, " ");
-   |                            ^ mismatched closing delimiter
-
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/issue-81804.rs b/tests/ui/parser/issue-81804.rs
index 803bde11e20..ebc4752a142 100644
--- a/tests/ui/parser/issue-81804.rs
+++ b/tests/ui/parser/issue-81804.rs
@@ -1,8 +1,5 @@
 // error-pattern: this file contains an unclosed delimiter
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected pattern, found `=`
-// error-pattern: expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
-// error-pattern: expected item, found `]`
 
 fn main() {}
 
diff --git a/tests/ui/parser/issue-81804.stderr b/tests/ui/parser/issue-81804.stderr
index 19c4422c622..de3b33ecd95 100644
--- a/tests/ui/parser/issue-81804.stderr
+++ b/tests/ui/parser/issue-81804.stderr
@@ -1,14 +1,13 @@
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-81804.rs:9:11
+error: mismatched closing delimiter: `}`
+  --> $DIR/issue-81804.rs:6:8
    |
 LL | fn p([=(}
-   |     --    ^
-   |     ||
-   |     |unclosed delimiter
-   |     unclosed delimiter
+   |        ^^ mismatched closing delimiter
+   |        |
+   |        unclosed delimiter
 
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-81804.rs:9:11
+  --> $DIR/issue-81804.rs:6:11
    |
 LL | fn p([=(}
    |     --    ^
@@ -16,26 +15,5 @@ LL | fn p([=(}
    |     |unclosed delimiter
    |     unclosed delimiter
 
-error: expected pattern, found `=`
-  --> $DIR/issue-81804.rs:9:7
-   |
-LL | fn p([=(}
-   |       ^ expected pattern
-
-error: expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
-  --> $DIR/issue-81804.rs:9:8
-   |
-LL | fn p([=(}
-   |        ^ -^
-   |        | |
-   |        | help: `)` may belong here
-   |        unclosed delimiter
-
-error: expected item, found `]`
-  --> $DIR/issue-81804.rs:9:11
-   |
-LL | fn p([=(}
-   |           ^ expected item
-
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/issue-81827.rs b/tests/ui/parser/issue-81827.rs
index 7ec58159413..91defd12a57 100644
--- a/tests/ui/parser/issue-81827.rs
+++ b/tests/ui/parser/issue-81827.rs
@@ -1,6 +1,5 @@
 // error-pattern: this file contains an unclosed delimiter
 // error-pattern: mismatched closing delimiter: `]`
-// error-pattern: expected one of `)` or `,`, found `{`
 
 #![crate_name="0"]
 
diff --git a/tests/ui/parser/issue-81827.stderr b/tests/ui/parser/issue-81827.stderr
index 867244b72e8..63d135f73e6 100644
--- a/tests/ui/parser/issue-81827.stderr
+++ b/tests/ui/parser/issue-81827.stderr
@@ -1,15 +1,14 @@
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-81827.rs:11:27
+error: mismatched closing delimiter: `]`
+  --> $DIR/issue-81827.rs:10:23
    |
 LL | fn r()->i{0|{#[cfg(r(0{]0
-   |          -  -          -  ^
-   |          |  |          |
-   |          |  |          missing open `[` for this delimiter
-   |          |  unclosed delimiter
-   |          unclosed delimiter
+   |               -       ^^ mismatched closing delimiter
+   |               |       |
+   |               |       unclosed delimiter
+   |               closing delimiter possibly meant for this
 
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-81827.rs:11:27
+  --> $DIR/issue-81827.rs:10:27
    |
 LL | fn r()->i{0|{#[cfg(r(0{]0
    |          -  -          -  ^
@@ -18,20 +17,5 @@ LL | fn r()->i{0|{#[cfg(r(0{]0
    |          |  unclosed delimiter
    |          unclosed delimiter
 
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-81827.rs:11:23
-   |
-LL | fn r()->i{0|{#[cfg(r(0{]0
-   |               -       ^^ mismatched closing delimiter
-   |               |       |
-   |               |       unclosed delimiter
-   |               closing delimiter possibly meant for this
-
-error: expected one of `)` or `,`, found `{`
-  --> $DIR/issue-81827.rs:11:23
-   |
-LL | fn r()->i{0|{#[cfg(r(0{]0
-   |                       ^ expected one of `)` or `,`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/issues/issue-104367.rs b/tests/ui/parser/issues/issue-104367.rs
new file mode 100644
index 00000000000..861761b64f4
--- /dev/null
+++ b/tests/ui/parser/issues/issue-104367.rs
@@ -0,0 +1,6 @@
+#[derive(A)]
+struct S {
+    d: [u32; {
+        #![cfg] {
+            #![w,) //~ ERROR mismatched closing delimiter
+                   //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-104367.stderr b/tests/ui/parser/issues/issue-104367.stderr
new file mode 100644
index 00000000000..e6e76535761
--- /dev/null
+++ b/tests/ui/parser/issues/issue-104367.stderr
@@ -0,0 +1,26 @@
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-104367.rs:5:15
+   |
+LL |             #![w,)
+   |               ^  ^ mismatched closing delimiter
+   |               |
+   |               unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-104367.rs:6:71
+   |
+LL | struct S {
+   |          - unclosed delimiter
+LL |     d: [u32; {
+   |        -     - unclosed delimiter
+   |        |
+   |        unclosed delimiter
+LL |         #![cfg] {
+   |                 - unclosed delimiter
+LL |             #![w,)
+   |                  - missing open `(` for this delimiter
+LL |
+   |                                                                       ^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issues/issue-105209.rs b/tests/ui/parser/issues/issue-105209.rs
new file mode 100644
index 00000000000..6146b795de1
--- /dev/null
+++ b/tests/ui/parser/issues/issue-105209.rs
@@ -0,0 +1,3 @@
+// compile-flags: -Zunpretty=ast-tree
+#![c={#![c[)x   //~ ERROR mismatched closing delimiter
+                //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-105209.stderr b/tests/ui/parser/issues/issue-105209.stderr
new file mode 100644
index 00000000000..c75eafa1833
--- /dev/null
+++ b/tests/ui/parser/issues/issue-105209.stderr
@@ -0,0 +1,22 @@
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-105209.rs:2:11
+   |
+LL | #![c={#![c[)x
+   |           ^^ mismatched closing delimiter
+   |           |
+   |           unclosed delimiter
+
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-105209.rs:3:68
+   |
+LL | #![c={#![c[)x
+   |   -  -  -  - missing open `(` for this delimiter
+   |   |  |  |
+   |   |  |  unclosed delimiter
+   |   |  unclosed delimiter
+   |   unclosed delimiter
+LL |
+   |                                                                    ^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/parser/issues/issue-10636-2.rs b/tests/ui/parser/issues/issue-10636-2.rs
index 6fb63639d5f..80d8ef65a69 100644
--- a/tests/ui/parser/issues/issue-10636-2.rs
+++ b/tests/ui/parser/issues/issue-10636-2.rs
@@ -1,11 +1,11 @@
+// error-pattern: mismatched closing delimiter: `}`
 // FIXME(31528) we emit a bunch of silly errors here due to continuing past the
 // first one. This would be easy-ish to address by better recovery in tokenisation.
 
 pub fn trace_option(option: Option<isize>) {
     option.map(|some| 42;
-                          //~^ ERROR: expected one of
+
 
 }
-//~^ ERROR: expected expression, found `)`
 
 fn main() {}
diff --git a/tests/ui/parser/issues/issue-10636-2.stderr b/tests/ui/parser/issues/issue-10636-2.stderr
index d4f2da9e3ab..4cd4be1803e 100644
--- a/tests/ui/parser/issues/issue-10636-2.stderr
+++ b/tests/ui/parser/issues/issue-10636-2.stderr
@@ -1,16 +1,13 @@
-error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
-  --> $DIR/issue-10636-2.rs:5:15
+error: mismatched closing delimiter: `}`
+  --> $DIR/issue-10636-2.rs:6:15
    |
+LL | pub fn trace_option(option: Option<isize>) {
+   |                                            - closing delimiter possibly meant for this
 LL |     option.map(|some| 42;
-   |               ^         ^ help: `)` may belong here
-   |               |
-   |               unclosed delimiter
-
-error: expected expression, found `)`
-  --> $DIR/issue-10636-2.rs:8:1
-   |
+   |               ^ unclosed delimiter
+...
 LL | }
-   | ^ expected expression
+   | ^ mismatched closing delimiter
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
index 25699f9fe11..a596a9f2de3 100644
--- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
+++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.rs
@@ -1,4 +1,5 @@
 // Fixed in #66054.
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 2 previous errors
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: aborting due to previous error
 #[Ѕ
\ No newline at end of file
diff --git a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
index 8a44ee761ed..c79e8b4fb70 100644
--- a/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
+++ b/tests/ui/parser/issues/issue-58094-missing-right-square-bracket.stderr
@@ -1,16 +1,10 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4
+  --> $DIR/issue-58094-missing-right-square-bracket.rs:5:4
    |
 LL | #[Ѕ
    |  - ^
    |  |
    |  unclosed delimiter
 
-error: expected item after attributes
-  --> $DIR/issue-58094-missing-right-square-bracket.rs:4:1
-   |
-LL | #[Ѕ
-   | ^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-58856-1.rs b/tests/ui/parser/issues/issue-58856-1.rs
index ea80eb8714f..799243d545a 100644
--- a/tests/ui/parser/issues/issue-58856-1.rs
+++ b/tests/ui/parser/issues/issue-58856-1.rs
@@ -1,8 +1,5 @@
 impl A {
-    //~^ ERROR cannot find type `A` in this scope
     fn b(self>
-    //~^ ERROR expected one of `)`, `,`, or `:`, found `>`
-    //~| ERROR expected one of `->`, `where`, or `{`, found `>`
-}
+} //~ ERROR mismatched closing delimiter
 
 fn main() {}
diff --git a/tests/ui/parser/issues/issue-58856-1.stderr b/tests/ui/parser/issues/issue-58856-1.stderr
index 96151f3fe07..77ad8acbd43 100644
--- a/tests/ui/parser/issues/issue-58856-1.stderr
+++ b/tests/ui/parser/issues/issue-58856-1.stderr
@@ -1,29 +1,12 @@
-error: expected one of `)`, `,`, or `:`, found `>`
-  --> $DIR/issue-58856-1.rs:3:9
-   |
-LL |     fn b(self>
-   |         ^    ^ help: `)` may belong here
-   |         |
-   |         unclosed delimiter
-
-error: expected one of `->`, `where`, or `{`, found `>`
-  --> $DIR/issue-58856-1.rs:3:14
+error: mismatched closing delimiter: `}`
+  --> $DIR/issue-58856-1.rs:2:9
    |
 LL | impl A {
-   |        - while parsing this item list starting here
-LL |
+   |        - closing delimiter possibly meant for this
 LL |     fn b(self>
-   |              ^ expected one of `->`, `where`, or `{`
-...
+   |         ^ unclosed delimiter
 LL | }
-   | - the item list ends here
-
-error[E0412]: cannot find type `A` in this scope
-  --> $DIR/issue-58856-1.rs:1:6
-   |
-LL | impl A {
-   |      ^ not found in this scope
+   | ^ mismatched closing delimiter
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/parser/issues/issue-58856-2.rs b/tests/ui/parser/issues/issue-58856-2.rs
index 9356d57b0e5..5edd7263905 100644
--- a/tests/ui/parser/issues/issue-58856-2.rs
+++ b/tests/ui/parser/issues/issue-58856-2.rs
@@ -4,11 +4,8 @@ trait Howness {}
 
 impl Howness for () {
     fn how_are_you(&self -> Empty {
-    //~^ ERROR expected one of `)` or `,`, found `->`
-    //~| ERROR method `how_are_you` is not a member of trait `Howness`
         Empty
     }
-}
-//~^ ERROR non-item in item list
+} //~ ERROR mismatched closing delimiter
 
 fn main() {}
diff --git a/tests/ui/parser/issues/issue-58856-2.stderr b/tests/ui/parser/issues/issue-58856-2.stderr
index 627dd389059..5fcf5bcc17e 100644
--- a/tests/ui/parser/issues/issue-58856-2.stderr
+++ b/tests/ui/parser/issues/issue-58856-2.stderr
@@ -1,34 +1,13 @@
-error: expected one of `)` or `,`, found `->`
+error: mismatched closing delimiter: `}`
   --> $DIR/issue-58856-2.rs:6:19
    |
-LL |     fn how_are_you(&self -> Empty {
-   |                   ^     -^^
-   |                   |     |
-   |                   |     help: `)` may belong here
-   |                   unclosed delimiter
-
-error: non-item in item list
-  --> $DIR/issue-58856-2.rs:11:1
-   |
 LL | impl Howness for () {
-   |                     - item list starts here
+   |                     - closing delimiter possibly meant for this
+LL |     fn how_are_you(&self -> Empty {
+   |                   ^ unclosed delimiter
 ...
 LL | }
-   | ^
-   | |
-   | non-item starts here
-   | item list ends here
-
-error[E0407]: method `how_are_you` is not a member of trait `Howness`
-  --> $DIR/issue-58856-2.rs:6:5
-   |
-LL | /     fn how_are_you(&self -> Empty {
-LL | |
-LL | |
-LL | |         Empty
-LL | |     }
-   | |_____^ not a member of trait `Howness`
+   | ^ mismatched closing delimiter
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0407`.
diff --git a/tests/ui/parser/issues/issue-60075.rs b/tests/ui/parser/issues/issue-60075.rs
index e89d78ee8a6..3c36e4d3ea7 100644
--- a/tests/ui/parser/issues/issue-60075.rs
+++ b/tests/ui/parser/issues/issue-60075.rs
@@ -3,9 +3,6 @@ fn main() {}
 trait T {
     fn qux() -> Option<usize> {
         let _ = if true {
-        });
-//~^ ERROR non-item in item list
-//~| ERROR mismatched closing delimiter: `)`
-//~| ERROR expected one of `.`, `;`
+        }); //~ ERROR mismatched closing delimiter
         Some(4)
     }
diff --git a/tests/ui/parser/issues/issue-60075.stderr b/tests/ui/parser/issues/issue-60075.stderr
index 210ef700cd4..cd8f1231fad 100644
--- a/tests/ui/parser/issues/issue-60075.stderr
+++ b/tests/ui/parser/issues/issue-60075.stderr
@@ -1,21 +1,3 @@
-error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}`
-  --> $DIR/issue-60075.rs:6:10
-   |
-LL |         });
-   |          ^ expected one of `.`, `;`, `?`, `else`, or an operator
-
-error: non-item in item list
-  --> $DIR/issue-60075.rs:6:11
-   |
-LL | trait T {
-   |         - item list starts here
-...
-LL |         });
-   |           ^ non-item starts here
-...
-LL |     }
-   |     - item list ends here
-
 error: mismatched closing delimiter: `)`
   --> $DIR/issue-60075.rs:4:31
    |
@@ -25,5 +7,5 @@ LL |         let _ = if true {
 LL |         });
    |          ^ mismatched closing delimiter
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-62524.rs b/tests/ui/parser/issues/issue-62524.rs
index 5259dfe2e65..fa7c626f5cc 100644
--- a/tests/ui/parser/issues/issue-62524.rs
+++ b/tests/ui/parser/issues/issue-62524.rs
@@ -1,5 +1,5 @@
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 3 previous errors
+// error-pattern: aborting due to previous error
 #![allow(uncommon_codepoints)]
 
 y![
diff --git a/tests/ui/parser/issues/issue-62524.stderr b/tests/ui/parser/issues/issue-62524.stderr
index 55eed0402a4..0cbaacd4c64 100644
--- a/tests/ui/parser/issues/issue-62524.stderr
+++ b/tests/ui/parser/issues/issue-62524.stderr
@@ -6,28 +6,5 @@ LL | y![
 LL | Ϥ,
    |   ^
 
-error: macros that expand to items must be delimited with braces or followed by a semicolon
-  --> $DIR/issue-62524.rs:5:3
-   |
-LL |   y![
-   |  ___^
-LL | | Ϥ,
-   | |__^
-   |
-help: change the delimiters to curly braces
-   |
-LL | y! { /* items */ }
-   |    ~~~~~~~~~~~~~~~
-help: add a semicolon
-   |
-LL | Ϥ,;
-   |   +
-
-error: cannot find macro `y` in this scope
-  --> $DIR/issue-62524.rs:5:1
-   |
-LL | y![
-   | ^
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-62546.rs b/tests/ui/parser/issues/issue-62546.rs
index f06b6505859..bb30d68eabd 100644
--- a/tests/ui/parser/issues/issue-62546.rs
+++ b/tests/ui/parser/issues/issue-62546.rs
@@ -1,3 +1 @@
-pub t(#
-//~^ ERROR missing `fn` or `struct` for function or struct definition
-//~ ERROR this file contains an unclosed delimiter
+pub t(# //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-62546.stderr b/tests/ui/parser/issues/issue-62546.stderr
index 32c61391e16..80c1c71689d 100644
--- a/tests/ui/parser/issues/issue-62546.stderr
+++ b/tests/ui/parser/issues/issue-62546.stderr
@@ -1,17 +1,8 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-62546.rs:3:52
+  --> $DIR/issue-62546.rs:1:60
    |
 LL | pub t(#
-   |      - unclosed delimiter
-LL |
-LL |
-   |                                                    ^
+   |      - unclosed delimiter                                  ^
 
-error: missing `fn` or `struct` for function or struct definition
-  --> $DIR/issue-62546.rs:1:4
-   |
-LL | pub t(#
-   | ---^- help: if you meant to call a macro, try: `t!`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-62554.rs b/tests/ui/parser/issues/issue-62554.rs
index cfd02183cb4..4b463a17333 100644
--- a/tests/ui/parser/issues/issue-62554.rs
+++ b/tests/ui/parser/issues/issue-62554.rs
@@ -1,5 +1,4 @@
 // error-pattern:this file contains an unclosed delimiter
-// error-pattern:xpected `{`, found `macro_rules`
 
 fn main() {}
 
diff --git a/tests/ui/parser/issues/issue-62554.stderr b/tests/ui/parser/issues/issue-62554.stderr
index 9e62572e388..4637c795ae5 100644
--- a/tests/ui/parser/issues/issue-62554.stderr
+++ b/tests/ui/parser/issues/issue-62554.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-62554.rs:6:89
+  --> $DIR/issue-62554.rs:5:89
    |
 LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
    |               -                       -         -                  -                  - ^
@@ -9,65 +9,5 @@ LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s
    |               |                       |         unclosed delimiter
    |               unclosed delimiter      unclosed delimiter
 
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-62554.rs:6:89
-   |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-   |               -                       -         -                  -                  - ^
-   |               |                       |         |                  |                  |
-   |               |                       |         |                  |                  unclosed delimiter
-   |               |                       |         |                  unclosed delimiter
-   |               |                       |         unclosed delimiter
-   |               unclosed delimiter      unclosed delimiter
-
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-62554.rs:6:89
-   |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-   |               -                       -         -                  -                  - ^
-   |               |                       |         |                  |                  |
-   |               |                       |         |                  |                  unclosed delimiter
-   |               |                       |         |                  unclosed delimiter
-   |               |                       |         unclosed delimiter
-   |               unclosed delimiter      unclosed delimiter
-
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-62554.rs:6:89
-   |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-   |               -                       -         -                  -                  - ^
-   |               |                       |         |                  |                  |
-   |               |                       |         |                  |                  unclosed delimiter
-   |               |                       |         |                  unclosed delimiter
-   |               |                       |         unclosed delimiter
-   |               unclosed delimiter      unclosed delimiter
-
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-62554.rs:6:89
-   |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-   |               -                       -         -                  -                  - ^
-   |               |                       |         |                  |                  |
-   |               |                       |         |                  |                  unclosed delimiter
-   |               |                       |         |                  unclosed delimiter
-   |               |                       |         unclosed delimiter
-   |               unclosed delimiter      unclosed delimiter
-
-error: expected `{`, found `macro_rules`
-  --> $DIR/issue-62554.rs:6:23
-   |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-   |                       ^^^^^^^^^^^ expected `{`
-   |
-note: the `if` expression is missing a block after this condition
-  --> $DIR/issue-62554.rs:6:20
-   |
-LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
-   |                    ^^
-help: try placing this code inside a block
-   |
-LL | fn foo(u: u8) { if u8 { macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 { }
-   |                       +                                                                    +
-
-error: aborting due to 6 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-62881.rs b/tests/ui/parser/issues/issue-62881.rs
index b9204595fb9..cc80d449930 100644
--- a/tests/ui/parser/issues/issue-62881.rs
+++ b/tests/ui/parser/issues/issue-62881.rs
@@ -1,6 +1,3 @@
 fn main() {}
 
-fn f() -> isize { fn f() -> isize {} pub f<
-//~^ ERROR missing `fn` or `struct` for function or struct definition
-//~| ERROR mismatched types
-//~ ERROR this file contains an unclosed delimiter
+fn f() -> isize { fn f() -> isize {} pub f< //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-62881.stderr b/tests/ui/parser/issues/issue-62881.stderr
index 87be69baadd..e57cbd1810a 100644
--- a/tests/ui/parser/issues/issue-62881.stderr
+++ b/tests/ui/parser/issues/issue-62881.stderr
@@ -1,26 +1,8 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-62881.rs:6:52
+  --> $DIR/issue-62881.rs:3:96
    |
 LL | fn f() -> isize { fn f() -> isize {} pub f<
-   |                 - unclosed delimiter
-...
-LL |
-   |                                                    ^
+   |                 - unclosed delimiter                                                           ^
 
-error: missing `fn` or `struct` for function or struct definition
-  --> $DIR/issue-62881.rs:3:41
-   |
-LL | fn f() -> isize { fn f() -> isize {} pub f<
-   |                                         ^
-
-error[E0308]: mismatched types
-  --> $DIR/issue-62881.rs:3:29
-   |
-LL | fn f() -> isize { fn f() -> isize {} pub f<
-   |                      -      ^^^^^ expected `isize`, found `()`
-   |                      |
-   |                      implicitly returns `()` as its body has no tail or `return` expression
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/issues/issue-62894.rs b/tests/ui/parser/issues/issue-62894.rs
index b9c0bf834dd..4dfa406ea2d 100644
--- a/tests/ui/parser/issues/issue-62894.rs
+++ b/tests/ui/parser/issues/issue-62894.rs
@@ -1,6 +1,5 @@
 // Regression test for #62894, shouldn't crash.
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected one of `(`, `[`, or `{`, found keyword `fn`
 
 fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
 
diff --git a/tests/ui/parser/issues/issue-62894.stderr b/tests/ui/parser/issues/issue-62894.stderr
index 07a203bf416..700479076df 100644
--- a/tests/ui/parser/issues/issue-62894.stderr
+++ b/tests/ui/parser/issues/issue-62894.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-62894.rs:7:14
+  --> $DIR/issue-62894.rs:6:14
    |
 LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
    |        -           -                   - unclosed delimiter
@@ -10,41 +10,5 @@ LL |
 LL | fn main() {}
    |              ^
 
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-62894.rs:7:14
-   |
-LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
-   |        -           -                   - unclosed delimiter
-   |        |           |
-   |        |           unclosed delimiter
-   |        unclosed delimiter
-LL |
-LL | fn main() {}
-   |              ^
-
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-62894.rs:7:14
-   |
-LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
-   |        -           -                   - unclosed delimiter
-   |        |           |
-   |        |           unclosed delimiter
-   |        unclosed delimiter
-LL |
-LL | fn main() {}
-   |              ^
-
-error: expected one of `(`, `[`, or `{`, found keyword `fn`
-  --> $DIR/issue-62894.rs:7:1
-   |
-LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq!
-   |                                                   - expected one of `(`, `[`, or `{`
-LL |
-LL | fn main() {}
-   | ^^ unexpected token
-  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-   = note: while parsing argument for this `expr` macro fragment
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-62895.rs b/tests/ui/parser/issues/issue-62895.rs
index 53f17405d79..33511dee93e 100644
--- a/tests/ui/parser/issues/issue-62895.rs
+++ b/tests/ui/parser/issues/issue-62895.rs
@@ -1,11 +1,11 @@
 fn main() {}
 
-fn v() -> isize { //~ ERROR mismatched types
-mod _ { //~ ERROR expected identifier
-pub fn g() -> isizee { //~ ERROR cannot find type `isizee` in this scope
-mod _ { //~ ERROR expected identifier
-pub    g() -> is //~ ERROR missing `fn` for function definition
-(), w20);
+fn v() -> isize {
+mod _ {
+pub fn g() -> isizee {
+mod _ {
+pub    g() -> is
+(), w20); //~ ERROR mismatched closing delimiter
 }
-(), w20); //~ ERROR expected item, found `;`
+(), w20); //~ ERROR mismatched closing delimiter
 }
diff --git a/tests/ui/parser/issues/issue-62895.stderr b/tests/ui/parser/issues/issue-62895.stderr
index 2e7e500f478..0ad9ac63ebd 100644
--- a/tests/ui/parser/issues/issue-62895.stderr
+++ b/tests/ui/parser/issues/issue-62895.stderr
@@ -1,47 +1,20 @@
-error: expected identifier, found reserved identifier `_`
-  --> $DIR/issue-62895.rs:4:5
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-62895.rs:6:7
    |
 LL | mod _ {
-   |     ^ expected identifier, found reserved identifier
-
-error: expected identifier, found reserved identifier `_`
-  --> $DIR/issue-62895.rs:6:5
-   |
-LL | mod _ {
-   |     ^ expected identifier, found reserved identifier
-
-error: missing `fn` for function definition
-  --> $DIR/issue-62895.rs:7:4
-   |
+   |       ^ unclosed delimiter
 LL | pub    g() -> is
-   |    ^^^^
-   |
-help: add `fn` here to parse `g` as a public function
-   |
-LL | pub fn g() -> is
-   |     ++
-
-error: expected item, found `;`
-  --> $DIR/issue-62895.rs:10:9
-   |
 LL | (), w20);
-   |         ^ help: remove this semicolon
-
-error[E0412]: cannot find type `isizee` in this scope
-  --> $DIR/issue-62895.rs:5:15
-   |
-LL | pub fn g() -> isizee {
-   |               ^^^^^^ help: a builtin type with a similar name exists: `isize`
+   |        ^ mismatched closing delimiter
 
-error[E0308]: mismatched types
-  --> $DIR/issue-62895.rs:3:11
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-62895.rs:4:7
    |
-LL | fn v() -> isize {
-   |    -      ^^^^^ expected `isize`, found `()`
-   |    |
-   |    implicitly returns `()` as its body has no tail or `return` expression
+LL | mod _ {
+   |       ^ unclosed delimiter
+...
+LL | (), w20);
+   |        ^ mismatched closing delimiter
 
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0308, E0412.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/issues/issue-62973.rs b/tests/ui/parser/issues/issue-62973.rs
index 1c5d0c6f8ab..22d75457702 100644
--- a/tests/ui/parser/issues/issue-62973.rs
+++ b/tests/ui/parser/issues/issue-62973.rs
@@ -1,5 +1,5 @@
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 7 previous errors
+// error-pattern: aborting due to 3 previous errors
 
 fn main() {}
 
diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr
index 3cb6d75a675..14411a8cb78 100644
--- a/tests/ui/parser/issues/issue-62973.stderr
+++ b/tests/ui/parser/issues/issue-62973.stderr
@@ -1,72 +1,3 @@
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-62973.rs:8:2
-   |
-LL | fn p() { match s { v, E { [) {) }
-   |        -         -         -  - missing open `(` for this delimiter
-   |        |         |         |
-   |        |         |         missing open `(` for this delimiter
-   |        |         unclosed delimiter
-   |        unclosed delimiter
-LL |
-LL |
-   |  ^
-
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-62973.rs:8:2
-   |
-LL | fn p() { match s { v, E { [) {) }
-   |        -         -         -  - missing open `(` for this delimiter
-   |        |         |         |
-   |        |         |         missing open `(` for this delimiter
-   |        |         unclosed delimiter
-   |        unclosed delimiter
-LL |
-LL |
-   |  ^
-
-error: expected one of `,`, `:`, or `}`, found `{`
-  --> $DIR/issue-62973.rs:6:8
-   |
-LL | fn p() { match s { v, E { [) {) }
-   |        ^       -        ^ expected one of `,`, `:`, or `}`
-   |        |       |
-   |        |       while parsing this struct
-   |        unclosed delimiter
-   |
-help: `}` may belong here
-   |
-LL | fn p() { match s { v, E} { [) {) }
-   |                        +
-help: try naming a field
-   |
-LL | fn p() { match s { v, E: E { [) {) }
-   |                       ++
-
-error: struct literals are not allowed here
-  --> $DIR/issue-62973.rs:6:16
-   |
-LL |   fn p() { match s { v, E { [) {) }
-   |  ________________^
-LL | |
-LL | |
-   | |_^
-   |
-help: surround the struct literal with parentheses
-   |
-LL ~ fn p() { match (s { v, E { [) {) }
-LL | 
-LL ~ )
-   |
-
-error: expected one of `.`, `?`, `{`, or an operator, found `}`
-  --> $DIR/issue-62973.rs:8:2
-   |
-LL | fn p() { match s { v, E { [) {) }
-   |          ----- while parsing this `match` expression
-LL |
-LL |
-   |  ^ expected one of `.`, `?`, `{`, or an operator
-
 error: mismatched closing delimiter: `)`
   --> $DIR/issue-62973.rs:6:27
    |
@@ -83,5 +14,18 @@ LL | fn p() { match s { v, E { [) {) }
    |                              |
    |                              unclosed delimiter
 
-error: aborting due to 7 previous errors
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-62973.rs:8:2
+   |
+LL | fn p() { match s { v, E { [) {) }
+   |        -         -         -  - missing open `(` for this delimiter
+   |        |         |         |
+   |        |         |         missing open `(` for this delimiter
+   |        |         unclosed delimiter
+   |        unclosed delimiter
+LL |
+LL |
+   |  ^
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/issues/issue-63116.rs b/tests/ui/parser/issues/issue-63116.rs
index 430bc1d716c..6b9d9cdbeb1 100644
--- a/tests/ui/parser/issues/issue-63116.rs
+++ b/tests/ui/parser/issues/issue-63116.rs
@@ -1,3 +1,3 @@
 // fixed by #66361
-// error-pattern: aborting due to 3 previous errors
+// error-pattern: aborting due to 2 previous errors
 impl W <s(f;Y(;]
diff --git a/tests/ui/parser/issues/issue-63116.stderr b/tests/ui/parser/issues/issue-63116.stderr
index a1f8a77ffa7..27c94f337bd 100644
--- a/tests/ui/parser/issues/issue-63116.stderr
+++ b/tests/ui/parser/issues/issue-63116.stderr
@@ -1,3 +1,11 @@
+error: mismatched closing delimiter: `]`
+  --> $DIR/issue-63116.rs:3:14
+   |
+LL | impl W <s(f;Y(;]
+   |              ^ ^ mismatched closing delimiter
+   |              |
+   |              unclosed delimiter
+
 error: this file contains an unclosed delimiter
   --> $DIR/issue-63116.rs:3:18
    |
@@ -7,19 +15,5 @@ LL | impl W <s(f;Y(;]
    |          |     missing open `[` for this delimiter
    |          unclosed delimiter
 
-error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
-  --> $DIR/issue-63116.rs:3:12
-   |
-LL | impl W <s(f;Y(;]
-   |            ^ expected one of 7 possible tokens
-
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-63116.rs:3:14
-   |
-LL | impl W <s(f;Y(;]
-   |              ^ ^ mismatched closing delimiter
-   |              |
-   |              unclosed delimiter
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/issues/issue-63135.rs b/tests/ui/parser/issues/issue-63135.rs
index a5a8de85466..d61197dc566 100644
--- a/tests/ui/parser/issues/issue-63135.rs
+++ b/tests/ui/parser/issues/issue-63135.rs
@@ -1,3 +1,3 @@
-// error-pattern: aborting due to 5 previous errors
-
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: aborting due to previous error
 fn i(n{...,f #
diff --git a/tests/ui/parser/issues/issue-63135.stderr b/tests/ui/parser/issues/issue-63135.stderr
index e0dc356d546..ff9d99c28fe 100644
--- a/tests/ui/parser/issues/issue-63135.stderr
+++ b/tests/ui/parser/issues/issue-63135.stderr
@@ -7,42 +7,5 @@ LL | fn i(n{...,f #
    |     | unclosed delimiter
    |     unclosed delimiter
 
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-63135.rs:3:16
-   |
-LL | fn i(n{...,f #
-   |     - -        ^
-   |     | |
-   |     | unclosed delimiter
-   |     unclosed delimiter
-
-error: expected field pattern, found `...`
-  --> $DIR/issue-63135.rs:3:8
-   |
-LL | fn i(n{...,f #
-   |        ^^^
-   |
-help: to omit remaining fields, use `..`
-   |
-LL | fn i(n{..,f #
-   |        ~~
-
-error: expected `}`, found `,`
-  --> $DIR/issue-63135.rs:3:11
-   |
-LL | fn i(n{...,f #
-   |        ---^
-   |        |  |
-   |        |  expected `}`
-   |        `..` must be at the end and cannot have a trailing comma
-
-error: expected one of `!` or `[`, found `}`
-  --> $DIR/issue-63135.rs:3:16
-   |
-LL | fn i(n{...,f #
-   |      -         ^ expected one of `!` or `[`
-   |      |
-   |      while parsing the fields for this pattern
-
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs
index aed428bfc2a..69a2dfe6cbd 100644
--- a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs
+++ b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.rs
@@ -9,6 +9,4 @@
 //
 // ended up bubbling up `Ok(true)` to `unexpected` which then used `unreachable!()`.
 
-fn f() { |[](* }
-//~^ ERROR expected one of `,` or `:`, found `(`
-//~| ERROR expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
+fn f() { |[](* } //~ ERROR mismatched closing delimiter
diff --git a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr
index 6cbab855c76..079fff37ea4 100644
--- a/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr
+++ b/tests/ui/parser/issues/issue-66357-unexpected-unreachable.stderr
@@ -1,16 +1,11 @@
-error: expected one of `,` or `:`, found `(`
+error: mismatched closing delimiter: `}`
   --> $DIR/issue-66357-unexpected-unreachable.rs:12:13
    |
 LL | fn f() { |[](* }
-   |             ^ expected one of `,` or `:`
+   |        -    ^  ^ mismatched closing delimiter
+   |        |    |
+   |        |    unclosed delimiter
+   |        closing delimiter possibly meant for this
 
-error: expected one of `&`, `(`, `)`, `-`, `...`, `..=`, `..`, `[`, `_`, `box`, `mut`, `ref`, `|`, identifier, or path, found `*`
-  --> $DIR/issue-66357-unexpected-unreachable.rs:12:13
-   |
-LL | fn f() { |[](* }
-   |             ^^ help: `)` may belong here
-   |             |
-   |             unclosed delimiter
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs
index 87222ef4b59..e712160fcf8 100644
--- a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs
+++ b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.rs
@@ -4,9 +4,6 @@ mod a {
     enum Bug {
         V = [PhantomData; { [ () ].len() ].len() as isize,
         //~^ ERROR mismatched closing delimiter: `]`
-        //~| ERROR mismatched closing delimiter: `]`
-        //~| ERROR mismatched closing delimiter: `]`
-        //~| ERROR mismatched closing delimiter: `]`
     }
 }
 
@@ -14,10 +11,6 @@ mod b {
     enum Bug {
         V = [Vec::new; { [].len()  ].len() as isize,
         //~^ ERROR mismatched closing delimiter: `]`
-        //~| ERROR mismatched closing delimiter: `]`
-        //~| ERROR mismatched closing delimiter: `]`
-        //~| ERROR mismatched closing delimiter: `]`
-        //~| ERROR type annotations needed
     }
 }
 
@@ -25,11 +18,6 @@ mod c {
     enum Bug {
         V = [Vec::new; { [0].len() ].len() as isize,
         //~^ ERROR mismatched closing delimiter: `]`
-        //~| ERROR mismatched closing delimiter: `]`
-        //~| ERROR mismatched closing delimiter: `]`
-        //~| ERROR mismatched closing delimiter: `]`
-        //~| ERROR type annotations needed
-    }
 }
 
-fn main() {}
+fn main() {} //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
index a00f37ed606..9f631edf680 100644
--- a/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
+++ b/tests/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
@@ -8,7 +8,7 @@ LL |         V = [PhantomData; { [ () ].len() ].len() as isize,
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:12:24
    |
 LL |         V = [Vec::new; { [].len()  ].len() as isize,
    |             -          ^           ^ mismatched closing delimiter
@@ -17,7 +17,7 @@ LL |         V = [Vec::new; { [].len()  ].len() as isize,
    |             closing delimiter possibly meant for this
 
 error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:19:24
    |
 LL |         V = [Vec::new; { [0].len() ].len() as isize,
    |             -          ^           ^ mismatched closing delimiter
@@ -25,104 +25,23 @@ LL |         V = [Vec::new; { [0].len() ].len() as isize,
    |             |          unclosed delimiter
    |             closing delimiter possibly meant for this
 
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
-   |
-LL |         V = [PhantomData; { [ () ].len() ].len() as isize,
-   |             -             ^              ^ mismatched closing delimiter
-   |             |             |
-   |             |             unclosed delimiter
-   |             closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
-   |
-LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |             -          ^           ^ mismatched closing delimiter
-   |             |          |
-   |             |          unclosed delimiter
-   |             closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
-   |
-LL |         V = [Vec::new; { [0].len() ].len() as isize,
-   |             -          ^           ^ mismatched closing delimiter
-   |             |          |
-   |             |          unclosed delimiter
-   |             closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
-   |
-LL |         V = [PhantomData; { [ () ].len() ].len() as isize,
-   |             -             ^              ^ mismatched closing delimiter
-   |             |             |
-   |             |             unclosed delimiter
-   |             closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
-   |
-LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |             -          ^           ^ mismatched closing delimiter
-   |             |          |
-   |             |          unclosed delimiter
-   |             closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
-   |
-LL |         V = [Vec::new; { [0].len() ].len() as isize,
-   |             -          ^           ^ mismatched closing delimiter
-   |             |          |
-   |             |          unclosed delimiter
-   |             closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:5:27
+error: this file contains an unclosed delimiter
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:23:65
    |
 LL |         V = [PhantomData; { [ () ].len() ].len() as isize,
-   |             -             ^              ^ mismatched closing delimiter
-   |             |             |
-   |             |             unclosed delimiter
-   |             closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:24
-   |
+   |                                          - missing open `[` for this delimiter
+...
 LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |             -          ^           ^ mismatched closing delimiter
-   |             |          |
-   |             |          unclosed delimiter
-   |             closing delimiter possibly meant for this
-
-error: mismatched closing delimiter: `]`
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:24
-   |
+   |                                    - missing open `[` for this delimiter
+...
+LL | mod c {
+   |       - unclosed delimiter
+LL |     enum Bug {
 LL |         V = [Vec::new; { [0].len() ].len() as isize,
-   |             -          ^           ^ mismatched closing delimiter
-   |             |          |
-   |             |          unclosed delimiter
-   |             closing delimiter possibly meant for this
-
-error[E0282]: type annotations needed
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:26
-   |
-LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |                          ^^ cannot infer type for type parameter `T`
-
-error[E0282]: type annotations needed
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:14
-   |
-LL |         V = [Vec::new; { [0].len() ].len() as isize,
-   |              ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Vec`
-   |
-help: consider specifying the generic argument
-   |
-LL |         V = [Vec::<T>::new; { [0].len() ].len() as isize,
-   |                 +++++
+   |                                    - missing open `[` for this delimiter
+...
+LL | fn main() {}
+   |                                                                 ^
 
-error: aborting due to 14 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/parser/issues/issue-68629.rs b/tests/ui/parser/issues/issue-68629.rs
index 672a31f12c8..af89bb58699 100644
--- a/tests/ui/parser/issues/issue-68629.rs
+++ b/tests/ui/parser/issues/issue-68629.rs
Binary files differdiff --git a/tests/ui/parser/issues/issue-68629.stderr b/tests/ui/parser/issues/issue-68629.stderr
index 43a903e6c46..2562baa1c49 100644
--- a/tests/ui/parser/issues/issue-68629.stderr
+++ b/tests/ui/parser/issues/issue-68629.stderr
Binary files differdiff --git a/tests/ui/parser/issues/issue-84104.rs b/tests/ui/parser/issues/issue-84104.rs
index 998949b94a4..962eb69bd83 100644
--- a/tests/ui/parser/issues/issue-84104.rs
+++ b/tests/ui/parser/issues/issue-84104.rs
@@ -1,3 +1,2 @@
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected one of
 #[i=i::<ښܖ<
diff --git a/tests/ui/parser/issues/issue-84104.stderr b/tests/ui/parser/issues/issue-84104.stderr
index aff31f2c971..7ad59f8450e 100644
--- a/tests/ui/parser/issues/issue-84104.stderr
+++ b/tests/ui/parser/issues/issue-84104.stderr
@@ -1,16 +1,10 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-84104.rs:3:13
+  --> $DIR/issue-84104.rs:2:13
    |
 LL | #[i=i::<ښܖ<
    |  -          ^
    |  |
    |  unclosed delimiter
 
-error: expected one of `>`, a const expression, lifetime, or type, found `]`
-  --> $DIR/issue-84104.rs:3:13
-   |
-LL | #[i=i::<ښܖ<
-   |             ^ expected one of `>`, a const expression, lifetime, or type
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-84148-2.rs b/tests/ui/parser/issues/issue-84148-2.rs
index 2f6a7facfb2..e677abde5f6 100644
--- a/tests/ui/parser/issues/issue-84148-2.rs
+++ b/tests/ui/parser/issues/issue-84148-2.rs
@@ -1,3 +1,2 @@
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: invalid `?` in type
 fn f(t:for<>t?
diff --git a/tests/ui/parser/issues/issue-84148-2.stderr b/tests/ui/parser/issues/issue-84148-2.stderr
index 71d543f9b73..20761180e77 100644
--- a/tests/ui/parser/issues/issue-84148-2.stderr
+++ b/tests/ui/parser/issues/issue-84148-2.stderr
@@ -1,27 +1,10 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-84148-2.rs:3:16
+  --> $DIR/issue-84148-2.rs:2:16
    |
 LL | fn f(t:for<>t?
    |     -          ^
    |     |
    |     unclosed delimiter
 
-error: invalid `?` in type
-  --> $DIR/issue-84148-2.rs:3:14
-   |
-LL | fn f(t:for<>t?
-   |              ^ `?` is only allowed on expressions, not types
-   |
-help: if you meant to express that the type might not contain a value, use the `Option` wrapper type
-   |
-LL | fn f(t:Option<for<>t>
-   |        +++++++      ~
-
-error: expected one of `->`, `where`, or `{`, found `<eof>`
-  --> $DIR/issue-84148-2.rs:3:16
-   |
-LL | fn f(t:for<>t?
-   |                ^ expected one of `->`, `where`, or `{`
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/issues/issue-88770.rs b/tests/ui/parser/issues/issue-88770.rs
index bb69951c7b4..9341415b2d9 100644
--- a/tests/ui/parser/issues/issue-88770.rs
+++ b/tests/ui/parser/issues/issue-88770.rs
@@ -1,9 +1,6 @@
 // Regression test for the ICE described in #88770.
 
 // error-pattern:this file contains an unclosed delimiter
-// error-pattern:expected one of
-// error-pattern:missing `in` in `for` loop
-// error-pattern:expected one of `!`, `)`, `,`, `.`, `::`, `;`, `?`, `{`, or an operator, found `e`
 
 fn m(){print!("",(c for&g
 u
diff --git a/tests/ui/parser/issues/issue-88770.stderr b/tests/ui/parser/issues/issue-88770.stderr
index 4e3a21613ec..836f44953d4 100644
--- a/tests/ui/parser/issues/issue-88770.stderr
+++ b/tests/ui/parser/issues/issue-88770.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-88770.rs:11:3
+  --> $DIR/issue-88770.rs:8:3
    |
 LL | fn m(){print!("",(c for&g
    |       -      -   - unclosed delimiter
@@ -10,51 +10,5 @@ LL | fn m(){print!("",(c for&g
 LL | e
    |   ^
 
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-88770.rs:11:3
-   |
-LL | fn m(){print!("",(c for&g
-   |       -      -   - unclosed delimiter
-   |       |      |
-   |       |      unclosed delimiter
-   |       unclosed delimiter
-...
-LL | e
-   |   ^
-
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-88770.rs:11:3
-   |
-LL | fn m(){print!("",(c for&g
-   |       -      -   - unclosed delimiter
-   |       |      |
-   |       |      unclosed delimiter
-   |       unclosed delimiter
-...
-LL | e
-   |   ^
-
-error: missing `in` in `for` loop
-  --> $DIR/issue-88770.rs:8:26
-   |
-LL |   fn m(){print!("",(c for&g
-   |  __________________________^
-LL | | u
-   | |_ help: try adding `in` here
-
-error: expected one of `!`, `)`, `,`, `.`, `::`, `?`, `{`, or an operator, found keyword `for`
-  --> $DIR/issue-88770.rs:8:21
-   |
-LL | fn m(){print!("",(c for&g
-   |                     ^^^ expected one of 8 possible tokens
-
-error: expected one of `!`, `)`, `,`, `.`, `::`, `;`, `?`, `{`, or an operator, found `e`
-  --> $DIR/issue-88770.rs:11:1
-   |
-LL | e
-   |  - expected one of 9 possible tokens
-LL | e
-   | ^ unexpected token
-
-error: aborting due to 6 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr b/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr
index 689ce1eb6b7..34217e21ae9 100644
--- a/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr
+++ b/tests/ui/parser/macro-mismatched-delim-paren-brace.stderr
@@ -1,3 +1,12 @@
+error: mismatched closing delimiter: `}`
+  --> $DIR/macro-mismatched-delim-paren-brace.rs:2:10
+   |
+LL |     foo! (
+   |          ^ unclosed delimiter
+LL |         bar, "baz", 1, 2.0
+LL |     }
+   |     ^ mismatched closing delimiter
+
 error: unexpected closing delimiter: `}`
   --> $DIR/macro-mismatched-delim-paren-brace.rs:5:1
    |
@@ -9,14 +18,5 @@ LL |     }
 LL | }
    | ^ unexpected closing delimiter
 
-error: mismatched closing delimiter: `}`
-  --> $DIR/macro-mismatched-delim-paren-brace.rs:2:10
-   |
-LL |     foo! (
-   |          ^ unclosed delimiter
-LL |         bar, "baz", 1, 2.0
-LL |     }
-   |     ^ mismatched closing delimiter
-
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/match-arm-without-braces.stderr b/tests/ui/parser/match-arm-without-braces.stderr
index 37d55aa53f8..ee1c8e562fc 100644
--- a/tests/ui/parser/match-arm-without-braces.stderr
+++ b/tests/ui/parser/match-arm-without-braces.stderr
@@ -2,10 +2,14 @@ error: `match` arm body without braces
   --> $DIR/match-arm-without-braces.rs:26:27
    |
 LL |         Some(Val::Foo) => 3;
-   |                        -- ^- help: use a comma to end a `match` arm expression: `,`
-   |                        |  |
-   |                        |  this statement is not surrounded by a body
+   |                        -- ^ this statement is not surrounded by a body
+   |                        |
    |                        while parsing the `match` arm starting here
+   |
+help: replace `;` with `,` to end a `match` arm expression
+   |
+LL |         Some(Val::Foo) => 3,
+   |                            ~
 
 error: `match` arm body without braces
   --> $DIR/match-arm-without-braces.rs:31:11
diff --git a/tests/ui/parser/mbe_missing_right_paren.rs b/tests/ui/parser/mbe_missing_right_paren.rs
index 689176b3eb7..9a92e67da4d 100644
--- a/tests/ui/parser/mbe_missing_right_paren.rs
+++ b/tests/ui/parser/mbe_missing_right_paren.rs
@@ -1,3 +1,3 @@
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 3 previous errors
+// error-pattern: this file contains an unclosed delimiter
 macro_rules! abc(ؼ
\ No newline at end of file
diff --git a/tests/ui/parser/mbe_missing_right_paren.stderr b/tests/ui/parser/mbe_missing_right_paren.stderr
index ccaf77d3995..d2af94683ef 100644
--- a/tests/ui/parser/mbe_missing_right_paren.stderr
+++ b/tests/ui/parser/mbe_missing_right_paren.stderr
@@ -6,26 +6,5 @@ LL | macro_rules! abc(ؼ
    |                 |
    |                 unclosed delimiter
 
-error: macros that expand to items must be delimited with braces or followed by a semicolon
-  --> $DIR/mbe_missing_right_paren.rs:3:17
-   |
-LL | macro_rules! abc(ؼ
-   |                 ^^
-   |
-help: change the delimiters to curly braces
-   |
-LL | macro_rules! abc { /* items */ }
-   |                  ~~~~~~~~~~~~~~~
-help: add a semicolon
-   |
-LL | macro_rules! abc(ؼ;
-   |                   +
-
-error: unexpected end of macro invocation
-  --> $DIR/mbe_missing_right_paren.rs:3:19
-   |
-LL | macro_rules! abc(ؼ
-   |                   ^ missing tokens in macro arguments
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
index 8f46970b1af..79de98d8b8c 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs
@@ -1,13 +1,13 @@
 fn main() {}
 
-impl T for () { //~ ERROR cannot find trait `T` in this scope
+impl T for () {
 
 fn foo(&self) {}
 
-trait T { //~ ERROR trait is not supported in `trait`s or `impl`s
+trait T {
     fn foo(&self);
 }
 
-pub(crate) struct Bar<T>(); //~ ERROR struct is not supported in `trait`s or `impl`s
+pub(crate) struct Bar<T>();
 
 //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
index cc7cc0c55d5..d91a7f0542d 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr
@@ -7,28 +7,5 @@ LL | impl T for () {
 LL |
    |                                                    ^
 
-error: trait is not supported in `trait`s or `impl`s
-  --> $DIR/missing-close-brace-in-impl-trait.rs:7:1
-   |
-LL | trait T {
-   | ^^^^^^^
-   |
-   = help: consider moving the trait out to a nearby module scope
-
-error: struct is not supported in `trait`s or `impl`s
-  --> $DIR/missing-close-brace-in-impl-trait.rs:11:1
-   |
-LL | pub(crate) struct Bar<T>();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider moving the struct out to a nearby module scope
-
-error[E0405]: cannot find trait `T` in this scope
-  --> $DIR/missing-close-brace-in-impl-trait.rs:3:6
-   |
-LL | impl T for () {
-   |      ^ not found in this scope
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs
index 090a17b413d..88bc7257687 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.rs
@@ -1,7 +1,7 @@
 pub(crate) struct Bar<T> {
   foo: T,
 
-trait T { //~ ERROR expected identifier, found keyword `trait`
+trait T {
     fn foo(&self);
 }
 
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
index ad1e90e43ec..d01d9ed60e4 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
@@ -7,14 +7,5 @@ LL | pub(crate) struct Bar<T> {
 LL | fn main() {}
    |                                                                 ^
 
-error: expected identifier, found keyword `trait`
-  --> $DIR/missing-close-brace-in-struct.rs:4:1
-   |
-LL | pub(crate) struct Bar<T> {
-   |                   --- while parsing this struct
-...
-LL | trait T {
-   | ^^^^^ expected identifier, found keyword
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
index b6932deb5c0..a05d6aa8edc 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs
@@ -2,10 +2,9 @@ trait T {
     fn foo(&self);
 
 pub(crate) struct Bar<T>();
-//~^ ERROR struct is not supported in `trait`s or `impl`s
 
 impl T for Bar<usize> {
-//~^ ERROR implementation is not supported in `trait`s or `impl`s
+
 fn foo(&self) {}
 }
 
diff --git a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
index 7c6254356e0..7418dd64c9e 100644
--- a/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
+++ b/tests/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/missing-close-brace-in-trait.rs:12:65
+  --> $DIR/missing-close-brace-in-trait.rs:11:65
    |
 LL | trait T {
    |         - unclosed delimiter
@@ -7,21 +7,5 @@ LL | trait T {
 LL | fn main() {}
    |                                                                 ^
 
-error: struct is not supported in `trait`s or `impl`s
-  --> $DIR/missing-close-brace-in-trait.rs:4:1
-   |
-LL | pub(crate) struct Bar<T>();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider moving the struct out to a nearby module scope
-
-error: implementation is not supported in `trait`s or `impl`s
-  --> $DIR/missing-close-brace-in-trait.rs:7:1
-   |
-LL | impl T for Bar<usize> {
-   | ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider moving the implementation out to a nearby module scope
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/missing_right_paren.rs b/tests/ui/parser/missing_right_paren.rs
index 810dee9571d..e240f8c6739 100644
--- a/tests/ui/parser/missing_right_paren.rs
+++ b/tests/ui/parser/missing_right_paren.rs
@@ -1,3 +1,4 @@
 // ignore-tidy-trailing-newlines
-// error-pattern: aborting due to 4 previous errors
+// error-pattern: this file contains an unclosed delimiter
+// error-pattern: aborting due to previous error
 fn main((ؼ
\ No newline at end of file
diff --git a/tests/ui/parser/missing_right_paren.stderr b/tests/ui/parser/missing_right_paren.stderr
index 3fe0d0f4273..994ce4d8541 100644
--- a/tests/ui/parser/missing_right_paren.stderr
+++ b/tests/ui/parser/missing_right_paren.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/missing_right_paren.rs:3:11
+  --> $DIR/missing_right_paren.rs:4:11
    |
 LL | fn main((ؼ
    |        -- ^
@@ -7,26 +7,5 @@ LL | fn main((ؼ
    |        |unclosed delimiter
    |        unclosed delimiter
 
-error: this file contains an unclosed delimiter
-  --> $DIR/missing_right_paren.rs:3:11
-   |
-LL | fn main((ؼ
-   |        -- ^
-   |        ||
-   |        |unclosed delimiter
-   |        unclosed delimiter
-
-error: expected one of `:` or `|`, found `)`
-  --> $DIR/missing_right_paren.rs:3:11
-   |
-LL | fn main((ؼ
-   |           ^ expected one of `:` or `|`
-
-error: expected one of `->`, `where`, or `{`, found `<eof>`
-  --> $DIR/missing_right_paren.rs:3:11
-   |
-LL | fn main((ؼ
-   |           ^ expected one of `->`, `where`, or `{`
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/parser/parser-recovery-1.rs b/tests/ui/parser/parser-recovery-1.rs
index 7e26b4f2b6a..5f729665cb8 100644
--- a/tests/ui/parser/parser-recovery-1.rs
+++ b/tests/ui/parser/parser-recovery-1.rs
@@ -3,11 +3,8 @@
 trait Foo {
     fn bar() {
         let x = foo();
-        //~^ ERROR cannot find function `foo` in this scope
 }
 
 fn main() {
     let x = y.;
-    //~^ ERROR unexpected token
-    //~| ERROR cannot find value `y` in this scope
 } //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/parser/parser-recovery-1.stderr b/tests/ui/parser/parser-recovery-1.stderr
index 0cb771ea39c..7045b6f5b78 100644
--- a/tests/ui/parser/parser-recovery-1.stderr
+++ b/tests/ui/parser/parser-recovery-1.stderr
@@ -1,35 +1,16 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/parser-recovery-1.rs:13:54
+  --> $DIR/parser-recovery-1.rs:10:54
    |
 LL | trait Foo {
    |           - unclosed delimiter
 LL |     fn bar() {
    |              - this delimiter might not be properly closed...
-...
+LL |         let x = foo();
 LL | }
    | - ...as it matches this but it has different indentation
 ...
 LL | }
    |                                                      ^
 
-error: unexpected token: `;`
-  --> $DIR/parser-recovery-1.rs:10:15
-   |
-LL |     let x = y.;
-   |               ^
-
-error[E0425]: cannot find value `y` in this scope
-  --> $DIR/parser-recovery-1.rs:10:13
-   |
-LL |     let x = y.;
-   |             ^ not found in this scope
-
-error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/parser-recovery-1.rs:5:17
-   |
-LL |         let x = foo();
-   |                 ^^^ not found in this scope
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/parser/parser-recovery-2.rs b/tests/ui/parser/parser-recovery-2.rs
index 48b22afffe7..203d8aac66c 100644
--- a/tests/ui/parser/parser-recovery-2.rs
+++ b/tests/ui/parser/parser-recovery-2.rs
@@ -2,11 +2,10 @@
 
 trait Foo {
     fn bar() {
-        let x = foo(); //~ ERROR cannot find function `foo` in this scope
+        let x = foo();
     ) //~ ERROR mismatched closing delimiter: `)`
 }
 
 fn main() {
-    let x = y.;  //~ ERROR unexpected token
-                 //~^ ERROR cannot find value `y` in this scope
+    let x = y.;
 }
diff --git a/tests/ui/parser/parser-recovery-2.stderr b/tests/ui/parser/parser-recovery-2.stderr
index 8829cf4c1e1..f396e5fde5b 100644
--- a/tests/ui/parser/parser-recovery-2.stderr
+++ b/tests/ui/parser/parser-recovery-2.stderr
@@ -1,9 +1,3 @@
-error: unexpected token: `;`
-  --> $DIR/parser-recovery-2.rs:10:15
-   |
-LL |     let x = y.;
-   |               ^
-
 error: mismatched closing delimiter: `)`
   --> $DIR/parser-recovery-2.rs:4:14
    |
@@ -13,18 +7,5 @@ LL |         let x = foo();
 LL |     )
    |     ^ mismatched closing delimiter
 
-error[E0425]: cannot find value `y` in this scope
-  --> $DIR/parser-recovery-2.rs:10:13
-   |
-LL |     let x = y.;
-   |             ^ not found in this scope
-
-error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/parser-recovery-2.rs:5:17
-   |
-LL |         let x = foo();
-   |                 ^^^ not found in this scope
-
-error: aborting due to 4 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/parser/unclosed-delimiter-in-dep.rs b/tests/ui/parser/unclosed-delimiter-in-dep.rs
index 6db1b66e9f7..4de83ee640a 100644
--- a/tests/ui/parser/unclosed-delimiter-in-dep.rs
+++ b/tests/ui/parser/unclosed-delimiter-in-dep.rs
@@ -2,5 +2,4 @@ mod unclosed_delim_mod;
 
 fn main() {
     let _: usize = unclosed_delim_mod::new();
-    //~^ ERROR mismatched types
 }
diff --git a/tests/ui/parser/unclosed-delimiter-in-dep.stderr b/tests/ui/parser/unclosed-delimiter-in-dep.stderr
index d1725c60dbb..a46d020b967 100644
--- a/tests/ui/parser/unclosed-delimiter-in-dep.stderr
+++ b/tests/ui/parser/unclosed-delimiter-in-dep.stderr
@@ -9,17 +9,5 @@ LL |     }
 LL | }
    | ^ mismatched closing delimiter
 
-error[E0308]: mismatched types
-  --> $DIR/unclosed-delimiter-in-dep.rs:4:20
-   |
-LL |     let _: usize = unclosed_delim_mod::new();
-   |            -----   ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `Result<Value, ()>`
-   |            |
-   |            expected due to this
-   |
-   = note: expected type `usize`
-              found enum `Result<Value, ()>`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/use-unclosed-brace.rs b/tests/ui/parser/use-unclosed-brace.rs
index 41742f37f3c..fcfe95b26f9 100644
--- a/tests/ui/parser/use-unclosed-brace.rs
+++ b/tests/ui/parser/use-unclosed-brace.rs
@@ -1,6 +1,4 @@
-// error-pattern: expected one of `,`, `::`, `as`, or `}`, found `;`
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected item, found `}`
 use foo::{bar, baz;
 
 use std::fmt::Display;
diff --git a/tests/ui/parser/use-unclosed-brace.stderr b/tests/ui/parser/use-unclosed-brace.stderr
index 438fe9c47ea..ad5bb2de1b2 100644
--- a/tests/ui/parser/use-unclosed-brace.stderr
+++ b/tests/ui/parser/use-unclosed-brace.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/use-unclosed-brace.rs:12:14
+  --> $DIR/use-unclosed-brace.rs:10:14
    |
 LL | use foo::{bar, baz;
    |          - unclosed delimiter
@@ -7,21 +7,5 @@ LL | use foo::{bar, baz;
 LL | fn main() {}
    |              ^
 
-error: expected one of `,`, `::`, `as`, or `}`, found `;`
-  --> $DIR/use-unclosed-brace.rs:4:10
-   |
-LL | use foo::{bar, baz;
-   |          ^        ^
-   |          |        |
-   |          |        expected one of `,`, `::`, `as`, or `}`
-   |          |        help: `}` may belong here
-   |          unclosed delimiter
-
-error: expected item, found `}`
-  --> $DIR/use-unclosed-brace.rs:12:14
-   |
-LL | fn main() {}
-   |              ^ expected item
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs
index 107eba45dc2..7ae14c6b84d 100644
--- a/tests/ui/process/process-sigpipe.rs
+++ b/tests/ui/process/process-sigpipe.rs
@@ -15,6 +15,7 @@
 // ignore-emscripten no threads support
 // ignore-vxworks no 'sh'
 // ignore-fuchsia no 'sh'
+// ignore-nto no 'yes'
 
 use std::process;
 use std::thread;
diff --git a/tests/ui/resolve/issue-108529.rs b/tests/ui/resolve/issue-108529.rs
new file mode 100644
index 00000000000..8e3aafab6aa
--- /dev/null
+++ b/tests/ui/resolve/issue-108529.rs
@@ -0,0 +1,8 @@
+#![allow(nonstandard_style)]
+use f::f::f; //~ ERROR
+
+trait f {
+    extern "C" fn f();
+}
+
+fn main() {}
diff --git a/tests/ui/resolve/issue-108529.stderr b/tests/ui/resolve/issue-108529.stderr
new file mode 100644
index 00000000000..cf4e4759c37
--- /dev/null
+++ b/tests/ui/resolve/issue-108529.stderr
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `f::f`
+  --> $DIR/issue-108529.rs:2:8
+   |
+LL | use f::f::f;
+   |        ^ expected type, found associated function `f` in `f`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/tests/ui/resolve/token-error-correct-2.rs b/tests/ui/resolve/token-error-correct-2.rs
index f7c7d908c78..a38755dae08 100644
--- a/tests/ui/resolve/token-error-correct-2.rs
+++ b/tests/ui/resolve/token-error-correct-2.rs
@@ -2,6 +2,5 @@
 
 fn main() {
     if foo {
-    //~^ ERROR: cannot find value `foo`
     ) //~ ERROR: mismatched closing delimiter: `)`
 }
diff --git a/tests/ui/resolve/token-error-correct-2.stderr b/tests/ui/resolve/token-error-correct-2.stderr
index cca9f2dc88c..be5fb18a5d8 100644
--- a/tests/ui/resolve/token-error-correct-2.stderr
+++ b/tests/ui/resolve/token-error-correct-2.stderr
@@ -3,16 +3,8 @@ error: mismatched closing delimiter: `)`
    |
 LL |     if foo {
    |            ^ unclosed delimiter
-LL |
 LL |     )
    |     ^ mismatched closing delimiter
 
-error[E0425]: cannot find value `foo` in this scope
-  --> $DIR/token-error-correct-2.rs:4:8
-   |
-LL |     if foo {
-   |        ^^^ not found in this scope
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/resolve/token-error-correct-3.rs b/tests/ui/resolve/token-error-correct-3.rs
index 52934085fa1..2793f1b90ff 100644
--- a/tests/ui/resolve/token-error-correct-3.rs
+++ b/tests/ui/resolve/token-error-correct-3.rs
@@ -9,12 +9,9 @@ pub mod raw {
                                                                callback: F)
                                                                -> io::Result<bool> {
         if !is_directory(path.as_ref()) {
-            //~^ ERROR cannot find function `is_directory`
             callback(path.as_ref();
-            //~^ ERROR expected one of
             fs::create_dir_all(path.as_ref()).map(|()| true)
-        } else {
-            //~^ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
+        } else {  //~ ERROR mismatched closing delimiter
             Ok(false);
         }
 
diff --git a/tests/ui/resolve/token-error-correct-3.stderr b/tests/ui/resolve/token-error-correct-3.stderr
index 77c87c78466..79d1d4883a1 100644
--- a/tests/ui/resolve/token-error-correct-3.stderr
+++ b/tests/ui/resolve/token-error-correct-3.stderr
@@ -1,25 +1,13 @@
-error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
-  --> $DIR/token-error-correct-3.rs:13:21
+error: mismatched closing delimiter: `}`
+  --> $DIR/token-error-correct-3.rs:12:21
    |
+LL |         if !is_directory(path.as_ref()) {
+   |                                         - closing delimiter possibly meant for this
 LL |             callback(path.as_ref();
-   |                     ^             ^ help: `)` may belong here
-   |                     |
-   |                     unclosed delimiter
-
-error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
-  --> $DIR/token-error-correct-3.rs:16:9
-   |
+   |                     ^ unclosed delimiter
 LL |             fs::create_dir_all(path.as_ref()).map(|()| true)
-   |                                                             - expected one of `.`, `;`, `?`, `}`, or an operator
 LL |         } else {
-   |         ^ unexpected token
-
-error[E0425]: cannot find function `is_directory` in this scope
-  --> $DIR/token-error-correct-3.rs:11:13
-   |
-LL |         if !is_directory(path.as_ref()) {
-   |             ^^^^^^^^^^^^ not found in this scope
+   |         ^ mismatched closing delimiter
 
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/resolve/token-error-correct-4.fixed b/tests/ui/resolve/token-error-correct-4.fixed
deleted file mode 100644
index 064b9e74e24..00000000000
--- a/tests/ui/resolve/token-error-correct-4.fixed
+++ /dev/null
@@ -1,10 +0,0 @@
-// run-rustfix
-// Test that we do some basic error correction in the tokeniser and apply suggestions.
-
-fn setsuna(_: ()) {}
-
-fn kazusa() {}
-
-fn main() {
-    setsuna(kazusa()); //~ ERROR: expected one of
-} //~ ERROR: expected expression
diff --git a/tests/ui/resolve/token-error-correct-4.rs b/tests/ui/resolve/token-error-correct-4.rs
index 5e31d71e7bf..49fad4bd97f 100644
--- a/tests/ui/resolve/token-error-correct-4.rs
+++ b/tests/ui/resolve/token-error-correct-4.rs
@@ -1,4 +1,3 @@
-// run-rustfix
 // Test that we do some basic error correction in the tokeniser and apply suggestions.
 
 fn setsuna(_: ()) {}
@@ -6,5 +5,5 @@ fn setsuna(_: ()) {}
 fn kazusa() {}
 
 fn main() {
-    setsuna(kazusa(); //~ ERROR: expected one of
-} //~ ERROR: expected expression
+    setsuna(kazusa();
+} //~ ERROR mismatched closing delimiter
diff --git a/tests/ui/resolve/token-error-correct-4.stderr b/tests/ui/resolve/token-error-correct-4.stderr
index 81e5a133691..3ec97171fd3 100644
--- a/tests/ui/resolve/token-error-correct-4.stderr
+++ b/tests/ui/resolve/token-error-correct-4.stderr
@@ -1,16 +1,12 @@
-error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
-  --> $DIR/token-error-correct-4.rs:9:12
+error: mismatched closing delimiter: `}`
+  --> $DIR/token-error-correct-4.rs:8:12
    |
+LL | fn main() {
+   |           - closing delimiter possibly meant for this
 LL |     setsuna(kazusa();
-   |            ^        ^ help: `)` may belong here
-   |            |
-   |            unclosed delimiter
-
-error: expected expression, found `)`
-  --> $DIR/token-error-correct-4.rs:10:1
-   |
+   |            ^ unclosed delimiter
 LL | }
-   | ^ expected expression
+   | ^ mismatched closing delimiter
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/resolve/token-error-correct.rs b/tests/ui/resolve/token-error-correct.rs
index 4f74df0bf1f..84ee90e3685 100644
--- a/tests/ui/resolve/token-error-correct.rs
+++ b/tests/ui/resolve/token-error-correct.rs
@@ -2,7 +2,6 @@
 
 fn main() {
     foo(bar(;
-    //~^ ERROR cannot find function `bar` in this scope
 }
 //~^ ERROR: mismatched closing delimiter: `}`
 
diff --git a/tests/ui/resolve/token-error-correct.stderr b/tests/ui/resolve/token-error-correct.stderr
index ca0c4c18ad4..35b2d0b323b 100644
--- a/tests/ui/resolve/token-error-correct.stderr
+++ b/tests/ui/resolve/token-error-correct.stderr
@@ -5,16 +5,8 @@ LL | fn main() {
    |           - closing delimiter possibly meant for this
 LL |     foo(bar(;
    |            ^ unclosed delimiter
-LL |
 LL | }
    | ^ mismatched closing delimiter
 
-error[E0425]: cannot find function `bar` in this scope
-  --> $DIR/token-error-correct.rs:4:9
-   |
-LL |     foo(bar(;
-   |         ^^^ not found in this scope
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/runtime/out-of-stack.rs b/tests/ui/runtime/out-of-stack.rs
index 6873abc49b2..ff45ace7857 100644
--- a/tests/ui/runtime/out-of-stack.rs
+++ b/tests/ui/runtime/out-of-stack.rs
@@ -6,6 +6,7 @@
 // ignore-emscripten no processes
 // ignore-sgx no processes
 // ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590)
+// ignore-nto no stack overflow handler used (no alternate stack available)
 
 #![feature(core_intrinsics)]
 #![feature(rustc_private)]
diff --git a/tests/ui/runtime/signal-alternate-stack-cleanup.rs b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
index 8a6d738959e..37c602ae0b0 100644
--- a/tests/ui/runtime/signal-alternate-stack-cleanup.rs
+++ b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
@@ -7,6 +7,7 @@
 // ignore-windows
 // ignore-sgx no libc
 // ignore-vxworks no SIGWINCH in user space
+// ignore-nto no SA_ONSTACK
 
 #![feature(rustc_private)]
 extern crate libc;
diff --git a/tests/ui/rust-2018/remove-extern-crate.fixed b/tests/ui/rust-2018/remove-extern-crate.fixed
index 832632268fb..15e0ccc5256 100644
--- a/tests/ui/rust-2018/remove-extern-crate.fixed
+++ b/tests/ui/rust-2018/remove-extern-crate.fixed
@@ -23,6 +23,7 @@ extern crate alloc;
 fn main() {
     another_name::mem::drop(3);
     another::foo();
+    with_visibility::foo();
     remove_extern_crate::foo!();
     bar!();
     alloc::vec![5];
@@ -37,3 +38,12 @@ mod another {
         remove_extern_crate::foo!();
     }
 }
+
+mod with_visibility {
+    pub use core; //~ WARNING `extern crate` is not idiomatic
+
+    pub fn foo() {
+        core::mem::drop(4);
+        remove_extern_crate::foo!();
+    }
+}
diff --git a/tests/ui/rust-2018/remove-extern-crate.rs b/tests/ui/rust-2018/remove-extern-crate.rs
index bbb84cd462d..aec0bc7c374 100644
--- a/tests/ui/rust-2018/remove-extern-crate.rs
+++ b/tests/ui/rust-2018/remove-extern-crate.rs
@@ -23,6 +23,7 @@ extern crate alloc;
 fn main() {
     another_name::mem::drop(3);
     another::foo();
+    with_visibility::foo();
     remove_extern_crate::foo!();
     bar!();
     alloc::vec![5];
@@ -37,3 +38,12 @@ mod another {
         remove_extern_crate::foo!();
     }
 }
+
+mod with_visibility {
+    pub extern crate core; //~ WARNING `extern crate` is not idiomatic
+
+    pub fn foo() {
+        core::mem::drop(4);
+        remove_extern_crate::foo!();
+    }
+}
diff --git a/tests/ui/rust-2018/remove-extern-crate.stderr b/tests/ui/rust-2018/remove-extern-crate.stderr
index bde4c180811..d07358e471b 100644
--- a/tests/ui/rust-2018/remove-extern-crate.stderr
+++ b/tests/ui/rust-2018/remove-extern-crate.stderr
@@ -12,10 +12,26 @@ LL | #![warn(rust_2018_idioms)]
    = note: `#[warn(unused_extern_crates)]` implied by `#[warn(rust_2018_idioms)]`
 
 warning: `extern crate` is not idiomatic in the new edition
-  --> $DIR/remove-extern-crate.rs:32:5
+  --> $DIR/remove-extern-crate.rs:33:5
    |
 LL |     extern crate core;
-   |     ^^^^^^^^^^^^^^^^^^ help: convert it to a `use`
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+help: convert it to a `use`
+   |
+LL |     use core;
+   |     ~~~
+
+warning: `extern crate` is not idiomatic in the new edition
+  --> $DIR/remove-extern-crate.rs:43:5
+   |
+LL |     pub extern crate core;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: convert it to a `use`
+   |
+LL |     pub use core;
+   |         ~~~
 
-warning: 2 warnings emitted
+warning: 3 warnings emitted
 
diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index eb3d3e4a67a..944cdc5f55d 100644
--- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Clone` captures lifetime that does not appea
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                          -----                 ^^^^^^^^
-   |                          |
+   |                          -----      ---------- ^^^^^^^^
+   |                          |          |
+   |                          |          opaque type defined here
    |                          hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
    |
 help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
diff --git a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
index 2c0b2a0d919..8a9b397ca70 100644
--- a/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
+++ b/tests/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -2,8 +2,9 @@ error[E0700]: hidden type for `impl Clone` captures lifetime that does not appea
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                    -----                   ^^^^
-   |                    |
+   |                    -----      ----------   ^^^^
+   |                    |          |
+   |                    |          opaque type defined here
    |                    hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
    |
 help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
index 4559da91e47..f20024e759a 100644
--- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
@@ -3,16 +3,10 @@
 pub struct A {}
 
 impl A {
-    async fn create(path: impl AsRef<std::path::Path>)  { //~ ERROR  `async fn` is not permitted in Rust 2015
-    //~^ WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures]
+    async fn create(path: impl AsRef<std::path::Path>)  {
     ;
-    crate(move || {} ).await //~ ERROR expected function, found module `crate`
+    crate(move || {} ).await
     }
 }
 
-trait C{async fn new(val: T) {} //~ ERROR  `async fn` is not permitted in Rust 2015
-//~^ ERROR functions in traits cannot be declared `async`
-//~| ERROR cannot find type `T` in this scope
-//~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures]
-
-//~ ERROR  this file contains an unclosed delimiter
+trait C{async fn new(val: T) {}  //~ ERROR this file contains an unclosed delimiter
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
index df1cafdb7d3..1ec8ca4275b 100644
--- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
@@ -1,95 +1,8 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:12:85
    |
 LL | trait C{async fn new(val: T) {}
-   |        - unclosed delimiter
-...
-LL |
-   |                                                     ^
+   |        - unclosed delimiter                                                         ^
 
-error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:5
-   |
-LL |     async fn create(path: impl AsRef<std::path::Path>)  {
-   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
-   |
-   = help: pass `--edition 2021` to `rustc`
-   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
-
-error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9
-   |
-LL | trait C{async fn new(val: T) {}
-   |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
-   |
-   = help: pass `--edition 2021` to `rustc`
-   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
-
-error[E0412]: cannot find type `T` in this scope
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:27
-   |
-LL | pub struct A {}
-   | ------------ similarly named struct `A` defined here
-...
-LL | trait C{async fn new(val: T) {}
-   |                           ^ help: a struct with a similar name exists: `A`
-
-error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:9
-   |
-LL | trait C{async fn new(val: T) {}
-   |         -----^^^^^^^^^^^^^^^
-   |         |
-   |         `async` because of this
-   |
-   = note: `async` trait functions are not currently supported
-   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
-   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
-   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
-
-error[E0423]: expected function, found module `crate`
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:9:5
-   |
-LL |     crate(move || {} ).await
-   |     ^^^^^ not a function
-
-warning: changes to closure capture in Rust 2021 will affect drop order
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:6:57
-   |
-LL |       async fn create(path: impl AsRef<std::path::Path>)  {
-   |  _____________________----_____________________________-__^
-   | |                     |                                |
-   | |                     |                                in Rust 2018, `path` is dropped here along with the closure, but in Rust 2021 `path` is not part of the closure
-   | |                     in Rust 2018, this causes the closure to capture `path`, but in Rust 2021, it has no effect
-LL | |
-LL | |     ;
-LL | |     crate(move || {} ).await
-LL | |     }
-   | |_____^
-   |
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
-   = note: requested on the command line with `-W rust-2021-incompatible-closure-captures`
-help: add a dummy let to cause `path` to be fully captured
-   |
-LL |     async fn create(path: impl AsRef<std::path::Path>)  { let _ = &path;
-   |                                                           ++++++++++++++
-
-warning: changes to closure capture in Rust 2021 will affect drop order
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30
-   |
-LL | trait C{async fn new(val: T) {}
-   |                      ---   - ^^
-   |                      |     |
-   |                      |     in Rust 2018, `val` is dropped here along with the closure, but in Rust 2021 `val` is not part of the closure
-   |                      in Rust 2018, this causes the closure to capture `val`, but in Rust 2021, it has no effect
-   |
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
-help: add a dummy let to cause `val` to be fully captured
-   |
-LL | trait C{async fn new(val: T) { let _ = &val;}
-   |                                +++++++++++++
-
-error: aborting due to 6 previous errors; 2 warnings emitted
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0412, E0423, E0670, E0706.
-For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs
index 40ede9705f1..f21c9b2c808 100644
--- a/tests/ui/structs-enums/rec-align-u64.rs
+++ b/tests/ui/structs-enums/rec-align-u64.rs
@@ -43,7 +43,9 @@ struct Outer {
           target_os = "netbsd",
           target_os = "openbsd",
           target_os = "solaris",
-          target_os = "vxworks"))]
+          target_os = "vxworks",
+          target_os = "nto",
+))]
 mod m {
     #[cfg(target_arch = "x86")]
     pub mod m {
diff --git a/tests/ui/suggestions/constrain-suggest-ice.rs b/tests/ui/suggestions/constrain-suggest-ice.rs
index 69b874bed1b..d6e5263ffe0 100644
--- a/tests/ui/suggestions/constrain-suggest-ice.rs
+++ b/tests/ui/suggestions/constrain-suggest-ice.rs
@@ -1,11 +1,9 @@
-struct Bug<S>{ //~ ERROR parameter `S` is never used [E0392]
+struct Bug<S>{
     A: [(); {
-        let x: [u8; Self::W] = [0; Self::W]; //~ ERROR generic `Self` types are currently not permitted in anonymous constants
-        //~^ ERROR generic `Self` types are currently not permitted in anonymous constants
-        //~^^ ERROR the size for values of type `S` cannot be known at compilation time [E0277]
-        F //~ ERROR cannot find value `F` in this scope [E0425]
+        let x: [u8; Self::W] = [0; Self::W];
+        F
     }
-} //~ ERROR mismatched closing delimiter: `}`
+}
 //~^ ERROR mismatched closing delimiter: `}`
 
 fn main() {}
diff --git a/tests/ui/suggestions/constrain-suggest-ice.stderr b/tests/ui/suggestions/constrain-suggest-ice.stderr
index 2af7c2f6971..9b92091de9f 100644
--- a/tests/ui/suggestions/constrain-suggest-ice.stderr
+++ b/tests/ui/suggestions/constrain-suggest-ice.stderr
@@ -9,64 +9,5 @@ LL |     A: [(); {
 LL | }
    | ^ mismatched closing delimiter
 
-error: mismatched closing delimiter: `}`
-  --> $DIR/constrain-suggest-ice.rs:2:8
-   |
-LL | struct Bug<S>{
-   |              - closing delimiter possibly meant for this
-LL |     A: [(); {
-   |        ^ unclosed delimiter
-...
-LL | }
-   | ^ mismatched closing delimiter
-
-error[E0425]: cannot find value `F` in this scope
-  --> $DIR/constrain-suggest-ice.rs:6:9
-   |
-LL |         F
-   |         ^ help: a local variable with a similar name exists: `x`
-
-error: generic `Self` types are currently not permitted in anonymous constants
-  --> $DIR/constrain-suggest-ice.rs:3:21
-   |
-LL |         let x: [u8; Self::W] = [0; Self::W];
-   |                     ^^^^
-
-error: generic `Self` types are currently not permitted in anonymous constants
-  --> $DIR/constrain-suggest-ice.rs:3:36
-   |
-LL |         let x: [u8; Self::W] = [0; Self::W];
-   |                                    ^^^^
-
-error[E0277]: the size for values of type `S` cannot be known at compilation time
-  --> $DIR/constrain-suggest-ice.rs:3:36
-   |
-LL | struct Bug<S>{
-   |            - this type parameter needs to be `std::marker::Sized`
-LL |     A: [(); {
-LL |         let x: [u8; Self::W] = [0; Self::W];
-   |                                    ^^^^^^^ doesn't have a size known at compile-time
-   |
-note: required by a bound in `Bug`
-  --> $DIR/constrain-suggest-ice.rs:1:12
-   |
-LL | struct Bug<S>{
-   |            ^ required by this bound in `Bug`
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | struct Bug<S: ?Sized>{
-   |             ++++++++
-
-error[E0392]: parameter `S` is never used
-  --> $DIR/constrain-suggest-ice.rs:1:12
-   |
-LL | struct Bug<S>{
-   |            ^ unused parameter
-   |
-   = help: consider removing `S`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `S` to be a const parameter, use `const S: usize` instead
-
-error: aborting due to 7 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0277, E0392, E0425.
-For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
index 679ebd61ead..da72c8ebf19 100644
--- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
+++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr
@@ -17,7 +17,7 @@ note: the used `impl` has a `'static` requirement
 LL |     impl<T> MyTrait<T> for dyn ObjectTrait<T> {
    |                                ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self<K>(&self) -> &() { panic!() }
-   |            -------- calling this method introduces the `impl`'s 'static` requirement
+   |            -------- calling this method introduces the `impl`'s `'static` requirement
 help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl<T> MyTrait<T> for dyn ObjectTrait<T> + '_ {
@@ -42,7 +42,7 @@ note: the used `impl` has a `'static` requirement
 LL |     impl dyn ObjectTrait {
    |              ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- calling this method introduces the `impl`'s 'static` requirement
+   |            -------- calling this method introduces the `impl`'s `'static` requirement
 help: consider relaxing the implicit `'static` requirement
    |
 LL |     impl dyn ObjectTrait + '_ {
@@ -65,7 +65,7 @@ note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:87:26
    |
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- calling this method introduces the `impl`'s 'static` requirement
+   |            -------- calling this method introduces the `impl`'s `'static` requirement
 ...
 LL |     impl MyTrait for dyn ObjectTrait {}
    |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
@@ -91,7 +91,7 @@ note: the used `impl` has a `'static` requirement
   --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:106:26
    |
 LL |         fn use_self(&self) -> &() { panic!() }
-   |            -------- calling this method introduces the `impl`'s 'static` requirement
+   |            -------- calling this method introduces the `impl`'s `'static` requirement
 ...
 LL |     impl MyTrait for dyn ObjectTrait {}
    |                          ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement
diff --git a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index c5c3f7b468c..93cfa60b5ab 100644
--- a/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/tests/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -10,7 +10,9 @@ error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not ap
   --> $DIR/missing-lifetimes-in-signature.rs:19:5
    |
 LL |   fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-   |                            ------ hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here
+   |                            ------     ------------- opaque type defined here
+   |                            |
+   |                            hidden type `[closure@$DIR/missing-lifetimes-in-signature.rs:19:5: 19:12]` captures the anonymous lifetime defined here
 ...
 LL | /     move || {
 LL | |
diff --git a/tests/ui/suggestions/multiline-multipart-suggestion.rs b/tests/ui/suggestions/multiline-multipart-suggestion.rs
new file mode 100644
index 00000000000..77d0322d05f
--- /dev/null
+++ b/tests/ui/suggestions/multiline-multipart-suggestion.rs
@@ -0,0 +1,19 @@
+// compile-flags: --error-format=human --color=always
+// ignore-windows
+
+fn short(foo_bar: &Vec<&i32>) -> &i32 { //~ ERROR missing lifetime specifier
+    &12
+}
+
+fn long( //~ ERROR missing lifetime specifier
+    foo_bar: &Vec<&i32>,
+    something_very_long_so_that_the_line_will_wrap_around__________: i32,
+) -> &i32 {
+    &12
+}
+
+fn long2( //~ ERROR missing lifetime specifier
+    foo_bar: &Vec<&i32>) -> &i32 {
+    &12
+}
+fn main() {}
diff --git a/tests/ui/suggestions/multiline-multipart-suggestion.stderr b/tests/ui/suggestions/multiline-multipart-suggestion.stderr
new file mode 100644
index 00000000000..045a86b4f54
--- /dev/null
+++ b/tests/ui/suggestions/multiline-multipart-suggestion.stderr
@@ -0,0 +1,46 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiline-multipart-suggestion.rs:4:34
+   |
+LL | fn short(foo_bar: &Vec<&i32>) -> &i32 {
+   |                   ----------     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `foo_bar`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+   |
+LL | fn short<'a>(foo_bar: &'a Vec<&'a i32>) -> &'a i32 {
+   |         ++++           ++      ++           ++
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiline-multipart-suggestion.rs:11:6
+   |
+LL |     foo_bar: &Vec<&i32>,
+   |              ----------
+LL |     something_very_long_so_that_the_line_will_wrap_around__________: i32,
+LL | ) -> &i32 {
+   |      ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `foo_bar`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+   |
+LL ~ fn long<'a>(
+LL ~     foo_bar: &'a Vec<&'a i32>,
+LL |     something_very_long_so_that_the_line_will_wrap_around__________: i32,
+LL ~ ) -> &'a i32 {
+   |
+
+error[E0106]: missing lifetime specifier
+  --> $DIR/multiline-multipart-suggestion.rs:16:29
+   |
+LL |     foo_bar: &Vec<&i32>) -> &i32 {
+   |              ----------     ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but the signature does not say which one of `foo_bar`'s 2 lifetimes it is borrowed from
+help: consider introducing a named lifetime parameter
+   |
+LL ~ fn long2<'a>(
+LL ~     foo_bar: &'a Vec<&'a i32>) -> &'a i32 {
+   |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0106`.
diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs
new file mode 100644
index 00000000000..fbaf41245e9
--- /dev/null
+++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.rs
@@ -0,0 +1,8 @@
+pub struct Bar<S>(S);
+
+pub trait Foo {}
+
+impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {}
+//~^ ERROR ambiguous associated type
+
+fn main() {}
diff --git a/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
new file mode 100644
index 00000000000..0ca5b9b9207
--- /dev/null
+++ b/tests/ui/suggestions/suggest-trait-in-ufcs-in-hrtb.stderr
@@ -0,0 +1,9 @@
+error[E0223]: ambiguous associated type
+  --> $DIR/suggest-trait-in-ufcs-in-hrtb.rs:5:38
+   |
+LL | impl<S> Foo for Bar<S> where for<'a> <&'a S>::Item: Foo {}
+   |                                      ^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'a S as IntoIterator>::Item`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/thir-print/thir-flat.stdout b/tests/ui/thir-print/thir-flat.stdout
index c399fa66b6a..910c0da2737 100644
--- a/tests/ui/thir-print/thir-flat.stdout
+++ b/tests/ui/thir-print/thir-flat.stdout
@@ -1,5 +1,8 @@
 DefId(0:3 ~ thir_flat[45a6]::main):
 Thir {
+    body_type: Fn(
+        ([]; c_variadic: false)->(),
+    ),
     arms: [],
     blocks: [
         Block {
@@ -14,21 +17,16 @@ Thir {
     ],
     exprs: [
         Expr {
-            ty: (),
-            temp_lifetime: Some(
-                Node(2),
-            ),
-            span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
             kind: Block {
                 block: b0,
             },
-        },
-        Expr {
             ty: (),
             temp_lifetime: Some(
                 Node(2),
             ),
             span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
+        },
+        Expr {
             kind: Scope {
                 region_scope: Node(2),
                 lint_level: Explicit(
@@ -36,18 +34,23 @@ Thir {
                 ),
                 value: e0,
             },
-        },
-        Expr {
             ty: (),
             temp_lifetime: Some(
                 Node(2),
             ),
             span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
+        },
+        Expr {
             kind: Scope {
                 region_scope: Destruction(2),
                 lint_level: Inherited,
                 value: e1,
             },
+            ty: (),
+            temp_lifetime: Some(
+                Node(2),
+            ),
+            span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
         },
     ],
     stmts: [],
diff --git a/tests/ui/thread-local/tls.rs b/tests/ui/thread-local/tls.rs
index fbd3413885f..f03bd3f991b 100644
--- a/tests/ui/thread-local/tls.rs
+++ b/tests/ui/thread-local/tls.rs
@@ -1,6 +1,7 @@
 // run-pass
 // ignore-emscripten no threads support
 // compile-flags: -O
+// ignore-nto Doesn't work without emulated TLS enabled (in LLVM)
 
 #![feature(thread_local)]
 
diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.rs b/tests/ui/tool-attributes/duplicate-diagnostic.rs
index 39c2ca1cb86..e2cf9508757 100644
--- a/tests/ui/tool-attributes/duplicate-diagnostic.rs
+++ b/tests/ui/tool-attributes/duplicate-diagnostic.rs
@@ -9,5 +9,5 @@ extern crate p1;
 extern crate p2;
 
 #[rustc_diagnostic_item = "Foo"]
-pub struct Foo {} //~ ERROR duplicate diagnostic item found
+pub struct Foo {} //~ ERROR duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo`
 fn main() {}
diff --git a/tests/ui/tool-attributes/duplicate-diagnostic.stderr b/tests/ui/tool-attributes/duplicate-diagnostic.stderr
index e315fdc7d84..26bd6a82e34 100644
--- a/tests/ui/tool-attributes/duplicate-diagnostic.stderr
+++ b/tests/ui/tool-attributes/duplicate-diagnostic.stderr
@@ -2,11 +2,13 @@ error: duplicate diagnostic item in crate `p2`: `Foo`.
    |
    = note: the diagnostic item is first defined in crate `p1`.
 
-error: duplicate diagnostic item found: `Foo`.
+error: duplicate diagnostic item in crate `duplicate_diagnostic`: `Foo`.
   --> $DIR/duplicate-diagnostic.rs:12:1
    |
 LL | pub struct Foo {}
    | ^^^^^^^^^^^^^^
+   |
+   = note: the diagnostic item is first defined in crate `p2`.
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/traits/issue-77982.stderr b/tests/ui/traits/issue-77982.stderr
index a397b0accc8..d4fea05fe4b 100644
--- a/tests/ui/traits/issue-77982.stderr
+++ b/tests/ui/traits/issue-77982.stderr
@@ -43,7 +43,7 @@ LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
    |                                            |
    |                                            required by a bound introduced by this call
    |
-   = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
+   = note: multiple `impl`s satisfying `u32: From<_>` found in the `core` crate:
            - impl From<Ipv4Addr> for u32;
            - impl From<NonZeroU32> for u32;
            - impl From<bool> for u32;
diff --git a/tests/ui/traits/new-solver/try-example.rs b/tests/ui/traits/new-solver/try-example.rs
new file mode 100644
index 00000000000..e826f3a0059
--- /dev/null
+++ b/tests/ui/traits/new-solver/try-example.rs
@@ -0,0 +1,28 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+use std::error::Error;
+
+fn main() -> Result<(), Box<dyn Error>> {
+    let x: i32 = parse()?;
+    Ok(())
+}
+
+trait Parse {}
+
+impl Parse for i32 {}
+
+#[derive(Debug)]
+struct ParseError;
+
+impl std::fmt::Display for ParseError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "ParseError")
+    }
+}
+
+impl Error for ParseError {}
+
+fn parse<T: Parse>() -> Result<T, ParseError> {
+    todo!()
+}
diff --git a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs
new file mode 100644
index 00000000000..3903bfe9bcf
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.rs
@@ -0,0 +1,11 @@
+#![feature(non_lifetime_binders, generic_const_exprs)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+//~| WARN the feature `generic_const_exprs` is incomplete
+
+fn foo() -> usize
+where
+    for<T> [i32; { let _: T = todo!(); 0 }]:,
+    //~^ ERROR cannot capture late-bound type parameter in a constant
+{}
+
+fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr
new file mode 100644
index 00000000000..fafff02dea6
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/late-bound-in-anon-ct.stderr
@@ -0,0 +1,27 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/late-bound-in-anon-ct.rs:1:12
+   |
+LL | #![feature(non_lifetime_binders, generic_const_exprs)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/late-bound-in-anon-ct.rs:1:34
+   |
+LL | #![feature(non_lifetime_binders, generic_const_exprs)]
+   |                                  ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+
+error: cannot capture late-bound type parameter in a constant
+  --> $DIR/late-bound-in-anon-ct.rs:7:27
+   |
+LL |     for<T> [i32; { let _: T = todo!(); 0 }]:,
+   |         -                 ^
+   |         |
+   |         parameter defined here
+
+error: aborting due to previous error; 2 warnings emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs
new file mode 100644
index 00000000000..9830241c377
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.rs
@@ -0,0 +1,7 @@
+// check-pass
+// compile-flags: --crate-type=lib
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+pub fn f<T>() where for<U> (T, U): Copy {}
diff --git a/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr
new file mode 100644
index 00000000000..667575b72d4
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/object-lifetime-default-for-late.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/object-lifetime-default-for-late.rs:4:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr
index 0ed8a703b6d..e52d5f9de69 100644
--- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr
+++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds_param.stderr
@@ -2,7 +2,9 @@ error[E0700]: hidden type for `impl PlusOne` captures lifetime that does not app
   --> $DIR/imply_bounds_from_bounds_param.rs:24:5
    |
 LL | fn test<'a>(y: &'a mut i32) -> impl PlusOne {
-   |         -- hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
+   |         --                     ------------ opaque type defined here
+   |         |
+   |         hidden type `<&'a mut i32 as Callable>::Output` captures the lifetime `'a` as defined here
 LL |     <&'a mut i32 as Callable>::call(y)
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
index 65a0af0d22f..d666e668d36 100644
--- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
+++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
@@ -1,6 +1,8 @@
 error[E0700]: hidden type for `Opaque<'a, T>` captures lifetime that does not appear in bounds
   --> $DIR/missing_lifetime_bound.rs:4:47
    |
+LL | type Opaque<'a, T> = impl Sized;
+   |                      ---------- opaque type defined here
 LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
    |             --                                ^
    |             |
diff --git a/tests/ui/type/issue-91268.rs b/tests/ui/type/issue-91268.rs
index f1e16bc7bd3..274ea839e8b 100644
--- a/tests/ui/type/issue-91268.rs
+++ b/tests/ui/type/issue-91268.rs
@@ -1,8 +1,4 @@
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: cannot find type `ţ` in this scope
-// error-pattern: parenthesized type parameters may only be used with a `Fn` trait
-// error-pattern: type arguments are not allowed on builtin type `u8`
-// error-pattern: mismatched types
 // ignore-tidy-trailing-newlines
 // `ţ` must be the last character in this file, it cannot be followed by a newline
 fn main() {
diff --git a/tests/ui/type/issue-91268.stderr b/tests/ui/type/issue-91268.stderr
index 6c9ee994584..a3619d863e2 100644
--- a/tests/ui/type/issue-91268.stderr
+++ b/tests/ui/type/issue-91268.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-91268.rs:9:12
+  --> $DIR/issue-91268.rs:5:12
    |
 LL | fn main() {
    |           - unclosed delimiter
@@ -8,56 +8,5 @@ LL |     0: u8(ţ
    |          |
    |          unclosed delimiter
 
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-91268.rs:9:12
-   |
-LL | fn main() {
-   |           - unclosed delimiter
-LL |     0: u8(ţ
-   |          - ^
-   |          |
-   |          unclosed delimiter
-
-error[E0412]: cannot find type `ţ` in this scope
-  --> $DIR/issue-91268.rs:9:11
-   |
-LL |     0: u8(ţ
-   |           ^ expecting a type here because of type ascription
-
-error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
-  --> $DIR/issue-91268.rs:9:8
-   |
-LL |     0: u8(ţ
-   |        ^^^^ only `Fn` traits may use parentheses
-   |
-help: use angle brackets instead
-   |
-LL |     0: u8<ţ>
-   |          ~ +
-
-error[E0109]: type arguments are not allowed on builtin type `u8`
-  --> $DIR/issue-91268.rs:9:11
-   |
-LL |     0: u8(ţ
-   |        -- ^ type argument not allowed
-   |        |
-   |        not allowed on builtin type `u8`
-   |
-help: primitive type `u8` doesn't have generic parameters
-   |
-LL -     0: u8(ţ
-LL +     0: u8
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/issue-91268.rs:9:5
-   |
-LL | fn main() {
-   |           - expected `()` because of default return type
-LL |     0: u8(ţ
-   |     ^^^^^^^ expected `()`, found `u8`
-
-error: aborting due to 6 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0109, E0214, E0308, E0412.
-For more information about an error, try `rustc --explain E0109`.
diff --git a/tests/ui/typeck/bad-type-in-vec-contains.rs b/tests/ui/typeck/bad-type-in-vec-contains.rs
new file mode 100644
index 00000000000..4433047b75a
--- /dev/null
+++ b/tests/ui/typeck/bad-type-in-vec-contains.rs
@@ -0,0 +1,7 @@
+// The error message here still is pretty confusing.
+
+fn main() {
+    let primes = Vec::new();
+    primes.contains(3);
+    //~^ ERROR mismatched types
+}
diff --git a/tests/ui/typeck/bad-type-in-vec-contains.stderr b/tests/ui/typeck/bad-type-in-vec-contains.stderr
new file mode 100644
index 00000000000..0e03388d2d5
--- /dev/null
+++ b/tests/ui/typeck/bad-type-in-vec-contains.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/bad-type-in-vec-contains.rs:5:21
+   |
+LL |     primes.contains(3);
+   |            -------- ^
+   |            |        |
+   |            |        expected `&_`, found integer
+   |            |        help: consider borrowing here: `&3`
+   |            arguments to this method are incorrect
+   |            here the type of `primes` is inferred to be `[_]`
+   |
+   = note: expected reference `&_`
+                   found type `{integer}`
+note: method defined here
+  --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/issue-31173.stderr b/tests/ui/typeck/issue-31173.stderr
index 8346c9a0aae..b622122f33e 100644
--- a/tests/ui/typeck/issue-31173.stderr
+++ b/tests/ui/typeck/issue-31173.stderr
@@ -24,8 +24,17 @@ note: required by a bound in `cloned`
 error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut IntoIter<u8>, [closure@issue-31173.rs:7:21]>>`, but its trait bounds were not satisfied
   --> $DIR/issue-31173.rs:12:10
    |
-LL |         .collect();
-   |          ^^^^^^^ method cannot be called due to unsatisfied trait bounds
+LL |       let temp: Vec<u8> = it
+   |  _________________________-
+LL | |         .take_while(|&x| {
+LL | |             found_e = true;
+LL | |             false
+LL | |         })
+LL | |         .cloned()
+LL | |         .collect();
+   | |         -^^^^^^^ method cannot be called due to unsatisfied trait bounds
+   | |_________|
+   | 
   --> $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
    |
    = note: doesn't satisfy `<_ as Iterator>::Item = &_`
diff --git a/tests/ui/typeck/issue-91334.rs b/tests/ui/typeck/issue-91334.rs
index bf9a5a62620..29204276bb3 100644
--- a/tests/ui/typeck/issue-91334.rs
+++ b/tests/ui/typeck/issue-91334.rs
@@ -1,9 +1,6 @@
 // Regression test for the ICE described in issue #91334.
 
 // error-pattern: this file contains an unclosed delimiter
-// error-pattern: expected one of
-// error-pattern: mismatched closing delimiter
-// error-pattern: mismatched types
 
 #![feature(generators)]
 
diff --git a/tests/ui/typeck/issue-91334.stderr b/tests/ui/typeck/issue-91334.stderr
index 78f392c9a8a..7cb30eea530 100644
--- a/tests/ui/typeck/issue-91334.stderr
+++ b/tests/ui/typeck/issue-91334.stderr
@@ -1,15 +1,14 @@
-error: this file contains an unclosed delimiter
-  --> $DIR/issue-91334.rs:10:23
+error: mismatched closing delimiter: `)`
+  --> $DIR/issue-91334.rs:7:19
    |
 LL | fn f(){||yield(((){),
-   |       -       -    -  ^
-   |       |       |    |
-   |       |       |    missing open `(` for this delimiter
-   |       |       unclosed delimiter
-   |       unclosed delimiter
+   |                -  ^^ mismatched closing delimiter
+   |                |  |
+   |                |  unclosed delimiter
+   |                closing delimiter possibly meant for this
 
 error: this file contains an unclosed delimiter
-  --> $DIR/issue-91334.rs:10:23
+  --> $DIR/issue-91334.rs:7:23
    |
 LL | fn f(){||yield(((){),
    |       -       -    -  ^
@@ -18,35 +17,5 @@ LL | fn f(){||yield(((){),
    |       |       unclosed delimiter
    |       unclosed delimiter
 
-error: expected one of `)`, `,`, `.`, `?`, or an operator, found `{`
-  --> $DIR/issue-91334.rs:10:19
-   |
-LL | fn f(){||yield(((){),
-   |                   ^
-   |                   |
-   |                   expected one of `)`, `,`, `.`, `?`, or an operator
-   |                   help: missing `,`
-
-error: mismatched closing delimiter: `)`
-  --> $DIR/issue-91334.rs:10:19
-   |
-LL | fn f(){||yield(((){),
-   |                -  ^^ mismatched closing delimiter
-   |                |  |
-   |                |  unclosed delimiter
-   |                closing delimiter possibly meant for this
-
-error[E0308]: mismatched types
-  --> $DIR/issue-91334.rs:10:8
-   |
-LL | fn f(){||yield(((){),
-   |       -^^^^^^^^^^^^^^^ expected `()`, found generator
-   |       |
-   |       help: a return type might be missing here: `-> _`
-   |
-   = note: expected unit type `()`
-              found generator `[generator@$DIR/issue-91334.rs:10:8: 10:10]`
-
-error: aborting due to 5 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/issue-92481.rs b/tests/ui/typeck/issue-92481.rs
index 0a6b1843d99..f752400bbcb 100644
--- a/tests/ui/typeck/issue-92481.rs
+++ b/tests/ui/typeck/issue-92481.rs
@@ -2,13 +2,8 @@
 
 #![crate_type="lib"]
 
-fn r({) {
-    Ok {             //~ ERROR mismatched types [E0308]
+fn r({) { //~ ERROR mismatched closing delimiter
+    Ok {
         d..||_=m
     }
 }
-//~^^^^^ ERROR expected parameter name, found `{`
-//~| ERROR expected one of `,`, `:`, or `}`, found `..`
-//~^^^^^ ERROR cannot find value `d` in this scope [E0425]
-//~| ERROR cannot find value `m` in this scope [E0425]
-//~| ERROR variant `Result<_, _>::Ok` has no field named `d` [E0559]
diff --git a/tests/ui/typeck/issue-92481.stderr b/tests/ui/typeck/issue-92481.stderr
index c3acbd2c067..d87d3277d56 100644
--- a/tests/ui/typeck/issue-92481.stderr
+++ b/tests/ui/typeck/issue-92481.stderr
@@ -1,60 +1,11 @@
-error: expected parameter name, found `{`
+error: mismatched closing delimiter: `)`
   --> $DIR/issue-92481.rs:5:6
    |
 LL | fn r({) {
-   |      ^ expected parameter name
+   |     -^^ mismatched closing delimiter
+   |     ||
+   |     |unclosed delimiter
+   |     closing delimiter possibly meant for this
 
-error: expected one of `,`, `:`, or `}`, found `..`
-  --> $DIR/issue-92481.rs:5:6
-   |
-LL | fn r({) {
-   |      ^ unclosed delimiter
-LL |     Ok {
-LL |         d..||_=m
-   |          -^
-   |          |
-   |          help: `}` may belong here
-
-error[E0425]: cannot find value `d` in this scope
-  --> $DIR/issue-92481.rs:7:9
-   |
-LL |         d..||_=m
-   |         ^ not found in this scope
-
-error[E0425]: cannot find value `m` in this scope
-  --> $DIR/issue-92481.rs:7:16
-   |
-LL |         d..||_=m
-   |                ^ not found in this scope
-
-error[E0559]: variant `Result<_, _>::Ok` has no field named `d`
-  --> $DIR/issue-92481.rs:7:9
-   |
-LL |         d..||_=m
-   |         ^ field does not exist
-  --> $SRC_DIR/core/src/result.rs:LL:COL
-   |
-   = note: `Result<_, _>::Ok` defined here
-   |
-help: `Result<_, _>::Ok` is a tuple variant, use the appropriate syntax
-   |
-LL |     Result<_, _>::Ok(/* fields */)
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/issue-92481.rs:6:5
-   |
-LL |   fn r({) {
-   |           - help: a return type might be missing here: `-> _`
-LL | /     Ok {
-LL | |         d..||_=m
-LL | |     }
-   | |_____^ expected `()`, found `Result<_, _>`
-   |
-   = note: expected unit type `()`
-                   found enum `Result<_, _>`
-
-error: aborting due to 6 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0308, E0425, E0559.
-For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs b/tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs
new file mode 100644
index 00000000000..019c6e81c50
--- /dev/null
+++ b/tests/ui/typeck/lazy-norm/equating-projection-cyclically.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Ztrait-solver=next
+// known-bug: unknown
+
+trait Test {
+    type Assoc;
+}
+
+fn transform<T: Test>(x: T) -> T::Assoc {
+    todo!()
+}
+
+impl Test for i32 {
+    type Assoc = i32;
+}
+
+impl Test for String {
+    type Assoc = String;
+}
+
+fn main() {
+    let mut x = Default::default();
+    x = transform(x);
+    x = 1i32;
+}
diff --git a/tests/ui/typeck/lazy-norm/equating-projection-cyclically.stderr b/tests/ui/typeck/lazy-norm/equating-projection-cyclically.stderr
new file mode 100644
index 00000000000..57cbc65a17a
--- /dev/null
+++ b/tests/ui/typeck/lazy-norm/equating-projection-cyclically.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/equating-projection-cyclically.rs:22:19
+   |
+LL |     x = transform(x);
+   |                   ^ expected inferred type, found associated type
+   |
+   = note:         expected type `_`
+           found associated type `<_ as Test>::Assoc`
+   = help: consider constraining the associated type `<_ as Test>::Assoc` to `_`
+   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/wait-forked-but-failed-child.rs b/tests/ui/wait-forked-but-failed-child.rs
index 674c26a43f2..82a1dd63713 100644
--- a/tests/ui/wait-forked-but-failed-child.rs
+++ b/tests/ui/wait-forked-but-failed-child.rs
@@ -3,6 +3,7 @@
 // ignore-sgx no processes
 // ignore-vxworks no 'ps'
 // ignore-fuchsia no 'ps'
+// ignore-nto no 'ps'
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/while/while-else-err.rs b/tests/ui/while/while-else-err.rs
new file mode 100644
index 00000000000..36b60fbd4be
--- /dev/null
+++ b/tests/ui/while/while-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+    while false {
+        //~^ NOTE `else` is attached to this loop
+    } else {
+        //~^ ERROR `while...else` loops are not supported
+        //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+    };
+}
diff --git a/tests/ui/while/while-else-err.stderr b/tests/ui/while/while-else-err.stderr
new file mode 100644
index 00000000000..88f715d5666
--- /dev/null
+++ b/tests/ui/while/while-else-err.stderr
@@ -0,0 +1,17 @@
+error: `while...else` loops are not supported
+  --> $DIR/while-else-err.rs:4:7
+   |
+LL |       while false {
+   |       ----- `else` is attached to this loop
+LL |
+LL |       } else {
+   |  _______^
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+   = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/tests/ui/while/while-else-let-else-err.rs b/tests/ui/while/while-else-let-else-err.rs
new file mode 100644
index 00000000000..6d9909347c3
--- /dev/null
+++ b/tests/ui/while/while-else-let-else-err.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let _ = while false {
+        //~^ NOTE `else` is attached to this loop
+    } else {
+        //~^ ERROR `while...else` loops are not supported
+        //~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+    };
+}
diff --git a/tests/ui/while/while-else-let-else-err.stderr b/tests/ui/while/while-else-let-else-err.stderr
new file mode 100644
index 00000000000..431d37c007c
--- /dev/null
+++ b/tests/ui/while/while-else-let-else-err.stderr
@@ -0,0 +1,17 @@
+error: `while...else` loops are not supported
+  --> $DIR/while-else-let-else-err.rs:4:7
+   |
+LL |       let _ = while false {
+   |               ----- `else` is attached to this loop
+LL |
+LL |       } else {
+   |  _______^
+LL | |
+LL | |
+LL | |     };
+   | |_____^
+   |
+   = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
+
+error: aborting due to previous error
+
diff --git a/triagebot.toml b/triagebot.toml
index 7a26457ab04..f7607d522c1 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -482,7 +482,6 @@ compiler-team = [
     "@davidtwco",
     "@oli-obk",
     "@lcnr",
-    "@nagisa",
     "@wesleywiser",
     "@michaelwoerister",
 ]
@@ -552,7 +551,6 @@ mir = [
     "@oli-obk",
 ]
 mir-opt = [
-    "@nagisa",
     "@oli-obk",
     "@wesleywiser",
 ]